Warn when using result variable with incompatible type to prepare possible
[vala-lang.git] / vala / valaclass.vala
blob6c06a4e1f04e57cb7c09d21b73d2ee768660fc1b
1 /* valaclass.vala
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
24 using Gee;
26 /**
27 * Represents a class declaration in the source code.
29 public class Vala.Class : ObjectTypeSymbol {
30 /**
31 * Specifies the base class.
33 public Class base_class { get; set; }
35 /**
36 * Specifies whether this class is abstract. Abstract classes may not be
37 * instantiated.
39 public bool is_abstract { get; set; }
41 /**
42 * Instances of compact classes are fast to create and have a
43 * compact memory layout. Compact classes don't support runtime
44 * type information or virtual methods.
46 public bool is_compact {
47 get {
48 if (base_class != null) {
49 return base_class.is_compact;
51 return _is_compact;
53 set {
54 _is_compact = value;
58 /**
59 * Instances of immutable classes are immutable after construction.
61 public bool is_immutable {
62 get {
63 if (base_class != null) {
64 return base_class.is_immutable;
66 return _is_immutable;
68 set {
69 _is_immutable = value;
73 /**
74 * Specifies wheather the ref function returns void instead of the
75 * object.
77 public bool ref_function_void { get; set; }
79 /**
80 * The name of the function to use to check whether a value is an instance of
81 * this class. If this is null then the default type check function should be
82 * used instead.
84 public string? type_check_function { get; set; }
86 /**
87 * Specifies whether this class has private fields.
89 public bool has_private_fields { get; private set; }
91 /**
92 * Specifies whether this class has class fields.
94 public bool has_class_private_fields { get; private set; }
96 private string cname;
97 private string const_cname;
98 private string lower_case_cprefix;
99 private string lower_case_csuffix;
100 private string type_id;
101 private string ref_function;
102 private string unref_function;
103 private string param_spec_function;
104 private string copy_function;
105 private string free_function;
106 private string marshaller_type_name;
107 private string get_value_function;
108 private string set_value_function;
109 private string? type_signature;
110 private bool _is_compact;
111 private bool _is_immutable;
113 private Gee.List<DataType> base_types = new ArrayList<DataType> ();
115 private Gee.List<Constant> constants = new ArrayList<Constant> ();
116 private Gee.List<Field> fields = new ArrayList<Field> ();
117 private Gee.List<Method> methods = new ArrayList<Method> ();
118 private Gee.List<Property> properties = new ArrayList<Property> ();
119 private Gee.List<Signal> signals = new ArrayList<Signal> ();
121 // inner types
122 private Gee.List<Class> classes = new ArrayList<Class> ();
123 private Gee.List<Struct> structs = new ArrayList<Struct> ();
124 private Gee.List<Enum> enums = new ArrayList<Enum> ();
125 private Gee.List<Delegate> delegates = new ArrayList<Delegate> ();
128 * Returns a copy of the list of classes.
130 * @return list of classes
132 public Gee.List<Class> get_classes () {
133 return new ReadOnlyList<Class> (classes);
137 * Returns a copy of the list of structs.
139 * @return list of structs
141 public Gee.List<Struct> get_structs () {
142 return new ReadOnlyList<Struct> (structs);
146 * Returns a copy of the list of enums.
148 * @return list of enums
150 public Gee.List<Enum> get_enums () {
151 return new ReadOnlyList<Enum> (enums);
155 * Returns a copy of the list of delegates.
157 * @return list of delegates
159 public Gee.List<Delegate> get_delegates () {
160 return new ReadOnlyList<Delegate> (delegates);
164 * Specifies the default construction method.
166 public Method default_construction_method { get; set; }
169 * Specifies the instance constructor.
171 public Constructor constructor { get; set; }
174 * Specifies the class constructor.
176 public Constructor class_constructor { get; set; }
179 * Specifies the static class constructor.
181 public Constructor static_constructor { get; set; }
184 * Specifies the instance destructor.
186 public Destructor? destructor {
187 get { return _destructor; }
188 set {
189 _destructor = value;
190 if (_destructor != null) {
191 if (_destructor.this_parameter != null) {
192 _destructor.scope.remove (_destructor.this_parameter.name);
194 _destructor.this_parameter = new FormalParameter ("this", new ObjectType (this));
195 _destructor.scope.add (_destructor.this_parameter.name, _destructor.this_parameter);
201 * Specifies the class destructor.
203 public Destructor? static_destructor { get; set; }
206 * Specifies the class destructor.
208 public Destructor? class_destructor { get; set; }
211 * Specifies whether this class denotes an error base.
213 public bool is_error_base {
214 get {
215 return get_attribute ("ErrorBase") != null;
219 Destructor? _destructor;
222 * Creates a new class.
224 * @param name type name
225 * @param source reference to source code
226 * @return newly created class
228 public Class (string name, SourceReference? source_reference = null) {
229 base (name, source_reference);
233 * Adds the specified class or interface to the list of base types of
234 * this class.
236 * @param type a class or interface reference
238 public void add_base_type (DataType type) {
239 base_types.add (type);
240 type.parent_node = this;
244 * Returns a copy of the base type list.
246 * @return list of base types
248 public Gee.List<DataType> get_base_types () {
249 return new ReadOnlyList<DataType> (base_types);
253 * Adds the specified constant as a member to this class.
255 * @param c a constant
257 public void add_constant (Constant c) {
258 constants.add (c);
259 scope.add (c.name, c);
263 * Adds the specified field as a member to this class.
265 * @param f a field
267 public void add_field (Field f) {
268 fields.add (f);
269 if (f.access == SymbolAccessibility.PRIVATE && f.binding == MemberBinding.INSTANCE) {
270 has_private_fields = true;
271 } else if (f.access == SymbolAccessibility.PRIVATE && f.binding == MemberBinding.CLASS) {
272 has_class_private_fields = true;
274 scope.add (f.name, f);
278 * Returns a copy of the list of fields.
280 * @return list of fields
282 public Gee.List<Field> get_fields () {
283 return new ReadOnlyList<Field> (fields);
287 * Returns a copy of the list of constants.
289 * @return list of constants
291 public Gee.List<Constant> get_constants () {
292 return new ReadOnlyList<Constant> (constants);
296 * Adds the specified method as a member to this class.
298 * @param m a method
300 public void add_method (Method m) {
301 if (m.binding == MemberBinding.INSTANCE || m is CreationMethod) {
302 if (m.this_parameter != null) {
303 m.scope.remove (m.this_parameter.name);
305 m.this_parameter = new FormalParameter ("this", new ObjectType (this));
306 m.scope.add (m.this_parameter.name, m.this_parameter);
308 if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
309 if (m.result_var != null) {
310 m.scope.remove (m.result_var.name);
312 m.result_var = new LocalVariable (m.return_type.copy (), "result");
314 if (m is CreationMethod) {
315 if (m.name == null) {
316 default_construction_method = m;
317 m.name = "new";
320 var cm = (CreationMethod) m;
321 if (cm.type_name != null && cm.type_name != name) {
322 // type_name is null for constructors generated by GIdlParser
323 Report.error (m.source_reference, "missing return type in method `%s.%s´".printf (get_full_name (), cm.type_name));
324 m.error = true;
325 return;
329 methods.add (m);
330 scope.add (m.name, m);
334 * Returns a copy of the list of methods.
336 * @return list of methods
338 public override Gee.List<Method> get_methods () {
339 return new ReadOnlyList<Method> (methods);
343 * Adds the specified property as a member to this class.
345 * @param prop a property
347 public void add_property (Property prop) {
348 properties.add (prop);
349 scope.add (prop.name, prop);
351 prop.this_parameter = new FormalParameter ("this", new ObjectType (this));
352 prop.scope.add (prop.this_parameter.name, prop.this_parameter);
354 if (prop.field != null) {
355 add_field (prop.field);
360 * Returns a copy of the list of properties.
362 * @return list of properties
364 public override Gee.List<Property> get_properties () {
365 return new ReadOnlyList<Property> (properties);
369 * Adds the specified signal as a member to this class.
371 * @param sig a signal
373 public void add_signal (Signal sig) {
374 signals.add (sig);
375 scope.add (sig.name, sig);
379 * Returns a copy of the list of signals.
381 * @return list of signals
383 public override Gee.List<Signal> get_signals () {
384 return new ReadOnlyList<Signal> (signals);
388 * Adds the specified class as an inner class.
390 * @param cl a class
392 public void add_class (Class cl) {
393 classes.add (cl);
394 scope.add (cl.name, cl);
398 * Adds the specified struct as an inner struct.
400 * @param st a struct
402 public void add_struct (Struct st) {
403 structs.add (st);
404 scope.add (st.name, st);
408 * Adds the specified enum as an inner enum.
410 * @param en an enum
412 public void add_enum (Enum en) {
413 enums.add (en);
414 scope.add (en.name, en);
418 * Adds the specified delegate as an inner delegate.
420 * @param d a delegate
422 public void add_delegate (Delegate d) {
423 delegates.add (d);
424 scope.add (d.name, d);
427 public override void accept (CodeVisitor visitor) {
428 visitor.visit_class (this);
431 public override void accept_children (CodeVisitor visitor) {
432 foreach (DataType type in base_types) {
433 type.accept (visitor);
436 foreach (TypeParameter p in get_type_parameters ()) {
437 p.accept (visitor);
440 /* process enums first to avoid order problems in C code */
441 foreach (Enum en in enums) {
442 en.accept (visitor);
445 foreach (Field f in fields) {
446 f.accept (visitor);
449 foreach (Constant c in constants) {
450 c.accept (visitor);
453 foreach (Method m in methods) {
454 m.accept (visitor);
457 foreach (Property prop in properties) {
458 prop.accept (visitor);
461 foreach (Signal sig in signals) {
462 sig.accept (visitor);
465 if (constructor != null) {
466 constructor.accept (visitor);
469 if (class_constructor != null) {
470 class_constructor.accept (visitor);
473 if (static_constructor != null) {
474 static_constructor.accept (visitor);
477 if (destructor != null) {
478 destructor.accept (visitor);
481 if (static_destructor != null) {
482 static_destructor.accept (visitor);
485 if (class_destructor != null) {
486 class_destructor.accept (visitor);
489 foreach (Class cl in classes) {
490 cl.accept (visitor);
493 foreach (Struct st in structs) {
494 st.accept (visitor);
497 foreach (Delegate d in delegates) {
498 d.accept (visitor);
502 public override string get_cprefix () {
503 return get_cname ();
506 public override string get_cname (bool const_type = false) {
507 if (const_type) {
508 if (const_cname != null) {
509 return const_cname;
510 } else if (is_immutable) {
511 return "const " + get_cname (false);
515 if (cname == null) {
516 var attr = get_attribute ("CCode");
517 if (attr != null) {
518 cname = attr.get_string ("cname");
520 if (cname == null) {
521 cname = get_default_cname ();
524 return cname;
528 * Returns the default name of this class as it is used in C code.
530 * @return the name to be used in C code by default
532 public string get_default_cname () {
533 return "%s%s".printf (parent_symbol.get_cprefix (), name);
537 * Sets the name of this class as it is used in C code.
539 * @param cname the name to be used in C code
541 public void set_cname (string cname) {
542 this.cname = cname;
545 private string get_lower_case_csuffix () {
546 if (lower_case_csuffix == null) {
547 lower_case_csuffix = camel_case_to_lower_case (name);
549 // remove underscores in some cases to avoid conflicts of type macros
550 if (lower_case_csuffix.has_prefix ("type_")) {
551 lower_case_csuffix = "type" + lower_case_csuffix.offset ("type_".len ());
552 } else if (lower_case_csuffix.has_prefix ("is_")) {
553 lower_case_csuffix = "is" + lower_case_csuffix.offset ("is_".len ());
555 if (lower_case_csuffix.has_suffix ("_class")) {
556 lower_case_csuffix = lower_case_csuffix.substring (0, lower_case_csuffix.len () - "_class".len ()) + "class";
559 return lower_case_csuffix;
562 public override string? get_lower_case_cname (string? infix) {
563 if (infix == null) {
564 infix = "";
566 return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
569 public override string get_lower_case_cprefix () {
570 if (lower_case_cprefix == null) {
571 lower_case_cprefix = "%s_".printf (get_lower_case_cname (null));
573 return lower_case_cprefix;
576 public override string? get_upper_case_cname (string? infix) {
577 return get_lower_case_cname (infix).up ();
580 public override string? get_type_signature () {
581 return type_signature;
584 public override bool is_reference_type () {
585 return true;
588 private void process_ccode_attribute (Attribute a) {
589 if (a.has_argument ("ref_function")) {
590 set_ref_function (a.get_string ("ref_function"));
592 if (a.has_argument ("ref_function_void")) {
593 this.ref_function_void = a.get_bool ("ref_function_void");
595 if (a.has_argument ("unref_function")) {
596 set_unref_function (a.get_string ("unref_function"));
598 if (a.has_argument ("copy_function")) {
599 set_dup_function (a.get_string ("copy_function"));
601 if (a.has_argument ("free_function")) {
602 set_free_function (a.get_string ("free_function"));
604 if (a.has_argument ("type_id")) {
605 type_id = a.get_string ("type_id");
607 if (a.has_argument ("marshaller_type_name")) {
608 marshaller_type_name = a.get_string ("marshaller_type_name");
610 if (a.has_argument ("get_value_function")) {
611 get_value_function = a.get_string ("get_value_function");
613 if (a.has_argument ("set_value_function")) {
614 set_value_function = a.get_string ("set_value_function");
617 if (a.has_argument ("const_cname")) {
618 const_cname = a.get_string ("const_cname");
620 if (a.has_argument ("cprefix")) {
621 lower_case_cprefix = a.get_string ("cprefix");
623 if (a.has_argument ("lower_case_csuffix")) {
624 lower_case_csuffix = a.get_string ("lower_case_csuffix");
626 if (a.has_argument ("cheader_filename")) {
627 var val = a.get_string ("cheader_filename");
628 foreach (string filename in val.split (",")) {
629 add_cheader_filename (filename);
632 if (a.has_argument ("type_signature")) {
633 type_signature = a.get_string ("type_signature");
635 if (a.has_argument ("type_check_function")) {
636 type_check_function = a.get_string ("type_check_function");
639 if (a.has_argument ("param_spec_function")) {
640 param_spec_function = a.get_string ("param_spec_function");
645 * Process all associated attributes.
647 public void process_attributes () {
648 foreach (Attribute a in attributes) {
649 if (a.name == "CCode") {
650 process_ccode_attribute (a);
651 } else if (a.name == "Compact") {
652 is_compact = true;
653 } else if (a.name == "Immutable") {
654 is_immutable = true;
659 public override string? get_type_id () {
660 if (type_id == null) {
661 if (!is_compact) {
662 type_id = get_upper_case_cname ("TYPE_");
663 } else {
664 type_id = "G_TYPE_POINTER";
668 return type_id;
671 public void set_type_id (string type_id) {
672 this.type_id = type_id;
675 public override string? get_marshaller_type_name () {
676 if (marshaller_type_name == null) {
677 if (base_class != null) {
678 marshaller_type_name = base_class.get_marshaller_type_name ();
679 } else {
680 marshaller_type_name = "POINTER";
684 return marshaller_type_name;
687 public override string? get_param_spec_function () {
688 if (param_spec_function == null ) {
689 if (!(is_compact || base_class == null)) {
690 param_spec_function = base_class.get_param_spec_function ();
694 return param_spec_function;
697 public void set_param_spec_function ( string name ) {
698 param_spec_function = name;
701 public override string? get_get_value_function () {
702 if (get_value_function == null) {
703 if (is_fundamental()) {
704 get_value_function = get_lower_case_cname ("value_get_");
705 } else if (base_class != null) {
706 get_value_function = base_class.get_get_value_function ();
707 } else {
708 get_value_function = "g_value_get_pointer";
712 return get_value_function;
715 public override string? get_set_value_function () {
716 if (set_value_function == null) {
717 if (is_fundamental()) {
718 set_value_function = get_lower_case_cname ("value_set_");
719 } else if (base_class != null) {
720 set_value_function = base_class.get_set_value_function ();
721 } else {
722 set_value_function = "g_value_set_pointer";
726 return set_value_function;
729 public override bool is_reference_counting () {
730 return get_ref_function () != null;
733 public bool is_fundamental () {
734 if (!is_compact && base_class == null) {
735 return true;
737 return false;
740 public override string? get_ref_function () {
741 if (ref_function == null && is_fundamental ()) {
742 ref_function = get_lower_case_cprefix () + "ref";
745 if (ref_function == null && base_class != null) {
746 return base_class.get_ref_function ();
747 } else {
748 return ref_function;
752 public void set_ref_function (string? name) {
753 this.ref_function = name;
756 public override string? get_unref_function () {
757 if (unref_function == null && is_fundamental ()) {
758 unref_function = get_lower_case_cprefix () + "unref";
761 if (unref_function == null && base_class != null) {
762 return base_class.get_unref_function ();
763 } else {
764 return unref_function;
768 public void set_unref_function (string? name) {
769 this.unref_function = name;
772 public override string? get_dup_function () {
773 return copy_function;
776 public void set_dup_function (string? name) {
777 this.copy_function = name;
780 public string get_default_free_function () {
781 return get_lower_case_cprefix () + "free";
784 public override string? get_free_function () {
785 if (free_function == null) {
786 free_function = get_default_free_function ();
788 return free_function;
791 public void set_free_function (string name) {
792 this.free_function = name;
795 public override bool is_subtype_of (TypeSymbol t) {
796 if (this == t) {
797 return true;
800 foreach (DataType base_type in base_types) {
801 if (base_type.data_type != null && base_type.data_type.is_subtype_of (t)) {
802 return true;
806 return false;
809 public override void replace_type (DataType old_type, DataType new_type) {
810 for (int i = 0; i < base_types.size; i++) {
811 if (base_types[i] == old_type) {
812 base_types[i] = new_type;
813 return;
818 private void get_all_prerequisites (Interface iface, Gee.List<TypeSymbol> list) {
819 foreach (DataType prereq in iface.get_prerequisites ()) {
820 TypeSymbol type = prereq.data_type;
821 /* skip on previous errors */
822 if (type == null) {
823 continue;
826 list.add (type);
827 if (type is Interface) {
828 get_all_prerequisites ((Interface) type, list);
834 private bool class_is_a (Class cl, TypeSymbol t) {
835 if (cl == t) {
836 return true;
839 foreach (DataType base_type in cl.get_base_types ()) {
840 if (base_type.data_type is Class) {
841 if (class_is_a ((Class) base_type.data_type, t)) {
842 return true;
844 } else if (base_type.data_type == t) {
845 return true;
849 return false;
852 public override bool check (SemanticAnalyzer analyzer) {
853 if (checked) {
854 return !error;
857 checked = true;
859 process_attributes ();
861 var old_source_file = analyzer.current_source_file;
862 var old_symbol = analyzer.current_symbol;
863 var old_class = analyzer.current_class;
865 if (source_reference != null) {
866 analyzer.current_source_file = source_reference.file;
868 analyzer.current_symbol = this;
869 analyzer.current_class = this;
871 foreach (DataType base_type_reference in get_base_types ()) {
872 if (!base_type_reference.check (analyzer)) {
873 error = true;
874 return false;
877 if (!(base_type_reference is ObjectType)) {
878 error = true;
879 Report.error (source_reference, "base type `%s` of class `%s` is not an object type".printf (base_type_reference.to_string (), get_full_name ()));
880 return false;
883 // check whether base type is at least as accessible as the class
884 if (!analyzer.is_type_accessible (this, base_type_reference)) {
885 error = true;
886 Report.error (source_reference, "base type `%s` is less accessible than class `%s`".printf (base_type_reference.to_string (), get_full_name ()));
887 return false;
890 analyzer.current_source_file.add_type_dependency (base_type_reference, SourceFileDependencyType.HEADER_FULL);
893 foreach (DataType type in base_types) {
894 type.check (analyzer);
897 foreach (TypeParameter p in get_type_parameters ()) {
898 p.check (analyzer);
901 /* process enums first to avoid order problems in C code */
902 foreach (Enum en in enums) {
903 en.check (analyzer);
906 foreach (Field f in fields) {
907 f.check (analyzer);
910 foreach (Constant c in constants) {
911 c.check (analyzer);
914 foreach (Method m in methods) {
915 m.check (analyzer);
918 foreach (Property prop in properties) {
919 prop.check (analyzer);
922 foreach (Signal sig in signals) {
923 sig.check (analyzer);
926 if (constructor != null) {
927 constructor.check (analyzer);
930 if (class_constructor != null) {
931 class_constructor.check (analyzer);
934 if (static_constructor != null) {
935 static_constructor.check (analyzer);
938 if (destructor != null) {
939 destructor.check (analyzer);
942 if (static_destructor != null) {
943 static_destructor.check (analyzer);
946 if (class_destructor != null) {
947 class_destructor.check (analyzer);
950 foreach (Class cl in classes) {
951 cl.check (analyzer);
954 foreach (Struct st in structs) {
955 st.check (analyzer);
958 foreach (Delegate d in delegates) {
959 d.check (analyzer);
962 /* compact classes cannot implement interfaces */
963 if (is_compact) {
964 foreach (DataType base_type in get_base_types ()) {
965 if (base_type.data_type is Interface) {
966 error = true;
967 Report.error (source_reference, "compact classes `%s` may not implement interfaces".printf (get_full_name ()));
972 /* gather all prerequisites */
973 Gee.List<TypeSymbol> prerequisites = new ArrayList<TypeSymbol> ();
974 foreach (DataType base_type in get_base_types ()) {
975 if (base_type.data_type is Interface) {
976 get_all_prerequisites ((Interface) base_type.data_type, prerequisites);
979 /* check whether all prerequisites are met */
980 Gee.List<string> missing_prereqs = new ArrayList<string> ();
981 foreach (TypeSymbol prereq in prerequisites) {
982 if (!class_is_a (this, prereq)) {
983 missing_prereqs.insert (0, prereq.get_full_name ());
986 /* report any missing prerequisites */
987 if (missing_prereqs.size > 0) {
988 error = true;
990 string error_string = "%s: some prerequisites (".printf (get_full_name ());
991 bool first = true;
992 foreach (string s in missing_prereqs) {
993 if (first) {
994 error_string = "%s`%s'".printf (error_string, s);
995 first = false;
996 } else {
997 error_string = "%s, `%s'".printf (error_string, s);
1000 error_string += ") are not met";
1001 Report.error (source_reference, error_string);
1004 /* VAPI classes don't have to specify overridden methods */
1005 if (!external_package) {
1006 /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */
1007 foreach (DataType base_type in get_base_types ()) {
1008 if (base_type.data_type is Interface) {
1009 Interface iface = (Interface) base_type.data_type;
1011 if (base_class != null && base_class.is_subtype_of (iface)) {
1012 // reimplementation of interface, class is not required to reimplement all methods
1013 break;
1016 /* We do not need to do expensive equality checking here since this is done
1017 * already. We only need to guarantee the symbols are present.
1020 /* check methods */
1021 foreach (Method m in iface.get_methods ()) {
1022 if (m.is_abstract) {
1023 Symbol sym = null;
1024 var base_class = this;
1025 while (base_class != null && !(sym is Method)) {
1026 sym = base_class.scope.lookup (m.name);
1027 base_class = base_class.base_class;
1029 if (!(sym is Method)) {
1030 error = true;
1031 Report.error (source_reference, "`%s' does not implement interface method `%s'".printf (get_full_name (), m.get_full_name ()));
1036 /* check properties */
1037 foreach (Property prop in iface.get_properties ()) {
1038 if (prop.is_abstract) {
1039 Symbol sym = null;
1040 var base_class = this;
1041 while (base_class != null && !(sym is Property)) {
1042 sym = base_class.scope.lookup (prop.name);
1043 base_class = base_class.base_class;
1045 if (!(sym is Property)) {
1046 error = true;
1047 Report.error (source_reference, "`%s' does not implement interface property `%s'".printf (get_full_name (), prop.get_full_name ()));
1054 /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */
1055 if (!is_abstract) {
1056 var base_class = base_class;
1057 while (base_class != null && base_class.is_abstract) {
1058 foreach (Method base_method in base_class.get_methods ()) {
1059 if (base_method.is_abstract) {
1060 var override_method = analyzer.symbol_lookup_inherited (this, base_method.name) as Method;
1061 if (override_method == null || !override_method.overrides) {
1062 error = true;
1063 Report.error (source_reference, "`%s' does not implement abstract method `%s'".printf (get_full_name (), base_method.get_full_name ()));
1067 foreach (Property base_property in base_class.get_properties ()) {
1068 if (base_property.is_abstract) {
1069 var override_property = analyzer.symbol_lookup_inherited (this, base_property.name) as Property;
1070 if (override_property == null || !override_property.overrides) {
1071 error = true;
1072 Report.error (source_reference, "`%s' does not implement abstract property `%s'".printf (get_full_name (), base_property.get_full_name ()));
1076 base_class = base_class.base_class;
1081 analyzer.current_source_file = old_source_file;
1082 analyzer.current_symbol = old_symbol;
1083 analyzer.current_class = old_class;
1085 return !error;