]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Collect error_types on demand to allow transformations
authorLuca Bruno <lucabru@src.gnome.org>
Sun, 7 Aug 2011 10:44:41 +0000 (12:44 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 23 Oct 2018 16:45:45 +0000 (18:45 +0200)
43 files changed:
codegen/valaccodedelegatemodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagasyncmodule.vala
codegen/valagdbusclientmodule.vala
codegen/valagdbusservermodule.vala
codegen/valagerrormodule.vala
vala/valaassignment.vala
vala/valabinaryexpression.vala
vala/valablock.vala
vala/valacallabletype.vala
vala/valacastexpression.vala
vala/valacodenode.vala
vala/valacodewriter.vala
vala/valaconditionalexpression.vala
vala/valaconstructor.vala
vala/valacreationmethod.vala
vala/valadeclarationstatement.vala
vala/valadelegate.vala
vala/valadelegatetype.vala
vala/valaelementaccess.vala
vala/valaexpressionstatement.vala
vala/valaflowanalyzer.vala
vala/valaforeachstatement.vala
vala/valagirparser.vala
vala/valaifstatement.vala
vala/valalambdaexpression.vala
vala/valaloop.vala
vala/valamemberaccess.vala
vala/valamethod.vala
vala/valamethodcall.vala
vala/valaobjectcreationexpression.vala
vala/valaparser.vala
vala/valapointerindirection.vala
vala/valapropertyaccessor.vala
vala/valareturnstatement.vala
vala/valastatementlist.vala
vala/valaswitchsection.vala
vala/valaswitchstatement.vala
vala/valathrowstatement.vala
vala/valatrystatement.vala
vala/valaunaryexpression.vala
valadoc/symbolresolver.vala
vapigen/valagidlparser.vala

index 042e2be0538e52e826d7a475ca6f8e097ea3bda8..4783029695a3d680eb76f27e2a969d2e40575c28 100644 (file)
@@ -115,7 +115,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        var cparam = new CCodeParameter ("user_data", "gpointer");
                        cfundecl.add_parameter (cparam);
                }
-               if (d.get_error_types ().size > 0) {
+               if (d.tree_can_fail) {
                        var cparam = new CCodeParameter ("error", "GError**");
                        cfundecl.add_parameter (cparam);
                }
@@ -263,7 +263,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        cparam_map.set (get_param_pos (-3), cparam);
                }
 
-               if (m.get_error_types ().size > 0) {
+               if (m.tree_can_fail) {
                        var cparam = new CCodeParameter ("error", "GError**");
                        cparam_map.set (get_param_pos (-1), cparam);
                }
@@ -387,7 +387,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        carg_map.set (get_param_pos (-3), new CCodeIdentifier ("result"));
                }
 
