[vala/switch-to-gir: 19/34] girparser: Generalize symbol merging process
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir: 19/34] girparser: Generalize symbol merging process
- Date: Sun, 29 Aug 2010 22:24:26 +0000 (UTC)
commit d5f8030f26def9df8455d4cc50e0907b07a84050
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Aug 29 14:15:10 2010 +0200
girparser: Generalize symbol merging process
vala/valagirparser.vala | 295 +++++++++++++++++++++++++---------------------
1 files changed, 160 insertions(+), 135 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 5bb7efd..dfd1421 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -463,6 +463,11 @@ public class Vala.GirParser : CodeVisitor {
}
}
+ class SymbolInfo {
+ public Symbol symbol;
+ public Metadata metadata;
+ }
+
class CallbackScope {
public Namespace parent_namespace;
public UnresolvedSymbol gtype_struct_for;
@@ -489,6 +494,8 @@ public class Vala.GirParser : CodeVisitor {
string[] cheader_filenames;
+ HashMap<string,ArrayList<SymbolInfo>> current_symbols_info;
+
HashMap<UnresolvedSymbol,Symbol> unresolved_symbols_map = new HashMap<UnresolvedSymbol,Symbol> (unresolved_symbol_hash, unresolved_symbol_equal);
HashMap<Symbol,Symbol> concrete_symbols_map = new HashMap<Symbol,Symbol> ();
@@ -726,6 +733,112 @@ public class Vala.GirParser : CodeVisitor {
}
}
+ SymbolInfo? add_symbol_info (Symbol symbol) {
+ var name = symbol.name;
+ if (symbol is CreationMethod && name == null) {
+ name = ".new";
+ }
+
+ var info = new SymbolInfo ();
+ info.symbol = symbol;
+ info.metadata = metadata;
+ var colliding = current_symbols_info[name];
+ if (colliding == null) {
+ colliding = new ArrayList<SymbolInfo> ();
+ current_symbols_info[name] = colliding;
+ }
+ colliding.add (info);
+ return info;
+ }
+
+ void merge (SymbolInfo info, ArrayList<SymbolInfo> colliding, ArrayList<SymbolInfo> merged) {
+ if (info.symbol is Property) {
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Signal || sym is Field) {
+ // properties take precedence
+ merged.add (cinfo);
+ } else if (sym is Method) {
+ // assume method is getter
+ merged.add (cinfo);
+ }
+ }
+ var getter_name = "get_%s".printf (info.symbol.name);
+ if (current_symbols_info.contains (getter_name)) {
+ ((Property) info.symbol).no_accessor_method = false;
+ }
+ } else if (info.symbol is Signal) {
+ var sig = (Signal) info.symbol;
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Method) {
+ var method = (Method) sym;
+ if (method.is_virtual) {
+ sig.is_virtual = true;
+ } else {
+ sig.has_emitter = true;
+ }
+ assume_parameter_names (sig, method);
+ merged.add (cinfo);
+ } else if (sym is Field) {
+ merged.add (cinfo);
+ }
+ }
+ } else if (info.symbol is Method && !(info.symbol is CreationMethod)) {
+ var method = (Method) info.symbol;
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym != method && method.is_virtual && sym is Method) {
+ // assume method is wrapper
+ merged.add (cinfo);
+ }
+ }
+ } else if (info.symbol is Field) {
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Method) {
+ // assume method is getter
+ merged.add (cinfo);
+ }
+ }
+
+ var field = (Field) info.symbol;
+ if (field.variable_type is ArrayType) {
+ SymbolInfo array_length = null;
+ if (current_symbols_info.contains ("n_%s".printf (field.name))) {
+ array_length = current_symbols_info.get ("n_%s".printf (field.name)).get (0);
+ } else if (current_symbols_info.contains ("%s_length".printf (field.name))) {
+ array_length = current_symbols_info.get ("%s_length".printf (field.name)).get (0);
+ }
+ if (array_length != null) {
+ // array has length
+ field.set_array_length_cname (array_length.symbol.name);
+ field.no_array_length = false;
+ merged.add (array_length);
+ }
+ }
+ }
+ }
+
+ void merge_add_process (Symbol container) {
+ var merged = new ArrayList<SymbolInfo> ();
+ foreach (var name in current_symbols_info.get_keys ()) {
+ var colliding = current_symbols_info[name];
+ foreach (var info in colliding) {
+ merge (info, colliding, merged);
+ }
+ }
+
+ foreach (var infos in current_symbols_info.get_values ()) {
+ foreach (var info in infos) {
+ if (merged.contains (info)) {
+ continue;
+ }
+ add_symbol_to_container (container, info.symbol);
+ }
+ }
+ }
+
void parse_repository () {
start_element ("repository");
next ();
@@ -846,72 +959,58 @@ public class Vala.GirParser : CodeVisitor {
current_namespace_methods = new ArrayList<Method> ();
namespace_methods[ns] = current_namespace_methods;
}
+ var old_symbols_info = current_symbols_info;
+ current_symbols_info = new HashMap<string,ArrayList<SymbolInfo>> (str_hash, str_equal);
while (current_token == MarkupTokenType.START_ELEMENT) {
if (reader.get_attribute ("introspectable") == "0") {
skip_element ();
continue;
}
- Symbol sym = null;
if (reader.name == "alias") {
var alias = parse_alias ();
aliases.add (alias);
} else if (reader.name == "enumeration") {
if (reader.get_attribute ("glib:error-quark") != null) {
- sym = parse_error_domain ();
+ add_symbol_info (parse_error_domain ());
} else {
- sym = parse_enumeration ();
+ add_symbol_info (parse_enumeration ());
}
} else if (reader.name == "bitfield") {
- sym = parse_bitfield ();
+ add_symbol_info (parse_bitfield ());
} else if (reader.name == "function") {
current_namespace_methods.add (parse_method ("function"));
} else if (reader.name == "callback") {
- sym = parse_callback ();
+ add_symbol_info (parse_callback ());
} else if (reader.name == "record") {
if (reader.get_attribute ("glib:get-type") != null) {
- sym = parse_boxed ();
+ add_symbol_info (parse_boxed ());
} else {
- sym = parse_record ();
+ var record = parse_record ();
+ if (record != null) {
+ add_symbol_info (record);
+ }
}
} else if (reader.name == "class") {
- sym = parse_class ();
+ add_symbol_info (parse_class ());
} else if (reader.name == "interface") {
- sym = parse_interface ();
+ add_symbol_info (parse_interface ());
} else if (reader.name == "glib:boxed") {
- sym = parse_boxed ();
+ add_symbol_info (parse_boxed ());
} else if (reader.name == "union") {
- sym = parse_union ();
+ add_symbol_info (parse_union ());
} else if (reader.name == "constant") {
- sym = parse_constant ();
+ add_symbol_info (parse_constant ());
} else {
// error
Report.error (get_current_src (), "unknown child element `%s' in `namespace'".printf (reader.name));
- break;
- }
-
- if (sym is Class) {
- ns.add_class ((Class) sym);
- } else if (sym is Interface) {
- ns.add_interface ((Interface) sym);
- } else if (sym is Struct) {
- ns.add_struct ((Struct) sym);
- } else if (sym is Enum) {
- ns.add_enum ((Enum) sym);
- } else if (sym is ErrorDomain) {
- ns.add_error_domain ((ErrorDomain) sym);
- } else if (sym is Delegate) {
- ns.add_delegate ((Delegate) sym);
- } else if (sym is Method) {
- ns.add_method ((Method) sym);
- } else if (sym is Constant) {
- ns.add_constant ((Constant) sym);
- } else if (sym == null) {
- continue;
+ skip_element ();
}
}
end_element ("namespace");
+ merge_add_process (ns);
+ current_symbols_info = old_symbols_info;
current_namespace = old_namespace;
if (!new_namespace) {
@@ -1306,10 +1405,8 @@ public class Vala.GirParser : CodeVisitor {
}
next ();
- var signals = new ArrayList<Signal> ();
- var methods = new ArrayList<Method> ();
- var vmethods = new ArrayList<Method> ();
- var fields = new ArrayList<Field> ();
+ var old_symbols_info = current_symbols_info;
+ current_symbols_info = new HashMap<string,ArrayList<SymbolInfo>> (str_hash, str_equal);
while (current_token == MarkupTokenType.START_ELEMENT) {
if (reader.get_attribute ("introspectable") == "0") {
skip_element ();
@@ -1318,91 +1415,42 @@ public class Vala.GirParser : CodeVisitor {
if (reader.name == "implements") {
start_element ("implements");
- cl.add_base_type (parse_type_from_name (reader.get_attribute ("name")));
+ cl.add_base_type (parse_type_from_gir_name (reader.get_attribute ("name")));
next ();
end_element ("implements");
} else if (reader.name == "constant") {
- cl.add_constant (parse_constant ());
+ add_symbol_info (parse_constant ());
} else if (reader.name == "field") {
- fields.add (parse_field ());
+ add_symbol_info (parse_field ());
} else if (reader.name == "property") {
- cl.add_property (parse_property ());
+ add_symbol_info (parse_property ());
} else if (reader.name == "constructor") {
- cl.add_method (parse_constructor (cname));
+ add_symbol_info (parse_constructor (cname));
} else if (reader.name == "function") {
- methods.add (parse_method ("function"));
+ add_symbol_info (parse_method ("function"));
} else if (reader.name == "method") {
- methods.add (parse_method ("method"));
+ add_symbol_info (parse_method ("method"));
} else if (reader.name == "virtual-method") {
- vmethods.add (parse_method ("virtual-method"));
+ add_symbol_info (parse_method ("virtual-method"));
} else if (reader.name == "union") {
Struct s = parse_union ();
var s_fields = s.get_fields ();
foreach (var f in s_fields) {
f.set_cname (s.get_cname () + "." + f.get_cname ());
f.name = s.name + "_" + f.name;
- fields.add (f);
+ add_symbol_info (f);
}
} else if (reader.name == "glib:signal") {
- signals.add (parse_signal ());
+ add_symbol_info (parse_signal ());
} else {
// error
Report.error (get_current_src (), "unknown child element `%s' in `class'".printf (reader.name));
- break;
- }
- }
-
- // signal merging
- foreach (Signal sig in signals) {
- var symbol = cl.scope.lookup (sig.name);
- if (symbol == null) {
- cl.add_signal (sig);
- } else if (symbol is Property) {
- // properties take precedence
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (sig.name, cl.name));
- }
- }
-
- // virtual method merging
- foreach (Method m in vmethods) {
- var symbol = cl.scope.lookup (m.name);
- if (symbol == null) {
- cl.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.is_virtual = true;
- } else if (symbol is Property || symbol is Field) {
- // assume method is getter for property/field ignore method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, cl.name));
- }
- }
-
- // method merging
- foreach (Method m in methods) {
- var symbol = cl.scope.lookup (m.name);
- if (symbol == null) {
- cl.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.has_emitter = true;
- } else if (symbol is Property || symbol is Field) {
- // assume method is getter for property/field ignore method
- } else if (symbol is Method) {
- // assume method is wrapper for virtual method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, cl.name));
+ skip_element ();
}
}
- // fields have lowest priority
- foreach (Field f in fields) {
- var symbol = cl.scope.lookup (f.name);
- if (symbol == null) {
- cl.add_field (f);
- }
- }
+ merge_add_process (cl);
+ current_symbols_info = old_symbols_info;
handle_async_methods (cl);
@@ -1422,8 +1470,8 @@ public class Vala.GirParser : CodeVisitor {
}
next ();
- var methods = new ArrayList<Method> ();
- var vmethods = new ArrayList<Method> ();
+ var old_symbols_info = current_symbols_info;
+ current_symbols_info = new HashMap<string,ArrayList<SymbolInfo>> (str_hash, str_equal);
while (current_token == MarkupTokenType.START_ELEMENT) {
if (reader.get_attribute ("introspectable") == "0") {
skip_element ();
@@ -1432,25 +1480,25 @@ public class Vala.GirParser : CodeVisitor {
if (reader.name == "prerequisite") {
start_element ("prerequisite");
- iface.add_prerequisite (parse_type_from_name (reader.get_attribute ("name")));
+ iface.add_prerequisite (parse_type_from_gir_name (reader.get_attribute ("name")));
next ();
end_element ("prerequisite");
} else if (reader.name == "field") {
parse_field ();
} else if (reader.name == "property") {
- iface.add_property (parse_property ());
+ add_symbol_info (parse_property ());
} else if (reader.name == "virtual-method") {
- vmethods.add (parse_method ("virtual-method"));
+ add_symbol_info (parse_method ("virtual-method"));
} else if (reader.name == "function") {
- methods.add (parse_method ("function"));
+ add_symbol_info (parse_method ("function"));
} else if (reader.name == "method") {
- methods.add (parse_method ("method"));
+ add_symbol_info (parse_method ("method"));
} else if (reader.name == "glib:signal") {
- iface.add_signal (parse_signal ());
+ add_symbol_info (parse_signal ());
} else {
// error
Report.error (get_current_src (), "unknown child element `%s' in `interface'".printf (reader.name));
- break;
+ skip_element ();
}
}
@@ -1466,33 +1514,8 @@ public class Vala.GirParser : CodeVisitor {
if (!has_instantiable_prereq)
iface.add_prerequisite (new ObjectType ((ObjectTypeSymbol) glib_ns.scope.lookup ("Object")));
- // virtual method merging
- foreach (Method m in vmethods) {
- var symbol = iface.scope.lookup (m.name);
- if (symbol == null) {
- iface.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.is_virtual = true;
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, iface.name));
- }
- }
-
- // method merging
- foreach (Method m in methods) {
- var symbol = iface.scope.lookup (m.name);
- if (symbol == null) {
- iface.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.has_emitter = true;
- } else if (symbol is Method) {
- // assume method is wrapper for virtual method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, iface.name));
- }
- }
+ merge_add_process (iface);
+ current_symbols_info = old_symbols_info;
handle_async_methods (iface);
@@ -1572,6 +1595,7 @@ public class Vala.GirParser : CodeVisitor {
}
var field = new Field (name, type, null, get_current_src ());
field.access = SymbolAccessibility.PUBLIC;
+ field.no_array_length = true;
if (allow_none == "1") {
type.nullable = true;
}
@@ -1590,6 +1614,7 @@ public class Vala.GirParser : CodeVisitor {
var type = parse_type ();
var prop = new Property (name, type, null, null, get_current_src ());
prop.access = SymbolAccessibility.PUBLIC;
+ prop.no_accessor_method = true;
if (readable != "0") {
prop.get_accessor = new PropertyAccessor (true, false, false, prop.property_type.copy (), null, null);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]