[anjuta] language-support-vala: support dropping from glade inside a class



commit 9c6e8159d01774aeb33d4d05acccad71662ccd3b
Author: Abderrahim Kitouni <akitouni src gnome org>
Date:   Mon Mar 7 21:50:37 2011 +0100

    language-support-vala: support dropping from glade inside a class
    
    This should also fix a bug and locate more accurately where the user is
    currently typing

 plugins/language-support-vala/locator.vala  |   73 +++++++++++++++++++++------
 plugins/language-support-vala/plugin.vala   |   69 ++++++++++++++++++++++---
 plugins/language-support-vala/provider.vala |    4 +-
 3 files changed, 121 insertions(+), 25 deletions(-)
---
diff --git a/plugins/language-support-vala/locator.vala b/plugins/language-support-vala/locator.vala
index 187e08f..bbe8b45 100644
--- a/plugins/language-support-vala/locator.vala
+++ b/plugins/language-support-vala/locator.vala
@@ -17,40 +17,83 @@
 
 /* Finds the innermost block containing the given location */
 public class BlockLocator : Vala.CodeVisitor {
-	double location;
-	Vala.Block innermost = null;
-	double innermost_begin;
-	double innermost_end;
+	struct Location {
+		int line;
+		int column;
+		public Location (int line, int column) {
+			this.line = line;
+			this.column = column;
+		}
+		public bool inside (Vala.SourceReference src) {
+			var begin = Location (src.first_line, src.first_column);
+			var end = Location (src.last_line, src.last_column);
 
-	public Vala.Block locate (Vala.SourceFile file, int line, int column) {
-		// XXX : assumes that line length < 1000
-		location = line + column / 1000.0;
+			return begin.before (this) && this.before(end);
+		}
+		public bool before (Location other) {
+			if (line > other.line)
+				return false;
+			if (line == other.line && column > other.column)
+				return false;
+			return true;
+		}
+	}
+
+	Location location;
+	Vala.Symbol innermost;
+	Location innermost_begin;
+	Location innermost_end;
+
+	public Vala.Symbol locate (Vala.SourceFile file, int line, int column) {
+		location = Location (line, column);
 		innermost = null;
 		file.accept_children(this);
 		return innermost;
 	}
-	public override void visit_block (Vala.Block b) {
-		var begin = b.source_reference.first_line + b.source_reference.first_column / 1000.0;
-		var end = b.source_reference.last_line + b.source_reference.last_column / 1000.0;
 
-		if (begin <= location && location <= end)
-			if (innermost == null || (innermost_begin <= begin && innermost_end >= end))
-				innermost = b;
-		b.accept_children(this);
+	bool update_location (Vala.Symbol s) {
+		if (!location.inside (s.source_reference))
+			return false;
+
+		var begin = Location (s.source_reference.first_line, s.source_reference.first_column);
+		var end = Location (s.source_reference.last_line, s.source_reference.last_column);
+
+		if (innermost == null || (innermost_begin.before(begin) && end.before(innermost_end))) {
+				innermost = s;
+				innermost_begin = begin;
+				innermost_end = end;
+				return true;
+		}
+
+		return false;
+	}
+
+	public override void visit_block (Vala.Block b) {
+		if (update_location (b))
+			b.accept_children(this);
 	}
 
 	public override void visit_namespace (Vala.Namespace ns) {
+		update_location (ns);
 		ns.accept_children(this);
 	}
 	public override void visit_class (Vala.Class cl) {
+		/* the location of a class contains only its declaration, not its content */
+		if (update_location (cl))
+			return;
 		cl.accept_children(this);
 	}
 	public override void visit_struct (Vala.Struct st) {
+		if (update_location (st))
+			return;
 		st.accept_children(this);
 	}
 	public override void visit_interface (Vala.Interface iface) {
+		if (update_location (iface))
+			return;
 		iface.accept_children(this);
 	}
+
 	public override void visit_method (Vala.Method m) {
 		m.accept_children(this);
 	}
@@ -76,7 +119,7 @@ public class BlockLocator : Vala.CodeVisitor {
 		stmt.accept_children(this);
 	}
 	public override void visit_switch_section (Vala.SwitchSection section) {
-		visit_block(section);
+		visit_block (section);
 	}
 	public override void visit_while_statement (Vala.WhileStatement stmt) {
 		stmt.accept_children(this);
diff --git a/plugins/language-support-vala/plugin.vala b/plugins/language-support-vala/plugin.vala
index 4c82034..d98792f 100644
--- a/plugins/language-support-vala/plugin.vala
+++ b/plugins/language-support-vala/plugin.vala
@@ -269,9 +269,47 @@ public class ValaPlugin : Plugin {
 		}
 	}
 
+	/* tries to find the opening brace of the scope the current position before calling
+	 * get_current_context since the source_reference of a class or namespace only
+	 * contain the declaration not the entire "content" */
+	Vala.Symbol? get_scope (IAnjuta.Editor editor, IAnjuta.Iterable position) {
+		var braces = new List<string> ();
+
+		do {
+			var current_char = (position as IAnjuta.EditorCell).get_character ();
+			if (current_char == "}") {
+				braces.prepend (current_char);
+			} else if (current_char == "{") {
+				if (braces != null && braces.data == "}") {
+					braces.delete_link (braces);
+				} else {
+					// a scope which contains the current position
+					do {
+						position.previous ();
+						current_char = (position as IAnjuta.EditorCell).get_character ();
+					} while (! current_char.get_char ().isalnum ());
+
+					return get_current_context (editor, position);
+				}
+			}
+		} while (position.previous ());
+
+		return null;
+	}
+
 	public bool on_drop_possible (IAnjuta.EditorGladeSignal editor, IAnjuta.Iterable position) {
-		// TODO: it'd  be better to check if we are inside a namespace or class
-		return true;
+		var scope = get_current_context (editor, position);
+		if (scope is Vala.Block) {
+			return false;
+		} else if (scope == null) {
+			scope = get_scope (editor, position.clone ());
+			if (scope == null || scope is Vala.Namespace || scope is Vala.Class)
+				return true;
+
+			return false;
+		}
+
+		return false;
 	}
 
 	public void on_drop (IAnjuta.EditorGladeSignal editor, IAnjuta.Iterable position, string signal_data) {
@@ -280,11 +318,20 @@ public class ValaPlugin : Plugin {
 		var signal_name = data[1].replace ("-", "_");
 		var handler_name = data[2];
 		var swapped = (data[4] == "1");
+		var scope = get_scope (editor, position.clone ());
 		var builder = new StringBuilder ();
 
-		if (data[2] != handler_name && !swapped) {
+		var scope_prefix = "";
+		if (scope != null) {
+			scope_prefix = scope.get_lower_case_cprefix ();
+			if (handler_name.has_prefix (scope_prefix))
+				handler_name = handler_name.substring (scope_prefix.length);
+		}
+		var handler_cname = scope_prefix + handler_name;
+
+		if (data[2] != handler_cname && !swapped) {
 			builder.append_printf ("[CCode (cname=\"%s\", instance_pos=-1)]\n", data[2]);
-		} else if (data[2] != handler_name) {
+		} else if (data[2] != handler_cname) {
 			builder.append_printf ("[CCode (cname=\"%s\")]\n", data[2]);
 		} else if (!swapped) {
 			builder.append ("[CCode (instance_pos=-1)]\n");
@@ -292,10 +339,8 @@ public class ValaPlugin : Plugin {
 
 		var widget = lookup_symbol_by_cname (widget_name);
 		var sigs = symbol_lookup_inherited (widget, signal_name, false);
-
 		if (sigs == null || !(sigs.data is Vala.Signal))
 			return;
-
 		Vala.Signal sig = (Vala.Signal) sigs.data;
 
 		builder.append_printf ("void %s (", handler_name);
@@ -333,7 +378,7 @@ public class ValaPlugin : Plugin {
 		return null;
 	}
 
-	internal Vala.Block get_current_block (IAnjuta.Editor editor) requires (editor is IAnjuta.File) {
+	internal Vala.Symbol get_current_context (IAnjuta.Editor editor, IAnjuta.Iterable? position=null) requires (editor is IAnjuta.File) {
 		var file = editor as IAnjuta.File;
 
 		var path = file.get_file().get_path();
@@ -353,7 +398,15 @@ public class ValaPlugin : Plugin {
 				context.add_source_file(source);
 				update_file(source);
 			}
-			return locator.locate(source, editor.get_lineno(), editor.get_column());
+			int line; int column;
+			if (position == null) {
+				line = editor.get_lineno ();
+				column = editor.get_column ();
+			} else {
+				line = editor.get_line_from_position (position);
+				column = editor.get_line_begin_position (line).diff (position);
+			}
+			return locator.locate(source, line, column);
 		}
 	}
 
diff --git a/plugins/language-support-vala/provider.vala b/plugins/language-support-vala/provider.vala
index d02a707..b18ab4b 100644
--- a/plugins/language-support-vala/provider.vala
+++ b/plugins/language-support-vala/provider.vala
@@ -64,7 +64,7 @@ public class ValaProvider : Object, IAnjuta.Provider {
 		var names = member_access_split.split (match_info.fetch(1));
 
 		var syms = plugin.lookup_symbol (construct_member_access (names), match_info.fetch(2),
-		                                 true, plugin.get_current_block(editor));
+		                                 true, plugin.get_current_context (editor) as Vala.Block);
 
 		var proposals = new GLib.List<IAnjuta.EditorAssistProposal?>();
 		foreach (var symbol in syms) {
@@ -134,7 +134,7 @@ public class ValaProvider : Object, IAnjuta.Provider {
 		var creation_method = (match_info.fetch(1) != "");
 		var names = member_access_split.split (match_info.fetch(2));
 		var syms = plugin.lookup_symbol (construct_member_access (names), match_info.fetch(3),
-		                                 false, plugin.get_current_block (editor));
+		                                 false, plugin.get_current_context (editor) as Vala.Block);
 
 		foreach (var sym in syms) {
 			Vala.List<Vala.Parameter> parameters = null;



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