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
> ();
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 () {
58 * Returns a copy of the list of structs.
60 * @return list of structs
62 public List
<Struct
> get_structs () {
67 * Returns a copy of the list of enums.
69 * @return list of enums
71 public List
<Enum
> get_enums () {
76 * Returns a copy of the list of delegates.
78 * @return list of delegates
80 public List
<Delegate
> get_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 prerequisites
;
126 * Adds the specified method as a member to this interface.
130 public override 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
Parameter ("this", get_this_type ());
139 m
.scope
.add (m
.this_parameter
.name
, m
.this_parameter
);
141 if (!(m
.return_type is VoidType
) && (CodeContext
.get ().profile
== Profile
.DOVA
|| m
.get_postconditions ().size
> 0)) {
142 m
.result_var
= new
LocalVariable (m
.return_type
.copy (), "result", null, source_reference
);
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 () {
160 * Adds the specified field as a member to this interface. The field
161 * must be private and static.
165 public override 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 () {
180 * Adds the specified constant as a member to this interface.
182 * @param c a constant
184 public override 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 () {
199 * Adds the specified property as a member to this interface.
201 * @param prop a property
203 public override void add_property (Property prop
) {
204 properties
.add (prop
);
205 scope
.add (prop
.name
, prop
);
207 prop
.this_parameter
= new
Parameter ("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 () {
221 * Adds the specified signal as a member to this interface.
223 * @param sig a signal
225 public override 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 () {
240 * Adds the specified class as an inner class.
244 public override void add_class (Class cl
) {
246 scope
.add (cl
.name
, cl
);
250 * Adds the specified struct as an inner struct.
254 public override void add_struct (Struct st
) {
256 scope
.add (st
.name
, st
);
260 * Adds the specified enum as an inner enum.
264 public override 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 override 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
.substring ("type_".length
);
325 } else if (result
.has_prefix ("is_")) {
326 result
= "is" + result
.substring ("is_".length
);
328 if (result
.has_suffix ("_class")) {
329 result
= result
.substring (0, result
.length
- "_class".length
) + "class";
336 * Returns default string for the type struct when used in C code.
338 * @return the type struct to be used in C code
340 public string get_default_type_cname () {
341 return "%sIface".printf (get_cname ());
345 * Sets the string to be prepended to the name of members of this
346 * interface when used in C code.
348 * @param csuffix the suffix to be used in C code
350 public void set_lower_case_csuffix (string csuffix
) {
351 this
.lower_case_csuffix
= csuffix
;
354 public override string?
get_lower_case_cname (string? infix
) {
358 return "%s%s%s".printf (parent_symbol
.get_lower_case_cprefix (), infix
, get_lower_case_csuffix ());
361 public override string get_lower_case_cprefix () {
362 return "%s_".printf (get_lower_case_cname (null));
365 public override string?
get_upper_case_cname (string? infix
) {
366 return get_lower_case_cname (infix
).up ();
369 public override void accept (CodeVisitor visitor
) {
370 visitor
.visit_interface (this
);
373 public override void accept_children (CodeVisitor visitor
) {
374 foreach (DataType type
in prerequisites
) {
375 type
.accept (visitor
);
378 foreach (TypeParameter p
in get_type_parameters ()) {
382 /* process enums first to avoid order problems in C code */
383 foreach (Enum en
in enums
) {
387 foreach (Method m
in methods
) {
391 foreach (Field f
in fields
) {
395 foreach (Constant c
in constants
) {
399 foreach (Property prop
in properties
) {
400 prop
.accept (visitor
);
403 foreach (Signal sig
in signals
) {
404 sig
.accept (visitor
);
407 foreach (Class cl
in classes
) {
411 foreach (Struct st
in structs
) {
415 foreach (Delegate d
in delegates
) {
420 public override bool is_reference_type () {
424 public override bool is_reference_counting () {
428 public override string?
get_ref_function () {
429 foreach (DataType prerequisite
in prerequisites
) {
430 string ref_func
= prerequisite
.data_type
.get_ref_function ();
431 if (ref_func
!= null) {
438 public override string?
get_unref_function () {
439 foreach (DataType prerequisite
in prerequisites
) {
440 string unref_func
= prerequisite
.data_type
.get_unref_function ();
441 if (unref_func
!= null) {
448 public override string?
get_ref_sink_function () {
449 foreach (DataType prerequisite
in prerequisites
) {
450 string ref_sink_func
= prerequisite
.data_type
.get_ref_sink_function ();
451 if (ref_sink_func
!= null) {
452 return ref_sink_func
;
458 public override bool is_subtype_of (TypeSymbol t
) {
463 foreach (DataType prerequisite
in prerequisites
) {
464 if (prerequisite
.data_type
!= null && prerequisite
.data_type
.is_subtype_of (t
)) {
472 private void process_ccode_attribute (Attribute a
) {
473 if (a
.has_argument ("type_cname")) {
474 set_type_cname (a
.get_string ("type_cname"));
476 if (a
.has_argument ("cheader_filename")) {
477 var val
= a
.get_string ("cheader_filename");
478 foreach (string filename
in val
.split (",")) {
479 add_cheader_filename (filename
);
482 if (a
.has_argument ("lower_case_csuffix")) {
483 lower_case_csuffix
= a
.get_string ("lower_case_csuffix");
488 * Process all associated attributes.
490 public void process_attributes () {
491 foreach (Attribute a
in attributes
) {
492 if (a
.name
== "CCode") {
493 process_ccode_attribute (a
);
494 } else if (a
.name
== "Deprecated") {
495 process_deprecated_attribute (a
);
496 } else if (a
.name
== "Experimental") {
497 process_experimental_attribute (a
);
503 * Returns the name of the type struct as it is used in C code.
505 * @return the type struct name to be used in C code
507 public string get_type_cname () {
508 if (type_cname
== null) {
509 type_cname
= get_default_type_cname ();
515 * Sets the name of the type struct as it is used in C code.
517 * @param type_cname the type struct name to be used in C code
519 public void set_type_cname (string type_cname
) {
520 this
.type_cname
= type_cname
;
523 public override string?
get_marshaller_type_name () {
524 foreach (DataType prerequisite
in prerequisites
) {
525 string type_name
= prerequisite
.data_type
.get_marshaller_type_name ();
526 if (type_name
!= null) {
533 public override string?
get_get_value_function () {
534 foreach (DataType prerequisite
in prerequisites
) {
535 string get_value_func
= prerequisite
.data_type
.get_get_value_function ();
536 if (get_value_func
!= null) {
537 return get_value_func
;
543 public override string?
get_set_value_function () {
544 foreach (DataType prerequisite
in prerequisites
) {
545 string set_value_func
= prerequisite
.data_type
.get_set_value_function ();
546 if (set_value_func
!= null) {
547 return set_value_func
;
553 public override string?
get_take_value_function () {
554 foreach (DataType prerequisite
in prerequisites
) {
555 string take_value_func
= prerequisite
.data_type
.get_take_value_function ();
556 if (take_value_func
!= null) {
557 return take_value_func
;
563 public override string?
get_type_id () {
564 if (type_id
== null) {
565 type_id
= get_upper_case_cname ("TYPE_");
571 public override void replace_type (DataType old_type
, DataType new_type
) {
572 for (int i
= 0; i
< prerequisites
.size
; i
++) {
573 if (prerequisites
[i
] == old_type
) {
574 prerequisites
[i
] = new_type
;
580 public override string?
get_param_spec_function () {
581 foreach (DataType prerequisite
in prerequisites
) {
582 var prereq
= prerequisite as ObjectType
;
583 var cl
= prereq
.type_symbol as Class
;
585 return cl
.get_param_spec_function ();
587 var interf
= prereq
.type_symbol as Interface
;
588 if (interf
!= null) {
589 var param_spec_function
= interf
.get_param_spec_function ();
590 if (param_spec_function
!= null) {
591 return param_spec_function
;
599 public override bool check (CodeContext context
) {
606 process_attributes ();
608 var old_source_file
= context
.analyzer
.current_source_file
;
609 var old_symbol
= context
.analyzer
.current_symbol
;
611 if (source_reference
!= null) {
612 context
.analyzer
.current_source_file
= source_reference
.file
;
614 context
.analyzer
.current_symbol
= this
;
616 foreach (DataType prerequisite_reference
in get_prerequisites ()) {
617 // check whether prerequisite is at least as accessible as the interface
618 if (!context
.analyzer
.is_type_accessible (this
, prerequisite_reference
)) {
620 Report
.error (source_reference
, "prerequisite `%s` is less accessible than interface `%s`".printf (prerequisite_reference
.to_string (), get_full_name ()));
625 /* check prerequisites */
626 Class prereq_class
= null;
627 foreach (DataType prereq
in get_prerequisites ()) {
628 TypeSymbol class_or_interface
= prereq
.data_type
;
629 /* skip on previous errors */
630 if (class_or_interface
== null) {
635 if (!(class_or_interface is ObjectTypeSymbol
)) {
637 Report
.error (source_reference
, "Prerequisite `%s` of interface `%s` is not a class or interface".printf (get_full_name (), class_or_interface
.to_string ()));
641 /* interfaces are not allowed to have multiple instantiable prerequisites */
642 if (class_or_interface is Class
) {
643 if (prereq_class
!= null) {
645 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 ()));
649 prereq_class
= (Class
) class_or_interface
;
653 foreach (DataType type
in prerequisites
) {
654 type
.check (context
);
657 foreach (TypeParameter p
in get_type_parameters ()) {
661 foreach (Enum en
in enums
) {
665 foreach (Method m
in methods
) {
669 foreach (Field f
in fields
) {
673 foreach (Constant c
in constants
) {
677 foreach (Property prop
in properties
) {
678 prop
.check (context
);
681 foreach (Signal sig
in signals
) {
685 foreach (Class cl
in classes
) {
689 foreach (Struct st
in structs
) {
693 foreach (Delegate d
in delegates
) {
697 context
.analyzer
.current_source_file
= old_source_file
;
698 context
.analyzer
.current_symbol
= old_symbol
;