[vala/switch-to-gir] girparser: Support reparenting symbols



commit 4398462ba04f7cd802f09fdea44316dce01927c2
Author: Luca Bruno <lethalman88 gmail com>
Date:   Thu Aug 26 21:56:24 2010 +0200

    girparser: Support reparenting symbols

 vala/valagirparser.vala  |  218 +++++++++++++++++++++++++++++++++++++++++-----
 vapigen/valavapigen.vala |   19 +++--
 2 files changed, 205 insertions(+), 32 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 8347503..ed71a54 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -29,7 +29,9 @@ using GLib;
  * 1) Parse metadata
  * 2) Parse GIR with metadata, track unresolved GIR symbols, create symbol mappings
  * 3) Reconciliate the tree by mapping tracked symbols
- * 4) Do post-parsing/symbol-resolving operations on the reconciliated tree
+ * 4) Reparent nodes
+ * 5) Process callbacks/virtual
+ * 6) Process aliases
  */
 public class Vala.GirParser : CodeVisitor {
 	enum MetadataType {
@@ -44,7 +46,8 @@ public class Vala.GirParser : CodeVisitor {
 		CHEADER_FILENAME,
 		NAME,
 		OWNED,
-		UNOWNED;
+		UNOWNED,
+		PARENT;
 
 		public static ArgumentType? from_string (string name) {
 			var enum_class = (EnumClass) typeof(ArgumentType).class_ref ();
@@ -143,7 +146,6 @@ public class Vala.GirParser : CodeVisitor {
 			if (lit != null) {
 				return lit.eval ();
 			}
-
 			return null;
 		}
 
@@ -173,9 +175,16 @@ public class Vala.GirParser : CodeVisitor {
 			if (lit != null) {
 				return lit.value;
 			}
-
 			return false;
 		}
+
+		public SourceReference? get_source_reference (ArgumentType arg) {
+			var val = args.get (arg);
+			if (val != null) {
+				return val.source_reference;
+			}
+			return null;
+		}
 	}
 
 	class MetadataParser {
@@ -457,6 +466,7 @@ public class Vala.GirParser : CodeVisitor {
 
 	HashMap<UnresolvedSymbol,Symbol> symbols_map = new HashMap<UnresolvedSymbol,Symbol> (unresolved_symbol_hash, unresolved_symbol_equal);
 	ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
+	HashMap<UnresolvedSymbol,ArrayList<Symbol>> symbol_reparent_map = new HashMap<UnresolvedSymbol,ArrayList<Symbol>> (unresolved_symbol_hash, unresolved_symbol_equal);
 
 	HashMap<CallbackScope,ArrayList<Delegate>> gtype_callbacks = new HashMap<CallbackScope,ArrayList<Delegate>> (callback_scope_hash, callback_scope_equal);
 	ArrayList<Alias> aliases = new ArrayList<Alias> ();
@@ -474,6 +484,7 @@ public class Vala.GirParser : CodeVisitor {
 
 		resolve_gir_symbols ();
 
+		postprocess_reparenting ();
 		postprocess_gtype_callbacks ();
 		postprocess_aliases ();
 	}
@@ -511,7 +522,9 @@ public class Vala.GirParser : CodeVisitor {
 		string metadata_filename = "%s.metadata".printf (source_file.filename.ndup (source_file.filename.length - ".gir".length));
 		if (FileUtils.test (metadata_filename, FileTest.EXISTS)) {
 			var metadata_parser = new MetadataParser ();
-			metadata = metadata_parser.parse_metadata (new SourceFile (context, metadata_filename, true));
+			var metadata_file = new SourceFile (context, metadata_filename, source_file.external_package);
+			context.add_source_file (metadata_file);
+			metadata = metadata_parser.parse_metadata (metadata_file);
 		}
 
 		reader = new MarkupReader (source_file.filename);
@@ -737,8 +750,7 @@ public class Vala.GirParser : CodeVisitor {
 		}
 
 		if (metadata.has_argument (arg_type)) {
-			var src = metadata.args.get (arg_type).expression.source_reference;
-			var new_type = parse_type_from_string (metadata.get_string (arg_type), owned_by_default, src);
+			var new_type = parse_type_from_string (metadata.get_string (arg_type), owned_by_default, metadata.get_source_reference (arg_type));
 			if (&changed != null) {
 				changed = true;
 			}
@@ -773,6 +785,25 @@ public class Vala.GirParser : CodeVisitor {
 		return str;
 	}
 
+	void element_reparent (Symbol symbol) {
+		if (metadata.has_argument (ArgumentType.PARENT)) {
+			var target_symbol = parse_symbol_from_string (metadata.get_string (ArgumentType.PARENT), metadata.get_source_reference (ArgumentType.PARENT));
+			var reparent_list = symbol_reparent_map[target_symbol];
+			if (reparent_list == null) {
+				reparent_list = new ArrayList<Symbol>();
+				symbol_reparent_map[target_symbol] = reparent_list;
+			}
+			reparent_list.add (symbol);
+		}
+	}
+
+	bool element_can_add () {
+		if (metadata.has_argument (ArgumentType.PARENT) || metadata.get_bool (ArgumentType.HIDDEN)) {
+			return false;
+		}
+		return true;
+	}
+
 	void parse_repository () {
 		start_element ("repository");
 		next ();
@@ -942,22 +973,24 @@ public class Vala.GirParser : CodeVisitor {
 				skip_element ();
 			}
 
-			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);
+			if (sym != null && element_can_add ()) {
+				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);
+				}
 			}
 
 			pop_metadata ();
@@ -2042,6 +2075,7 @@ public class Vala.GirParser : CodeVisitor {
 		var c = new Constant (name, type, null, get_current_src ());
 		c.access = SymbolAccessibility.PUBLIC;
 		c.external = true;
+		element_reparent (c);
 		end_element ("constant");
 		return c;
 	}
@@ -2098,11 +2132,147 @@ public class Vala.GirParser : CodeVisitor {
 		return null;
 	}
 
+	private void add_symbol_to_container (Symbol container, Symbol sym) {
+		if (container is Class) {
+			unowned Class cl = (Class) container;
+
+			if (sym is Class) {
+				cl.add_class ((Class) sym);
+			} else if (sym is Constant) {
+				cl.add_constant ((Constant) sym);
+			} else if (sym is Enum) {
+				cl.add_enum ((Enum) sym);
+			} else if (sym is Field) {
+				cl.add_field ((Field) sym);
+			} else if (sym is Method) {
+				cl.add_method ((Method) sym);
+			} else if (sym is Property) {
+				cl.add_property ((Property) sym);
+			} else if (sym is Signal) {
+				cl.add_signal ((Signal) sym);
+			} else if (sym is Struct) {
+				cl.add_struct ((Struct) sym);
+			}
+		} else if (container is Enum) {
+			unowned Enum en = (Enum) container;
+
+			if (sym is EnumValue) {
+				en.add_value ((EnumValue) sym);
+			} else if (sym is Constant) {
+				en.add_constant ((Constant) sym);
+			} else if (sym is Method) {
+				en.add_method ((Method) sym);
+			}
+		} else if (container is Interface) {
+			unowned Interface iface = (Interface) container;
+
+			if (sym is Class) {
+				iface.add_class ((Class) sym);
+			} else if (sym is Constant) {
+				iface.add_constant ((Constant) sym);
+			} else if (sym is Enum) {
+				iface.add_enum ((Enum) sym);
+			} else if (sym is Field) {
+				iface.add_field ((Field) sym);
+			} else if (sym is Method) {
+				iface.add_method ((Method) sym);
+			} else if (sym is Property) {
+				iface.add_property ((Property) sym);
+			} else if (sym is Signal) {
+				iface.add_signal ((Signal) sym);
+			} else if (sym is Struct) {
+				iface.add_struct ((Struct) sym);
+			}
+		} else if (container is Namespace) {
+			unowned Namespace ns = (Namespace) container;
+
+			if (sym is Namespace) {
+				ns.add_namespace ((Namespace) sym);
+			} else if (sym is Class) {
+				ns.add_class ((Class) sym);
+			} else if (sym is Constant) {
+				ns.add_constant ((Constant) sym);
+			} else if (sym is Delegate) {
+				ns.add_delegate ((Delegate) 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 Field) {
+				ns.add_field ((Field) sym);
+			} else if (sym is Interface) {
+				ns.add_interface ((Interface) sym);
+			} else if (sym is Method) {
+				ns.add_method ((Method) sym);
+			} else if (sym is Namespace) {
+				ns.add_namespace ((Namespace) sym);
+			} else if (sym is Struct) {
+				ns.add_struct ((Struct) sym);
+			}
+		} else if (container is Struct) {
+			unowned Struct st = (Struct) container;
+
+			if (sym is Constant) {
+				st.add_constant ((Constant) sym);
+			} else if (sym is Field) {
+				st.add_field ((Field) sym);
+			} else if (sym is Method) {
+				st.add_method ((Method) sym);
+			} else if (sym is Property) {
+				st.add_property ((Property) sym);
+			}
+		} else {
+			Report.error (sym.source_reference, "impossible to add to container `%s'".printf (container.name));
+		}
+	}
+
+	void postprocess_reparenting () {
+		foreach (UnresolvedSymbol target_unresolved_symbol in symbol_reparent_map.get_keys ()) {
+			var target_symbol = resolve_symbol (context.root.scope, target_unresolved_symbol);
+			if (target_symbol == null) {
+				// create namespaces backward
+				var sym = target_unresolved_symbol;
+				var ns = new Namespace (sym.name, sym.source_reference);
+				var result = ns;
+				sym = sym.inner;
+				while (sym != null) {
+					var res = resolve_symbol (context.root.scope, sym);
+					if (res != null && !(res is Namespace)) {
+						result = null;
+						break;
+					}
+					var parent = res as Namespace;
+					if (res == null) {
+						parent = new Namespace (sym.name, sym.source_reference);
+					}
+					if (parent.scope.lookup (ns.name) == null) {
+						parent.add_namespace (ns);
+					}
+					ns = parent;
+					sym = sym.inner;
+				}
+				if (result != null && sym == null && context.root.scope.lookup (ns.name) == null) {
+					// a new root namespace, helpful for a possible non-gobject gir?
+					context.root.add_namespace (ns);
+				}
+				target_symbol = result;
+			}
+			if (target_symbol == null) {
+				Report.error (null, "unable to reparent into `%s'".printf (target_unresolved_symbol.to_string ()));
+				continue;
+			}
+			var symbols = symbol_reparent_map[target_unresolved_symbol];
+			foreach (var symbol in symbols) {
+				add_symbol_to_container (target_symbol, symbol);
+			}
+		}
+	}
+
 	void postprocess_gtype_callbacks () {
 		foreach (CallbackScope callback_scope in gtype_callbacks.get_keys ()) {
 			var gtype = resolve_symbol (callback_scope.parent_namespace.scope, callback_scope.gtype_struct_for) as ObjectTypeSymbol;
 			if (gtype == null) {
-				Report.error (null, "unknown symbol %s".printf (callback_scope.gtype_struct_for.to_string ()));
+				Report.error (null, "unknown symbol `%s'".printf (callback_scope.gtype_struct_for.to_string ()));
 				continue;
 			}
 			ArrayList<Delegate> callbacks = gtype_callbacks.get (callback_scope);
diff --git a/vapigen/valavapigen.vala b/vapigen/valavapigen.vala
index f0a4697..3dd19fe 100644
--- a/vapigen/valavapigen.vala
+++ b/vapigen/valavapigen.vala
@@ -119,18 +119,13 @@ class Vala.VAPIGen : Object {
 			return quit ();
 		}
 		
-		/* source files to be later unmarked as external_package */
-		var source_files = new ArrayList<SourceFile> ();
 		foreach (string source in sources) {
 			if (FileUtils.test (source, FileTest.EXISTS)) {
-				var source_file = new SourceFile (context, source, true);
-				source_files.add (source_file);
-				context.add_source_file (source_file);
+				context.add_source_file (new SourceFile (context, source, true));
 			} else {
 				Report.error (null, "%s not found".printf (source));
 			}
 		}
-		sources = null;
 		
 		if (context.report.get_errors () > 0) {
 			return quit ();
@@ -172,9 +167,17 @@ class Vala.VAPIGen : Object {
 		}
 		
 		// interface writer ignores external packages
-		foreach (SourceFile file in source_files) {
-			if (!file.filename.has_suffix (".vapi")) {
+		foreach (SourceFile file in context.get_source_files ()) {
+			if (file.filename.has_suffix (".vapi")) {
+				continue;
+			}
+			if (file.filename in sources) {
 				file.external_package = false;
+			} else if (file.filename.has_suffix (".metadata")) {
+				string gir_filename = "%s.gir".printf (file.filename.ndup (file.filename.length - ".metadata".length));
+				if (gir_filename in sources) {
+					file.external_package = false;
+				}
 			}
 		}
 



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