fix method compatibility checks, based on patch by Andreas Brauchli, fixes
authorJuerg Billeter <j@bitron.ch>
Sun, 13 Apr 2008 20:20:54 +0000 (20:20 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sun, 13 Apr 2008 20:20:54 +0000 (20:20 +0000)
2008-04-13  Juerg Billeter  <j@bitron.ch>

* vala/valamethod.vala, vala/valasemanticanalyzer.vala:
  fix method compatibility checks,
  based on patch by Andreas Brauchli, fixes bug 527751

svn path=/trunk/; revision=1217

ChangeLog
vala/valamethod.vala
vala/valasemanticanalyzer.vala

index d493ed9..9744bc7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2008-04-13  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valamethod.vala, vala/valasemanticanalyzer.vala:
+         fix method compatibility checks,
+         based on patch by Andreas Brauchli, fixes bug 527751
+
+2008-04-13  Jürg Billeter  <j@bitron.ch>
+
        * vapi/glib-2.0.vapi: add GDatalist bindings,
          patch by Marc-Andre Lureau, fixes bug 527243
 
index a108aa0..1a33bf6 100644 (file)
@@ -379,44 +379,55 @@ public class Vala.Method : Member {
                        }
                }
        }
-       
+
        /**
-        * Checks whether the arguments and return type of the specified method
-        * matches this method.
+        * Checks whether the parameters and return type of this method are
+        * compatible with the specified method
         *
-        * @param m a method
-        * @return  true if the specified method is compatible to this method
+        * @param base_method a method
+        * @param invalid_match error string about which check failed
+        * @return true if the specified method is compatible to this method
         */
-       public bool equals (Method m2) {
-               if (!m2.return_type.equals (return_type)) {
+       public bool compatible (Method base_method, out string? invalid_match) {
+               if (!return_type.equals (base_method.return_type)) {
+                       invalid_match = "incompatible return type";
                        return false;
                }
                
-               Iterator<FormalParameter> method_params_it = m2.get_parameters ().iterator ();
-               foreach (FormalParameter param in parameters) {
-                       /* method may not expect less arguments */
+               Iterator<FormalParameter> method_params_it = parameters.iterator ();
+               int param_index = 1;
+               foreach (FormalParameter base_param in base_method.parameters) {
+                       /* this method may not expect less arguments */
                        if (!method_params_it.next ()) {
+                               invalid_match = "too few parameters";
                                return false;
                        }
                        
-                       if (!method_params_it.get ().type_reference.equals (param.type_reference)) {
+                       if (!base_param.type_reference.equals (method_params_it.get ().type_reference)) {
+                               invalid_match = "incompatible type of parameter %d".printf (param_index);
                                return false;
                        }
+                       param_index++;
                }
                
-               /* method may not expect more arguments */
+               /* this method may not expect more arguments */
                if (method_params_it.next ()) {
+                       invalid_match = "too many parameters";
                        return false;
                }
 
-               Iterator<DataType> method_error_domains_it = m2.get_error_domains ().iterator ();
-               foreach (DataType error_domain in error_domains) {
-                       /* method may not have less error domains */
-                       if (!method_error_domains_it.next ()) {
-                               return false;
+               /* this method may throw more but not less errors than the base method */
+               foreach (DataType method_error_domain in error_domains) {
+                       bool match = false;
+                       foreach (DataType base_method_error_domain in base_method.error_domains) {
+                               if (method_error_domain.compatible (base_method_error_domain)) {
+                                       match = true;
+                                       break;
+                               }
                        }
 
-                       if (!method_error_domains_it.get ().equals (error_domain)) {
+                       if (!match) {
+                               invalid_match = "incompatible error domain `%s'".printf (method_error_domain.to_string ());
                                return false;
                        }
                }
index 2dc5330..ecebf76 100644 (file)
@@ -458,9 +458,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                if (sym is Method) {
                        var base_method = (Method) sym;
                        if (base_method.is_abstract || base_method.is_virtual) {
-                               if (!m.equals (base_method)) {
+                               string invalid_match;
+                               if (!m.compatible (base_method, out invalid_match)) {
                                        m.error = true;
-                                       Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.get_full_name (), base_method.get_full_name ()));
+                                       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;
                                }
 
@@ -482,9 +483,10 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                if (sym is Method) {
                                        var base_method = (Method) sym;
                                        if (base_method.is_abstract) {
-                                               if (!m.equals (base_method)) {
+                                               string invalid_match;
+                                               if (!m.compatible (base_method, out invalid_match)) {
                                                        m.error = true;
-                                                       Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.get_full_name (), base_method.get_full_name ()));
+                                                       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;
                                                }