Compute Method.base_method and Property.base_property when needed so that
authorJuerg Billeter <j@bitron.ch>
Wed, 28 May 2008 16:07:50 +0000 (16:07 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Wed, 28 May 2008 16:07:50 +0000 (16:07 +0000)
2008-05-28  Juerg Billeter  <j@bitron.ch>

* vala/valainterfacewriter.vala:
* vala/valamethod.vala:
* vala/valaproperty.vala:
* vala/valasemanticanalyzer.vala:
* gobject/valagidlwriter.vala:

Compute Method.base_method and Property.base_property when needed
so that we can already use them in the semantic analyzer

svn path=/trunk/; revision=1460

ChangeLog
gobject/valagidlwriter.vala
vala/valainterfacewriter.vala
vala/valamethod.vala
vala/valaproperty.vala
vala/valasemanticanalyzer.vala

index 420b4f3..87e6cd3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2008-05-28  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valainterfacewriter.vala:
+       * vala/valamethod.vala:
+       * vala/valaproperty.vala:
+       * vala/valasemanticanalyzer.vala:
+       * gobject/valagidlwriter.vala:
+
+       Compute Method.base_method and Property.base_property when needed
+       so that we can already use them in the semantic analyzer
+
+2008-05-28  Jürg Billeter  <j@bitron.ch>
+
        * ccode/valaccodecastexpression.vala:
 
        Use parentheses to ensure that the full expression is cast
index e42058c..a57ce92 100644 (file)
@@ -426,7 +426,7 @@ public class Vala.GIdlWriter : CodeVisitor {
        }
 
        public override void visit_property (Property prop) {
-               if (!check_accessibility (prop) || prop.overrides || prop.base_interface_property != null) {
+               if (!check_accessibility (prop) || prop.overrides || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
                        return;
                }
 
index a787da3..6fe154b 100644 (file)
@@ -743,7 +743,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
        }
 
        public override void visit_property (Property prop) {
-               if (!check_accessibility (prop) || prop.overrides || prop.base_interface_property != null) {
+               if (!check_accessibility (prop) || prop.overrides || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
                        return;
                }
 
index 6dca30b..6b002a9 100644 (file)
@@ -129,12 +129,22 @@ public class Vala.Method : Member {
         * Reference must be weak as virtual methods set base_method to
         * themselves.
         */
-       public weak Method base_method { get; set; }
+       public Method base_method {
+               get {
+                       find_base_methods ();
+                       return _base_method;
+               }
+       }
        
        /**
         * Specifies the abstract interface method this method implements.
         */
-       public Method base_interface_method { get; set; }
+       public Method base_interface_method {
+               get {
+                       find_base_methods ();
+                       return _base_interface_method;
+               }
+       }
        
        /**
         * Specifies the generated `this' parameter for instance methods.
@@ -194,6 +204,10 @@ public class Vala.Method : Member {
        private DataType _return_type;
        private Block _body;
 
+       private weak Method _base_method;
+       private Method _base_interface_method;
+       private bool base_methods_valid;
+
        /**
         * Creates a new method.
         *
@@ -491,4 +505,75 @@ public class Vala.Method : Member {
        public override CodeBinding? create_code_binding (CodeGenerator codegen) {
                return codegen.create_method_binding (this);
        }
+
+       private void find_base_methods () {
+               if (base_methods_valid) {
+                       return;
+               }
+
+               if (parent_symbol is Class) {
+                       /* VAPI classes don't specify overridden methods */
+                       if (!parent_symbol.external_package) {
+                               if (!(this is CreationMethod)) {
+                                       find_base_interface_method ((Class) parent_symbol);
+                                       if (is_virtual || overrides) {
+                                               find_base_class_method ((Class) parent_symbol);
+                                       }
+                               }
+                       } else if (is_virtual || is_abstract) {
+                               _base_method = this;
+                       }
+               } else if (parent_symbol is Interface) {
+                       if (is_virtual || is_abstract) {
+                               _base_interface_method = this;
+                       }
+               }
+
+               base_methods_valid = true;
+       }
+
+       private void find_base_class_method (Class cl) {
+               var sym = cl.scope.lookup (name);
+               if (sym is Method) {
+                       var base_method = (Method) sym;
+                       if (base_method.is_abstract || base_method.is_virtual) {
+                               string invalid_match;
+                               if (!compatible (base_method, out invalid_match)) {
+                                       error = true;
+                                       Report.error (source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method.get_full_name (), invalid_match));
+                                       return;
+                               }
+
+                               _base_method = base_method;
+                               return;
+                       }
+               }
+
+               if (cl.base_class != null) {
+                       find_base_class_method (cl.base_class);
+               }
+       }
+
+       private void find_base_interface_method (Class cl) {
+               // FIXME report error if multiple possible base methods are found
+               foreach (DataType type in cl.get_base_types ()) {
+                       if (type.data_type is Interface) {
+                               var sym = type.data_type.scope.lookup (name);
+                               if (sym is Method) {
+                                       var base_method = (Method) sym;
+                                       if (base_method.is_abstract || base_method.is_virtual) {
+                                               string invalid_match;
+                                               if (!compatible (base_method, out invalid_match)) {
+                                                       error = true;
+                                                       Report.error (source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method.get_full_name (), invalid_match));
+                                                       return;
+                                               }
+
+                                               _base_interface_method = base_method;
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       }
 }
index 884c8bb..cc277e3 100644 (file)
@@ -105,12 +105,22 @@ public class Vala.Property : Member, Lockable {
         * Reference must be weak as virtual properties set base_property to
         * themselves.
         */
-       public weak Property base_property { get; set; }
+       public Property base_property {
+               get {
+                       find_base_properties ();
+                       return _base_property;
+               }
+       }
        
        /**
         * Specifies the abstract interface property this property implements.
         */
-       public Property base_interface_property { get; set; }
+       public Property base_interface_property {
+               get {
+                       find_base_properties ();
+                       return _base_interface_property;
+               }
+       }
 
        /**
         * Specifies the default value of this property.
@@ -150,6 +160,10 @@ public class Vala.Property : Member, Lockable {
        private string? _nick;
        private string? _blurb;
 
+       private weak Property _base_property;
+       private Property _base_interface_property;
+       private bool base_properties_valid;
+
        /**
         * Creates a new property.
         *
@@ -296,4 +310,71 @@ public class Vala.Property : Member, Lockable {
                        property_type = new_type;
                }
        }
+
+       private void find_base_properties () {
+               if (base_properties_valid) {
+                       return;
+               }
+
+               if (parent_symbol is Class) {
+                       /* VAPI classes don't specify overridden properties */
+                       if (!parent_symbol.external_package) {
+                               find_base_interface_property ((Class) parent_symbol);
+                               if (is_virtual || overrides) {
+                                       find_base_class_property ((Class) parent_symbol);
+                               }
+                       } else if (is_virtual || is_abstract) {
+                               _base_property = this;
+                       }
+               } else if (parent_symbol is Interface) {
+                       if (is_virtual || is_abstract) {
+                               _base_interface_property = this;
+                       }
+               }
+
+               base_properties_valid = true;
+       }
+
+       private void find_base_class_property (Class cl) {
+               var sym = cl.scope.lookup (name);
+               if (sym is Property) {
+                       var base_property = (Property) sym;
+                       if (base_property.is_abstract || base_property.is_virtual) {
+                               if (!equals (base_property)) {
+                                       error = true;
+                                       Report.error (source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (get_full_name (), base_property.get_full_name ()));
+                                       return;
+                               }
+
+                               _base_property = base_property;
+                               return;
+                       }
+               }
+
+               if (cl.base_class != null) {
+                       find_base_class_property (cl.base_class);
+               }
+       }
+
+       private void find_base_interface_property (Class cl) {
+               // FIXME report error if multiple possible base properties are found
+               foreach (DataType type in cl.get_base_types ()) {
+                       if (type.data_type is Interface) {
+                               var sym = type.data_type.scope.lookup (name);
+                               if (sym is Property) {
+                                       var base_property = (Property) sym;
+                                       if (base_property.is_abstract) {
+                                               if (!equals (base_property)) {
+                                                       error = true;
+                                                       Report.error (source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (get_full_name (), base_property.get_full_name ()));
+                                                       return;
+                                               }
+
+                                               _base_interface_property = base_property;
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       }
 }
index c6b4961..9832582 100644 (file)
@@ -417,30 +417,13 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        current_return_type = up_method.return_type;
                }
 
-               if (current_symbol is Class) {
-                       /* VAPI classes don't specify overridden methods */
-                       if (!current_symbol.external_package) {
-                               if (!(m is CreationMethod)) {
-                                       find_base_interface_method (m, (Class) current_symbol);
-                                       if (m.is_virtual || m.overrides) {
-                                               find_base_class_method (m, (Class) current_symbol);
-                                               if (m.base_method == null) {
-                                                       Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.get_full_name ()));
-                                               }
-                                       }
-                               }
-                       } else if (m.is_virtual || m.is_abstract) {
-                               m.base_method = m;
-                       }
-               } else if (current_symbol is Interface) {
-                       if (m.is_virtual || m.is_abstract) {
-                               m.base_interface_method = m;
-                       }
-               } else if (current_symbol is Struct) {
+               if (current_symbol is Struct) {
                        if (m.is_abstract || m.is_virtual || m.overrides) {
                                Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ()));
                                return;
                        }
+               } else if (m.overrides && m.base_method == null) {
+                       Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.get_full_name ()));
                }
 
                // check whether return type is at least as accessible as the method
