[vala/switch-to-gir] girparser: Autoreparent static methods to the best-matching symbol



commit 6b3556ff30673f5b27384dc83215874acc0b4019
Author: Luca Bruno <lethalman88 gmail com>
Date:   Fri Aug 27 23:59:26 2010 +0200

    girparser: Autoreparent static methods to the best-matching symbol

 vala/valagirparser.vala |   98 +++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 86 insertions(+), 12 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index a3b7665..95e6b0a 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -256,14 +256,6 @@ public class Vala.GirParser : CodeVisitor {
 			return ((string) begin.pos).ndup ((end.pos - begin.pos));
 		}
 
-		inline bool accept (TokenType type) {
-			if (current == type) {
-				next ();
-				return true;
-			}
-			return false;
-		}
-
 		MetadataType? parse_metadata_access () {
 			switch (current) {
 			case TokenType.DOT:
@@ -486,6 +478,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<Namespace,ArrayList<Method>> namespace_methods = new HashMap<Namespace,ArrayList<Method>> ();
 
 	HashMap<CallbackScope,ArrayList<Delegate>> gtype_callbacks = new HashMap<CallbackScope,ArrayList<Delegate>> (callback_scope_hash, callback_scope_equal);
 	ArrayList<Alias> aliases = new ArrayList<Alias> ();
@@ -506,6 +499,7 @@ public class Vala.GirParser : CodeVisitor {
 		postprocess_reparenting ();
 		postprocess_gtype_callbacks ();
 		postprocess_aliases ();
+		postprocess_namespace_methods ();
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
@@ -823,7 +817,7 @@ public class Vala.GirParser : CodeVisitor {
 
 	int element_get_integer (string attribute_name, ArgumentType arg_type, int default_value = -1) {
 		var value = default_value;
-		var str = reader.get_attribute ("length");
+		var str = reader.get_attribute (attribute_name);
 		if (str != null) {
 			value = str.to_int ();
 		}
@@ -919,7 +913,7 @@ public class Vala.GirParser : CodeVisitor {
 						if (sym is Property) {
 							// assume getter for property
 							((Property) sym).no_accessor_method = false;
-							return true;
+							break;
 						}
 					}
 				}
@@ -1106,6 +1100,11 @@ public class Vala.GirParser : CodeVisitor {
 		}
 
 		next ();
+		var current_namespace_methods = namespace_methods[ns];
+		if (current_namespace_methods == null) {
+			current_namespace_methods = new ArrayList<Method> ();
+			namespace_methods[ns] = current_namespace_methods;
+		}
 		while (current_token == MarkupTokenType.START_ELEMENT) {
 			if (!push_metadata ()) {
 				skip_element ();
@@ -1125,7 +1124,7 @@ public class Vala.GirParser : CodeVisitor {
 			} else if (reader.name == "bitfield") {
 				sym = parse_bitfield ();
 			} else if (reader.name == "function") {
-				sym = parse_method ("function");
+				current_namespace_methods.add (parse_method ("function"));
 			} else if (reader.name == "callback") {
 				sym = parse_callback ();
 			} else if (reader.name == "record") {
@@ -1612,7 +1611,6 @@ public class Vala.GirParser : CodeVisitor {
 				continue;
 			}
 
-			Symbol sym = null;
 			if (reader.name == "implements") {
 				start_element ("implements");
 				cl.add_base_type (parse_type_from_gir_name (reader.get_attribute ("name")));
@@ -1774,6 +1772,7 @@ public class Vala.GirParser : CodeVisitor {
 		next ();
 
 		var type = parse_type ();
+		type = element_get_type (type, true);
 		if (type is DelegateType && current_gtype_struct_for != null) {
 			// virtual
 			var callback_scope = new CallbackScope ();
@@ -2464,6 +2463,81 @@ public class Vala.GirParser : CodeVisitor {
 		}
 	}
 
+	void find_static_method_parent (string cname, Symbol current, ref Symbol best, ref double match, double match_char) {
+		var old_best = best;
+		if (current.scope.get_symbol_table () != null) {
+			foreach (var child in current.scope.get_symbol_table().get_values ()) {
+				if (child is Struct || child is ObjectTypeSymbol || child is Namespace) {
+					find_static_method_parent (cname, child, ref best, ref match, match_char);
+				}
+			}
+		}
+		if (best != old_best) {
+			// child is better
+			return;
+		}
+
+		var current_cprefix = current.get_lower_case_cprefix ();
+		if (cname.has_prefix (current_cprefix)) {
+			var current_match = match_char * current_cprefix.length;
+			if (current_match > match) {
+				match = current_match;
+				best = current;
+			}
+		}
+	}
+
+	void postprocess_namespace_methods () {
+		/* transform static methods into instance methods if possible.
+		   In most of cases this is a .gir fault we are going to fix */
+		foreach (var ns in namespace_methods.get_keys ()) {
+			var ns_cprefix = ns.get_lower_case_cprefix ();
+			var methods = namespace_methods[ns];
+			foreach (var method in methods) {
+				if (method.parent_node != null) {
+					// fixed earlier by metadata
+					continue;
+				}
+
+				var cname = method.get_cname ();
+
+				FormalParameter first_param = null;
+				if (method.get_parameters ().size > 0) {
+					first_param = method.get_parameters()[0];
+				}
+				if (first_param != null && first_param.variable_type is UnresolvedType) {
+					// check if it's a missed instance method (often happens for structs)
+					var parent = resolve_symbol (ns.scope, ((UnresolvedType) first_param.variable_type).unresolved_symbol);
+					if (parent != null && (parent is Struct || parent is ObjectTypeSymbol || parent is Namespace)
+						&& cname.has_prefix (parent.get_lower_case_cprefix ())) {
+						// instance method
+						var new_name = method.name.offset (parent.get_lower_case_cprefix().length-ns_cprefix.length);
+						if (parent.scope.lookup (new_name) == null) {
+							method.name = new_name;
+							method.get_parameters().remove_at (0);
+							method.binding = MemberBinding.INSTANCE;
+							add_symbol_to_container (parent, method);
+						} else {
+							ns.add_method (method);
+						}
+						continue;
+					}
+				}
+
+				double match = 0;
+				Symbol parent = ns;
+				find_static_method_parent (cname, ns, ref parent, ref match, 1.0/cname.length);
+				var new_name = method.name.offset (parent.get_lower_case_cprefix().length-ns_cprefix.length);
+				if (parent.scope.lookup (new_name) == null) {
+					method.name = new_name;
+					add_symbol_to_container (parent, method);
+				} else {
+					ns.add_method (method);
+				}
+			}
+		}
+	}
+
 	/* Reporting */
 	void report_unused_metadata (Metadata metadata) {
 		if (metadata == Metadata.empty) {



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