[vala/wip/transform: 3/32] Collect error_types on demand to allow transformations
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 3/32] Collect error_types on demand to allow transformations
- Date: Wed, 4 Jan 2012 14:09:13 +0000 (UTC)
commit 6e86af5e856c95f037fd35a72f20236c4dd481ea
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Aug 7 12:44:41 2011 +0200
Collect error_types on demand to allow transformations
codegen/valaccodedelegatemodule.vala | 6 +-
codegen/valaccodemethodmodule.vala | 6 +-
codegen/valadovaerrormodule.vala | 10 ++--
codegen/valagasyncmodule.vala | 2 +-
codegen/valagdbusclientmodule.vala | 4 +-
codegen/valagdbusservermodule.vala | 4 +-
codegen/valagerrormodule.vala | 10 ++--
vala/valaassignment.vala | 8 ++-
vala/valablock.vala | 11 +++-
vala/valacodenode.vala | 46 +++------------
vala/valacodewriter.vala | 8 ++-
vala/valaconstructor.vala | 4 +-
vala/valacreationmethod.vala | 24 +++++---
vala/valadeclarationstatement.vala | 21 +++----
vala/valadelegate.vala | 65 ++++++++++++++++-----
vala/valaexpressionstatement.vala | 6 +-
vala/valaflowanalyzer.vala | 4 +-
vala/valaforeachstatement.vala | 11 +++-
vala/valagirparser.vala | 23 ++++++--
vala/valaifstatement.vala | 15 +++--
vala/valalambdaexpression.vala | 4 +-
vala/valaloop.vala | 6 +-
vala/valamethod.vala | 99 ++++++++++++++++++++++---------
vala/valamethodcall.vala | 59 +++++++------------
vala/valaobjectcreationexpression.vala | 24 ++++----
vala/valaparser.vala | 2 +-
vala/valapropertyaccessor.vala | 4 +-
vala/valareturnstatement.vala | 8 ++-
vala/valastatementlist.vala | 6 ++
vala/valaswitchsection.vala | 12 ++--
vala/valaswitchstatement.vala | 7 ++-
vala/valathrowstatement.vala | 14 +++--
vala/valatrystatement.vala | 49 ++++++++--------
vapigen/valagidlparser.vala | 6 +-
34 files changed, 347 insertions(+), 241 deletions(-)
---
diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala
index 0c2242d..bb3a969 100644
--- a/codegen/valaccodedelegatemodule.vala
+++ b/codegen/valaccodedelegatemodule.vala
@@ -110,7 +110,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
var cparam = new CCodeParameter ("user_data", "void*");
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);
}
@@ -258,7 +258,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);
}
@@ -376,7 +376,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"));
}
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 982f5ce..a8970cd 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -107,8 +107,10 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
}
}
- if (m.get_error_types ().size > 0 || (m.base_method != null && m.base_method.get_error_types ().size > 0) || (m.base_interface_method != null && m.base_interface_method.get_error_types ().size > 0)) {
- foreach (DataType error_type in m.get_error_types ()) {
+ if (m.tree_can_fail || (m.base_method != null && m.base_method.tree_can_fail) || (m.base_interface_method != null && m.base_interface_method.tree_can_fail)) {
+ 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);
}
diff --git a/codegen/valadovaerrormodule.vala b/codegen/valadovaerrormodule.vala
index 68f7a86..78b5be2 100644
--- a/codegen/valadovaerrormodule.vala
+++ b/codegen/valadovaerrormodule.vala
@@ -95,9 +95,7 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
append_local_free (current_symbol, false, current_try);
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;
@@ -150,11 +148,13 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
} else {
assert_not_reached ();
}
- } 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
CCodeExpression 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 Dova.Error is allowed we propagate everything
if (error_type.equals (new ObjectType (error_class))) {
ccond = null;
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index 64ec2b5..bc10818 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -417,7 +417,7 @@ public class Vala.GAsyncModule : GSignalModule {
var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
- if (m.get_error_types ().size > 0) {
+ if (m.tree_can_fail) {
// propagate error from async method
var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error"));
propagate_error.add_argument (simple_async_result_cast);
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 695ccbc..a47b95c 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -526,7 +526,9 @@ public class Vala.GDBusClientModule : GDBusModule {
timeout.add_argument (gdbusproxy);
// 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)));
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
index c92a444..436db89 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -232,7 +232,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")));
}
}
@@ -244,7 +244,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"));
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 23d11a3..4c2a7ca 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -185,9 +185,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;
@@ -252,11 +250,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;
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 69434a5..41fbcfe 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -97,6 +97,11 @@ public class Vala.Assignment : Expression {
return false;
}
+ 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;
@@ -440,9 +445,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;
}
diff --git a/vala/valablock.vala b/vala/valablock.vala
index 0daff83..df2f1eb 100644
--- a/vala/valablock.vala
+++ b/vala/valablock.vala
@@ -158,12 +158,17 @@ public class Vala.Block : Symbol, Statement {
constant.active = false;
}
+ return !error;
+ }
+
+ public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
+ if (source_reference == null) {
+ source_reference = this.source_reference;
+ }
// 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 ());
+ stmt.get_error_types (collection, source_reference);
}
-
- return !error;
}
public override void emit (CodeGenerator codegen) {
diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala
index 3872a46..2452e3f 100644
--- a/vala/valacodenode.vala
+++ b/vala/valacodenode.vala
@@ -62,52 +62,19 @@ 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.
*
* @param visitor the visitor to be called while traversing
@@ -383,6 +350,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 ();
}
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index f79c2af..ddd7e3b 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -627,7 +627,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 (";");
@@ -708,7 +710,9 @@ public class Vala.CodeWriter : CodeVisitor {
write_params (m.get_parameters ());
if (context.profile != Profile.DOVA) {
- 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);
diff --git a/vala/valaconstructor.vala b/vala/valaconstructor.vala
index 3d19596..86f24de 100644
--- a/vala/valaconstructor.vala
+++ b/vala/valaconstructor.vala
@@ -74,7 +74,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()));
}
diff --git a/vala/valacreationmethod.vala b/vala/valacreationmethod.vala
index c8fb157..0ab396f 100644
--- a/vala/valacreationmethod.vala
+++ b/vala/valacreationmethod.vala
@@ -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 ()) {
@@ -95,8 +97,10 @@ public class Vala.CreationMethod : Method {
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);
+ }
}
foreach (Expression precondition in get_preconditions ()) {
@@ -141,11 +145,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) {
diff --git a/vala/valadeclarationstatement.vala b/vala/valadeclarationstatement.vala
index c4c778f..12303cd 100644
--- a/vala/valadeclarationstatement.vala
+++ b/vala/valadeclarationstatement.vala
@@ -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;
}
diff --git a/vala/valadelegate.vala b/vala/valadelegate.vala
index 71de1aa..d09bf92 100644
--- a/vala/valadelegate.vala
+++ b/vala/valadelegate.vala
@@ -68,6 +68,8 @@ public class Vala.Delegate : TypeSymbol {
private DataType _return_type;
private bool? _has_target;
+ private List<DataType> error_types;
+
/**
* Creates a new delegate.
*
@@ -186,12 +188,16 @@ public class Vala.Delegate : TypeSymbol {
}
// method may throw less but not more errors than the delegate
- foreach (DataType method_error_type in m.get_error_types ()) {
+ var method_errors = new ArrayList<DataType> ();
+ m.get_error_types (method_errors);
+ foreach (DataType method_error_type in method_errors) {
bool match = false;
- foreach (DataType delegate_error_type in get_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;
+ }
}
}
@@ -218,8 +224,10 @@ public class Vala.Delegate : TypeSymbol {
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);
+ }
}
}
@@ -227,16 +235,43 @@ public class Vala.Delegate : TypeSymbol {
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;
+ }
}
}
}
@@ -306,8 +341,10 @@ public class Vala.Delegate : TypeSymbol {
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);
+ }
}
return !error;
diff --git a/vala/valaexpressionstatement.vala b/vala/valaexpressionstatement.vala
index 6d01a98..c0c55f3 100644
--- a/vala/valaexpressionstatement.vala
+++ b/vala/valaexpressionstatement.vala
@@ -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);
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index ada3254..fffb17a 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -851,7 +851,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;
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 68df1d6..3195159 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -373,12 +373,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);
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index eecb9d4..2ef1df4 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -2694,12 +2694,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));
+ }
}
}
@@ -3352,8 +3361,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;
diff --git a/vala/valaifstatement.vala b/vala/valaifstatement.vala
index 7655ffd..f2d22e7 100644
--- a/vala/valaifstatement.vala
+++ b/vala/valaifstatement.vala
@@ -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;
}
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index 2c9f066..3859285 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -199,7 +199,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 ());
}
diff --git a/vala/valaloop.vala b/vala/valaloop.vala
index 5782070..bf44a9c 100644
--- a/vala/valaloop.vala
+++ b/vala/valaloop.vala
@@ -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;
}
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 9edb525..09b5de1 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -179,6 +179,8 @@ public class Vala.Method : Subroutine {
private List<Expression> postconditions;
private DataType _return_type;
+ protected List<DataType> error_types;
+
private weak Method _base_method;
private Method _base_interface_method;
private bool base_methods_valid;
@@ -248,8 +250,10 @@ public class Vala.Method : Subroutine {
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);
+ }
}
if (result_var != null) {
@@ -334,18 +338,22 @@ public class Vala.Method : Subroutine {
}
/* this method may throw less but not more errors than the base method */
- foreach (DataType method_error_type in get_error_types ()) {
- bool match = false;
- foreach (DataType base_method_error_type in base_method.get_error_types ()) {
- if (method_error_type.compatible (base_method_error_type)) {
- match = true;
- break;
+ 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_errors) {
+ if (method_error_type.compatible (base_method_error_type)) {
+ match = true;
+ break;
+ }
}
- }
- if (!match) {
- invalid_match = "incompatible error type `%s'".printf (method_error_type.to_string ());
- return false;
+ if (!match) {
+ invalid_match = "incompatible error type `%s'".printf (method_error_type.to_string ());
+ return false;
+ }
}
}
if (base_method.coroutine != this.coroutine) {
@@ -456,16 +464,43 @@ public class Vala.Method : Subroutine {
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 (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;
+ }
}
}
}
@@ -561,7 +596,7 @@ public class Vala.Method : Subroutine {
this_parameter.variable_type.value_owned = true;
}
if (get_attribute ("NoThrow") != null) {
- get_error_types ().clear ();
+ error_types = null;
}
if (is_abstract) {
@@ -646,14 +681,16 @@ public class Vala.Method : Subroutine {
}
}
- 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);
- // check whether error type is at least as accessible as the method
- if (!context.analyzer.is_type_accessible (this, error_type)) {
- error = true;
- Report.error (source_reference, "error type `%s` is less accessible than method `%s`".printf (error_type.to_string (), get_full_name ()));
- return false;
+ // check whether error type is at least as accessible as the method
+ if (!context.analyzer.is_type_accessible (this, error_type)) {
+ error = true;
+ Report.error (source_reference, "error type `%s` is less accessible than method `%s`".printf (error_type.to_string (), get_full_name ()));
+ return false;
+ }
}
}
@@ -732,11 +769,15 @@ public class Vala.Method : Subroutine {
// 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;
+ }
}
}
bool is_dynamic_error = body_error_type is ErrorType && ((ErrorType) body_error_type).dynamic_error;
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 6030b39..afdf6b9 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -147,6 +147,27 @@ public class Vala.MethodCall : Expression {
}
}
+ 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;
@@ -583,19 +604,7 @@ public class Vala.MethodCall : Expression {
}
current_method.yield_count++;
}
- 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;
}
@@ -682,30 +691,6 @@ public class Vala.MethodCall : Expression {
value_type = formal_value_type.get_actual_type (target_object_type, call as MemberAccess, this);
}
}
- } 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 ())) {
@@ -713,7 +698,7 @@ public class Vala.MethodCall : Expression {
return false;
}
- 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.get_current_symbol (this) is Block)) {
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index 9a18774..210fb86 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -228,8 +228,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;
@@ -351,16 +349,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);
@@ -396,7 +384,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.get_current_symbol (this) is Block)) {
@@ -437,6 +425,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);
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 76ea0b9..487a3ee 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2816,7 +2816,7 @@ public class Vala.Parser : CodeVisitor {
} else {
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");
}
diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala
index 1f6769b..3c56e01 100644
--- a/vala/valapropertyaccessor.vala
+++ b/vala/valapropertyaccessor.vala
@@ -170,7 +170,9 @@ public class Vala.PropertyAccessor : Subroutine {
body.check (context);
if (context.profile != Profile.DOVA) {
- 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()));
}
diff --git a/vala/valareturnstatement.vala b/vala/valareturnstatement.vala
index ee14a71..6760aff 100644
--- a/vala/valareturnstatement.vala
+++ b/vala/valareturnstatement.vala
@@ -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;
@@ -145,8 +151,6 @@ public class Vala.ReturnStatement : CodeNode, Statement {
Report.warning (source_reference, "`null' incompatible with return type `%s`".printf (current_return_type.to_string ()));
}
- add_error_types (return_expression.get_error_types ());
-
return !error;
}
diff --git a/vala/valastatementlist.vala b/vala/valastatementlist.vala
index 934227a..5159598 100644
--- a/vala/valastatementlist.vala
+++ b/vala/valastatementlist.vala
@@ -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);
diff --git a/vala/valaswitchsection.vala b/vala/valaswitchsection.vala
index b79e39e..5580ac6 100644
--- a/vala/valaswitchsection.vala
+++ b/vala/valaswitchsection.vala
@@ -81,6 +81,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;
@@ -102,11 +109,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 ());
- }
-
return !error;
}
diff --git a/vala/valaswitchstatement.vala b/vala/valaswitchstatement.vala
index c583f8d..d6d2999 100644
--- a/vala/valaswitchstatement.vala
+++ b/vala/valaswitchstatement.vala
@@ -92,6 +92,12 @@ public class Vala.SwitchStatement : CodeNode, Statement {
expression = new_node;
}
}
+
+ 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) {
@@ -140,7 +146,6 @@ public class Vala.SwitchStatement : CodeNode, Statement {
}
}
}
- add_error_types (section.get_error_types ());
}
return !error;
diff --git a/vala/valathrowstatement.vala b/vala/valathrowstatement.vala
index 2dbcc3d..5de6447 100644
--- a/vala/valathrowstatement.vala
+++ b/vala/valathrowstatement.vala
@@ -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;
@@ -105,11 +114,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;
}
diff --git a/vala/valatrystatement.vala b/vala/valatrystatement.vala
index 38000f5..3ae8924 100644
--- a/vala/valatrystatement.vala
+++ b/vala/valatrystatement.vala
@@ -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;
@@ -113,38 +138,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;
}
diff --git a/vapigen/valagidlparser.vala b/vapigen/valagidlparser.vala
index 66141dd..b351801 100644
--- a/vapigen/valagidlparser.vala
+++ b/vapigen/valagidlparser.vala
@@ -1780,8 +1780,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);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]