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; private 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
FormalParameter ("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 void add_constant (Constant c
) {
279 scope
.add (c
.name
, c
);
283 * Adds the specified field as a member to this class.
287 public 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
);
301 prop
.get_accessor
.access
= SymbolAccessibility
.PUBLIC
;
303 prop
.set_accessor
= new
PropertyAccessor (false, true, false, prop
.property_type
.copy (), null, f
.source_reference
);
304 prop
.set_accessor
.access
= SymbolAccessibility
.PUBLIC
;
306 f
.name
= "_%s".printf (f
.name
);
307 f
.access
= SymbolAccessibility
.PRIVATE
;
315 if (f
.access
== SymbolAccessibility
.PRIVATE
&& f
.binding
== MemberBinding
.INSTANCE
) {
316 has_private_fields
= true;
317 } else if (f
.access
== SymbolAccessibility
.PRIVATE
&& f
.binding
== MemberBinding
.CLASS
) {
318 has_class_private_fields
= true;
320 scope
.add (f
.name
, f
);
324 * Returns a copy of the list of fields.
326 * @return list of fields
328 public List
<Field
> get_fields () {
333 * Returns a copy of the list of constants.
335 * @return list of constants
337 public List
<Constant
> get_constants () {
342 * Adds the specified method as a member to this class.
346 public void add_method (Method m
) {
347 if (m
.binding
== MemberBinding
.INSTANCE
|| m is CreationMethod
) {
348 if (m
.this_parameter
!= null) {
349 m
.scope
.remove (m
.this_parameter
.name
);
351 m
.this_parameter
= new
FormalParameter ("this", get_this_type ());
352 m
.scope
.add (m
.this_parameter
.name
, m
.this_parameter
);
354 if (!(m
.return_type is VoidType
) && (CodeContext
.get ().profile
== Profile
.DOVA
|| m
.get_postconditions ().size
> 0)) {
355 if (m
.result_var
!= null) {
356 m
.scope
.remove (m
.result_var
.name
);
358 m
.result_var
= new
LocalVariable (m
.return_type
.copy (), "result", null, source_reference
);
359 m
.result_var
.is_result
= true;
361 if (m is CreationMethod
) {
362 if (m
.name
== null) {
363 default_construction_method
= m
;
367 var cm
= (CreationMethod
) m
;
368 if (cm
.class_name
!= null && cm
.class_name
!= name
) {
369 // class_name is null for constructors generated by GIdlParser
370 Report
.error (m
.source_reference
, "missing return type in method `%s.%s´".printf (get_full_name (), cm
.class_name
));
377 scope
.add (m
.name
, m
);
381 * Returns a copy of the list of methods.
383 * @return list of methods
385 public override List
<Method
> get_methods () {
390 * Adds the specified property as a member to this class.
392 * @param prop a property
394 public void add_property (Property prop
) {
395 properties
.add (prop
);
396 scope
.add (prop
.name
, prop
);
398 prop
.this_parameter
= new
FormalParameter ("this", get_this_type ());
399 prop
.scope
.add (prop
.this_parameter
.name
, prop
.this_parameter
);
401 if (prop
.field
!= null) {
402 add_field (prop
.field
);
407 * Returns a copy of the list of properties.
409 * @return list of properties
411 public override List
<Property
> get_properties () {
416 * Adds the specified signal as a member to this class.
418 * @param sig a signal
420 public void add_signal (Signal sig
) {
422 scope
.add (sig
.name
, sig
);
426 * Returns a copy of the list of signals.
428 * @return list of signals
430 public override List
<Signal
> get_signals () {
435 * Adds the specified class as an inner class.
439 public void add_class (Class cl
) {
441 scope
.add (cl
.name
, cl
);
445 * Adds the specified struct as an inner struct.
449 public void add_struct (Struct st
) {
451 scope
.add (st
.name
, st
);
455 * Adds the specified enum as an inner enum.
459 public void add_enum (Enum en
) {
461 scope
.add (en
.name
, en
);
465 * Adds the specified delegate as an inner delegate.
467 * @param d a delegate
469 public void add_delegate (Delegate d
) {
471 scope
.add (d
.name
, d
);
474 public override void accept (CodeVisitor visitor
) {
475 visitor
.visit_class (this
);
478 public override void accept_children (CodeVisitor visitor
) {
479 foreach (DataType type
in base_types
) {
480 type
.accept (visitor
);
483 foreach (TypeParameter p
in get_type_parameters ()) {
487 /* process enums first to avoid order problems in C code */
488 foreach (Enum en
in enums
) {
492 foreach (Field f
in fields
) {
496 foreach (Constant c
in constants
) {
500 foreach (Method m
in methods
) {
504 foreach (Property prop
in properties
) {
505 prop
.accept (visitor
);
508 foreach (Signal sig
in signals
) {
509 sig
.accept (visitor
);
512 if (constructor
!= null) {
513 constructor
.accept (visitor
);
516 if (class_constructor
!= null) {
517 class_constructor
.accept (visitor
);
520 if (static_constructor
!= null) {
521 static_constructor
.accept (visitor
);
524 if (destructor
!= null) {
525 destructor
.accept (visitor
);
528 if (static_destructor
!= null) {
529 static_destructor
.accept (visitor
);
532 if (class_destructor
!= null) {
533 class_destructor
.accept (visitor
);
536 foreach (Class cl
in classes
) {
540 foreach (Struct st
in structs
) {
544 foreach (Delegate d
in delegates
) {
549 public override string get_cprefix () {
553 public override string get_cname (bool const_type
= false) {
555 if (const_cname
!= null) {
557 } else if (is_immutable
) {
558 return "const " + get_cname (false);
563 var attr
= get_attribute ("CCode");
565 cname
= attr
.get_string ("cname");
568 cname
= get_default_cname ();
575 * Returns the default name of this class as it is used in C code.
577 * @return the name to be used in C code by default
579 public string get_default_cname () {
580 return "%s%s".printf (parent_symbol
.get_cprefix (), name
);
584 * Sets the name of this class as it is used in C code.
586 * @param cname the name to be used in C code
588 public void set_cname (string cname
) {
592 private string get_lower_case_csuffix () {
593 if (lower_case_csuffix
== null) {
594 lower_case_csuffix
= camel_case_to_lower_case (name
);
596 // remove underscores in some cases to avoid conflicts of type macros
597 if (lower_case_csuffix
.has_prefix ("type_")) {
598 lower_case_csuffix
= "type" + lower_case_csuffix
.offset ("type_".len ());
599 } else if (lower_case_csuffix
.has_prefix ("is_")) {
600 lower_case_csuffix
= "is" + lower_case_csuffix
.offset ("is_".len ());
602 if (lower_case_csuffix
.has_suffix ("_class")) {
603 lower_case_csuffix
= lower_case_csuffix
.substring (0, lower_case_csuffix
.len () - "_class".len ()) + "class";
606 return lower_case_csuffix
;
609 public override string?
get_lower_case_cname (string? infix
) {
613 return "%s%s%s".printf (parent_symbol
.get_lower_case_cprefix (), infix
, get_lower_case_csuffix ());
616 public override string get_lower_case_cprefix () {
617 if (lower_case_cprefix
== null) {
618 lower_case_cprefix
= "%s_".printf (get_lower_case_cname (null));
620 return lower_case_cprefix
;
623 public override string?
get_upper_case_cname (string? infix
) {
624 return get_lower_case_cname (infix
).up ();
627 public override bool is_reference_type () {
631 private void process_ccode_attribute (Attribute a
) {
632 if (a
.has_argument ("ref_function")) {
633 set_ref_function (a
.get_string ("ref_function"));
635 if (a
.has_argument ("ref_function_void")) {
636 this
.ref_function_void
= a
.get_bool ("ref_function_void");
638 if (a
.has_argument ("unref_function")) {
639 set_unref_function (a
.get_string ("unref_function"));
641 if (a
.has_argument ("ref_sink_function")) {
642 set_ref_sink_function (a
.get_string ("ref_sink_function"));
644 if (a
.has_argument ("copy_function")) {
645 set_dup_function (a
.get_string ("copy_function"));
647 if (a
.has_argument ("free_function")) {
648 set_free_function (a
.get_string ("free_function"));
650 if (a
.has_argument ("free_function_address_of")) {
651 free_function_address_of
= a
.get_bool ("free_function_address_of");
653 if (a
.has_argument ("type_id")) {
654 type_id
= a
.get_string ("type_id");
656 if (a
.has_argument ("marshaller_type_name")) {
657 marshaller_type_name
= a
.get_string ("marshaller_type_name");
659 if (a
.has_argument ("get_value_function")) {
660 get_value_function
= a
.get_string ("get_value_function");
662 if (a
.has_argument ("set_value_function")) {
663 set_value_function
= a
.get_string ("set_value_function");
665 if (a
.has_argument ("take_value_function")) {
666 take_value_function
= a
.get_string ("take_value_function");
669 if (a
.has_argument ("const_cname")) {
670 const_cname
= a
.get_string ("const_cname");
672 if (a
.has_argument ("cprefix")) {
673 lower_case_cprefix
= a
.get_string ("cprefix");
675 if (a
.has_argument ("lower_case_csuffix")) {
676 lower_case_csuffix
= a
.get_string ("lower_case_csuffix");
678 if (a
.has_argument ("cheader_filename")) {
679 var val
= a
.get_string ("cheader_filename");
680 foreach (string filename
in val
.split (",")) {
681 add_cheader_filename (filename
);
684 if (a
.has_argument ("type_check_function")) {
685 type_check_function
= a
.get_string ("type_check_function");
688 if (a
.has_argument ("param_spec_function")) {
689 param_spec_function
= a
.get_string ("param_spec_function");
694 * Process all associated attributes.
696 public void process_attributes () {
697 foreach (Attribute a
in attributes
) {
698 if (a
.name
== "CCode") {
699 process_ccode_attribute (a
);
700 } else if (a
.name
== "Compact") {
702 } else if (a
.name
== "Immutable") {
704 } else if (a
.name
== "Deprecated") {
705 process_deprecated_attribute (a
);
710 public string?
get_default_type_id () {
712 return "G_TYPE_POINTER";
715 return get_upper_case_cname ("TYPE_");
718 public override string?
get_type_id () {
719 if (type_id
== null) {
720 type_id
= get_default_type_id ();
726 public void set_type_id (string type_id
) {
727 this
.type_id
= type_id
;
730 public override string?
get_marshaller_type_name () {
731 if (marshaller_type_name
== null) {
732 if (base_class
!= null) {
733 marshaller_type_name
= base_class
.get_marshaller_type_name ();
734 } else if (!is_compact
) {
735 marshaller_type_name
= get_upper_case_cname ();
736 } else if (get_type_id () == "G_TYPE_POINTER") {
737 marshaller_type_name
= "POINTER";
739 marshaller_type_name
= "BOXED";
743 return marshaller_type_name
;
746 public override string?
get_param_spec_function () {
747 if (param_spec_function
== null) {
748 param_spec_function
= get_default_param_spec_function ();
751 return param_spec_function
;
754 public string?
get_default_param_spec_function () {
755 if (is_fundamental ()) {
756 return get_lower_case_cname ("param_spec_");
757 } else if (base_class
!= null) {
758 return base_class
.get_param_spec_function ();
759 } else if (get_type_id () == "G_TYPE_POINTER") {
760 return "g_param_spec_pointer";
762 return "g_param_spec_boxed";
766 public override string?
get_get_value_function () {
767 if (get_value_function
== null) {
768 if (is_fundamental ()) {
769 get_value_function
= get_lower_case_cname ("value_get_");
770 } else if (base_class
!= null) {
771 get_value_function
= base_class
.get_get_value_function ();
772 } else if (get_type_id () == "G_TYPE_POINTER") {
773 get_value_function
= "g_value_get_pointer";
775 get_value_function
= "g_value_get_boxed";
779 return get_value_function
;
782 public override string?
get_set_value_function () {
783 if (set_value_function
== null) {
784 if (is_fundamental ()) {
785 set_value_function
= get_lower_case_cname ("value_set_");
786 } else if (base_class
!= null) {
787 set_value_function
= base_class
.get_set_value_function ();
788 } else if (get_type_id () == "G_TYPE_POINTER") {
789 set_value_function
= "g_value_set_pointer";
791 set_value_function
= "g_value_set_boxed";
795 return set_value_function
;
798 public override string?
get_take_value_function () {
799 if (take_value_function
== null) {
800 if (is_fundamental ()) {
801 take_value_function
= get_lower_case_cname ("value_take_");
802 } else if (base_class
!= null) {
803 take_value_function
= base_class
.get_take_value_function ();
804 } else if (get_type_id () == "G_TYPE_POINTER") {
805 take_value_function
= "g_value_set_pointer";
807 take_value_function
= "g_value_take_boxed";
811 return take_value_function
;
814 public override bool is_reference_counting () {
815 return get_ref_function () != null;
818 public bool is_fundamental () {
819 if (!is_compact
&& base_class
== null) {
821 } else if (CodeContext
.get ().profile
== Profile
.DOVA
&& base_class
.base_class
== null) {
827 public override string?
get_ref_function () {
828 if (ref_function
== null && is_fundamental ()) {
829 ref_function
= get_lower_case_cprefix () + "ref";
832 if (ref_function
== null && base_class
!= null) {
833 return base_class
.get_ref_function ();
839 public void set_ref_function (string? name
) {
840 this
.ref_function
= name
;
843 public override string?
get_unref_function () {
844 if (unref_function
== null && is_fundamental ()) {
845 unref_function
= get_lower_case_cprefix () + "unref";
848 if (unref_function
== null && base_class
!= null) {
849 return base_class
.get_unref_function ();
851 return unref_function
;
855 public void set_unref_function (string? name
) {
856 this
.unref_function
= name
;
859 public override string?
get_ref_sink_function () {
860 if (ref_sink_function
== null && base_class
!= null) {
861 return base_class
.get_ref_sink_function ();
863 return ref_sink_function
;
867 public void set_ref_sink_function (string? name
) {
868 this
.ref_sink_function
= name
;
871 public override string?
get_dup_function () {
872 return copy_function
;
875 public void set_dup_function (string? name
) {
876 this
.copy_function
= name
;
879 public string get_default_free_function () {
880 return get_lower_case_cprefix () + "free";
883 public override string?
get_free_function () {
884 if (free_function
== null) {
885 if (base_class
!= null) {
886 return base_class
.get_free_function ();
888 free_function
= get_default_free_function ();
890 return free_function
;
893 public void set_free_function (string name
) {
894 this
.free_function
= name
;
897 public override bool is_subtype_of (TypeSymbol t
) {
902 foreach (DataType base_type
in base_types
) {
903 if (base_type
.data_type
!= null && base_type
.data_type
.is_subtype_of (t
)) {
911 public override void replace_type (DataType old_type
, DataType new_type
) {
912 for (int i
= 0; i
< base_types
.size
; i
++) {
913 if (base_types
[i
] == old_type
) {
914 base_types
[i
] = new_type
;
920 private void get_all_prerequisites (Interface iface
, List
<TypeSymbol
> list
) {
921 foreach (DataType prereq
in iface
.get_prerequisites ()) {
922 TypeSymbol type
= prereq
.data_type
;
923 /* skip on previous errors */
929 if (type is Interface
) {
930 get_all_prerequisites ((Interface
) type
, list
);
936 private bool class_is_a (Class cl
, TypeSymbol t
) {
941 foreach (DataType base_type
in cl
.get_base_types ()) {
942 if (base_type
.data_type is Class
) {
943 if (class_is_a ((Class
) base_type
.data_type
, t
)) {
946 } else if (base_type
.data_type
== t
) {
954 public override bool check (SemanticAnalyzer analyzer
) {
961 process_attributes ();
963 var old_source_file
= analyzer
.current_source_file
;
964 var old_symbol
= analyzer
.current_symbol
;
966 if (source_reference
!= null) {
967 analyzer
.current_source_file
= source_reference
.file
;
969 analyzer
.current_symbol
= this
;
971 foreach (DataType base_type_reference
in get_base_types ()) {
972 if (!base_type_reference
.check (analyzer
)) {
977 if (!(base_type_reference is ObjectType
)) {
979 Report
.error (source_reference
, "base type `%s` of class `%s` is not an object type".printf (base_type_reference
.to_string (), get_full_name ()));
983 // check whether base type is at least as accessible as the class
984 if (!analyzer
.is_type_accessible (this
, base_type_reference
)) {
986 Report
.error (source_reference
, "base type `%s` is less accessible than class `%s`".printf (base_type_reference
.to_string (), get_full_name ()));
990 int n_type_args
= base_type_reference
.get_type_arguments ().size
;
991 int n_type_params
= ((ObjectTypeSymbol
) base_type_reference
.data_type
).get_type_parameters ().size
;
992 if (n_type_args
< n_type_params
) {
994 Report
.error (base_type_reference
.source_reference
, "too few type arguments");
996 } else if (n_type_args
> n_type_params
) {
998 Report
.error (base_type_reference
.source_reference
, "too many type arguments");
1003 foreach (DataType type
in base_types
) {
1004 type
.check (analyzer
);
1007 foreach (TypeParameter p
in get_type_parameters ()) {
1011 /* process enums first to avoid order problems in C code */
1012 foreach (Enum en
in enums
) {
1013 en
.check (analyzer
);
1016 foreach (Field f
in fields
) {
1020 foreach (Constant c
in constants
) {
1024 foreach (Method m
in methods
) {
1028 foreach (Property prop
in properties
) {
1029 prop
.check (analyzer
);
1032 foreach (Signal sig
in signals
) {
1033 sig
.check (analyzer
);
1036 if (constructor
!= null) {
1037 constructor
.check (analyzer
);
1040 if (class_constructor
!= null) {
1041 class_constructor
.check (analyzer
);
1044 if (static_constructor
!= null) {
1045 static_constructor
.check (analyzer
);
1048 if (destructor
!= null) {
1049 destructor
.check (analyzer
);
1052 if (static_destructor
!= null) {
1053 static_destructor
.check (analyzer
);
1056 if (class_destructor
!= null) {
1057 class_destructor
.check (analyzer
);
1060 foreach (Class cl
in classes
) {
1061 cl
.check (analyzer
);
1064 foreach (Struct st
in structs
) {
1065 st
.check (analyzer
);
1068 foreach (Delegate d
in delegates
) {
1072 /* compact classes cannot implement interfaces */
1074 foreach (DataType base_type
in get_base_types ()) {
1075 if (base_type
.data_type is Interface
) {
1077 Report
.error (source_reference
, "compact classes `%s` may not implement interfaces".printf (get_full_name ()));
1081 if (!external
&& !external_package
&& base_class
!= null) {
1082 foreach (Field f
in fields
) {
1083 if (f
.binding
== MemberBinding
.INSTANCE
) {
1085 Report
.error (source_reference
, "derived compact classes may not have instance fields");
1092 /* gather all prerequisites */
1093 List
<TypeSymbol
> prerequisites
= new ArrayList
<TypeSymbol
> ();
1094 foreach (DataType base_type
in get_base_types ()) {
1095 if (base_type
.data_type is Interface
) {
1096 get_all_prerequisites ((Interface
) base_type
.data_type
, prerequisites
);
1099 /* check whether all prerequisites are met */
1100 List
<string> missing_prereqs
= new ArrayList
<string> ();
1101 foreach (TypeSymbol prereq
in prerequisites
) {
1102 if (!class_is_a (this
, prereq
)) {
1103 missing_prereqs
.insert (0, prereq
.get_full_name ());
1106 /* report any missing prerequisites */
1107 if (missing_prereqs
.size
> 0) {
1110 string error_string
= "%s: some prerequisites (".printf (get_full_name ());
1112 foreach (string s
in missing_prereqs
) {
1114 error_string
= "%s`%s'".printf (error_string
, s
);
1117 error_string
= "%s, `%s'".printf (error_string
, s
);
1120 error_string
+= ") are not met";
1121 Report
.error (source_reference
, error_string
);
1124 /* VAPI classes don't have to specify overridden methods */
1125 if (!external_package
) {
1126 /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */
1127 foreach (DataType base_type
in get_base_types ()) {
1128 if (base_type
.data_type is Interface
) {
1129 Interface iface
= (Interface
) base_type
.data_type
;
1131 if (base_class
!= null && base_class
.is_subtype_of (iface
)) {
1132 // reimplementation of interface, class is not required to reimplement all methods
1136 /* We do not need to do expensive equality checking here since this is done
1137 * already. We only need to guarantee the symbols are present.
1141 foreach (Method m
in iface
.get_methods ()) {
1142 if (m
.is_abstract
) {
1144 var base_class
= this
;
1145 while (base_class
!= null && !(sym is Method
)) {
1146 sym
= base_class
.scope
.lookup (m
.name
);
1147 base_class
= base_class
.base_class
;
1149 if (sym is Method
) {
1150 // method is used as interface implementation, so it is not unused
1151 sym
.check_deprecated (source_reference
);
1155 Report
.error (source_reference
, "`%s' does not implement interface method `%s'".printf (get_full_name (), m
.get_full_name ()));
1160 /* check properties */
1161 foreach (Property prop
in iface
.get_properties ()) {
1162 if (prop
.is_abstract
) {
1164 var base_class
= this
;
1165 while (base_class
!= null && !(sym is Property
)) {
1166 sym
= base_class
.scope
.lookup (prop
.name
);
1167 base_class
= base_class
.base_class
;
1169 if (sym is Property
) {
1170 // property is used as interface implementation, so it is not unused
1171 sym
.check_deprecated (source_reference
);
1175 Report
.error (source_reference
, "`%s' does not implement interface property `%s'".printf (get_full_name (), prop
.get_full_name ()));
1182 /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */
1184 var base_class
= base_class
;
1185 while (base_class
!= null && base_class
.is_abstract
) {
1186 foreach (Method base_method
in base_class
.get_methods ()) {
1187 if (base_method
.is_abstract
) {
1188 var override_method
= analyzer
.symbol_lookup_inherited (this
, base_method
.name
) as Method
;
1189 if (override_method
== null || !override_method
.overrides
) {
1191 Report
.error (source_reference
, "`%s' does not implement abstract method `%s'".printf (get_full_name (), base_method
.get_full_name ()));
1195 foreach (Property base_property
in base_class
.get_properties ()) {
1196 if (base_property
.is_abstract
) {
1197 var override_property
= analyzer
.symbol_lookup_inherited (this
, base_property
.name
) as Property
;
1198 if (override_property
== null || !override_property
.overrides
) {
1200 Report
.error (source_reference
, "`%s' does not implement abstract property `%s'".printf (get_full_name (), base_property
.get_full_name ()));
1204 base_class
= base_class
.base_class
;
1209 analyzer
.current_source_file
= old_source_file
;
1210 analyzer
.current_symbol
= old_symbol
;