3 * Copyright (C) 2006-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
27 * Represents a class declaration in the source code.
29 public class Vala
.Class
: ObjectTypeSymbol
{
31 * Specifies the base class.
33 public Class base_class
{ get; set; }
36 * Specifies whether this class is abstract. Abstract classes may not be
39 public bool is_abstract
{ get; set; }
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
{
48 if (base_class
!= null) {
49 return base_class
.is_compact
;
59 * Instances of immutable classes are immutable after construction.
61 public bool is_immutable
{
63 if (base_class
!= null) {
64 return base_class
.is_immutable
;
69 _is_immutable
= value
;
74 * Specifies wheather the ref function returns void instead of the
77 public bool ref_function_void
{ get; set; }
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
84 public string? type_check_function
{ get; set; }
87 * Specifies whether this class has private fields.
89 public bool has_private_fields
{ get; private set; }
92 * Specifies whether this class has class fields.
94 public bool has_class_private_fields
{ get; private set; }
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
> ();
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
; }
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
{
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
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
) {
259 scope
.add (c
.name
, c
);
263 * Adds the specified field as a member to this class.
267 public void add_field (Field 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.
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
;
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
));
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
) {
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.
392 public void add_class (Class cl
) {
394 scope
.add (cl
.name
, cl
);
398 * Adds the specified struct as an inner struct.
402 public void add_struct (Struct st
) {
404 scope
.add (st
.name
, st
);
408 * Adds the specified enum as an inner enum.
412 public void add_enum (Enum 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
) {
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 ()) {
440 /* process enums first to avoid order problems in C code */
441 foreach (Enum en
in enums
) {
445 foreach (Field f
in fields
) {
449 foreach (Constant c
in constants
) {
453 foreach (Method m
in methods
) {
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
) {
493 foreach (Struct st
in structs
) {
497 foreach (Delegate d
in delegates
) {
502 public override string get_cprefix () {
506 public override string get_cname (bool const_type
= false) {
508 if (const_cname
!= null) {
510 } else if (is_immutable
) {
511 return "const " + get_cname (false);
516 var attr
= get_attribute ("CCode");
518 cname
= attr
.get_string ("cname");
521 cname
= get_default_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
) {
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
) {
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 () {
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") {
653 } else if (a
.name
== "Immutable") {
659 public override string?
get_type_id () {
660 if (type_id
== null) {
662 type_id
= get_upper_case_cname ("TYPE_");
664 type_id
= "G_TYPE_POINTER";
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 ();
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 ();
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 ();
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) {
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 ();
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 ();
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
) {
800 foreach (DataType base_type
in base_types
) {
801 if (base_type
.data_type
!= null && base_type
.data_type
.is_subtype_of (t
)) {
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
;
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 */
827 if (type is Interface
) {
828 get_all_prerequisites ((Interface
) type
, list
);
834 private bool class_is_a (Class cl
, TypeSymbol t
) {
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
)) {
844 } else if (base_type
.data_type
== t
) {
852 public override bool check (SemanticAnalyzer analyzer
) {
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
)) {
877 if (!(base_type_reference is ObjectType
)) {
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 ()));
883 // check whether base type is at least as accessible as the class
884 if (!analyzer
.is_type_accessible (this
, base_type_reference
)) {
886 Report
.error (source_reference
, "base type `%s` is less accessible than class `%s`".printf (base_type_reference
.to_string (), get_full_name ()));
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 ()) {
901 /* process enums first to avoid order problems in C code */
902 foreach (Enum en
in enums
) {
906 foreach (Field f
in fields
) {
910 foreach (Constant c
in constants
) {
914 foreach (Method m
in methods
) {
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
) {
954 foreach (Struct st
in structs
) {
958 foreach (Delegate d
in delegates
) {
962 /* compact classes cannot implement interfaces */
964 foreach (DataType base_type
in get_base_types ()) {
965 if (base_type
.data_type is Interface
) {
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) {
990 string error_string
= "%s: some prerequisites (".printf (get_full_name ());
992 foreach (string s
in missing_prereqs
) {
994 error_string
= "%s`%s'".printf (error_string
, s
);
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
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.
1021 foreach (Method m
in iface
.get_methods ()) {
1022 if (m
.is_abstract
) {
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
)) {
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
) {
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
)) {
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 */
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
) {
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
) {
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
;