[geany/geany] 491a45: Improve symbols_get_current_function() a lot and make it more flexible

Colomban Wendling git-noreply at xxxxx
Mon Sep 17 20:50:32 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:50:32
Commit:      491a45f614bc1c4633168e97a06734eff6886601
             https://github.com/geany/geany/commit/491a45f614bc1c4633168e97a06734eff6886601

Log Message:
-----------
Improve symbols_get_current_function() a lot and make it more flexible

Finding the current function now better handles the case the current
line is after a function but outside its scope, and many other issues
the scope reporting had.


Modified Paths:
--------------
    src/symbols.c

Modified: src/symbols.c
164 files changed, 101 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 + 1);
+		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 - 1;
-			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,52 @@ 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);
+}
+
+
 static void on_symbol_tree_sort_clicked(GtkMenuItem *menuitem, gpointer user_data)
 {
 	gint sort_mode = GPOINTER_TO_INT(user_data);


@@ 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