Le 17/03/2012 15:28, Colomban Wendling a écrit :
> Le 16/03/2012 11:30, Lex Trotman a écrit :
>> Hi All,
> 
> Hey,
> 
> I haven't had the time yet to try to fix the sidebar bug, but...
> 
>> So that I don't look unreasonable for criticising just Geany I
> 
> Sweet :p
> 
>> [...]
>>
>> In fact it would even be better if . and -> autocomplete was turned
>> off for C++ rather than offering complete crap (and that isn't related
>> to this particular file unfortunately).
> 
> Try the attached patch maybe.

Hum, it'd be easier with an attachment.  Here it is.


> It's not really polished and I haven't
> published it because it's not really "the right fix", but if scope
> completion is *that* broken with C++ maybe it's worth committing this at
> least as an interim solution 'till I manage to get another tagmanager
> impl working [1].  That patch is a reimpl of the feature that at least I
> can understand (no TM stuff, heh), and it shows quite good results at
> least for C (and smaaaaaaal C++ tests).
> 
> 
> Cheers,
> Colomban
> 
> 
> [1] It's somewhat on the way, but it's far from being trivial work and I
> have/had some non-geany stuff lately, so I wasn't able to work on this
> that much
> 
>> As my brain is now drained from all those, I leave it to someone else
>> to suggest some idea of a path forward.
>>
>> Cheers
>> Lex
>> _______________________________________________
>> Geany-devel mailing list
>> Geany-devel@uvena.de
>> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel
> 
> _______________________________________________
> Geany-devel mailing list
> Geany-devel@uvena.de
> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

>From a96669230b860ae3229150715ff65621d3c37657 Mon Sep 17 00:00:00 2001
From: Colomban Wendling <b...@herbesfolles.org>
Date: Tue, 23 Aug 2011 02:20:11 +0200
Subject: [PATCH] First attempt at fixing scope completion

Actually it's a re-implementation that looks pretty well working.
---
 src/editor.c |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 186 insertions(+), 18 deletions(-)

diff --git a/src/editor.c b/src/editor.c
index 67dd295..739c940 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -683,14 +683,190 @@ static void request_reshowing_calltip(SCNotification *nt)
 }
 
 
