[vala/switch-to-gir: 14/34] girparser: Postprocess symbols remapping



commit 043dba3c13ced44c57b85ddc105a586a44af7ff7
Author: Luca Bruno <lucabru src gnome org>
Date:   Sun Aug 29 13:22:37 2010 +0200

    girparser: Postprocess symbols remapping

 vala/valagirparser.vala |  158 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 144 insertions(+), 14 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index cea46da..66da5ca 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -475,6 +475,11 @@ public class Vala.GirParser : CodeVisitor {
 
 	string[] cheader_filenames;
 
+	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> ();
+
+	ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
+
 	HashMap<string,ArrayList<Method>> gtype_callbacks = new HashMap<string,ArrayList<Method>> (str_hash, str_equal);
 
 	/**
@@ -487,9 +492,30 @@ public class Vala.GirParser : CodeVisitor {
 		this.context = context;
 		glib_ns = context.root.scope.lookup ("GLib") as Namespace;
 		context.accept (this);
+
+		resolve_gir_symbols ();
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
+		// collect gir namespaces
+		foreach (var node in source_file.get_nodes ()) {
+			if (node is Namespace) {
+				var ns = (Namespace) node;
+				var gir_namespace = source_file.gir_namespace;
+				if (gir_namespace == null) {
+					var a = ns.get_attribute ("CCode");
+					if (a != null && a.has_argument ("gir_namespace")) {
+						gir_namespace = a.get_string ("gir_namespace");
+					}
+				}
+				if (gir_namespace != null && gir_namespace != ns.name) {
+					var map_from = new UnresolvedSymbol (null, gir_namespace);
+					set_symbol_mapping (map_from, ns);
+					break;
+				}
+			}
+		}
+
 		if (source_file.filename.has_suffix (".gir")) {
 			parse_file (source_file);
 		}
@@ -576,6 +602,29 @@ public class Vala.GirParser : CodeVisitor {
 		return sym;
 	}
 
+	UnresolvedSymbol get_unresolved_symbol (Symbol symbol) {
+		if (symbol is UnresolvedSymbol) {
+			return (UnresolvedSymbol) symbol;
+		}
+		var sym = new UnresolvedSymbol (null, symbol.name);
+		var result = sym;
+		var cur = symbol.parent_node as Symbol;
+		while (cur != null && cur.name != null) {
+			sym = new UnresolvedSymbol (sym, cur.name);
+			cur = cur.parent_node as Symbol;
+		}
+		return result;
+	}
+
+	void set_symbol_mapping (Symbol map_from, Symbol map_to) {
+		// last mapping is the most up-to-date
+		if (map_from is UnresolvedSymbol) {
+			unresolved_symbols_map[(UnresolvedSymbol) map_from] = map_to;
+		} else {
+			concrete_symbols_map[map_from] = map_to;
+		}
+	}
+
 	void parse_repository () {
 		start_element ("repository");
 		next ();
@@ -655,7 +704,16 @@ public class Vala.GirParser : CodeVisitor {
 		start_element ("namespace");
 
 		bool new_namespace = false;
-		string namespace_name = transform_namespace_name (reader.get_attribute ("name"));
+		string? cprefix = reader.get_attribute ("c:prefix");
+		string namespace_name = cprefix;
+		string gir_namespace = reader.get_attribute ("name");
+		string gir_version = reader.get_attribute ("version");
+		if (namespace_name == null) {
+			namespace_name = gir_namespace;
+		}
+		current_source_file.gir_namespace = gir_namespace;
+		current_source_file.gir_version = gir_version;
+
 		var ns = context.root.scope.lookup (namespace_name) as Namespace;
 		if (ns == null) {
 			ns = new Namespace (namespace_name, get_current_src ());
@@ -666,8 +724,10 @@ public class Vala.GirParser : CodeVisitor {
 				ns.source_reference = get_current_src ();
 			}
 		}
+		if (gir_namespace != ns.name) {
+			set_symbol_mapping (new UnresolvedSymbol (null, gir_namespace), ns);
+		}
 
-		string? cprefix = reader.get_attribute ("c:prefix");
 		if (cprefix != null) {
 			ns.add_cprefix (cprefix);
 			ns.set_lower_case_cprefix (Symbol.camel_case_to_lower_case (cprefix) + "_");
@@ -1037,6 +1097,7 @@ public class Vala.GirParser : CodeVisitor {
 		} else if (type_name == "GObject.Strv") {
 			type = new ArrayType (new UnresolvedType.from_symbol (new UnresolvedSymbol (null, "string")), 1, get_current_src ());
 		} else {
+			bool known_type = true;
 			if (type_name == "utf8") {
 				type_name = "string";
 			} else if (type_name == "boolean") {
@@ -1057,25 +1118,19 @@ public class Vala.GirParser : CodeVisitor {
 				type_name = "GLib.Datalist";
 			} else if (type_name == "Atk.ImplementorIface") {
 				type_name = "Atk.Implementor";
+			} else {
+				known_type = false;
 			}
 			var sym = parse_symbol_from_string (type_name, get_current_src ());
 			type = new UnresolvedType.from_symbol (sym, get_current_src ());
+			if (!known_type) {
+				unresolved_gir_symbols.add (sym);
+			}
 		}
 
 		return type;
 	}
 
-	string transform_namespace_name (string gir_module_name) {
-		if (gir_module_name == "GObject") {
-			return "GLib";
-		} else if (gir_module_name == "Gio") {
-			return "GLib";
-		} else if (gir_module_name == "GModule") {
-			return "GLib";
-		}
-		return gir_module_name;
-	}
-
 	Struct parse_record () {
 		start_element ("record");
 		var st = new Struct (reader.get_attribute ("name"), get_current_src ());
@@ -1801,5 +1856,80 @@ public class Vala.GirParser : CodeVisitor {
 		end_element ("constant");
 		return c;
 	}
-}
 
+	/* Post-parsing */
+
+	void resolve_gir_symbols () {
+		// we are remapping unresolved symbols, so create them from concrete symbols
+		foreach (var map_from in concrete_symbols_map.get_keys ()) {
+			unresolved_symbols_map[get_unresolved_symbol(map_from)] = concrete_symbols_map[map_from];
+		}
+
+		// gir has simple namespaces, we won't get deeper than 2 levels here, except reparenting
+		foreach (var map_from in unresolved_gir_symbols) {
+			while (map_from != null) {
+				var map_to = unresolved_symbols_map[map_from];
+				if (map_to != null) {
+					// remap the original symbol to match the target
+					map_from.inner = null;
+					map_from.name = map_to.name;
+					if (map_to is UnresolvedSymbol) {
+						var umap_to = (UnresolvedSymbol) map_to;
+						while (umap_to.inner != null) {
+							umap_to = umap_to.inner;
+							map_from.inner = new UnresolvedSymbol (null, umap_to.name);
+							map_from = map_from.inner;
+						}
+					} else {
+						while (map_to.parent_symbol != null && map_to.parent_symbol != context.root) {
+							map_to = map_to.parent_symbol;
+							map_from.inner = new UnresolvedSymbol (null, map_to.name);
+							map_from = map_from.inner;
+						}
+					}
+					break;
+				}
+				map_from = map_from.inner;
+			}
+		}
+	}
+
+	/* Hash and equal functions */
+
+	static uint unresolved_symbol_hash (void *ptr) {
+		var sym = (UnresolvedSymbol) ptr;
+		var builder = new StringBuilder ();
+		while (sym != null) {
+			builder.append (sym.name);
+			sym = sym.inner;
+		}
+		return builder.str.hash ();
+	}
+
+	static bool unresolved_symbol_equal (void *ptr1, void *ptr2) {
+		var sym1 = (UnresolvedSymbol) ptr1;
+		var sym2 = (UnresolvedSymbol) ptr2;
+		while (sym1 != sym2) {
+			if (sym1 == null || sym2 == null) {
+				return false;
+			}
+			if (sym1.name != sym2.name) {
+				return false;
+			}
+			sym1 = sym1.inner;
+			sym2 = sym2.inner;
+		}
+		return true;
+	}
+
+	static uint callback_scope_hash (void *ptr) {
+		var cs = (CallbackScope) ptr;
+		return unresolved_symbol_hash (cs.gtype_struct_for);
+	}
+
+	static bool callback_scope_equal (void *ptr1, void *ptr2) {
+		var cs1 = (CallbackScope) ptr1;
+		var cs2 = (CallbackScope) ptr2;
+		return cs1.parent_namespace == cs2.parent_namespace && unresolved_symbol_equal (cs1.gtype_struct_for, cs2.gtype_struct_for);
+	}
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]