3 * Copyright (C) 2006-2009 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
> ();
38 private List
<Class
> classes
= new ArrayList
<Class
> ();
39 private List
<Struct
> structs
= new ArrayList
<Struct
> ();
40 private List
<Enum
> enums
= new ArrayList
<Enum
> ();
41 private List
<Delegate
> delegates
= new ArrayList
<Delegate
> ();
44 private string lower_case_csuffix
;
45 private string type_cname
;
46 private string type_id
;
49 * Returns a copy of the list of classes.
51 * @return list of classes
53 public List
<Class
> get_classes () {
54 return new ReadOnlyList
<Class
> (classes
);
58 * Returns a copy of the list of structs.
60 * @return list of structs
62 public List
<Struct
> get_structs () {
63 return new ReadOnlyList
<Struct
> (structs
);
67 * Returns a copy of the list of enums.
69 * @return list of enums
71 public List
<Enum
> get_enums () {
72 return new ReadOnlyList
<Enum
> (enums
);
76 * Returns a copy of the list of delegates.
78 * @return list of delegates
80 public List
<Delegate
> get_delegates () {
81 return new ReadOnlyList
<Delegate
> (delegates
);
85 * Creates a new interface.
87 * @param name type name
88 * @param source reference to source code
89 * @return newly created interface
91 public Interface (string name
, SourceReference? source_reference
= null, Comment? comment
= null) {
92 base (name
, source_reference
, comment
);
96 * Adds the specified interface or class to the list of prerequisites of
99 * @param type an interface or class reference
101 public void add_prerequisite (DataType type
) {
102 prerequisites
.add (type
);
103 type
.parent_node
= this
;
107 * Prepends the specified interface or class to the list of
108 * prerequisites of this interface.
110 * @param type an interface or class reference
112 public void prepend_prerequisite (DataType type
) {
113 prerequisites
.insert (0, type
);
117 * Returns a copy of the base type list.
119 * @return list of base types
121 public List
<DataType
> get_prerequisites () {
122 return new ReadOnlyList
<DataType
> (prerequisites
);
126 * Adds the specified method as a member to this interface.
130 public void add_method (Method m
) {
131 if (m is CreationMethod
) {
132 Report
.error (m
.source_reference
, "construction methods may only be declared within classes and structs");
137 if (m
.binding
== MemberBinding
.INSTANCE
) {
138 m
.this_parameter
= new
FormalParameter ("this", new
ObjectType (this
));
139 m
.scope
.add (m
.this_parameter
.name
, m
.this_parameter
);
141 if (!(m
.return_type is VoidType
) && m
.get_postconditions ().size
> 0) {
142 m
.result_var
= new
LocalVariable (m
.return_type
.copy (), "result");
143 m
.result_var
.is_result
= true;
147 scope
.add (m
.name
, m
);
151 * Returns a copy of the list of methods.
153 * @return list of methods
155 public override List
<Method
> get_methods () {
156 return new ReadOnlyList
<Method
> (methods
);
160 * Adds the specified field as a member to this interface. The field
161 * must be private and static.
165 public void add_field (Field f
) {
167 scope
.add (f
.name
, f
);
171 * Returns a copy of the list of fields.
173 * @return list of fields
175 public List
<Field
> get_fields () {
176 return new ReadOnlyList
<Field
> (fields
);
180 * Adds the specified constant as a member to this interface.
182 * @param c a constant
184 public void add_constant (Constant c
) {
186 scope
.add (c
.name
, c
);
190 * Returns a copy of the list of constants.
192 * @return list of constants
194 public List
<Constant
> get_constants () {
195 return new ReadOnlyList
<Constant
> (constants
);
199 * Adds the specified property as a member to this interface.
201 * @param prop a property
203 public void add_property (Property prop
) {
204 properties
.add (prop
);
205 scope
.add (prop
.name
, prop
);
207 prop
.this_parameter
= new
FormalParameter ("this", new
ObjectType (this
));
208 prop
.scope
.add (prop
.this_parameter
.name
, prop
.this_parameter
);
212 * Returns a copy of the list of properties.
214 * @return list of properties
216 public override List
<Property
> get_properties () {
217 return new ReadOnlyList
<Property
> (properties
);
221 * Adds the specified signal as a member to this interface.
223 * @param sig a signal
225 public void add_signal (Signal sig
) {
227 scope
.add (sig
.name
, sig
);
231 * Returns a copy of the list of signals.
233 * @return list of signals
235 public override List
<Signal
> get_signals () {
236 return new ReadOnlyList
<Signal
> (signals
);
240 * Adds the specified class as an inner class.
244 public void add_class (Class cl
) {
246 scope
.add (cl
.name
, cl
);
250 * Adds the specified struct as an inner struct.
254 public void add_struct (Struct st
) {
256 scope
.add (st
.name
, st
);
260 * Adds the specified enum as an inner enum.
264 public void add_enum (Enum en
) {
266 scope
.add (en
.name
, en
);
270 * Adds the specified delegate as an inner delegate.
272 * @param d a delegate
274 public void add_delegate (Delegate d
) {
276 scope
.add (d
.name
, d
);
279 public override string get_cprefix () {
283 public override string get_cname (bool const_type
= false) {
285 var attr
= get_attribute ("CCode");
287 cname
= attr
.get_string ("cname");
290 cname
= "%s%s".printf (parent_symbol
.get_cprefix (), name
);
296 public void set_cname (string cname
) {
301 * Returns the string to be prepended to the name of members of this
302 * interface when used in C code.
304 * @return the suffix to be used in C code
306 public string get_lower_case_csuffix () {
307 if (lower_case_csuffix
== null) {
308 lower_case_csuffix
= get_default_lower_case_csuffix ();
310 return lower_case_csuffix
;
314 * Returns default string to be prepended to the name of members of this
315 * interface when used in C code.
317 * @return the suffix to be used in C code
319 public string get_default_lower_case_csuffix () {
320 string result
= camel_case_to_lower_case (name
);
322 // remove underscores in some cases to avoid conflicts of type macros
323 if (result
.has_prefix ("type_")) {
324 result
= "type" + result
.offset ("type_".len ());
325 } else if (result
.has_prefix ("is_")) {
326 result
= "is" + result
.offset ("is_".len ());
328 if (result
.has_suffix ("_class")) {
329 result
= result
.substring (0, result
.len () - "_class".len ()) + "class";
336 * Sets the string to be prepended to the name of members of this
337 * interface when used in C code.
339 * @param csuffix the suffix to be used in C code
341 public void set_lower_case_csuffix (string csuffix
) {
342 this
.lower_case_csuffix
= csuffix
;
345 public override string?
get_lower_case_cname (string? infix
) {
349 return "%s%s%s".printf (parent_symbol
.get_lower_case_cprefix (), infix
, get_lower_case_csuffix ());
352 public override string get_lower_case_cprefix () {
353 return "%s_".printf (get_lower_case_cname (null));
356 public override string?
get_upper_case_cname (string? infix
) {
357 return get_lower_case_cname (infix
).up ();
360 public override void accept (CodeVisitor visitor
) {
361 visitor
.visit_interface (this
);
364 public override void accept_children (CodeVisitor visitor
) {
365 foreach (DataType type
in prerequisites
) {
366 type
.accept (visitor
);
369 foreach (TypeParameter p
in get_type_parameters ()) {
373 /* process enums first to avoid order problems in C code */
374 foreach (Enum en
in enums
) {
378 foreach (Method m
in methods
) {
382 foreach (Field f
in fields
) {
386 foreach (Constant c
in constants
) {
390 foreach (Property prop
in properties
) {
391 prop
.accept (visitor
);
394 foreach (Signal sig
in signals
) {
395 sig
.accept (visitor
);
398 foreach (Class cl
in classes
) {
402 foreach (Struct st
in structs
) {
406 foreach (Delegate d
in delegates
) {
411 public override bool is_reference_type () {
415 public override bool is_reference_counting () {
419 public override string?
get_ref_function () {
420 foreach (DataType prerequisite
in prerequisites
) {
421 string ref_func
= prerequisite
.data_type
.get_ref_function ();
422 if (ref_func
!= null) {
429 public override string?
get_unref_function () {
430 foreach (DataType prerequisite
in prerequisites
) {
431 string unref_func
= prerequisite
.data_type
.get_unref_function ();
432 if (unref_func
!= null) {
439 public override string?
get_ref_sink_function () {
440 foreach (DataType prerequisite
in prerequisites
) {
441 string ref_sink_func
= prerequisite
.data_type
.get_ref_sink_function ();
442 if (ref_sink_func
!= null) {
443 return ref_sink_func
;
449 public override bool is_subtype_of (TypeSymbol t
) {
454 foreach (DataType prerequisite
in prerequisites
) {
455 if (prerequisite
.data_type
!= null && prerequisite
.data_type
.is_subtype_of (t
)) {
463 private void process_ccode_attribute (Attribute a
) {
464 if (a
.has_argument ("type_cname")) {
465 set_type_cname (a
.get_string ("type_cname"));
467 if (a
.has_argument ("cheader_filename")) {
468 var val
= a
.get_string ("cheader_filename");
469 foreach (string filename
in val
.split (",")) {
470 add_cheader_filename (filename
);
473 if (a
.has_argument ("lower_case_csuffix")) {
474 lower_case_csuffix
= a
.get_string ("lower_case_csuffix");
479 * Process all associated attributes.
481 public void process_attributes () {
482 foreach (Attribute a
in attributes
) {
483 if (a
.name
== "CCode") {
484 process_ccode_attribute (a
);
490 * Returns the name of the type struct as it is used in C code.
492 * @return the type struct name to be used in C code
494 public string get_type_cname () {
495 if (type_cname
== null) {
496 type_cname
= "%sIface".printf (get_cname ());
502 * Sets the name of the type struct as it is used in C code.
504 * @param type_cname the type struct name to be used in C code
506 public void set_type_cname (string type_cname
) {
507 this
.type_cname
= type_cname
;
510 public override string?
get_marshaller_type_name () {
514 public override string?
get_get_value_function () {
515 return "g_value_get_object";
518 public override string?
get_set_value_function () {
519 return "g_value_set_object";
522 public override string?
get_type_id () {
523 if (type_id
== null) {
524 type_id
= get_upper_case_cname ("TYPE_");
530 public override void replace_type (DataType old_type
, DataType new_type
) {
531 for (int i
= 0; i
< prerequisites
.size
; i
++) {
532 if (prerequisites
[i
] == old_type
) {
533 prerequisites
[i
] = new_type
;
539 public override string?
get_param_spec_function () {
540 foreach (DataType prerequisite
in prerequisites
) {
541 var prereq
= prerequisite as ObjectType
;
542 var cl
= prereq
.type_symbol as Class
;
544 return cl
.get_param_spec_function ();
546 var interf
= prereq
.type_symbol as Interface
;
547 if (interf
!= null) {
548 var param_spec_function
= interf
.get_param_spec_function ();
549 if (param_spec_function
!= null) {
550 return param_spec_function
;
558 public override bool check (SemanticAnalyzer analyzer
) {
565 process_attributes ();
567 var old_source_file
= analyzer
.current_source_file
;
568 var old_symbol
= analyzer
.current_symbol
;
570 if (source_reference
!= null) {
571 analyzer
.current_source_file
= source_reference
.file
;
573 analyzer
.current_symbol
= this
;
575 foreach (DataType prerequisite_reference
in get_prerequisites ()) {
576 // check whether prerequisite is at least as accessible as the interface
577 if (!analyzer
.is_type_accessible (this
, prerequisite_reference
)) {
579 Report
.error (source_reference
, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference
.to_string (), get_full_name ()));
584 /* check prerequisites */
585 Class prereq_class
= null;
586 foreach (DataType prereq
in get_prerequisites ()) {
587 TypeSymbol class_or_interface
= prereq
.data_type
;
588 /* skip on previous errors */
589 if (class_or_interface
== null) {
594 if (!(class_or_interface is ObjectTypeSymbol
)) {
596 Report
.error (source_reference
, "Prerequisite `%s` of interface `%s` is not a class or interface".printf (get_full_name (), class_or_interface
.to_string ()));
600 /* interfaces are not allowed to have multiple instantiable prerequisites */
601 if (class_or_interface is Class
) {
602 if (prereq_class
!= null) {
604 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 ()));
608 prereq_class
= (Class
) class_or_interface
;
612 foreach (DataType type
in prerequisites
) {
613 type
.check (analyzer
);
616 foreach (TypeParameter p
in get_type_parameters ()) {
620 foreach (Enum en
in enums
) {
624 foreach (Method m
in methods
) {
628 foreach (Field f
in fields
) {
632 foreach (Constant c
in constants
) {
636 foreach (Property prop
in properties
) {
637 prop
.check (analyzer
);
640 foreach (Signal sig
in signals
) {
641 sig
.check (analyzer
);
644 foreach (Class cl
in classes
) {
648 foreach (Struct st
in structs
) {
652 foreach (Delegate d
in delegates
) {
656 analyzer
.current_source_file
= old_source_file
;
657 analyzer
.current_symbol
= old_symbol
;