@@ -494,51 +477,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
-       private void find_base_class_method (Method m, Class cl) {
-               var sym = cl.scope.lookup (m.name);
-               if (sym is Method) {
-                       var base_method = (Method) sym;
-                       if (base_method.is_abstract || base_method.is_virtual) {
-                               string invalid_match;
-                               if (!m.compatible (base_method, out invalid_match)) {
-                                       m.error = true;
-                                       Report.error (m.source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (m.get_full_name (), base_method.get_full_name (), invalid_match));
-                                       return;
-                               }
-
-                               m.base_method = base_method;
-                               return;
-                       }
-               }
-
-               if (cl.base_class != null) {
-                       find_base_class_method (m, cl.base_class);
-               }
-       }
-
-       private void find_base_interface_method (Method m, Class cl) {
-               // FIXME report error if multiple possible base methods are found
-               foreach (DataType type in cl.get_base_types ()) {
-                       if (type.data_type is Interface) {
-                               var sym = type.data_type.scope.lookup (m.name);
-                               if (sym is Method) {
-                                       var base_method = (Method) sym;
-                                       if (base_method.is_abstract || base_method.is_virtual) {
-                                               string invalid_match;
-                                               if (!m.compatible (base_method, out invalid_match)) {
-                                                       m.error = true;
-                                                       Report.error (m.source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (m.get_full_name (), base_method.get_full_name (), invalid_match));
-                                                       return;
-                                               }
-
-                                               m.base_interface_method = base_method;
-                                               return;
-                                       }
-                               }
-                       }
-               }
-       }
-
        public override void visit_creation_method (CreationMethod m) {
                if (m.type_name != null && m.type_name != current_symbol.name) {
                        // type_name is null for constructors generated by GIdlParser
@@ -622,49 +560,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return true;
        }
 
-       private void find_base_class_property (Property prop, Class cl) {
-               var sym = cl.scope.lookup (prop.name);
-               if (sym is Property) {
-                       var base_property = (Property) sym;
-                       if (base_property.is_abstract || base_property.is_virtual) {
-                               if (!prop.equals (base_property)) {
-                                       prop.error = true;
-                                       Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.get_full_name (), base_property.get_full_name ()));
-                                       return;
-                               }
-
-                               prop.base_property = base_property;
-                               return;
-                       }
-               }
-
-               if (cl.base_class != null) {
-                       find_base_class_property (prop, cl.base_class);
-               }
-       }
-
-       private void find_base_interface_property (Property prop, Class cl) {
-               // FIXME report error if multiple possible base properties are found
-               foreach (DataType type in cl.get_base_types ()) {
-                       if (type.data_type is Interface) {
-                               var sym = type.data_type.scope.lookup (prop.name);
-                               if (sym is Property) {
-                                       var base_property = (Property) sym;
-                                       if (base_property.is_abstract) {
-                                               if (!prop.equals (base_property)) {
-                                                       prop.error = true;
-                                                       Report.error (prop.source_reference, "Type and/or accessors of overriding property `%s' do not match overridden property `%s'.".printf (prop.get_full_name (), base_property.get_full_name ()));
-                                                       return;
-                                               }
-
-                                               prop.base_interface_property = base_property;
-                                               return;
-                                       }
-                               }
-                       }
-               }
-       }
-
        public override void visit_property (Property prop) {
                current_symbol = prop;
 
@@ -706,20 +601,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
                current_source_file.add_type_dependency (prop.property_type, SourceFileDependencyType.SOURCE);
 
-               if (prop.parent_symbol is Class) {
-                       var cl = (Class) prop.parent_symbol;
-
-                       /* VAPI classes don't specify overridden properties */
-                       if (!cl.external_package) {
-                               find_base_interface_property (prop, cl);
-                               if (prop.is_virtual || prop.overrides) {
-                                       find_base_class_property (prop, cl);
-                                       if (prop.base_property == null) {
-                                               prop.error = true;
-                                               Report.error (prop.source_reference, "%s: no suitable property found to override".printf (prop.get_full_name ()));
-                                       }
-                               }
-                       }
+               if (prop.overrides && prop.base_property == null) {
+                       Report.error (prop.source_reference, "%s: no suitable property found to override".printf (prop.get_full_name ()));
                }
 
                /* construct properties must be public */