This is one more attempt on unifying `TMTag`s and externally provided symbols for the symbol tree before giving up and making the plugins create the symbol tree by themselves (which leads to quite a significant code duplication). This time (unlike the previous attempts) I'm quite happy with the result though. I called the new structure `GeanySymbol` - could be renamed to something else if someone has better idea.
The idea is to make `GeanySymbol` operate in two modes: - either it is backed by a `TMTag` and created using `GeanySymbol *geany_symbol_new_from_tag(TMTag *tag)` - or it is created by some external source such as the LSP plugin using ```C GeanySymbol *geany_symbol_new(gchar *name, gchar *detail, gchar *scope, gchar *file, TMParserType lang, glong kind, gulong line, gulong pos, guint icon) ``` The corresponding structure looks this way: ```C typedef struct GeanySymbol { gchar *name; gchar *detail; gchar *scope; gchar *file; TMParserType lang; gulong line; gulong pos; glong kind; guint icon;
TMTag *tag;
gint refcount; /* the reference count of the symbol */ } GeanySymbol; ``` where either `tag != NULL` when using `geany_symbol_new_from_tag()`, or `tag == NULL` for `geany_symbol_new()`.
The important part is that the members of `GeanySymbol` cannot be accessed directly from other files but only using getters that either use the `tag` or the member of `GeanySymbol` such as ```C const gchar *geany_symbol_get_name(const GeanySymbol *sym) { if (sym->tag) return sym->tag->name; return sym->name; } ```
By this interface, all callers like the symbol tree implementation are completely shielded from the details of where the symbol comes from. The bulk of the diffs inside `symbols.c` is pretty much just using this interface instead of using `TMTag` directly and renaming `tag` to `symbol`. `get_symbol_name()` and `get_symbol_tooltip()` were moved to `GeanySymbol` implementation, and also (previously inlined) `geany_symbol_get_name_with_scope()` was moved there too.
The additional `PluginExtension` interface for using these symbols would be more or less identical to what I proposed in https://github.com/geany/geany/pull/3850, i.e. ```C gboolean (*doc_symbols_provided)(GeanyDocument *doc); GPtrArray *(*doc_symbols_get)(GeanyDocument *doc); ``` and - either additional `void (*doc_symbols_request)(GeanyDocument *doc, GCallback on_done);` in this interface making Geany request the extension for symbols (asynchronously) - or some `symbol_tree_reload()` function the plugin could call which would make Geany re-request symbols using `doc_symbols_get()` after the plugin gets them e.g. from the LSP server
@b4n How does something like this sound? The implementation here is incomplete (only tested with the `TMTag` "backend" of `GeanySymbol`) but I don't want to continue in case you have some reservations regarding this approach. You can view, comment on, or merge this pull request online at:
https://github.com/geany/geany/pull/3910
-- Commit Summary --
* Possible extension interface for symbol tree
-- File Changes --
M meson.build (3) M src/Makefile.am (1) M src/sidebar.c (7) M src/sidebar.h (2) A src/symbol.c (341) A src/symbol.h (67) M src/symbols.c (426) M src/symbols.h (2)
-- Patch Links --
https://github.com/geany/geany/pull/3910.patch https://github.com/geany/geany/pull/3910.diff