From: Juerg Billeter Date: Wed, 28 May 2008 16:07:50 +0000 (+0000) Subject: Compute Method.base_method and Property.base_property when needed so that X-Git-Tag: VALA_0_3_3~98 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b8d57a0394926a1a3582c15a0a50c24fb6da749;p=platform%2Fupstream%2Fvala.git Compute Method.base_method and Property.base_property when needed so that 2008-05-28 Juerg Billeter * 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 --- diff --git a/ChangeLog b/ChangeLog index 420b4f3..87e6cd3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2008-05-28 Jürg Billeter + * 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 + * ccode/valaccodecastexpression.vala: Use parentheses to ensure that the full expression is cast diff --git a/gobject/valagidlwriter.vala b/gobject/valagidlwriter.vala index e42058c..a57ce92 100644 --- a/gobject/valagidlwriter.vala +++ b/gobject/valagidlwriter.vala @@ -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; } diff --git a/vala/valainterfacewriter.vala b/vala/valainterfacewriter.vala index a787da3..6fe154b 100644 --- a/vala/valainterfacewriter.vala +++ b/vala/valainterfacewriter.vala @@ -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; } diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 6dca30b..6b002a9 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -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; + } + } + } + } + } } diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala index 884c8bb..cc277e3 100644 --- a/vala/valaproperty.vala +++ b/vala/valaproperty.vala @@ -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; + } + } + } + } + } } diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index c6b4961..9832582 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -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 */