[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 16:21:19 +0000 (UTC)
commit dadf88a047c267bacb1acce1ccfbf992577b74d1
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Aug 29 14:15:10 2010 +0200
girparser: Generalize symbol merging process
vala/valagirparser.vala | 308 ++++++++++++++++++++++++++---------------------
1 files changed, 173 insertions(+), 135 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 5bb7efd..1b7f4c6 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,125 @@ 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;
+ }
+
+ bool merge (SymbolInfo info, ArrayList<SymbolInfo> colliding) {
+ if (info.symbol is Signal) {
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Property) {
+ // properties take precedence
+ return true;
+ }
+ }
+ } else if (info.symbol is Method && !(info.symbol is CreationMethod)) {
+ var method = (Method) info.symbol;
+ if (method.name.has_prefix ("get_")) {
+ var infos = current_symbols_info[method.name.offset ("get_".length)];
+ if (infos != null) {
+ foreach (var cinfo in infos) {
+ var sym = cinfo.symbol;
+ if (sym is Property) {
+ // assume getter for property
+ ((Property) sym).no_accessor_method = false;
+ break;
+ }
+ }
+ }
+ }
+ if (method.is_virtual) {
+ // virtual-method
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Signal) {
+ var sig = (Signal) sym;
+ sig.is_virtual = true;
+ assume_parameter_names (sig, method);
+ return true;
+ } else if (sym is Property || sym is Field) {
+ // assume method is getter for property/field ignore method
+ return true;
+ }
+ }
+ } else {
+ // method
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Signal) {
+ var sig = (Signal) sym;
+ sig.has_emitter = true;
+ assume_parameter_names (sig, method);
+ return true;
+ } else if (sym is Property || sym is Field) {
+ // assume method is getter for property/field ignore method
+ return true;
+ } else if (sym is Method && ((Method) sym).is_virtual) {
+ // assume method is wrapper for virtual method
+ return true;
+ }
+ }
+ }
+ } else if (info.symbol is Field) {
+ // fields have lowest priority
+ if (colliding.size > 1) {
+ return true;
+ }
+ // length?
+ string array_name = null;
+ if (info.symbol.name.has_prefix ("n_")) {
+ array_name = info.symbol.name.offset (2);
+ } else if (info.symbol.name.has_suffix ("_length")) {
+ array_name = info.symbol.name.ndup (info.symbol.name.length - "_length".length);
+ }
+ if (array_name != null && current_symbols_info.contains (array_name)) {
+ var infos = current_symbols_info[array_name];
+ foreach (var cinfo in infos) {
+ var field = cinfo.symbol as Field;
+ if (field != null && field.variable_type is ArrayType) {
+ // found it
+ field.set_array_length_cname (info.symbol.name);
+ field.no_array_length = false;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ void merge_add_process (Symbol container) {
+ var add_list = new ArrayList<SymbolInfo> ();
+ foreach (var name in current_symbols_info.get_keys ()) {
+ var colliding = current_symbols_info[name];
+ foreach (var info in colliding) {
+ if (!merge (info, colliding)) {
+ add_list.add (info);
+ }
+ }
+ }
+
+ foreach (var info in add_list) {
+ add_symbol_to_container (container, info.symbol);
+ }
+ }
+
void parse_repository () {
start_element ("repository");
next ();
@@ -846,72 +972,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 +1418,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 +1428,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 +1483,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 +1493,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 +1527,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 +1608,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 +1627,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]