[vala/switch-to-gir: 15/34] girparser: Postprocess gtype callbacks and fix them for gir 1.0



commit 7d49dd6a6aa0413dbe22f64000ab39aadda1ceae
Author: Luca Bruno <lucabru src gnome org>
Date:   Sun Aug 29 13:31:58 2010 +0200

    girparser: Postprocess gtype callbacks and fix them for gir 1.0

 vala/valagirparser.vala |  135 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 96 insertions(+), 39 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 66da5ca..c5f263c 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -463,12 +463,19 @@ public class Vala.GirParser : CodeVisitor {
 		}
 	}
 
+	class CallbackScope {
+		public Namespace parent_namespace;
+		public UnresolvedSymbol gtype_struct_for;
+	}
+
 	MarkupReader reader;
 
 	CodeContext context;
 	Namespace glib_ns;
 
 	SourceFile current_source_file;
+	Namespace current_namespace;
+	string current_gtype_struct_for;
 	SourceLocation begin;
 	SourceLocation end;
 	MarkupTokenType current_token;
@@ -480,7 +487,7 @@ public class Vala.GirParser : CodeVisitor {
 
 	ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
 
-	HashMap<string,ArrayList<Method>> gtype_callbacks = new HashMap<string,ArrayList<Method>> (str_hash, str_equal);
+	HashMap<CallbackScope,ArrayList<Delegate>> gtype_callbacks = new HashMap<CallbackScope,ArrayList<Delegate>> (callback_scope_hash, callback_scope_equal);
 
 	/**
 	 * Parses all .gir source files in the specified code
@@ -494,6 +501,8 @@ public class Vala.GirParser : CodeVisitor {
 		context.accept (this);
 
 		resolve_gir_symbols ();
+
+		postprocess_gtype_callbacks ();
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
@@ -625,6 +634,22 @@ public class Vala.GirParser : CodeVisitor {
 		}
 	}
 
+	void assume_parameter_names (Signal sig, Symbol sym) {
+		Iterator<FormalParameter> iter;
+		if (sym is Method) {
+			iter = ((Method) sym).get_parameters ().iterator ();
+		} else {
+			iter = ((Delegate) sym).get_parameters ().iterator ();
+		}
+		foreach (var param in sig.get_parameters ()) {
+			if (!iter.next ()) {
+				// unreachable for valid GIR
+				break;
+			}
+			param.name = iter.get ().name;
+		}
+	}
+
 	void parse_repository () {
 		start_element ("repository");
 		next ();
@@ -728,6 +753,9 @@ public class Vala.GirParser : CodeVisitor {
 			set_symbol_mapping (new UnresolvedSymbol (null, gir_namespace), ns);
 		}
 
+		var old_namespace = current_namespace;
+		current_namespace = ns;
+
 		if (cprefix != null) {
 			ns.add_cprefix (cprefix);
 			ns.set_lower_case_cprefix (Symbol.camel_case_to_lower_case (cprefix) + "_");
@@ -802,7 +830,7 @@ public class Vala.GirParser : CodeVisitor {
 		}
 		end_element ("namespace");
 
-		postprocess_gtype_callbacks (ns);
+		current_namespace = old_namespace;
 
 		if (!new_namespace) {
 			ns = null;
@@ -1136,7 +1164,7 @@ public class Vala.GirParser : CodeVisitor {
 		var st = new Struct (reader.get_attribute ("name"), get_current_src ());
 		st.external = true;
 
-		string glib_is_gtype_struct_for = reader.get_attribute ("glib:is-gtype-struct-for");
+		current_gtype_struct_for = reader.get_attribute ("glib:is-gtype-struct-for");
 
 		st.access = SymbolAccessibility.PUBLIC;
 		next ();
@@ -1148,17 +1176,6 @@ public class Vala.GirParser : CodeVisitor {
 
 			if (reader.name == "field") {
 				st.add_field (parse_field ());
-			} else if (reader.name == "callback") {
-				if (glib_is_gtype_struct_for != null) {
-					ArrayList<Method> callbacks = gtype_callbacks.get (glib_is_gtype_struct_for);
-					if (callbacks == null) {
-						callbacks = new ArrayList<Method> ();
-						gtype_callbacks.set (glib_is_gtype_struct_for, callbacks);
-					}
-					callbacks.add (parse_method ("callback"));
-				} else {
-					parse_callback ();
-				}
 			} else if (reader.name == "constructor") {
 				parse_constructor ();
 			} else if (reader.name == "method") {
@@ -1181,31 +1198,6 @@ public class Vala.GirParser : CodeVisitor {
 		return st;
 	}
 
-	void postprocess_gtype_callbacks (Namespace ns) {
-		foreach (string gtype_name in gtype_callbacks.get_keys ()) {
-			var gtype = ns.scope.lookup (gtype_name) as ObjectTypeSymbol;
-			ArrayList<Method> callbacks = gtype_callbacks.get (gtype_name);
-			foreach (Method m in callbacks) {
-				var symbol = gtype.scope.lookup (m.name);
-				if (symbol == null) {
-					continue;
-				} else if (symbol is Method)  {
-					var meth = (Method) symbol;
-					if (gtype is Class) {
-						meth.is_virtual = true;
-					} else if (gtype is Interface) {
-						meth.is_abstract = true;
-					}
-				} else if (symbol is Signal) {
-					var sig = (Signal) symbol;
-					sig.is_virtual = true;
-				} else {
-					Report.error (get_current_src (), "unknown member type `%s' in `%s'".printf (m.name, gtype.name));
-				}
-			}
-		}
-	}
-
 	Class parse_class () {
 		start_element ("class");
 		var cl = new Class (reader.get_attribute ("name"), get_current_src ());
@@ -1475,6 +1467,18 @@ public class Vala.GirParser : CodeVisitor {
 		string allow_none = reader.get_attribute ("allow-none");
 		next ();
 		var type = parse_type ();
+		if (type is DelegateType && current_gtype_struct_for != null) {
+			// virtual
+			var callback_scope = new CallbackScope ();
+			callback_scope.parent_namespace = current_namespace;
+			callback_scope.gtype_struct_for = parse_symbol_from_string (current_gtype_struct_for);
+			ArrayList<Delegate> callbacks = gtype_callbacks.get (callback_scope);
+			if (callbacks == null) {
+				callbacks = new ArrayList<Delegate> ();
+				gtype_callbacks.set (callback_scope, callbacks);
+			}
+			callbacks.add (((DelegateType) type).delegate_symbol);
+		}
 		var field = new Field (name, type, null, get_current_src ());
 		field.access = SymbolAccessibility.PUBLIC;
 		if (allow_none == "1") {
@@ -1894,6 +1898,59 @@ public class Vala.GirParser : CodeVisitor {
 		}
 	}
 
+	Symbol? resolve_symbol (Scope parent_scope, UnresolvedSymbol unresolved_symbol) {
+		// simple symbol resolver, enough for gir
+		if (unresolved_symbol.inner == null) {
+			var scope = parent_scope;
+			while (scope != null) {
+				var sym = scope.lookup (unresolved_symbol.name);
+				if (sym != null) {
+					return sym;
+				}
+				scope = scope.parent_scope;
+			}
+		} else {
+			var inner = resolve_symbol (parent_scope, unresolved_symbol.inner);
+			if (inner != null) {
+				return inner.scope.lookup (unresolved_symbol.name);
+			}
+		}
+		return null;
+	}
+
+	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 ()));
+				continue;
+			}
+			ArrayList<Delegate> callbacks = gtype_callbacks.get (callback_scope);
+			foreach (Delegate d in callbacks) {
+				var symbol = gtype.scope.lookup (d.name);
+				if (symbol == null) {
+					continue;
+				} else if (symbol is Method)  {
+					var meth = (Method) symbol;
+					if (gtype is Class) {
+						meth.is_virtual = true;
+					} else if (gtype is Interface) {
+						meth.is_abstract = true;
+					}
+				} else if (symbol is Signal) {
+					var sig = (Signal) symbol;
+					sig.is_virtual = true;
+					assume_parameter_names (sig, d);
+				} else if (symbol is Property) {
+					var prop = (Property) symbol;
+					prop.is_virtual = true;
+				} else {
+					Report.error (get_current_src (), "unknown member type `%s' in `%s'".printf (d.name, gtype.name));
+				}
+			}
+		}
+	}
+
 	/* Hash and equal functions */
 
 	static uint unresolved_symbol_hash (void *ptr) {



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