[geany/geany] b886ac: Merge branch 'improve-scope-detection'

Colomban Wendling git-noreply at xxxxx
Mon Sep 17 20:59:52 UTC 2012


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Mon, 17 Sep 2012 20:59:52
Commit:      b886ac1b2e601248238a5ab85848d78108e3550e
             https://github.com/geany/geany/commit/b886ac1b2e601248238a5ab85848d78108e3550e

Log Message:
-----------
Merge branch 'improve-scope-detection'


Modified Paths:
--------------
    src/callbacks.c
    src/symbols.c
    src/symbols.h
    src/ui_utils.c
    tagmanager/src/tm_workspace.c
    tagmanager/src/tm_workspace.h

Modified: src/callbacks.c
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1171,7 +1171,7 @@ G_MODULE_EXPORT void on_comments_function_activate(GtkMenuItem *menuitem, gpoint
 	/* symbols_get_current_function returns -1 on failure, so sci_get_position_from_line
 	 * returns the current position, so it should be safe */
 	line = symbols_get_current_function(doc, &cur_tag);
-	pos = sci_get_position_from_line(doc->editor->sci, line - 1);
+	pos = sci_get_position_from_line(doc->editor->sci, line);
 
 	text = templates_get_template_function(doc, cur_tag);
 


Modified: src/symbols.c
178 files changed, 115 insertions(+), 63 deletions(-)
===================================================================
@@ -1959,20 +1959,22 @@ static gint get_function_fold_number(GeanyDocument *doc)
 }
 
 
-/* Should be used only with symbols_get_current_function. */
-static gboolean current_function_changed(GeanyDocument *doc, gint cur_line, gint fold_level)
+/* Should be used only with get_current_tag_cached.
+ * tag_types caching might trigger recomputation too often but this isn't used differently often
+ * enough to be an issue for now */
+static gboolean current_tag_changed(GeanyDocument *doc, gint cur_line, gint fold_level, guint tag_types)
 {
 	static gint old_line = -2;
 	static GeanyDocument *old_doc = NULL;
 	static gint old_fold_num = -1;
+	static guint old_tag_types = 0;
 	const gint fold_num = fold_level & SC_FOLDLEVELNUMBERMASK;
 	gboolean ret;
 
 	/* check if the cached line and file index have changed since last time: */
-	if (doc == NULL || doc != old_doc)
+	if (doc == NULL || doc != old_doc || old_tag_types != tag_types)
 		ret = TRUE;
-	else
-	if (cur_line == old_line)
+	else if (cur_line == old_line)
 		ret = FALSE;
 	else
 	{
@@ -1989,6 +1991,7 @@ static gboolean current_function_changed(GeanyDocument *doc, gint cur_line, gint
 	old_line = cur_line;
 	old_doc = doc;
 	old_fold_num = fold_num;
+	old_tag_types = tag_types;
 	return ret;
 }
 
@@ -2069,83 +2072,79 @@ static gchar *parse_cpp_function_at_line(ScintillaObject *sci, gint tag_line)
 }
 
 
-/* Sets *tagname to point at the current function or tag name.
- * If doc is NULL, reset the cached current tag data to ensure it will be reparsed on the next
- * call to this function.
- * Returns: line number of the current tag, or -1 if unknown. */
-gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname)
+static gint get_fold_header_after(ScintillaObject *sci, gint line)
 {
-	static gint tag_line = -1;
-	static gchar *cur_tag = NULL;
-	gint line;
-	gint fold_level;
-	TMWorkObject *tm_file;
+	gint line_count = sci_get_line_count(sci);
 
-	if (doc == NULL)	/* reset current function */
+	for (; line < line_count; line++)
 	{
-		current_function_changed(NULL, -1, -1);
-		g_free(cur_tag);
-		cur_tag = g_strdup(_("unknown"));
-		if (tagname != NULL)
-			*tagname = cur_tag;
-		tag_line = -1;
-		return tag_line;
+		if (sci_get_fold_level(sci, line) & SC_FOLDLEVELHEADERFLAG)
+			return line;
 	}
 
-	line = sci_get_current_line(doc->editor->sci);
-	fold_level = sci_get_fold_level(doc->editor->sci, line);
-	/* check if the cached line and file index have changed since last time: */
-	if (! current_function_changed(doc, line, fold_level))
-	{
-		/* we can assume same current function as before */
-		*tagname = cur_tag;
-		return tag_line;
-	}
-	g_free(cur_tag); /* free the old tag, it will be replaced. */
+	return -1;
+}
 
-	/* if line is at base fold level, we're not in a function */
-	if ((fold_level & SC_FOLDLEVELNUMBERMASK) == SC_FOLDLEVELBASE)
-	{
-		cur_tag = g_strdup(_("unknown"));
-		*tagname = cur_tag;
-		tag_line = -1;
-		return tag_line;
-	}
-	tm_file = doc->tm_file;
 
