[vala/switch-to-gir: 19/34] girparser: Generalize symbol merging process



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]