3 * Copyright (C) 2006-2010 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
26 * Represents a class declaration in the source code.
28 public class Vala
.Interface
: ObjectTypeSymbol
{
29 private List
<DataType
> prerequisites
= new ArrayList
<DataType
> ();
31 private List
<Method
> methods
= new ArrayList
<Method
> ();
32 private List
<Field
> fields
= new ArrayList
<Field
> ();
33 private List
<Constant
> constants
= new ArrayList
<Constant
> ();
34 private List
<Property
> properties
= new ArrayList
<Property
> ();
35 private List
<Signal
> signals
= new ArrayList
<Signal
> ();
36 private List
<Symbol
> virtuals
= new ArrayList
<Symbol
> ();
39 private List
<Class
> classes
= new ArrayList
<Class
> ();
40 private List
<Struct
> structs
= new ArrayList
<Struct
> ();
41 private List
<Enum
> enums
= new ArrayList
<Enum
> ();
42 private List
<Delegate
> delegates
= new ArrayList
<Delegate
> ();
45 * Returns a copy of the list of classes.
47 * @return list of classes
49 public List
<Class
> get_classes () {
54 * Returns a copy of the list of structs.
56 * @return list of structs
58 public List
<Struct
> get_structs () {
63 * Returns a copy of the list of enums.
65 * @return list of enums
67 public List
<Enum
> get_enums () {
72 * Returns a copy of the list of delegates.
74 * @return list of delegates
76 public List
<Delegate
> get_delegates () {
81 * Creates a new interface.
83 * @param name type name
84 * @param source_reference reference to source code
85 * @return newly created interface
87 public Interface (string name
, SourceReference? source_reference
= null, Comment? comment
= null) {
88 base (name
, source_reference
, comment
);
92 * Adds the specified interface or class to the list of prerequisites of
95 * @param type an interface or class reference
97 public void add_prerequisite (DataType type
) {
98 prerequisites
.add (type
);
99 type
.parent_node
= this
;
103 * Prepends the specified interface or class to the list of
104 * prerequisites of this interface.
106 * @param type an interface or class reference
108 public void prepend_prerequisite (DataType type
) {
109 prerequisites
.insert (0, type
);
113 * Returns a copy of the base type list.
115 * @return list of base types
117 public List
<DataType
> get_prerequisites () {
118 return prerequisites
;
122 * Adds the specified method as a member to this interface.
126 public override void add_method (Method m
) {
127 if (m is CreationMethod
) {
128 Report
.error (m
.source_reference
, "construction methods may only be declared within classes and structs");
133 if (m
.binding
== MemberBinding
.INSTANCE
) {
134 m
.this_parameter
= new
Parameter ("this", get_this_type ());
135 m
.scope
.add (m
.this_parameter
.name
, m
.this_parameter
);
137 if (!(m
.return_type is VoidType
) && m
.get_postconditions ().size
> 0) {
138 m
.result_var
= new
LocalVariable (m
.return_type
.copy (), "result", null, source_reference
);
139 m
.result_var
.is_result
= true;
143 scope
.add (m
.name
, m
);
147 * Returns a copy of the list of methods.
149 * @return list of methods
151 public override List
<Method
> get_methods () {
156 * Adds the specified field as a member to this interface. The field
157 * must be private and static.
161 public override void add_field (Field f
) {
163 scope
.add (f
.name
, f
);
167 * Returns a copy of the list of fields.
169 * @return list of fields
171 public List
<Field
> get_fields () {
176 * Adds the specified constant as a member to this interface.
178 * @param c a constant
180 public override void add_constant (Constant c
) {
182 scope
.add (c
.name
, c
);
186 * Returns a copy of the list of constants.
188 * @return list of constants
190 public List
<Constant
> get_constants () {
195 * Adds the specified property as a member to this interface.
197 * @param prop a property
199 public override void add_property (Property prop
) {
200 if (prop
.field
!= null) {
201 Report
.error (prop
.source_reference
, "automatic properties are not allowed in interfaces");
207 properties
.add (prop
);
208 scope
.add (prop
.name
, prop
);
210 prop
.this_parameter
= new
Parameter ("this", new
ObjectType (this
));
211 prop
.scope
.add (prop
.this_parameter
.name
, prop
.this_parameter
);
215 * Returns a copy of the list of properties.
217 * @return list of properties
219 public override List
<Property
> get_properties () {
224 * Adds the specified signal as a member to this interface.
226 * @param sig a signal
228 public override void add_signal (Signal sig
) {
230 scope
.add (sig
.name
, sig
);
234 * Returns a copy of the list of signals.
236 * @return list of signals
238 public override List
<Signal
> get_signals () {
242 public virtual List
<Symbol
> get_virtuals () {
247 * Adds the specified class as an inner class.
251 public override void add_class (Class cl
) {
253 scope
.add (cl
.name
, cl
);
257 * Adds the specified struct as an inner struct.
261 public override void add_struct (Struct st
) {
263 scope
.add (st
.name
, st
);
267 * Adds the specified enum as an inner enum.
271 public override void add_enum (Enum en
) {
273 scope
.add (en
.name
, en
);
277 * Adds the specified delegate as an inner delegate.
279 * @param d a delegate
281 public override void add_delegate (Delegate d
) {
283 scope
.add (d
.name
, d
);
286 public override void accept (CodeVisitor visitor
) {
287 visitor
.visit_interface (this
);
290 public override void accept_children (CodeVisitor visitor
) {
291 foreach (DataType type
in prerequisites
) {
292 type
.accept (visitor
);
295 foreach (TypeParameter p
in get_type_parameters ()) {
299 /* process enums first to avoid order problems in C code */
300 foreach (Enum en
in enums
) {
304 foreach (Method m
in methods
) {
308 foreach (Field f
in fields
) {
312 foreach (Constant c
in constants
) {
316 foreach (Property prop
in properties
) {
317 prop
.accept (visitor
);
320 foreach (Signal sig
in signals
) {
321 sig
.accept (visitor
);
324 foreach (Class cl
in classes
) {
328 foreach (Struct st
in structs
) {
332 foreach (Delegate d
in delegates
) {
337 public override bool is_reference_type () {
341 public override bool is_subtype_of (TypeSymbol t
) {
346 foreach (DataType prerequisite
in prerequisites
) {
347 if (prerequisite
.data_type
!= null && prerequisite
.data_type
.is_subtype_of (t
)) {
355 public override void replace_type (DataType old_type
, DataType new_type
) {
356 for (int i
= 0; i
< prerequisites
.size
; i
++) {
357 if (prerequisites
[i
] == old_type
) {
358 prerequisites
[i
] = new_type
;
359 new_type
.parent_node
= this
;
365 public override bool check (CodeContext context
) {
372 var old_source_file
= context
.analyzer
.current_source_file
;
373 var old_symbol
= context
.analyzer
.current_symbol
;
375 if (source_reference
!= null) {
376 context
.analyzer
.current_source_file
= source_reference
.file
;
378 context
.analyzer
.current_symbol
= this
;
380 foreach (DataType prerequisite_reference
in get_prerequisites ()) {
381 // check whether prerequisite is at least as accessible as the interface
382 if (!context
.analyzer
.is_type_accessible (this
, prerequisite_reference
)) {
384 Report
.error (source_reference
, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference
.to_string (), get_full_name ()));
389 /* check prerequisites */
390 Class prereq_class
= null;
391 foreach (DataType prereq
in get_prerequisites ()) {
392 TypeSymbol class_or_interface
= prereq
.data_type
;
393 /* skip on previous errors */
394 if (class_or_interface
== null) {
399 if (!(class_or_interface is ObjectTypeSymbol
)) {
401 Report
.error (source_reference
, "Prerequisite `%s` of interface `%s` is not a class or interface".printf (get_full_name (), class_or_interface
.to_string ()));
405 /* interfaces are not allowed to have multiple instantiable prerequisites */
406 if (class_or_interface is Class
) {
407 if (prereq_class
!= null) {
409 Report
.error (source_reference
, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (get_full_name (), class_or_interface
.get_full_name (), prereq_class
.get_full_name ()));
413 prereq_class
= (Class
) class_or_interface
;
417 foreach (DataType type
in prerequisites
) {
418 type
.check (context
);
421 foreach (TypeParameter p
in get_type_parameters ()) {
425 foreach (Enum en
in enums
) {
429 foreach (Method m
in methods
) {
431 if (m
.is_virtual
|| m
.is_abstract
) {
436 foreach (Field f
in fields
) {
440 foreach (Constant c
in constants
) {
444 foreach (Signal sig
in signals
) {
446 if (sig
.is_virtual
) {
451 foreach (Property prop
in properties
) {
452 prop
.check (context
);
453 if (prop
.is_virtual
|| prop
.is_abstract
) {
458 foreach (Class cl
in classes
) {
462 foreach (Struct st
in structs
) {
466 foreach (Delegate d
in delegates
) {
470 Map
<int, Symbol
>? positions
= new HashMap
<int, Symbol
> ();
471 bool ordered_seen
= false;
472 bool unordered_seen
= false;
473 foreach (Symbol sym
in virtuals
) {
474 int ordering
= sym
.get_attribute_integer ("CCode", "ordering", -1);
476 Report
.error (sym
.source_reference
, "%s: Invalid ordering".printf (sym
.get_full_name ()));
477 // Mark state as invalid
480 unordered_seen
= true;
483 bool ordered
= ordering
!= -1;
484 if (ordered
&& unordered_seen
&& !ordered_seen
) {
485 Report
.error (sym
.source_reference
, "%s: Cannot mix ordered and unordered virtuals".printf (sym
.get_full_name ()));
488 ordered_seen
= ordered_seen
|| ordered
;
489 if (!ordered
&& !unordered_seen
&& ordered_seen
) {
490 Report
.error (sym
.source_reference
, "%s: Cannot mix ordered and unordered virtuals".printf (sym
.get_full_name ()));
493 unordered_seen
= unordered_seen
|| !ordered
;
494 if (!ordered_seen
|| !unordered_seen
) {
496 Symbol? prev
= positions
[ordering
];
498 Report
.error (sym
.source_reference
, "%s: Duplicate ordering (previous virtual with the same position is %s)".printf (sym
.get_full_name (), prev
.name
));
501 positions
[ordering
] = sym
;
506 for (int i
= 0; i
< virtuals
.size
; i
++) {
507 Symbol? sym
= positions
[i
];
509 Report
.error (source_reference
, "%s: Gap in ordering in position %d".printf (get_full_name (), i
));
518 context
.analyzer
.current_source_file
= old_source_file
;
519 context
.analyzer
.current_symbol
= old_symbol
;