-	/* if the tags are up-to-date, get the previous function name from TM */
-	if (tm_file != NULL && tm_file->tags_array != NULL &&
+static gint get_current_tag_name(GeanyDocument *doc, gchar **tagname, guint tag_types)
+{
+	gint line;
+	gint parent;
+
+	line = sci_get_current_line(doc->editor->sci);
+	parent = sci_get_fold_parent(doc->editor->sci, line);
+	/* if we're inside a fold level and we have up-to-date tags, get the function from TM */
+	if (parent >= 0 && doc->tm_file != NULL && doc->tm_file->tags_array != NULL &&
 		(! doc->changed || editor_prefs.autocompletion_update_freq > 0))
 	{
-		const TMTag *tag = (const TMTag*) tm_get_current_function(tm_file->tags_array, line);
+		const TMTag *tag = tm_get_current_tag(doc->tm_file->tags_array, parent + 1, tag_types);
 
-		if (tag != NULL)
+		if (tag)
 		{
-			gchar *tmp;
-			tmp = tag->atts.entry.scope;
-			cur_tag = tmp ? g_strconcat(tmp, "::", tag->name, NULL) : g_strdup(tag->name);
-			*tagname = cur_tag;
-			tag_line = tag->atts.entry.line;
-			return tag_line;
+			gint tag_line = tag->atts.entry.line - 1;
+			gint last_child = line + 1;
+
+			/* if it may be a false positive because we're inside a fold level not inside anything
+			 * we match, e.g. a #if in C or C++, we check we're inside the fold level that start
+			 * right after the tag we got from TM */
+			if (abs(tag_line - parent) > 1)
+			{
+				gint tag_fold = get_fold_header_after(doc->editor->sci, tag_line);
+				if (tag_fold >= 0)
+					last_child = scintilla_send_message(doc->editor->sci, SCI_GETLASTCHILD, tag_fold, -1);
+			}
+
+			if (line <= last_child)
+			{
+				if (tag->atts.entry.scope)
+					*tagname = g_strconcat(tag->atts.entry.scope,
+							symbols_get_context_separator(doc->file_type->id), tag->name, NULL);
+				else
+					*tagname = g_strdup(tag->name);
+
+				return tag_line;
+			}
 		}
 	}
-
-	/* parse the current function name here because TM line numbers may have changed,
-	 * and it would take too long to reparse the whole file. */
-	if (doc->file_type != NULL && doc->file_type->id != GEANY_FILETYPES_NONE)
+	/* for the poor guy with a modified document and without real time tag parsing, we fallback
+	 * to dirty and inaccurate hand-parsing */
+	else if (parent >= 0 && doc->file_type != NULL && doc->file_type->id != GEANY_FILETYPES_NONE)
 	{
 		const gint fn_fold = get_function_fold_number(doc);
+		gint tag_line = parent;
+		gint fold_level = sci_get_fold_level(doc->editor->sci, tag_line);
 
-		tag_line = line;
-		do	/* find the top level fold point */
+		/* find the top level fold point */
+		while (tag_line >= 0 && (fold_level & SC_FOLDLEVELNUMBERMASK) != fn_fold)
 		{
 			tag_line = sci_get_fold_parent(doc->editor->sci, tag_line);
 			fold_level = sci_get_fold_level(doc->editor->sci, tag_line);
-		} while (tag_line >= 0 &&
-			(fold_level & SC_FOLDLEVELNUMBERMASK) != fn_fold);
+		}
 
 		if (tag_line >= 0)
 		{
+			gchar *cur_tag;
+
 			if (sci_get_lexer(doc->editor->sci) == SCLEX_CPP)
 				cur_tag = parse_cpp_function_at_line(doc->editor->sci, tag_line);
 			else
@@ -2159,13 +2158,66 @@ gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname)
 		}
 	}
 
-	cur_tag = g_strdup(_("unknown"));
-	*tagname = cur_tag;
-	tag_line = -1;
+	*tagname = g_strdup(_("unknown"));
+	return -1;
+}
+
+
+static gint get_current_tag_name_cached(GeanyDocument *doc, const gchar **tagname, guint tag_types)
+{
+	static gint tag_line = -1;
+	static gchar *cur_tag = NULL;
+
+	if (doc == NULL)	/* reset current function */
+	{
+		current_tag_changed(NULL, -1, -1, 0);
+		g_free(cur_tag);
+		cur_tag = g_strdup(_("unknown"));
+		if (tagname != NULL)
+			*tagname = cur_tag;
+		tag_line = -1;
+	}
+	else
+	{
+		gint line = sci_get_current_line(doc->editor->sci);
+		gint fold_level = sci_get_fold_level(doc->editor->sci, line);
+
+		if (current_tag_changed(doc, line, fold_level, tag_types))
+		{
+			g_free(cur_tag);
+			tag_line = get_current_tag_name(doc, &cur_tag, tag_types);
+		}
+		*tagname = cur_tag;
+	}
+
 	return tag_line;
 }
 
 
