The implementation of this function is almost the same like the original
m_workspace_find_scoped_members() and there's nothing interesting here
we wouldn't be able to recreate trivially.
By comparing the file pointer in the loop we can speed it up a bit
because we can avoid the strcmp() (this function is the slowest part of
the scope completion based on profiling).
Also move the pointer array creation to this function and return it which
is a bit cleaner.
Disclaimer: I have absolutely no idea how the original function works.
After gazing into the code for one hour, I just gave up and wrote my own
version of it based on what I think the function should do
but maybe I'm just missing something what justifies the original
implementation's insanity.
The previous commit fixed the situation when e.g. anon_struct_0 was in the
current file by checking the current file first.
In the case the struct type definition isn't found in the current file,
at the moment we get all members from all anon_struct_0 which can be a
really long list. This list isn't very helpful to users because all the
members from all the structs are mixed. Moreover, not all possible members
are in the list because there are e.g. just members from anon_struct_0 but
not from anon_struct_1 etc. which from the point of view of this function
is a different type.
Instead, restrict the returned members to just a single file (anonymous
structs have unique name per file so it means there will be just one
from the file). Of course the picked file can be wrong and the returned
members might be from a different struct the user wanted but at least
the list will make more sense to users.
At the moment it can happen that even though a member is found in the
currently edited file, the search at the end of the function finds
the type inside another file. This typically happens for anonymous
structs so e.g. for anon_struct_0{...} from the current file we get
members from anon_struct_0{...} from all open documents plus gloabl tags.
Search in an increasing "circle" - start with current file only (trying
all possible types of the variable), continue with workspace array and
finally, if not found, search in the global tags.
This function won't work correctly on unsorted array because the second
part of the function (after the tags search) expects the array is sorted
by name. The only user of this is tm_source_file_set_tag_arglist() in which
we can go through the tags manually by ourselves (it needs only a single
value so the original behavior of tm_tags_find() wasn't a problem).
Eliminate the tags_search() function as it isn't needed any more.
Just cleanup, not functional change.
Do the same with struct/class/union... member tags as we do with
typenames - extract them from the edited file and merge them with
the array containing all of them so while editing, there should
be no slowdowns because one file usually doesn't contain so many
tags. This eliminates about 2s freeze when typing "." on a linux
kernel project with 2300000 tags.
Extract typename and member tags also for global tags in case someone
creates a giant tags file - this needs to be done just once when
loading the tag files.
All the remaining tm_tags_extract() in Geany are called on
file tag array only so there shouldn't be any performance problems.
This patch contains a bit too many things which are however related.
It started by the part in editor.c (where we previously used only the
first type we found to perform scoped search) by going through all the
possible variable types until the scoped search returns some result
(this is useful if variable foo is used once as int and once as struct
and if the int is the first type found, we won't get the struct's members).
This didn't work. After an hour of debugging, it turned out that
because tm_workspace_find_scope_members() calls internally
tm_workspace_find() and this function returns static array, this
invalidates the array returned by the tm_workspace_find() used
previously to get all the possible variable types.
Since this is really dangerous and hard to notice, I tried to eliminate
the static returns from both tm_workspace_find() and
tm_workspace_find_scoped_members().
The tm_workspace_find_scoped_members() function is where I got
stuck because as I started to understand what it's doing, I found
many problems there. This patch does the following in this function:
1. Eliminates search_global and no_definitions parameters because
we always search the whole workspace and this simplifies the slightly
strange logic at the end of the function.
2. Returns members from global tags even when something found in
workspace tags - previously global tags were skipped when something
was found from workspace tags but I don't see a reason why.
3. Adds the lang parameter to restrict tags by language (we do this
with normal search and the same should be done here).
4. Previously when searching for types with members the function
returned NULL when more than one such type was found (there should
have been >=1 instead of ==1 at line 906). This patch improves the
logic a bit and if multiple types are found, it tries to use the one
which is other than typedef because it probably has some members (the
typedef can resolve to e.g. int).
5. Previously the function prevented only direct typedef loops like
typedef A B;
typedef B A;
but a loop like A->B->C->A would lead to an infinite cycle. This patch
restricts the number how many times the typedef can be resolved by
using for loop with limited number of repetitions and giving up when
nothing useful is resolved.
6. Finally the patch tries to simplify the function a bit, make it
easier to read and adds some comments to make it clearer what the
function does.
They are basically identical except:
1. _scoped() compares scope in addition
2. _scoped() is missing the C/CPP tag compatibility part
3. _scoped() allows returning just single result (unused)
4. _scoped() allows not searching in global tags (unused)
Since we now always put lang also under tag->lang, the match_langs()
function is not necessary.
Extend the add_filtered_tags() (and rename it to fill_find_tags_array()) to
perform the tm_tags_find(), compare the scope and add scope
as parameter of tm_workspace_find() and eliminate tm_workspace_find_scoped()
completely.
1. Factor-out the part common to tags_array and global_tags
2. Get both C/CPP tags when either of the languages is specified (both
for global_tags and tags_array)
3. Remove unnecessary strcmp()s (tm_tags_find() should return only tags
with the specified name)
4. Various minor cleanups
We want it disabled by default in 1.25 for everyone, but want to be
able to get it back on by default later on when the UI is more
polished.
So we will need to have a way to tell whether the configuration comes
from 1.25 and should be upgraded or was willfully disabled by the user
in a later version. So, use a temporary setting name that defaults to
disabled for 1.25
See #553.
Hide spawn_get_program_name(), spawn_async_with_pipes() and
spawn_get_exit_status_cb(), which are not used by anyone else and
should not be part of the plugin API unless explicitly required.
See http://lists.geany.org/pipermail/devel/2015-June/thread.html#9521
Note: this duplicates some documentation when a now hidden function was
referred to.
While the feature is nice, it might be unexpected and lacks user
feedback. This might lead to user thinking they lost their work
because they don't know they can undo the reload operation.
So, disable the feature by default until we introduce appropriate user
feedback allowing the user to learn about the feature and new behavior.
See http://lists.geany.org/pipermail/devel/2015-June/thread.html#9537