-               if (m.get_error_types ().size > 0) {
+               if (m.tree_can_fail) {
                        carg_map.set (get_param_pos (-1), new CCodeIdentifier ("error"));
                }
 
index b536e749f9e9c74858db564bfb7f8e7a4298636b..cdedbee6757850a8ee21a781c5126e39a3da5609 100644 (file)
@@ -110,7 +110,9 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                }
 
                if (m.has_error_type_parameter ()) {
-                       foreach (DataType error_type in m.get_error_types ()) {
+                       var error_types = new ArrayList<DataType> ();
+                       m.get_error_types (error_types);
+                       foreach (DataType error_type in error_types) {
                                generate_type_declaration (error_type, decl_space);
                        }
 
index f234afdb440929437a92bfe5a2e36d159ded6de6..89da47c404f81e7f6b1f38f72f17308eb0b93bab 100644 (file)
@@ -615,7 +615,7 @@ public class Vala.GAsyncModule : GtkModule {
                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer"));
                ccall.add_argument (async_result_cast);
 
-               if (m.get_error_types ().size > 0) {
+               if (m.tree_can_fail) {
                        ccall.add_argument (new CCodeIdentifier ("error"));
                } else {
                        ccall.add_argument (new CCodeConstant ("NULL"));
@@ -633,7 +633,7 @@ public class Vala.GAsyncModule : GtkModule {
                }
 
                // If a task is cancelled, g_task_propagate_pointer returns NULL
-               if (m.get_error_types ().size > 0 || has_cancellable) {
+               if (m.tree_can_fail || has_cancellable) {
                        var is_null = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), data_var);
 
                        ccode.open_if (is_null);
index 32a45de2120b21fa6ceda64633bccc7b863164f2..91bdce3637edf694c95a3794356cb8648b639568 100644 (file)
@@ -566,7 +566,7 @@ public class Vala.GDBusClientModule : GDBusModule {
                        ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
                }
 
-               bool has_error_argument = (m.get_error_types ().size > 0);
+               bool has_error_argument = m.tree_can_fail;
                CCodeExpression error_argument;
                if (has_error_argument) {
                        error_argument = new CCodeIdentifier ("error");
@@ -593,7 +593,9 @@ public class Vala.GDBusClientModule : GDBusModule {
                        }
 
                        // register errors
-                       foreach (var error_type in m.get_error_types ()) {
+                       var error_types = new ArrayList<DataType> ();
+                       m.get_error_types (error_types);
+                       foreach (var error_type in error_types) {
                                var errtype = (ErrorType) error_type;
                                if (errtype.error_domain != null) {
                                        ccode.add_expression (new CCodeIdentifier (get_ccode_upper_case_name (errtype.error_domain)));
index e1984e24f796ee27431be86765e8c41eef77f93c..6b2f31ab45dde78926b8dc6d4c9544f9e9e8a040 100644 (file)
@@ -273,7 +273,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
                }
 
                if (!m.coroutine || ready) {
-                       if (m.get_error_types ().size > 0) {
+                       if (m.tree_can_fail) {
                                ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
                        }
                }
@@ -285,7 +285,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
                                ccode.add_assignment (new CCodeIdentifier ("result"), ccall);
                        }
 
-                       if (m.get_error_types ().size > 0) {
+                       if (m.tree_can_fail) {
                                ccode.open_if (new CCodeIdentifier ("error"));
 
                                var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_return_gerror"));
index ea8367fd361a924f6f006287f5bd8d610af3f7c6..a0cefb9d11c0eb5e751173244cd071adcaa61848 100644 (file)
@@ -191,9 +191,7 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                        }
 
                        var error_types = new ArrayList<DataType> ();
-                       foreach (DataType node_error_type in node.get_error_types ()) {
-                               error_types.add (node_error_type);
-                       }
+                       node.get_error_types (error_types);
 
                        bool has_general_catch_clause = false;
 
@@ -258,11 +256,13 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                                // should never happen with correct bindings
                                uncaught_error_statement (inner_error, true);
                        }
-               } else if (current_method != null && current_method.get_error_types ().size > 0) {
+               } else if (current_method != null && current_method.tree_can_fail) {
                        // current method can fail, propagate error
                        CCodeBinaryExpression ccond = null;
 
-                       foreach (DataType error_type in current_method.get_error_types ()) {
+                       var error_types = new ArrayList<DataType> ();
+                       current_method.get_error_types (error_types);
+                       foreach (DataType error_type in error_types) {
                                // If GLib.Error is allowed we propagate everything
                                if (error_type.equals (gerror_type)) {
                                        ccond = null;
index 98c9c77c1a87f54ce3fd5b08897a050e8e7c9b75..440ac5edca9ab0d874f5954afcc4fcfeaddbfa3b 100644 (file)
@@ -101,6 +101,11 @@ public class Vala.Assignment : Expression {
                return left.is_accessible (sym) && right.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               left.get_error_types (collection, source_reference);
+               right.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -388,9 +393,6 @@ public class Vala.Assignment : Expression {
                        value_type = null;
                }
 
-               add_error_types (left.get_error_types ());
-               add_error_types (right.get_error_types ());
-
                return !error;
        }
 
index be62ed64da8bf308d69fcee38414406ae24db6b2..1e24968aa28fb6717040e989ed3e0a8e5ab9e650 100644 (file)
@@ -154,6 +154,11 @@ public class Vala.BinaryExpression : Expression {
                return left.is_accessible (sym) && right.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               left.get_error_types (collection, source_reference);
+               right.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index cfe0e2498127bac5650048a983e29f5443aebf37..7419b5b9defeb79fe64986578ac4f3f2fa472a39 100644 (file)
@@ -170,17 +170,19 @@ public class Vala.Block : Symbol, Statement {
                        constant.active = false;
                }
 
-               // use get_statements () instead of statement_list to not miss errors within StatementList objects
-               foreach (Statement stmt in get_statements ()) {
-                       add_error_types (stmt.get_error_types ());
-               }
-
                context.analyzer.current_symbol = old_symbol;
                context.analyzer.insert_block = old_insert_block;
 
                return !error;
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               // use get_statements () instead of statement_list to not miss errors within StatementList objects
+               foreach (Statement stmt in get_statements ()) {
+                       stmt.get_error_types (collection, source_reference);
+               }
+       }
+
        public override void emit (CodeGenerator codegen) {
                codegen.visit_block (this);
        }
index 0642fa644f30c92b5813d8065c480dc1833eaf03..c604de8ecaa5c885d41ffe1055e52170fe7e61fd 100644 (file)
@@ -90,7 +90,8 @@ public abstract class Vala.CallableType : DataType {
                builder.append_c (')');
 
                // Append error-types
-               var error_types = get_error_types ();
+               var error_types = new ArrayList<DataType> ();
+               get_error_types (error_types);
                if (error_types.size > 0) {
                        builder.append (" throws ");
 
index 5c050be2a2dc81161fff91259682cb7280675dbd..18ed153b8a8888bfe29deba0570542d572d87051 100644 (file)
@@ -122,6 +122,10 @@ public class Vala.CastExpression : Expression {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               inner.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index e8ab35725c3d542ad3ba081fa343b998fa6471cb..216b5604f90cb05eb89ee226b53ff31412680459 100644 (file)
@@ -62,51 +62,18 @@ public abstract class Vala.CodeNode {
         * Specifies that this node or a child node may throw an exception.
         */
        public bool tree_can_fail {
-               get { return _error_types != null && _error_types.size > 0; }
+               get {
+                       var error_types = new ArrayList<DataType> ();
+                       get_error_types (error_types);
+                       return error_types.size > 0;
+               }
        }
 
-       private List<DataType> _error_types;
-       private static List<DataType> _empty_type_list;
        private AttributeCache[] attributes_cache;
 
        static int last_temp_nr = 0;
        static int next_attribute_cache_index = 0;
 
-       /**
-        * Specifies the exceptions that can be thrown by this node or a child node
-        */
-       public List<DataType> get_error_types () {
-               if (_error_types != null) {
-                       return _error_types;
-               }
-               if (_empty_type_list == null) {
-                       _empty_type_list = new ArrayList<DataType> ();
-               }
-               return _empty_type_list;
-       }
-
-       /**
-        * Adds an error type to the exceptions that can be thrown by this node
-        * or a child node
-        */
-       public void add_error_type (DataType error_type) {
-               if (_error_types == null) {
-                       _error_types = new ArrayList<DataType> ();
-               }
-               _error_types.add (error_type);
-               error_type.parent_node = this;
-       }
-
-       /**
-        * Adds a collection of error types to the exceptions that can be thrown by this node
-        * or a child node
-        */
-       public void add_error_types (List<DataType> error_types) {
-               foreach (DataType error_type in error_types) {
-                       add_error_type (error_type);
-               }
-       }
-
        /**
         * Visits this code node with the specified CodeVisitor.
         *
@@ -377,6 +344,9 @@ public abstract class Vala.CodeNode {
        public virtual void get_used_variables (Collection<Variable> collection) {
        }
 
+       public virtual void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+       }
+
        public static string get_temp_name () {
                return "." + (++last_temp_nr).to_string ();
        }
index a71a6a38299443b83618cd3fab5975fe27b09deb..38fc217f3ba8f9c3101b76eb99a28e2771346d43 100644 (file)
@@ -706,7 +706,9 @@ public class Vala.CodeWriter : CodeVisitor {
 
                write_params (cb.get_parameters ());
 
-               write_error_domains (cb.get_error_types ());
+               var error_types = new ArrayList<DataType> ();
+               cb.get_error_types (error_types);
+               write_error_domains (error_types);
 
                write_string (";");
 
@@ -794,7 +796,9 @@ public class Vala.CodeWriter : CodeVisitor {
 
                write_params (m.get_parameters ());
 
-               write_error_domains (m.get_error_types ());
+               var error_types = new ArrayList<DataType> ();
+               m.get_error_types (error_types);
+               write_error_domains (error_types);
 
                write_code_block (m.body);
 
index 98facaaed512ce60d3201a9f57c75c1798bb9d02..27f7d8618114ea41676e5a2265e8b5f148707ea7 100644 (file)
@@ -104,6 +104,12 @@ public class Vala.ConditionalExpression : Expression {
                return condition.is_accessible (sym) && true_expression.is_accessible (sym) && false_expression.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               condition.get_error_types (collection, source_reference);
+               true_expression.get_error_types (collection, source_reference);
+               false_expression.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index d16fc13a4677597afb18af0d24657ceaa587276a..ae8f19e8da8e9a43ce3fb384946f92973199be6e 100644 (file)
@@ -77,7 +77,9 @@ public class Vala.Constructor : Subroutine {
                        body.check (context);
                }
 
-               foreach (DataType body_error_type in body.get_error_types ()) {
+               var body_errors = new ArrayList<DataType> ();
+               body.get_error_types (body_errors);
+               foreach (DataType body_error_type in body_errors) {
                        if (!((ErrorType) body_error_type).dynamic_error) {
                                Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
                        }
index 198f031c17497d687ad9195ec572b46ab58801e1..ae8daab3853a5e046daa2528187e82d237baa616 100644 (file)
@@ -60,8 +60,10 @@ public class Vala.CreationMethod : Method {
                        param.accept (visitor);
                }
 
-               foreach (DataType error_type in get_error_types ()) {
-                       error_type.accept (visitor);
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
+                               error_type.accept (visitor);
+                       }
                }
 
                foreach (Expression precondition in get_preconditions ()) {
@@ -109,8 +111,10 @@ public class Vala.CreationMethod : Method {
                        i++;
                }
 
-               foreach (DataType error_type in get_error_types ()) {
-                       error_type.check (context);
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
+                               error_type.check (context);
+                       }
                }
 
                foreach (Expression precondition in get_preconditions ()) {
@@ -172,11 +176,15 @@ public class Vala.CreationMethod : Method {
 
                // check that all errors that can be thrown in the method body are declared
                if (body != null) {
-                       foreach (DataType body_error_type in body.get_error_types ()) {
+                       var body_errors = new ArrayList<DataType> ();
+                       body.get_error_types (body_errors);
+                       foreach (DataType body_error_type in body_errors) {
                                bool can_propagate_error = false;
-                               foreach (DataType method_error_type in get_error_types ()) {
-                                       if (body_error_type.compatible (method_error_type)) {
-                                               can_propagate_error = true;
+                               if (error_types != null) {
+                                       foreach (DataType method_error_type in error_types) {
+                                               if (body_error_type.compatible (method_error_type)) {
+                                                       can_propagate_error = true;
+                                               }
                                        }
                                }
                                if (!can_propagate_error && !((ErrorType) body_error_type).dynamic_error) {
index f0a3d4161c190f3ec1df1a49e16a2d0947ec288c..ab652e90673b5488227f4355195069fa60cda3ac 100644 (file)
@@ -62,6 +62,16 @@ public class Vala.DeclarationStatement : CodeNode, Statement {
                declaration.accept (visitor);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (source_reference == null) {
+                       source_reference = this.source_reference;
+               }
+               var local = declaration as LocalVariable;
+               if (local != null && local.initializer != null) {
+                       local.initializer.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -71,17 +81,6 @@ public class Vala.DeclarationStatement : CodeNode, Statement {
 
                declaration.check (context);
 
-               var local = declaration as LocalVariable;
-               if (local != null && local.initializer != null) {
-                       foreach (DataType error_type in local.initializer.get_error_types ()) {
-                               // ensure we can trace back which expression may throw errors of this type
-                               var initializer_error_type = error_type.copy ();
-                               initializer_error_type.source_reference = local.initializer.source_reference;
-
-                               add_error_type (initializer_error_type);
-                       }
-               }
-
                return !error;
        }
 
index 258fe4d4ec4200ac10cc4855e1aeb35a0ac5d494..16db6f1b89645062c7d75649d856e8dcd88621fb 100644 (file)
@@ -68,6 +68,8 @@ public class Vala.Delegate : TypeSymbol, Callable {
        private DataType _return_type;
        private bool? _has_target;
 
+       private List<DataType> error_types;
+
        /**
         * Creates a new delegate.
         *
@@ -185,21 +187,23 @@ public class Vala.Delegate : TypeSymbol, Callable {
                        return false;
                }
 
-               var error_types = get_error_types ();
-               var method_error_types = m.get_error_types ();
+               var method_error_types = new ArrayList<DataType> ();
+               m.get_error_types (method_error_types);
 
                // method must throw error if the delegate does
-               if (error_types.size > 0 && method_error_types.size == 0) {
+               if (error_types != null && error_types.size > 0 && method_error_types.size == 0) {
                        return false;
                }
 
                // method may throw less but not more errors than the delegate
                foreach (DataType method_error_type in method_error_types) {
                        bool match = false;
-                       foreach (DataType delegate_error_type in error_types) {
-                               if (method_error_type.compatible (delegate_error_type)) {
-                                       match = true;
-                                       break;
+                       if (error_types != null) {
+                               foreach (DataType delegate_error_type in error_types) {
+                                       if (method_error_type.compatible (delegate_error_type)) {
+                                               match = true;
+                                               break;
+                                       }
                                }
                        }
 
@@ -226,8 +230,10 @@ public class Vala.Delegate : TypeSymbol, Callable {
                        param.accept (visitor);
                }
 
-               foreach (DataType error_type in get_error_types ()) {
-                       error_type.accept (visitor);
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
+                               error_type.accept (visitor);
+                       }
                }
        }
 
@@ -235,16 +241,43 @@ public class Vala.Delegate : TypeSymbol, Callable {
                return false;
        }
 
+       /**
+        * Adds an error type to the exceptions that can be
+        * thrown by this delegate.
+        */
+       public void add_error_type (DataType error_type) {
+               if (error_types == null) {
+                       error_types = new ArrayList<DataType> ();
+               }
+               error_types.add (error_type);
+               error_type.parent_node = this;
+       }
+
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (error_types != null) {
+                       foreach (var error_type in error_types) {
+                               if (source_reference != null) {
+                                       var type = error_type.copy ();
+                                       type.source_reference = source_reference;
+                                       collection.add (type);
+                               } else {
+                                       collection.add (error_type);
+                               }
+                       }
+               }
+       }
+
        public override void replace_type (DataType old_type, DataType new_type) {
                if (return_type == old_type) {
                        return_type = new_type;
                        return;
                }
-               var error_types = get_error_types ();
-               for (int i = 0; i < error_types.size; i++) {
-                       if (error_types[i] == old_type) {
-                               error_types[i] = new_type;
-                               return;
+               if (error_types != null) {
+                       for (int i = 0; i < error_types.size; i++) {
+                               if (error_types[i] == old_type) {
+                                       error_types[i] = new_type;
+                                       return;
+                               }
                        }
                }
        }
@@ -272,8 +305,10 @@ public class Vala.Delegate : TypeSymbol, Callable {
                        param.check (context);
                }
 
-               foreach (DataType error_type in get_error_types ()) {
-                       error_type.check (context);
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
+                               error_type.check (context);
+                       }
                }
 
                context.analyzer.current_source_file = old_source_file;
index 0f4edfdb3e231df1032f23b8641a204d90a1a420..4fbaca1752605fd10eff831afeef2a0aa8279773 100644 (file)
@@ -189,9 +189,13 @@ public class Vala.DelegateType : CallableType {
                }
 
                // target-delegate may throw less but not more errors than the delegate
-               foreach (DataType error_type in get_error_types ()) {
+               var error_types = new ArrayList<DataType> ();
+               get_error_types (error_types);
+               foreach (DataType error_type in error_types) {
                        bool match = false;
-                       foreach (DataType delegate_error_type in dt_target.get_error_types ()) {
+                       var delegate_error_types = new ArrayList<DataType> ();
+                       dt_target.get_error_types (delegate_error_types);
+                       foreach (DataType delegate_error_type in delegate_error_types) {
                                if (error_type.compatible (delegate_error_type)) {
                                        match = true;
                                        break;
index 62cd1a65d833970c475bd7d6da65032cca2971d1..88c396ae14bcdd955ed3610683af0c77f71294e5 100644 (file)
@@ -106,6 +106,13 @@ public class Vala.ElementAccess : Expression {
                return container.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               container.get_error_types (collection, source_reference);
+               foreach (Expression e in indices) {
+                       e.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index 912e5d91ab585d109f5058c5fc7b19a8577efc26..43cebbe626d14d27089cc03248a1e0760d1f7b39 100644 (file)
@@ -80,11 +80,13 @@ public class Vala.ExpressionStatement : CodeNode, Statement {
                        return false;
                }
 
-               add_error_types (expression.get_error_types ());
-
                return !error;
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               expression.get_error_types (collection, source_reference);
+       }
+
        public override void emit (CodeGenerator codegen) {
                expression.emit (codegen);
 
index 8b436f5f031cf602aefe09f147fd17148562afe8..dc7e471a324be8f7a512ea0e5cf36d40d6fedfba 100644 (file)
@@ -870,7 +870,9 @@ public class Vala.FlowAnalyzer : CodeVisitor {
                        var last_block = current_block;
 
                        // exceptional control flow
-                       foreach (DataType error_data_type in node.get_error_types()) {
+                       var error_types = new ArrayList<DataType> ();
+                       node.get_error_types (error_types);
+                       foreach (DataType error_data_type in error_types) {
                                var error_type = error_data_type as ErrorType;
                                var error_class = error_data_type.data_type as Class;
                                current_block = last_block;
index 416fb55d2dc44a2afc726b770cbf9c0393329804..d0e35485d1c60f45b722d5026e9f9226cc9d3d6c 100644 (file)
@@ -380,12 +380,17 @@ public class Vala.ForeachStatement : Block {
                add_local_variable (collection_variable);
                collection_variable.active = true;
 
-               add_error_types (collection.get_error_types ());
-               add_error_types (body.get_error_types ());
-
                return !error;
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (source_reference == null) {
+                       source_reference = this.source_reference;
+               }
+               this.collection.get_error_types (collection, source_reference);
+               body.get_error_types (collection, source_reference);
+       }
+
        public override void emit (CodeGenerator codegen) {
                if (use_iterator) {
                        base.emit (codegen);
index 8d266917aab5caeb9f2829f1b772255326725e42..23958dbe9341ff350407f80acd8c1f183f481d34 100644 (file)
@@ -1007,7 +1007,7 @@ public class Vala.GirParser : CodeVisitor {
                                                // ensure getter vfunc if the property is abstract
                                                if (m != null) {
                                                        getter.process (parser);
-                                                       if (m.return_type is VoidType || m.get_parameters().size != 0 || m.get_error_types ().size > 0) {
+                                                       if (m.return_type is VoidType || m.get_parameters().size != 0 || m.tree_can_fail) {
                                                                prop.set_attribute ("NoAccessorMethod", true);
                                                        } else {
                                                                if (getter.name == name) {
@@ -1034,7 +1034,7 @@ public class Vala.GirParser : CodeVisitor {
                                                // ensure setter vfunc if the property is abstract
                                                if (m != null) {
                                                        setter.process (parser);
-                                                       if (!(m.return_type is VoidType || m.return_type is BooleanType) || m.get_parameters ().size != 1 || m.get_error_types ().size > 0) {
+                                                       if (!(m.return_type is VoidType || m.return_type is BooleanType) || m.get_parameters ().size != 1 || m.tree_can_fail) {
                                                                prop.set_attribute ("NoAccessorMethod", true);
                                                                prop.set_attribute ("ConcreteAccessor", false);
                                                        } else {
@@ -3188,12 +3188,21 @@ public class Vala.GirParser : CodeVisitor {
 
                if (!(metadata.get_expression (ArgumentType.THROWS) is NullLiteral)) {
                        if (metadata.has_argument (ArgumentType.THROWS)) {
-                               var error_types = metadata.get_string(ArgumentType.THROWS).split(",");
-                               foreach (var error_type in error_types) {
-                                       s.add_error_type (parse_type_from_string (error_type, true, metadata.get_source_reference (ArgumentType.THROWS)));
+                               var error_types = metadata.get_string (ArgumentType.THROWS).split(",");
+                               foreach (var error_type_name in error_types) {
+                                       var error_type = parse_type_from_string (error_type_name, true, metadata.get_source_reference (ArgumentType.THROWS));
+                                       if (s is Method) {
+                                               ((Method) s).add_error_type (error_type);
+                                       } else {
+                                               ((Delegate) s).add_error_type (error_type);
+                                       }
                                }
                        } else if (throws_string == "1") {
-                               s.add_error_type (new ErrorType (null, null));
+                               if (s is Method) {
+                                       ((Method) s).add_error_type (new ErrorType (null, null));
+                               } else {
+                                       ((Delegate) s).add_error_type (new ErrorType (null, null));
+                               }
                        }
                }
 
@@ -3710,7 +3719,9 @@ public class Vala.GirParser : CodeVisitor {
                                deleg.add_parameter (param.copy ());
                        }
 
-                       foreach (var error_type in orig.get_error_types ()) {
+                       var error_types = new ArrayList<DataType> ();
+                       orig.get_error_types (error_types, alias.source_reference);
+                       foreach (var error_type in error_types) {
                                deleg.add_error_type (error_type.copy ());
                        }
 
@@ -4118,8 +4129,10 @@ public class Vala.GirParser : CodeVisitor {
                                }
                        }
 
-                       foreach (DataType error_type in finish_method.get_error_types ()) {
-                               method.add_error_type (error_type.copy ());
+                       var error_types = new ArrayList<DataType> ();
+                       finish_method.get_error_types (error_types, method.source_reference);
+                       foreach (DataType error_type in error_types) {
+                               method.add_error_type (error_type);
                        }
                        finish_method_node.processed = true;
                        finish_method_node.merged = true;
index 0f9476d36a4ec9805148499d31eca19213cb3499..61c87ba3fe90dee4c3bacdfa9750338d557b9e90 100644 (file)
@@ -102,6 +102,14 @@ public class Vala.IfStatement : CodeNode, Statement {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               condition.get_error_types (collection, source_reference);
+               true_statement.get_error_types (collection, source_reference);
+               if (false_statement != null) {
+                       false_statement.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -130,13 +138,6 @@ public class Vala.IfStatement : CodeNode, Statement {
                        return false;
                }
 
-               add_error_types (condition.get_error_types ());
-               add_error_types (true_statement.get_error_types ());
-
-               if (false_statement != null) {
-                       add_error_types (false_statement.get_error_types ());
-               }
-
                return !error;
        }
 
index 3223e747a7e846b3dc2a307d9d2d54a757f2c555..a22497e70a94623f2a21baf4052b70afdab50372 100644 (file)
@@ -197,7 +197,9 @@ public class Vala.LambdaExpression : Expression {
                        return false;
                }
 
-               foreach (var error_type in cb.get_error_types ()) {
+               var error_types = new ArrayList<DataType> ();
+               cb.get_error_types (error_types);
+               foreach (var error_type in error_types) {
                        method.add_error_type (error_type.copy ());
                }
 
index 4e6edbe6324d9f2e6a0ecb02baf50769189c4926..ce6894633d4ac2ce8825e4eb259bdcd3620c96e4 100644 (file)
@@ -61,6 +61,10 @@ public class Vala.Loop : CodeNode, Statement {
                body.accept (visitor);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               body.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -70,8 +74,6 @@ public class Vala.Loop : CodeNode, Statement {
 
                body.check (context);
 
-               add_error_types (body.get_error_types ());
-
                return !error;
        }
 
index 64263ba3e3b7b5cfcf4475dc0bf181dfa16b6366..805b168f3bbb4994221b2050eab2d0f8a77b0a95 100644 (file)
@@ -193,6 +193,12 @@ public class Vala.MemberAccess : Expression {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (inner != null) {
+                       inner.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index 1db46ae456193271619b16ea934c002b128a7cfc..f567b246edb0be3bd4b17a6795dc837c46881541 100644 (file)
@@ -188,6 +188,8 @@ public class Vala.Method : Subroutine, Callable {
        private List<Expression> postconditions;
        private DataType _return_type;
 
+       protected List<DataType> error_types;
+
        private weak Method _base_method;
        private weak Method _base_interface_method;
        private DataType _base_interface_type;
@@ -272,9 +274,11 @@ public class Vala.Method : Subroutine, Callable {
                        param.accept (visitor);
                }
 
-               foreach (DataType error_type in get_error_types ()) {
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
                        error_type.accept (visitor);
                }
+               }
 
                if (result_var != null) {
                        result_var.accept (visitor);
@@ -387,9 +391,12 @@ public class Vala.Method : Subroutine, Callable {
                }
 
                /* this method may throw less but not more errors than the base method */
-               foreach (DataType method_error_type in get_error_types ()) {
+               var base_method_errors = new ArrayList<DataType> ();
+               base_method.get_error_types (base_method_errors);
+               if (error_types != null) {
+                       foreach (DataType method_error_type in error_types) {
                        bool match = false;
-                       foreach (DataType base_method_error_type in base_method.get_error_types ()) {
+                               foreach (DataType base_method_error_type in base_method_errors) {
                                if (method_error_type.compatible (base_method_error_type)) {
                                        match = true;
                                        break;
@@ -401,6 +408,7 @@ public class Vala.Method : Subroutine, Callable {
                                return false;
                        }
                }
+               }
                if (base_method.coroutine != this.coroutine) {
                        invalid_match = "async mismatch";
                        return false;
@@ -509,6 +517,32 @@ public class Vala.Method : Subroutine, Callable {
                return _empty_expression_list;
        }
 
+       /**
+        * Adds an error type to the exceptions that can be
+        * thrown by this method.
+        */
+       public void add_error_type (DataType error_type) {
+               if (error_types == null) {
+                       error_types = new ArrayList<DataType> ();
+               }
+               error_types.add (error_type);
+               error_type.parent_node = this;
+       }
+
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (error_types != null) {
+                       foreach (var error_type in error_types) {
+                               if (source_reference != null) {
+                                       var type = error_type.copy ();
+                                       type.source_reference = source_reference;
+                                       collection.add (type);
+                               } else {
+                                       collection.add (error_type);
+                               }
+                       }
+               }
+       }
+
        public override void replace_type (DataType old_type, DataType new_type) {
                if (base_interface_type == old_type) {
                        base_interface_type = new_type;
@@ -518,7 +552,7 @@ public class Vala.Method : Subroutine, Callable {
                        return_type = new_type;
                        return;
                }
-               var error_types = get_error_types ();
+               if (error_types != null) {
                for (int i = 0; i < error_types.size; i++) {
                        if (error_types[i] == old_type) {
                                error_types[i] = new_type;
@@ -526,6 +560,7 @@ public class Vala.Method : Subroutine, Callable {
                        }
                }
        }
+       }
 
        private void find_base_methods () {
                if (base_methods_valid) {
@@ -635,7 +670,7 @@ public class Vala.Method : Subroutine, Callable {
                        this_parameter.variable_type.value_owned = true;
                }
                if (get_attribute ("NoThrow") != null) {
-                       get_error_types ().clear ();
+                       error_types = null;
                }
 
                if (parent_symbol is Class && (is_abstract || is_virtual)) {
@@ -746,7 +781,8 @@ public class Vala.Method : Subroutine, Callable {
                        }
                }
 
-               foreach (DataType error_type in get_error_types ()) {
+               if (error_types != null) {
+                       foreach (DataType error_type in error_types) {
                        error_type.check (context);
 
                        // check whether error type is at least as accessible as the method
@@ -756,6 +792,7 @@ public class Vala.Method : Subroutine, Callable {
                                return false;
                        }
                }
+               }
 
                if (result_var != null) {
                        result_var.check (context);
@@ -849,13 +886,17 @@ public class Vala.Method : Subroutine, Callable {
 
                // check that all errors that can be thrown in the method body are declared
                if (body != null) {
-                       foreach (DataType body_error_type in body.get_error_types ()) {
+                       var body_errors = new ArrayList<DataType> ();
+                       body.get_error_types (body_errors);
+                       foreach (DataType body_error_type in body_errors) {
                                bool can_propagate_error = false;
-                               foreach (DataType method_error_type in get_error_types ()) {
+                               if (error_types != null) {
+                                       foreach (DataType method_error_type in error_types) {
                                        if (body_error_type.compatible (method_error_type)) {
                                                can_propagate_error = true;
                                        }
                                }
+                               }
                                bool is_dynamic_error = body_error_type is ErrorType && ((ErrorType) body_error_type).dynamic_error;
                                if (!can_propagate_error && !is_dynamic_error) {
                                        Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
@@ -872,7 +913,9 @@ public class Vala.Method : Subroutine, Callable {
                                bool throws_gerror = false;
                                bool throws_gioerror = false;
                                bool throws_gdbuserror = false;
-                               foreach (DataType error_type in get_error_types ()) {
+                               var error_types = new ArrayList<DataType> ();
+                               get_error_types (error_types);
+                               foreach (DataType error_type in error_types) {
                                        if (!(error_type is ErrorType)) {
                                                continue;
                                        }
@@ -1123,7 +1166,7 @@ public class Vala.Method : Subroutine, Callable {
        }
 
        public bool has_error_type_parameter () {
-               if (get_error_types ().size > 0) {
+               if (tree_can_fail) {
                        return true;
                }
                if (base_method != null && base_method != this && base_method.has_error_type_parameter ()) {
index 082e061f7d3b1bc128064eb9db441219cd14d1bd..a09db9b11bb8611e29265437db813dcd3c9e26fc 100644 (file)
@@ -142,6 +142,27 @@ public class Vala.MethodCall : Expression {
                return call.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (source_reference == null) {
+                       source_reference = this.source_reference;
+               }
+               var mtype = call.value_type;
+               if (mtype is MethodType) {
+                       var m = ((MethodType) mtype).method_symbol;
+                       if (!(m != null && m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end")) {
+                               m.get_error_types (collection, source_reference);
+                       }
+               } else if (mtype is ObjectType) {
+                       // constructor
+                       var cl = (Class) ((ObjectType) mtype).type_symbol;
+                       var m = cl.default_construction_method;
+                       m.get_error_types (collection, source_reference);
+               } else if (mtype is DelegateType) {
+                       var d = ((DelegateType) mtype).delegate_symbol;
+                       d.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -471,8 +492,6 @@ public class Vala.MethodCall : Expression {
                formal_value_type = ret_type.copy ();
                value_type = formal_value_type.get_actual_type (target_object_type, method_type_args, this);
 
-               bool may_throw = false;
-
                if (mtype is MethodType) {
                        var m = ((MethodType) mtype).method_symbol;
                        if (is_yield_expression) {
@@ -485,19 +504,7 @@ public class Vala.MethodCall : Expression {
                                        Report.error (source_reference, "yield expression not available outside async method");
                                }
                        }
-                       if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end") {
-                               // .begin call of async method, no error can happen here
-                       } else {
-                               foreach (DataType error_type in m.get_error_types ()) {
-                                       may_throw = true;
 
-                                       // ensure we can trace back which expression may throw errors of this type
-                                       var call_error_type = error_type.copy ();
-                                       call_error_type.source_reference = source_reference;
-
-                                       add_error_type (call_error_type);
-                               }
-                       }
                        if (m.returns_floating_reference) {
                                value_type.floating_reference = true;
                        }
@@ -505,7 +512,7 @@ public class Vala.MethodCall : Expression {
                                ((MemberAccess) call).inner.lvalue = true;
                        }
                        // avoid passing possible null to ref_sink_function without checking
-                       if (may_throw && !value_type.nullable && value_type.floating_reference && ret_type is ObjectType) {
+                       if (tree_can_fail && !value_type.nullable && value_type.floating_reference && ret_type is ObjectType) {
                                value_type.nullable = true;
                        }
 
@@ -589,30 +596,6 @@ public class Vala.MethodCall : Expression {
                                        mtype = new MethodType (m.get_end_method ());
                                }
                        }
-               } else if (mtype is ObjectType) {
-                       // constructor
-                       var cl = (Class) ((ObjectType) mtype).type_symbol;
-                       var m = cl.default_construction_method;
-                       foreach (DataType error_type in m.get_error_types ()) {
-                               may_throw = true;
-
-                               // ensure we can trace back which expression may throw errors of this type
-                               var call_error_type = error_type.copy ();
-                               call_error_type.source_reference = source_reference;
-
-                               add_error_type (call_error_type);
-                       }
-               } else if (mtype is DelegateType) {
-                       var d = ((DelegateType) mtype).delegate_symbol;
-                       foreach (DataType error_type in d.get_error_types ()) {
-                               may_throw = true;
-
-                               // ensure we can trace back which expression may throw errors of this type
-                               var call_error_type = error_type.copy ();
-                               call_error_type.source_reference = source_reference;
-
-                               add_error_type (call_error_type);
-                       }
                }
 
                if (!context.analyzer.check_arguments (this, mtype, params, get_argument_list ())) {
@@ -628,7 +611,7 @@ public class Vala.MethodCall : Expression {
                        }
                }
 
-               if (may_throw) {
+               if (tree_can_fail) {
                        if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
                                // simple statements, no side effects after method call
                        } else if (!(context.analyzer.current_symbol is Block)) {
index 8bef09b25f7b3d52499453efd3b55115ceebf737..4b609aee7dc4be4819bb909e36f690de8ba0774b 100644 (file)
@@ -246,8 +246,6 @@ public class Vala.ObjectCreationExpression : Expression {
                value_type = type_reference.copy ();
                value_type.value_owned = true;
 
-               bool may_throw = false;
-
                int given_num_type_args = type_reference.get_type_arguments ().size;
                int expected_num_type_args = 0;
 
@@ -423,16 +421,6 @@ public class Vala.ObjectCreationExpression : Expression {
                        }
 
                        context.analyzer.check_arguments (this, new MethodType (m), m.get_parameters (), args);
-
-                       foreach (DataType error_type in m.get_error_types ()) {
-                               may_throw = true;
-
-                               // ensure we can trace back which expression may throw errors of this type
-                               var call_error_type = error_type.copy ();
-                               call_error_type.source_reference = source_reference;
-
-                               add_error_type (call_error_type);
-                       }
                } else if (type_reference is ErrorType) {
                        if (type_reference != null) {
                                type_reference.check (context);
@@ -484,7 +472,7 @@ public class Vala.ObjectCreationExpression : Expression {
                        context.analyzer.visit_member_initializer (init, type_reference);
                }
 
-               if (may_throw) {
+               if (tree_can_fail) {
                        if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
                                // simple statements, no side effects after method call
                        } else if (!(context.analyzer.current_symbol is Block)) {
@@ -519,6 +507,16 @@ public class Vala.ObjectCreationExpression : Expression {
                return !error;
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (symbol_reference is Method) {
+                       if (source_reference == null) {
+                               source_reference = this.source_reference;
+                       }
+                       var m = (Method) symbol_reference;
+                       m.get_error_types (collection, source_reference);
+               }
+       }
+
        public override void emit (CodeGenerator codegen) {
                foreach (Expression arg in argument_list) {
                        arg.emit (codegen);
index 01ad01d2942c39137d4e509d57ea6a13620ebdaf..f52fba8938e108ba89d4635cba81efd3883c783b 100644 (file)
@@ -2805,7 +2805,7 @@ public class Vala.Parser : CodeVisitor {
 
                if (accept (TokenType.THROWS)) {
                        do {
-                               prop.add_error_type (parse_type (true, false));
+                               parse_type (true, false);
                        } while (accept (TokenType.COMMA));
                        Report.error (prop.source_reference, "properties throwing errors are not supported yet");
                }
index 97f6473a80e42456c32c8e186000650742d9a613..20dbcbfdeec73499fb9ff9813a2981d0505817f5 100644 (file)
@@ -73,6 +73,10 @@ public class Vala.PointerIndirection : Expression {
                return inner.is_accessible (sym);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               inner.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index 46952bb197743ff541b89f762c6c3853eff0487e..e348c2510f555354af31d4b56580dec96b43d627 100644 (file)
@@ -197,7 +197,9 @@ public class Vala.PropertyAccessor : Subroutine {
 
                        body.check (context);
 
-                       foreach (DataType body_error_type in body.get_error_types ()) {
+                       var error_types = new ArrayList<DataType> ();
+                       body.get_error_types (error_types);
+                       foreach (DataType body_error_type in error_types) {
                                if (!((ErrorType) body_error_type).dynamic_error) {
                                        Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
                                }
index 83e81a2cc9cd46e726b713c9a58df0663c6bc985..cdb782cf29367634fa17975373935c8c94b46768 100644 (file)
@@ -70,6 +70,12 @@ public class Vala.ReturnStatement : CodeNode, Statement {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (return_expression != null) {
+                       return_expression.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -138,8 +144,6 @@ public class Vala.ReturnStatement : CodeNode, Statement {
                        Report.warning (source_reference, "`null' incompatible with return type `%s'".printf (context.analyzer.current_return_type.to_string ()));
                }
 
-               add_error_types (return_expression.get_error_types ());
-
                return !error;
        }
 
index 934227a1a7485f1e9d712b29fedee5cc9a5cbb44..5159598151c653776347b55fa90767acee96fedd 100644 (file)
@@ -48,6 +48,12 @@ public class Vala.StatementList : CodeNode, Statement {
                list.insert (index, stmt);
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               foreach (var stmt in list) {
+                       stmt.get_error_types (collection, source_reference);
+               }
+       }
+
        public override void accept (CodeVisitor visitor) {
                foreach (Statement stmt in list) {
                        stmt.accept (visitor);
index 156740f80be56841ddbf9945cfb657db5701b04f..2b0da58377a0c55640f71a909f433562bcf20b20 100644 (file)
@@ -85,6 +85,13 @@ public class Vala.SwitchSection : Block {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               // use get_statements () instead of statement_list to not miss errors within StatementList objects
+               foreach (var stmt in get_statements ()) {
+                       stmt.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -111,11 +118,6 @@ public class Vala.SwitchSection : Block {
                        local.active = false;
                }
 
-               // use get_statements () instead of statement_list to not miss errors within StatementList objects
-               foreach (Statement stmt in get_statements ()) {
-                       add_error_types (stmt.get_error_types ());
-               }
-
                context.analyzer.current_symbol = old_symbol;
                context.analyzer.insert_block = old_insert_block;
 
index 66dab0193a4de94533d062ef744c8f32d298cf26..78cfa3d82fcf19f54b8dd146660f1c1a6d994482 100644 (file)
@@ -93,6 +93,12 @@ public class Vala.SwitchStatement : CodeNode, Statement {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               foreach (SwitchSection section in sections) {
+                       section.get_error_types (collection, source_reference);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -140,7 +146,6 @@ public class Vala.SwitchStatement : CodeNode, Statement {
                                        }
                                }
                        }
-                       add_error_types (section.get_error_types ());
                }
 
                return !error;
index d4cade7a24b6d7d3e22be498a5d9d78fa42f1297..9349b18188cf3917a89c2f515c31a269211926be 100644 (file)
@@ -72,6 +72,15 @@ public class Vala.ThrowStatement : CodeNode, Statement {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               if (source_reference == null) {
+                       source_reference = this.source_reference;
+               }
+               var error_type = error_expression.value_type.copy ();
+               error_type.source_reference = source_reference;
+               collection.add (error_type);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -107,11 +116,6 @@ public class Vala.ThrowStatement : CodeNode, Statement {
                        }
                }
 
-               var error_type = error_expression.value_type.copy ();
-               error_type.source_reference = source_reference;
-
-               add_error_type (error_type);
-
                return !error;
        }
 
index 7e82228a5cb46d65b12d82d28a78861fe43caed4..fcacfc7fba3c2df114e417160d988f2d7462d4fd 100644 (file)
@@ -104,6 +104,31 @@ public class Vala.TryStatement : CodeNode, Statement {
                }
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               var error_types = new ArrayList<DataType> ();
+               body.get_error_types (error_types, source_reference);
+
+               foreach (CatchClause clause in catch_clauses) {
+                       for (int i=0; i < error_types.size; i++) {
+                               var error_type = error_types[i];
+                               if (clause.error_type == null || error_type.compatible (clause.error_type)) {
+                                       error_types.remove_at (i);
+                                       i--;
+                               }
+                       }
+
+                       clause.body.get_error_types (collection, source_reference);
+               }
+
+               if (finally_body != null) {
+                       finally_body.get_error_types (collection, source_reference);
+               }
+
+               foreach (var error_type in error_types) {
+                       collection.add (error_type);
+               }
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -119,38 +144,14 @@ public class Vala.TryStatement : CodeNode, Statement {
 
                body.check (context);
 
-               var error_types = new ArrayList<DataType> ();
-               foreach (DataType body_error_type in body.get_error_types ()) {
-                       error_types.add (body_error_type);
-               }
-
-               var handled_error_types = new ArrayList<DataType> ();
                foreach (CatchClause clause in catch_clauses) {
-                       foreach (DataType body_error_type in error_types) {
-                               if (clause.error_type == null || body_error_type.compatible (clause.error_type)) {
-                                       handled_error_types.add (body_error_type);
-                               }
-                       }
-                       foreach (DataType handled_error_type in handled_error_types) {
-                               error_types.remove (handled_error_type);
-                       }
-                       handled_error_types.clear ();
-
                        clause.check (context);
-                       foreach (DataType body_error_type in clause.body.get_error_types ()) {
-                               error_types.add (body_error_type);
-                       }
                }
 
                if (finally_body != null) {
                        finally_body.check (context);
-                       foreach (DataType body_error_type in finally_body.get_error_types ()) {
-                               error_types.add (body_error_type);
-                       }
                }
 
-               add_error_types (error_types);
-
                return !error;
        }
 
index 87f4032efc192496153bbe9c56eb032815df7cdc..7ccbecb1d00e3bbec8d7ff558e1d27e580c3aa45 100644 (file)
@@ -150,6 +150,10 @@ public class Vala.UnaryExpression : Expression {
                return null;
        }
 
+       public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+               inner.get_error_types (collection, source_reference);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
index 4980e88ab19fdba2237d0c5b4a2429b8d83d9151..adf19a34a1d251f22d96215f8d384d09f719eb1c 100644 (file)
@@ -37,8 +37,10 @@ public class Valadoc.Drivers.SymbolResolver : Visitor {
                return symbol_map.get (symbol);
        }
 
-       private void resolve_thrown_list (Symbol symbol, Vala.List<Vala.DataType> types) {
-               foreach (Vala.DataType type in types) {
+       private void resolve_thrown_list (Symbol symbol, Vala.Symbol vala_symbol) {
+               var error_types = new Vala.ArrayList<Vala.DataType> ();
+               vala_symbol.get_error_types (error_types);
+               foreach (Vala.DataType type in error_types) {
                        Vala.ErrorDomain vala_edom = (Vala.ErrorDomain) type.data_type;
                        Symbol? edom = symbol_map.get (vala_edom);
                        symbol.add_child (edom ?? glib_error);
@@ -216,7 +218,7 @@ public class Valadoc.Drivers.SymbolResolver : Visitor {
 
                resolve_type_reference (item.return_type);
 
-               resolve_thrown_list (item, vala_delegate.get_error_types ());
+               resolve_thrown_list (item, vala_delegate);
 
                item.accept_all_children (this, false);
        }
@@ -248,7 +250,7 @@ public class Valadoc.Drivers.SymbolResolver : Visitor {
                        item.base_method = (Method?) resolve (base_vala_method);
                }
 
-               resolve_thrown_list (item, vala_method.get_error_types ());
+               resolve_thrown_list (item, vala_method);
 
                resolve_type_reference (item.return_type);
 
index a187c6df321bc7041841d0064e1493fa4e9d62c1..1d07cc63afc527a5a165d751b1041a67fb2b8e9a 100644 (file)
@@ -1817,8 +1817,10 @@ public class Vala.GIdlParser : CodeVisitor {
                                                        m.add_parameter (async_param);
                                                }
                                        }
-                                       foreach (DataType error_type in finish_method.get_error_types ()) {
-                                               m.add_error_type (error_type.copy ());
+                                       var error_types = new ArrayList<DataType> ();
+                                       finish_method.get_error_types (error_types, m.source_reference);
+                                       foreach (DataType error_type in error_types) {
+                                               m.add_error_type (error_type);
                                        }
                                        finish_methods.add (finish_method);
                                }