+/* Sets *tagname to point at the current function or tag name.
+ * If doc is NULL, reset the cached current tag data to ensure it will be reparsed on the next
+ * call to this function.
+ * Returns: line number of the current tag, or -1 if unknown. */
+gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname)
+{
+	return get_current_tag_name_cached(doc, tagname, tm_tag_function_t | tm_tag_method_t);
+}
+
+
+/* same as symbols_get_current_function() but finds class, namespaces and more */
+gint symbols_get_current_scope(GeanyDocument *doc, const gchar **tagname)
+{
+	guint tag_types = (tm_tag_function_t | tm_tag_method_t | tm_tag_class_t |
+			tm_tag_struct_t | tm_tag_enum_t | tm_tag_union_t);
+
+	/* Python parser reports imports as namespaces which confuses the scope detection */
+	if (doc && doc->file_type->lang != filetypes[GEANY_FILETYPES_PYTHON]->lang)
+		tag_types |= tm_tag_namespace_t;
+
+	return get_current_tag_name_cached(doc, tagname, tag_types);
+}
+
+
 static void on_symbol_tree_sort_clicked(GtkMenuItem *menuitem, gpointer user_data)
 {
 	gint sort_mode = GPOINTER_TO_INT(user_data);


Modified: src/symbols.h
2 files changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -61,4 +61,6 @@ enum
 
 gint symbols_get_current_function(GeanyDocument *doc, const gchar **tagname);
 
+gint symbols_get_current_scope(GeanyDocument *doc, const gchar **tagname);
+
 #endif


Modified: src/ui_utils.c
2 files changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -272,7 +272,7 @@ static void add_statusbar_statistics(GString *stats_str,
 				g_string_append(stats_str, filetypes_get_display_name(doc->file_type));
 				break;
 			case 'S':
-				symbols_get_current_function(doc, &cur_tag);
+				symbols_get_current_scope(doc, &cur_tag);
 				g_string_append(stats_str, cur_tag);
 				break;
 			default:


Modified: tagmanager/src/tm_workspace.c
23 files changed, 15 insertions(+), 8 deletions(-)
===================================================================
@@ -733,30 +733,37 @@ static gboolean match_langs(gint lang, const TMTag *tag)
 
 
 const TMTag *
-tm_get_current_function (GPtrArray * file_tags, const gulong line)
+tm_get_current_tag (GPtrArray * file_tags, const gulong line, const guint tag_types)
 {
-	GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t | tm_tag_method_t);
-	TMTag *function_tag = NULL;
+	GPtrArray *const local = tm_tags_extract (file_tags, tag_types);
+	TMTag *matching_tag = NULL;
 	if (local && local->len)
 	{
 		guint i;
-		gulong function_line = 0;
+		gulong matching_line = 0;
 		glong delta;
 
 		for (i = 0; (i < local->len); ++i)
 		{
 			TMTag *tag = TM_TAG (local->pdata[i]);
 			delta = line - tag->atts.entry.line;
-			if (delta >= 0 && (gulong)delta < line - function_line)
+			if (delta >= 0 && (gulong)delta < line - matching_line)
 			{
-				function_tag = tag;
-				function_line = tag->atts.entry.line;
+				matching_tag = tag;
+				matching_line = tag->atts.entry.line;
 			}
 		}
 	}
 	if (local)
 		g_ptr_array_free (local, TRUE);
-	return function_tag;
+	return matching_tag;
+}
+
+
+const TMTag *
+tm_get_current_function (GPtrArray * file_tags, const gulong line)
+{
+	return tm_get_current_tag (file_tags, line, tm_tag_function_t | tm_tag_method_t);
 }
 
 


Modified: tagmanager/src/tm_workspace.h
7 files changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -152,6 +152,13 @@ const GPtrArray *tm_workspace_find_scope_members(const GPtrArray *file_tags,
 tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name,
                                      gboolean search_global);
 
+/* Returns TMTag which "own" given line
+ \param line Current line in edited file.
+ \param file_tags A GPtrArray of edited file TMTag pointers.
+ \param tag_types the tag types to include in the match
+ \return TMTag pointers to owner tag. */
+const TMTag *tm_get_current_tag(GPtrArray *file_tags, const gulong line, const guint tag_types);
+
 /* Returns TMTag to function or method which "own" given line
  \param line Current line in edited file.
  \param file_tags A GPtrArray of edited file TMTag pointers.


@@ Diff output truncated at 100000 characters. @@


--------------
This E-Mail was brought to you by github_commit_mail.py (Source: TBD).



More information about the Commits mailing list