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
.Class
: ObjectTypeSymbol
{
30 * Specifies the base class.
32 public Class base_class
{ get; set; }
35 * Specifies whether this class is abstract. Abstract classes may not be
38 public bool is_abstract
{ get; set; }
41 * Instances of compact classes are fast to create and have a
42 * compact memory layout. Compact classes don't support runtime
43 * type information or virtual methods.
45 public bool is_compact
{
47 if (base_class
!= null) {
48 return base_class
.is_compact
;
58 * Instances of immutable classes are immutable after construction.
60 public bool is_immutable
{
62 if (base_class
!= null) {
63 return base_class
.is_immutable
;
68 _is_immutable
= value
;
73 * Specifies wheather the ref function returns void instead of the
76 public bool ref_function_void
{
78 if (base_class
!= null) {
79 return base_class
.ref_function_void
;
81 return _ref_function_void
;
84 _ref_function_void
= value
;
89 * The name of the function to use to check whether a value is an instance of
90 * this class. If this is null then the default type check function should be
93 public string? type_check_function
{ get; set; }
96 * Specifies whether this class has private fields.
98 public bool has_private_fields
{ get; set; }
101 * Specifies whether this class has class fields.
103 public bool has_class_private_fields
{ get; private set; }
106 * Specifies whether the free function requires the address of a
107 * pointer instead of just the pointer.
109 public bool free_function_address_of
{ get; private set; }
111 public bool is_gboxed
{ get { return (free_function
== "g_boxed_free"); } }
113 private string cname
;
114 public string const_cname
{ get; set; }
115 private string lower_case_cprefix
;
116 private string lower_case_csuffix
;
117 private string type_id
;
118 private string ref_function
;
119 private string unref_function
;
120 private bool _ref_function_void
;
121 private string ref_sink_function
;
122 private string param_spec_function
;
123 private string copy_function
;
124 private string free_function
;
125 private string marshaller_type_name
;
126 private string get_value_function
;
127 private string set_value_function
;
128 private string take_value_function
;
129 private bool _is_compact
;
130 private bool _is_immutable
;
132 private List
<DataType
> base_types
= new ArrayList
<DataType
> ();
134 private List
<Constant
> constants
= new ArrayList
<Constant
> ();
135 private List
<Field
> fields
= new ArrayList
<Field
> ();
136 private List
<Method
> methods
= new ArrayList
<Method
> ();
137 private List
<Property
> properties
= new ArrayList
<Property
> ();
138 private List
<Signal
> signals
= new ArrayList
<Signal
> ();
141 private List
<Class
> classes
= new ArrayList
<Class
> ();
142 private List
<Struct
> structs
= new ArrayList
<Struct
> ();
143 private List
<Enum
> enums
= new ArrayList
<Enum
> ();
144 private List
<Delegate
> delegates
= new ArrayList
<Delegate
> ();
147 * Returns a copy of the list of classes.
149 * @return list of classes
151 public List
<Class
> get_classes () {
156 * Returns a copy of the list of structs.
158 * @return list of structs
160 public List
<Struct
> get_structs () {
165 * Returns a copy of the list of enums.
167 * @return list of enums
169 public List
<Enum
> get_enums () {
174 * Returns a copy of the list of delegates.
176 * @return list of delegates
178 public List
<Delegate
> get_delegates () {
183 * Specifies the default construction method.
185 public Method default_construction_method
{ get; set; }
188 * Specifies the instance constructor.
190 public Constructor constructor
{ get; set; }
193 * Specifies the class constructor.
195 public Constructor class_constructor
{ get; set; }
198 * Specifies the static class constructor.
200 public Constructor static_constructor
{ get; set; }
203 * Specifies the instance destructor.
205 public Destructor? destructor
{
206 get { return _destructor
; }
209 if (_destructor
!= null) {
210 if (_destructor
.this_parameter
!= null) {
211 _destructor
.scope
.remove (_destructor
.this_parameter
.name
);
213 _destructor
.this_parameter
= new
Parameter ("this", get_this_type ());
214 _destructor
.scope
.add (_destructor
.this_parameter
.name
, _destructor
.this_parameter
);
220 * Specifies the class destructor.
222 public Destructor? static_destructor
{ get; set; }
225 * Specifies the class destructor.
227 public Destructor? class_destructor
{ get; set; }
230 * Specifies whether this class denotes an error base.
232 public bool is_error_base
{
234 return get_attribute ("ErrorBase") != null;
238 Destructor? _destructor
;
241 * Creates a new class.
243 * @param name type name
244 * @param source reference to source code
245 * @param comment class documentation
246 * @return newly created class
248 public Class (string name
, SourceReference? source_reference
= null, Comment? comment
= null) {
249 base (name
, source_reference
, comment
);
253 * Adds the specified class or interface to the list of base types of
256 * @param type a class or interface reference
258 public void add_base_type (DataType type
) {
259 base_types
.add (type
);
260 type
.parent_node
= this
;
264 * Returns a copy of the base type list.
266 * @return list of base types
268 public List
<DataType
> get_base_types () {
273 * Adds the specified constant as a member to this class.
275 * @param c a constant
277 public override void add_constant (Constant c
) {
279 scope
.add (c
.name
, c
);
283 * Adds the specified field as a member to this class.
287 public override void add_field (Field f
) {
288 if (CodeContext
.get ().profile
== Profile
.DOVA
&&
289 f
.binding
== MemberBinding
.INSTANCE
&&
290 (f
.access
== SymbolAccessibility
.PUBLIC
|| f
.access
== SymbolAccessibility
.PROTECTED
) &&
291 name
!= "any" /* temporary workaround */) {
292 // public/protected instance fields not supported, convert to automatic property
294 var prop
= new
Property (f
.name
, f
.variable_type
.copy (), null, null, f
.source_reference
, comment
);
295 prop
.access
= access
;
297 var get_type
= prop
.property_type
.copy ();
298 get_type
.value_owned
= true;
300 prop
.get_accessor
= new
PropertyAccessor (true, false, false, get_type
, null, f
.source_reference
);
302 prop
.set_accessor
= new
PropertyAccessor (false, true, false, prop
.property_type
.copy (), null, f
.source_reference
);
304 f
.name
= "_%s".printf (f
.name
);
305 f
.access
= SymbolAccessibility
.PRIVATE
;
313 if (f
.access
== SymbolAccessibility
.PRIVATE
&& f
.binding
== MemberBinding
.INSTANCE
) {
314 has_private_fields
= true;
315 } else if (f
.access
== SymbolAccessibility
.PRIVATE
&& f
.binding
== MemberBinding
.CLASS
) {
316 has_class_private_fields
= true;
318 scope
.add (f
.name
, f
);
322 * Returns a copy of the list of fields.
324 * @return list of fields
326 public List
<Field
> get_fields () {
331 * Returns a copy of the list of constants.
333 * @return list of constants
335 public List
<Constant
> get_constants () {
340 * Adds the specified method as a member to this class.
344 public override void add_method (Method m
) {
345 if (m
.binding
== MemberBinding
.INSTANCE
|| m is CreationMethod
) {
346 if (m
.this_parameter
!= null) {
347 m
.scope
.remove (m
.this_parameter
.name
);
349 m
.this_parameter
= new
Parameter ("this", get_this_type ());
350 m
.scope
.add (m
.this_parameter
.name
, m
.this_parameter
);
352 if (!(m
.return_type is VoidType
) && (CodeContext
.get ().profile
== Profile
.DOVA
|| m
.get_postconditions ().size
> 0)) {
353 if (m
.result_var
!= null) {
354 m
.scope
.remove (m
.result_var
.name
);
356 m
.result_var
= new
LocalVariable (m
.return_type
.copy (), "result", null, source_reference
);
357 m
.result_var
.is_result
= true;
359 if (m is CreationMethod
) {
360 if (m
.name
== null) {
361 default_construction_method
= m
;
365 var cm
= (CreationMethod
) m
;
366 if (cm
.class_name
!= null && cm
.class_name
!= name
) {
367 // class_name is null for constructors generated by GIdlParser
368 Report
.error (m
.source_reference
, "missing return type in method `%s.%s´".printf (get_full_name (), cm
.class_name
));
375 scope
.add (m
.name
, m
);
379 * Returns a copy of the list of methods.
381 * @return list of methods
383 public override List
<Method
> get_methods () {
388 * Adds the specified property as a member to this class.
390 * @param prop a property
392 public override void add_property (Property prop
) {
393 properties
.add (prop
);
394 scope
.add (prop
.name
, prop
);
396 prop
.this_parameter
= new
Parameter ("this", get_this_type ());
397 prop
.scope
.add (prop
.this_parameter
.name
, prop
.this_parameter
);
399 if (prop
.field
!= null) {
400 add_field (prop
.field
);
405 * Returns a copy of the list of properties.
407 * @return list of properties
409 public override List
<Property
> get_properties () {
414 * Adds the specified signal as a member to this class.
416 * @param sig a signal
418 public override void add_signal (Signal sig
) {
420 scope
.add (sig
.name
, sig
);
424 * Returns a copy of the list of signals.
426 * @return list of signals
428 public override List
<Signal
> get_signals () {
433 * Adds the specified class as an inner class.
437 public override void add_class (Class cl
) {
439 scope
.add (cl
.name
, cl
);
443 * Adds the specified struct as an inner struct.
447 public override void add_struct (Struct st
) {
449 scope
.add (st
.name
, st
);
453 * Adds the specified enum as an inner enum.
457 public override void add_enum (Enum en
) {
459 scope
.add (en
.name
, en
);
463 * Adds the specified delegate as an inner delegate.
465 * @param d a delegate
467 public override void add_delegate (Delegate d
) {
469 scope
.add (d
.name
, d
);
472 public override void add_constructor (Constructor c
) {
473 if (c
.binding
== MemberBinding
.INSTANCE
) {
474 if (constructor
!= null) {
475 Report
.error (c
.source_reference
, "class already contains a constructor");
478 } else if (c
.binding
== MemberBinding
.CLASS
) {
479 if (class_constructor
!= null) {
480 Report
.error (c
.source_reference
, "class already contains a class constructor");
482 class_constructor
= c
;
484 if (static_constructor
!= null) {
485 Report
.error (c
.source_reference
, "class already contains a static constructor");
487 static_constructor
= c
;
491 public override void add_destructor (Destructor d
) {
492 if (d
.binding
== MemberBinding
.INSTANCE
) {
493 if (destructor
!= null) {
494 Report
.error (d
.source_reference
, "class already contains a destructor");
497 } else if (d
.binding
== MemberBinding
.CLASS
) {
498 if (class_destructor
!= null) {
499 Report
.error (d
.source_reference
, "class already contains a class destructor");
501 class_destructor
= d
;
503 if (static_destructor
!= null) {
504 Report
.error (d
.source_reference
, "class already contains a static destructor");
506 static_destructor
= d
;
510 public override void accept (CodeVisitor visitor
) {
511 visitor
.visit_class (this
);
514 public override void accept_children (CodeVisitor visitor
) {
515 foreach (DataType type
in base_types
) {
516 type
.accept (visitor
);
519 foreach (TypeParameter p
in get_type_parameters ()) {
523 /* process enums first to avoid order problems in C code */
524 foreach (Enum en
in enums
) {
528 foreach (Field f
in fields
) {
532 foreach (Constant c
in constants
) {
536 foreach (Method m
in methods
) {
540 foreach (Property prop
in properties
) {
541 prop
.accept (visitor
);
544 foreach (Signal sig
in signals
) {
545 sig
.accept (visitor
);
548 if (constructor
!= null) {
549 constructor
.accept (visitor
);
552 if (class_constructor
!= null) {
553 class_constructor
.accept (visitor
);
556 if (static_constructor
!= null) {
557 static_constructor
.accept (visitor
);
560 if (destructor
!= null) {
561 destructor
.accept (visitor
);
564 if (static_destructor
!= null) {
565 static_destructor
.accept (visitor
);
568 if (class_destructor
!= null) {
569 class_destructor
.accept (visitor
);
572 foreach (Class cl
in classes
) {
576 foreach (Struct st
in structs
) {
580 foreach (Delegate d
in delegates
) {
585 public override string get_cprefix () {
589 public override string get_cname (bool const_type
= false) {
591 if (const_cname
!= null) {
593 } else if (is_immutable
) {
594 return "const " + get_cname (false);
599 var attr
= get_attribute ("CCode");
601 cname
= attr
.get_string ("cname");
604 cname
= get_default_cname ();
611 * Returns the default name of this class as it is used in C code.
613 * @return the name to be used in C code by default
615 public string get_default_cname () {
616 return "%s%s".printf (parent_symbol
.get_cprefix (), name
);
620 * Sets the name of this class as it is used in C code.
622 * @param cname the name to be used in C code
624 public void set_cname (string cname
) {
628 private string get_lower_case_csuffix () {
629 if (lower_case_csuffix
== null) {
630 lower_case_csuffix
= camel_case_to_lower_case (name
);
632 // remove underscores in some cases to avoid conflicts of type macros
633 if (lower_case_csuffix
.has_prefix ("type_")) {
634 lower_case_csuffix
= "type" + lower_case_csuffix
.substring ("type_".length
);
635 } else if (lower_case_csuffix
.has_prefix ("is_")) {
636 lower_case_csuffix
= "is" + lower_case_csuffix
.substring ("is_".length
);
638 if (lower_case_csuffix
.has_suffix ("_class")) {
639 lower_case_csuffix
= lower_case_csuffix
.substring (0, lower_case_csuffix
.length
- "_class".length
) + "class";
642 return lower_case_csuffix
;
645 public override string?
get_lower_case_cname (string? infix
) {
649 return "%s%s%s".printf (parent_symbol
.get_lower_case_cprefix (), infix
, get_lower_case_csuffix ());
652 public override string get_lower_case_cprefix () {
653 if (lower_case_cprefix
== null) {
654 lower_case_cprefix
= "%s_".printf (get_lower_case_cname (null));
656 return lower_case_cprefix
;
659 public override string?
get_upper_case_cname (string? infix
) {
660 return get_lower_case_cname (infix
).up ();
663 public override bool is_reference_type () {
667 private void process_gir_attribute (Attribute a
) {
668 if (a
.has_argument ("name")) {
669 gir_name
= a
.get_string ("name");
673 private void process_ccode_attribute (Attribute a
) {
674 if (a
.has_argument ("ref_function")) {
675 set_ref_function (a
.get_string ("ref_function"));
677 if (a
.has_argument ("ref_function_void")) {
678 this
.ref_function_void
= a
.get_bool ("ref_function_void");
680 if (a
.has_argument ("unref_function")) {
681 set_unref_function (a
.get_string ("unref_function"));
683 if (a
.has_argument ("ref_sink_function")) {
684 set_ref_sink_function (a
.get_string ("ref_sink_function"));
686 if (a
.has_argument ("copy_function")) {
687 set_dup_function (a
.get_string ("copy_function"));
689 if (a
.has_argument ("free_function")) {
690 set_free_function (a
.get_string ("free_function"));
692 if (a
.has_argument ("free_function_address_of")) {
693 free_function_address_of
= a
.get_bool ("free_function_address_of");
695 if (a
.has_argument ("type_id")) {
696 type_id
= a
.get_string ("type_id");
698 if (a
.has_argument ("marshaller_type_name")) {
699 marshaller_type_name
= a
.get_string ("marshaller_type_name");
701 if (a
.has_argument ("get_value_function")) {
702 get_value_function
= a
.get_string ("get_value_function");
704 if (a
.has_argument ("set_value_function")) {
705 set_value_function
= a
.get_string ("set_value_function");
707 if (a
.has_argument ("take_value_function")) {
708 take_value_function
= a
.get_string ("take_value_function");
711 if (a
.has_argument ("const_cname")) {
712 const_cname
= a
.get_string ("const_cname");
714 if (a
.has_argument ("cprefix")) {
715 lower_case_cprefix
= a
.get_string ("cprefix");
717 if (a
.has_argument ("lower_case_csuffix")) {
718 lower_case_csuffix
= a
.get_string ("lower_case_csuffix");
720 if (a
.has_argument ("cheader_filename")) {
721 var val
= a
.get_string ("cheader_filename");
722 foreach (string filename
in val
.split (",")) {
723 add_cheader_filename (filename
);
726 if (a
.has_argument ("type_check_function")) {
727 type_check_function
= a
.get_string ("type_check_function");
730 if (a
.has_argument ("param_spec_function")) {
731 param_spec_function
= a
.get_string ("param_spec_function");
736 * Process all associated attributes.
738 public void process_attributes () {
739 foreach (Attribute a
in attributes
) {
740 if (a
.name
== "CCode") {
741 process_ccode_attribute (a
);
742 } else if (a
.name
== "Compact") {
744 } else if (a
.name
== "Immutable") {
746 } else if (a
.name
== "Deprecated") {
747 process_deprecated_attribute (a
);
748 } else if (a
.name
== "GIR") {
749 process_gir_attribute (a
);
750 } else if (a
.name
== "Experimental") {
751 process_experimental_attribute (a
);
756 public string?
get_default_type_id () {
758 return "G_TYPE_POINTER";
761 return get_upper_case_cname ("TYPE_");
764 public override string?
get_type_id () {
765 if (type_id
== null) {
766 type_id
= get_default_type_id ();
772 public void set_type_id (string type_id
) {
773 this
.type_id
= type_id
;
776 public override string?
get_marshaller_type_name () {
777 if (marshaller_type_name
== null) {
778 if (base_class
!= null) {
779 marshaller_type_name
= base_class
.get_marshaller_type_name ();
780 } else if (!is_compact
) {
781 marshaller_type_name
= get_upper_case_cname ();
782 } else if (get_type_id () == "G_TYPE_POINTER") {
783 marshaller_type_name
= "POINTER";
785 marshaller_type_name
= "BOXED";
789 return marshaller_type_name
;
792 public override string?
get_param_spec_function () {
793 if (param_spec_function
== null) {
794 param_spec_function
= get_default_param_spec_function ();
797 return param_spec_function
;
800 public string?
get_default_param_spec_function () {
801 if (is_fundamental ()) {
802 return get_lower_case_cname ("param_spec_");
803 } else if (base_class
!= null) {
804 return base_class
.get_param_spec_function ();
805 } else if (get_type_id () == "G_TYPE_POINTER") {
806 return "g_param_spec_pointer";
808 return "g_param_spec_boxed";
812 public override string?
get_get_value_function () {
813 if (get_value_function
== null) {
814 if (is_fundamental ()) {
815 get_value_function
= get_lower_case_cname ("value_get_");
816 } else if (base_class
!= null) {
817 get_value_function
= base_class
.get_get_value_function ();
818 } else if (get_type_id () == "G_TYPE_POINTER") {
819 get_value_function
= "g_value_get_pointer";
821 get_value_function
= "g_value_get_boxed";
825 return get_value_function
;
828 public override string?
get_set_value_function () {
829 if (set_value_function
== null) {
830 if (is_fundamental ()) {
831 set_value_function
= get_lower_case_cname ("value_set_");
832 } else if (base_class
!= null) {
833 set_value_function
= base_class
.get_set_value_function ();
834 } else if (get_type_id () == "G_TYPE_POINTER") {
835 set_value_function
= "g_value_set_pointer";
837 set_value_function
= "g_value_set_boxed";
841 return set_value_function
;
844 public override string?
get_take_value_function () {
845 if (take_value_function
== null) {
846 if (is_fundamental ()) {
847 take_value_function
= get_lower_case_cname ("value_take_");
848 } else if (base_class
!= null) {
849 take_value_function
= base_class
.get_take_value_function ();
850 } else if (get_type_id () == "G_TYPE_POINTER") {
851 take_value_function
= "g_value_set_pointer";
853 take_value_function
= "g_value_take_boxed";
857 return take_value_function
;
860 public override bool is_reference_counting () {
861 return get_ref_function () != null;
864 public bool is_fundamental () {
865 if (!is_compact
&& base_class
== null) {
867 } else if (CodeContext
.get ().profile
== Profile
.DOVA
&& base_class
.base_class
== null) {
873 public override string?
get_ref_function () {
874 if (ref_function
== null && is_fundamental ()) {
875 ref_function
= get_lower_case_cprefix () + "ref";
878 if (ref_function
== null && base_class
!= null) {
879 return base_class
.get_ref_function ();
885 public void set_ref_function (string? name
) {
886 this
.ref_function
= name
;
889 public override string?
get_unref_function () {
890 if (unref_function
== null && is_fundamental ()) {
891 unref_function
= get_lower_case_cprefix () + "unref";
894 if (unref_function
== null && base_class
!= null) {
895 return base_class
.get_unref_function ();
897 return unref_function
;
901 public void set_unref_function (string? name
) {
902 this
.unref_function
= name
;
905 public override string?
get_ref_sink_function () {
906 if (ref_sink_function
== null && base_class
!= null) {
907 return base_class
.get_ref_sink_function ();
909 return ref_sink_function
;
913 public void set_ref_sink_function (string? name
) {
914 this
.ref_sink_function
= name
;
917 public override string?
get_dup_function () {
918 return copy_function
;
921 public void set_dup_function (string? name
) {
922 this
.copy_function
= name
;
925 public string get_default_free_function () {
926 return get_lower_case_cprefix () + "free";
929 public override string?
get_free_function () {
930 if (free_function
== null) {
931 if (base_class
!= null) {
932 return base_class
.get_free_function ();
934 free_function
= get_default_free_function ();
936 return free_function
;
939 public void set_free_function (string name
) {
940 this
.free_function
= name
;
943 public override bool is_subtype_of (TypeSymbol t
) {
948 foreach (DataType base_type
in base_types
) {
949 if (base_type
.data_type
!= null && base_type
.data_type
.is_subtype_of (t
)) {
957 public override void replace_type (DataType old_type
, DataType new_type
) {
958 for (int i
= 0; i
< base_types
.size
; i
++) {
959 if (base_types
[i
] == old_type
) {
960 base_types
[i
] = new_type
;
966 private void get_all_prerequisites (Interface iface
, List
<TypeSymbol
> list
) {
967 foreach (DataType prereq
in iface
.get_prerequisites ()) {
968 TypeSymbol type
= prereq
.data_type
;
969 /* skip on previous errors */
975 if (type is Interface
) {
976 get_all_prerequisites ((Interface
) type
, list
);
982 private bool class_is_a (Class cl
, TypeSymbol t
) {
987 foreach (DataType base_type
in cl
.get_base_types ()) {
988 if (base_type
.data_type is Class
) {
989 if (class_is_a ((Class
) base_type
.data_type
, t
)) {
992 } else if (base_type
.data_type
== t
) {
1000 public override bool check (CodeContext context
) {
1007 process_attributes ();
1009 var old_source_file
= context
.analyzer
.current_source_file
;
1010 var old_symbol
= context
.analyzer
.current_symbol
;
1012 if (source_reference
!= null) {
1013 context
.analyzer
.current_source_file
= source_reference
.file
;
1015 context
.analyzer
.current_symbol
= this
;
1017 foreach (DataType base_type_reference
in get_base_types ()) {
1018 if (!base_type_reference
.check (context
)) {
1023 if (!(base_type_reference is ObjectType
)) {
1025 Report
.error (source_reference
, "base type `%s` of class `%s` is not an object type".printf (base_type_reference
.to_string (), get_full_name ()));
1029 // check whether base type is at least as accessible as the class
1030 if (!context
.analyzer
.is_type_accessible (this
, base_type_reference
)) {
1032 Report
.error (source_reference
, "base type `%s` is less accessible than class `%s`".printf (base_type_reference
.to_string (), get_full_name ()));
1036 int n_type_args
= base_type_reference
.get_type_arguments ().size
;
1037 int n_type_params
= ((ObjectTypeSymbol
) base_type_reference
.data_type
).get_type_parameters ().size
;
1038 if (n_type_args
< n_type_params
) {
1040 Report
.error (base_type_reference
.source_reference
, "too few type arguments");
1042 } else if (n_type_args
> n_type_params
) {
1044 Report
.error (base_type_reference
.source_reference
, "too many type arguments");
1049 foreach (DataType type
in base_types
) {
1050 type
.check (context
);
1053 foreach (TypeParameter p
in get_type_parameters ()) {
1057 /* process enums first to avoid order problems in C code */
1058 foreach (Enum en
in enums
) {
1062 foreach (Field f
in fields
) {
1066 foreach (Constant c
in constants
) {
1070 foreach (Method m
in methods
) {
1074 foreach (Property prop
in properties
) {
1075 prop
.check (context
);
1078 foreach (Signal sig
in signals
) {
1079 sig
.check (context
);
1082 if (constructor
!= null) {
1083 constructor
.check (context
);
1086 if (class_constructor
!= null) {
1087 class_constructor
.check (context
);
1090 if (static_constructor
!= null) {
1091 static_constructor
.check (context
);
1094 if (destructor
!= null) {
1095 destructor
.check (context
);
1098 if (static_destructor
!= null) {
1099 static_destructor
.check (context
);
1102 if (class_destructor
!= null) {
1103 class_destructor
.check (context
);
1106 foreach (Class cl
in classes
) {
1110 foreach (Struct st
in structs
) {
1114 foreach (Delegate d
in delegates
) {
1118 /* compact classes cannot implement interfaces */
1120 foreach (DataType base_type
in get_base_types ()) {
1121 if (base_type
.data_type is Interface
) {
1123 Report
.error (source_reference
, "compact classes `%s` may not implement interfaces".printf (get_full_name ()));
1127 if (!external
&& !external_package
&& base_class
!= null) {
1128 foreach (Field f
in fields
) {
1129 if (f
.binding
== MemberBinding
.INSTANCE
) {
1131 Report
.error (source_reference
, "derived compact classes may not have instance fields");
1138 /* gather all prerequisites */
1139 List
<TypeSymbol
> prerequisites
= new ArrayList
<TypeSymbol
> ();
1140 foreach (DataType base_type
in get_base_types ()) {
1141 if (base_type
.data_type is Interface
) {
1142 get_all_prerequisites ((Interface
) base_type
.data_type
, prerequisites
);
1145 /* check whether all prerequisites are met */
1146 List
<string> missing_prereqs
= new ArrayList
<string> ();
1147 foreach (TypeSymbol prereq
in prerequisites
) {
1148 if (!class_is_a (this
, prereq
)) {
1149 missing_prereqs
.insert (0, prereq
.get_full_name ());
1152 /* report any missing prerequisites */
1153 if (missing_prereqs
.size
> 0) {
1156 string error_string
= "%s: some prerequisites (".printf (get_full_name ());
1158 foreach (string s
in missing_prereqs
) {
1160 error_string
= "%s`%s'".printf (error_string
, s
);
1163 error_string
= "%s, `%s'".printf (error_string
, s
);
1166 error_string
+= ") are not met";
1167 Report
.error (source_reference
, error_string
);
1170 /* VAPI classes don't have to specify overridden methods */
1171 if (source_type
== SourceFileType
.SOURCE
) {
1172 /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */
1173 foreach (DataType base_type
in get_base_types ()) {
1174 if (base_type
.data_type is Interface
) {
1175 Interface iface
= (Interface
) base_type
.data_type
;
1177 if (base_class
!= null && base_class
.is_subtype_of (iface
)) {
1178 // reimplementation of interface, class is not required to reimplement all methods
1182 /* We do not need to do expensive equality checking here since this is done
1183 * already. We only need to guarantee the symbols are present.
1187 foreach (Method m
in iface
.get_methods ()) {
1188 if (m
.is_abstract
) {
1190 var base_class
= this
;
1191 while (base_class
!= null && !(sym is Method
)) {
1192 sym
= base_class
.scope
.lookup (m
.name
);
1193 base_class
= base_class
.base_class
;
1195 if (sym is Method
) {
1196 // method is used as interface implementation, so it is not unused
1197 sym
.check_deprecated (source_reference
);
1198 sym
.check_experimental (source_reference
);
1202 Report
.error (source_reference
, "`%s' does not implement interface method `%s'".printf (get_full_name (), m
.get_full_name ()));
1207 /* check properties */
1208 foreach (Property prop
in iface
.get_properties ()) {
1209 if (prop
.is_abstract
) {
1211 var base_class
= this
;
1212 while (base_class
!= null && !(sym is Property
)) {
1213 sym
= base_class
.scope
.lookup (prop
.name
);
1214 base_class
= base_class
.base_class
;
1216 if (sym is Property
) {
1217 // property is used as interface implementation, so it is not unused
1218 sym
.check_deprecated (source_reference
);
1219 sym
.check_experimental (source_reference
);
1223 Report
.error (source_reference
, "`%s' does not implement interface property `%s'".printf (get_full_name (), prop
.get_full_name ()));
1230 /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */
1232 var base_class
= base_class
;
1233 while (base_class
!= null && base_class
.is_abstract
) {
1234 foreach (Method base_method
in base_class
.get_methods ()) {
1235 if (base_method
.is_abstract
) {
1236 var override_method
= context
.analyzer
.symbol_lookup_inherited (this
, base_method
.name
) as Method
;
1237 if (override_method
== null || !override_method
.overrides
) {
1239 Report
.error (source_reference
, "`%s' does not implement abstract method `%s'".printf (get_full_name (), base_method
.get_full_name ()));
1243 foreach (Property base_property
in base_class
.get_properties ()) {
1244 if (base_property
.is_abstract
) {
1245 var override_property
= context
.analyzer
.symbol_lookup_inherited (this
, base_property
.name
) as Property
;
1246 if (override_property
== null || !override_property
.overrides
) {
1248 Report
.error (source_reference
, "`%s' does not implement abstract property `%s'".printf (get_full_name (), base_property
.get_full_name ()));
1252 base_class
= base_class
.base_class
;
1257 context
.analyzer
.current_source_file
= old_source_file
;
1258 context
.analyzer
.current_symbol
= old_symbol
;