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