+/* mostly stolen from tm_workspace.c:match_langs() */
+static gboolean lang_matches(const TMTag *tag, langType lang)
+{
+	if (lang == -1)
+		return TRUE;
+
+	if (tag->atts.entry.file)
+	{	/* workspace tag */
+		if (lang == tag->atts.entry.file->lang)
+			return TRUE;
+	}
+	else
+	{	/* global tag */
+		if (lang == tag->atts.file.lang)
+			return TRUE;
+	}
+	return FALSE;
+}
+
+
+/* gets the real type of @name_orig by resolving the typedefs
+ * @file: (in/out) the preferred TMSourceFile, will be filled with the TMSourceFile in which the
+ *   returned is found. This may point to @NULL, but cannot be a NULL pointer */
+static const gchar *resolve_typedef(TMWorkObject **file, const gchar *type_name, langType lang)
+{
+	const TMWorkspace *ws = tm_get_workspace();
+	guint i, pass = 0;
+	GPtrArray *tag_arrays[3];
+	gboolean again;
+
+	g_return_val_if_fail(file != NULL, NULL);
+	g_return_val_if_fail(type_name != NULL, NULL);
+
+	tag_arrays[0] = (*file) ? (*file)->tags_array : NULL;
+	tag_arrays[1] = TM_WORK_OBJECT(ws)->tags_array;
+	tag_arrays[2] = ws->global_tags;
+
+	do
+	{
+		again = FALSE;
+
+		g_debug("resolving %s...", type_name);
+		for (i = 0; i < G_N_ELEMENTS(tag_arrays); i++)
+		{
+			const TMTag *tag;
+			guint j;
+
+			if (! tag_arrays[i] || tag_arrays[i]->len < 1)
+				continue;
+
+			foreach_ptr_array(tag, j, tag_arrays[i])
+			{
+				if (! lang_matches(tag, lang))
+					continue;
+
+				if (tag->type & tm_tag_typedef_t && strcmp(type_name, tag->name) == 0 &&
+					tag->atts.entry.var_type && strcmp (type_name, tag->atts.entry.var_type) != 0)
+				{
+					type_name = tag->atts.entry.var_type;
+					/* we need to resolve the new name in case it is typedefed again, trying the
+					 * file containing the typedef first */
+					again = TRUE;
+					*file = TM_WORK_OBJECT(tag->atts.entry.file);
+					tag_arrays[0] = (*file) ? (*file)->tags_array : NULL;
+					break;
+				}
+			}
+		}
+		pass++;
+	}
+	while (again && pass <= 8);
+	/* 8 is an arbitrary limit not to loop infinitely on recurive self-referencing typedefs */
+
+	g_debug("resolved to %s.", type_name);
+	return type_name;
+}
+
+
+/* tries to find children of type @type_name
+ * @file: the preferred TMSourceFile (e.g. the one containing the type definitions) */
+static GPtrArray *find_type_children(TMWorkObject *file, const gchar *type_name, langType lang)
+{
+	const TMWorkspace *ws = tm_get_workspace();
+	guint i;
+	gsize len;
+	const GPtrArray *tag_arrays[3];
+	GPtrArray *children = NULL;
+
+	g_return_val_if_fail(type_name != NULL, NULL);
+
+	g_debug("searching children for %s...", type_name);
+
+	type_name = resolve_typedef(&file, type_name, lang);
+	len = strlen(type_name);
+
+	tag_arrays[0] = file ? file->tags_array : NULL;
+	tag_arrays[1] = TM_WORK_OBJECT(ws)->tags_array;
+	tag_arrays[2] = ws->global_tags;
+
+	for (i = 0; ! children && i < G_N_ELEMENTS(tag_arrays); i++)
+	{
+		const TMTag *tag;
+		guint j;
+
+		if (! tag_arrays[i])
+			continue;
+
+		foreach_ptr_array(tag, j, tag_arrays[i])
+		{
+			if (G_UNLIKELY(tag->type & tm_tag_file_t))
+				continue;
+			if (! lang_matches(tag, lang))
+				continue;
+
+			if (tag->atts.entry.scope && strncmp(tag->atts.entry.scope, type_name, len) == 0 &&
+				(tag->atts.entry.scope[len] == 0 || tag->atts.entry.scope[len] == '.' ||
+				 tag->atts.entry.scope[len] == ':'))
+			{
+				if (! children)
+					children = g_ptr_array_new();
+				g_debug("found child %s", tag->name);
+				g_ptr_array_add(children, (gpointer)tag);
+			}
+		}
+	}
+
+	return children;
+}
+
+
+/* finds scope completions for @name
+ * @file: the preferred TMSourceFile (e.g. the one containing the name) */
+static GPtrArray *find_scope_members(TMWorkObject *file, const gchar *name, langType lang)
+{
+	const TMWorkspace *ws = tm_get_workspace();
+	guint i;
+	const GPtrArray *tag_arrays[3];
+	GPtrArray *children = NULL;
+
+	tag_arrays[0] = file ? file->tags_array : NULL;
+	tag_arrays[1] = TM_WORK_OBJECT(ws)->tags_array;
+	tag_arrays[2] = ws->global_tags;
+
+	g_debug("finding scope member for %s", name);
+
+	for (i = 0; ! children && i < G_N_ELEMENTS(tag_arrays); i++)
+	{
+		const TMTag *tag;
+		guint j;
+
+		if (! tag_arrays[i])
+			continue;
+
+		foreach_ptr_array(tag, j, tag_arrays[i])
+		{
+			if (G_UNLIKELY(tag->type & tm_tag_file_t))
+				continue;
+			if (! lang_matches(tag, lang))
+				continue;
+			if (strcmp(tag->name, name) != 0)
+				continue;
+			if (tag->atts.entry.var_type == NULL)
+				continue;
+
+			/* this doesn't work properly for e.g. C functions because their return type includes
+			 * type modifiers such as "const" or "*". */
+			children = find_type_children(TM_WORK_OBJECT(tag->atts.entry.file),
+										  tag->atts.entry.var_type, lang);
+			if (children)
+				break;
+		}
+	}
+
+	return children;
+}
+
+
 static void autocomplete_scope(GeanyEditor *editor)
 {
 	ScintillaObject *sci = editor->sci;
 	gint pos = sci_get_current_position(editor->sci);
 	gchar typed = sci_get_char_at(sci, pos - 1);
 	gchar *name;
-	const GPtrArray *tags = NULL;
-	const TMTag *tag;
+	GPtrArray *tags = NULL;
 	GeanyFiletype *ft = editor->document->file_type;
 
 	if (ft->id == GEANY_FILETYPES_C || ft->id == GEANY_FILETYPES_CPP)
@@ -703,29 +879,21 @@ static void autocomplete_scope(GeanyEditor *editor)
 	else if (typed != '.')
 		return;
 
-	/* allow for a space between word and operator */
-	if (isspace(sci_get_char_at(sci, pos - 2)))
+	/* allow for spaces between word and operator */
+	while (pos >= 2 && (isspace(sci_get_char_at(sci, pos - 2)) ||
+						highlighting_is_comment_style(sci_get_lexer(sci), sci_get_style_at(sci, pos - 2))))
 		pos--;
 	name = editor_get_word_at_pos(editor, pos - 1, NULL);
 	if (!name)
 		return;
 
-	tags = tm_workspace_find(name, tm_tag_max_t, NULL, FALSE, ft->lang);
+	tags = find_scope_members(editor->document->tm_file, name, ft->lang);
 	g_free(name);
-	if (!tags || tags->len == 0)
+	if (! tags)
 		return;
-
-	tag = g_ptr_array_index(tags, 0);
-	name = tag->atts.entry.var_type;
-	if (name)
-	{
-		TMWorkObject *obj = editor->document->tm_file;
-
-		tags = tm_workspace_find_scope_members(obj ? obj->tags_array : NULL,
-			name, TRUE, FALSE);
-		if (tags)
-			show_tags_list(editor, tags, 0);
-	}
+	if (tags->len > 0)
+		show_tags_list(editor, tags, 0);
+	g_ptr_array_free(tags, TRUE);
 }
 
 
-- 
1.7.9.1

_______________________________________________
Geany-devel mailing list
Geany-devel@uvena.de
https://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to