This PR enables local variable (and function parameter) tags and fixes related problems:
1. Disables local variables for the symbol tree (it becomes too crowded when these are shown IMO). 2. Disables local variables for generated tag files - these aren't interesting for what we use global tags for. This however also means that unit tests don't cover local variables because they are generated in the same way as global tag files. 3. Update goto tag definition/declaration to ignore local tags from other functions than the current one and also ignoring local variables defined on a line which is behind the current line. 4. Update non-scope autocompletion ignoring local variables like in (3). 5. Update scope autocompletion ignoring local variables like in (3). In addition, when searching for applicable types for the variable for which we perform scope autocompletion, sort the candidate types so local variables from current function above the current line are preferred to global variables from the current file which are preferred to other variables.
This PR also improves the scope autocompletion a bit by 1. Removing some keywords like "const", "struct" from the type, also removing `&` and contents of `<>` braces and `[]` braces so we only get the "pure" type without additional garbage. 2. Supporting (multiple) inheritance and including members of parent classes in the result.
More details are in the individual commit messages.
@elextr Your turn, bring your evil C++ code :-) You can view, comment on, or merge this pull request online at:
https://github.com/geany/geany/pull/3175
-- Commit Summary --
* Rename tm_tag_file_t to tm_tag_local_var_t * Enable local tag generation for C/C++ * Update goto symbol definitions to take into account local variables * Update (non-scope) autocompletion to take into account local variables * Update scope completion to take into account local variables * Strip more things from variable type * Move strip_type() above find_scope_members_tags() * Support (multiple) inheritance by scope completion
-- File Changes --
M src/editor.c (14) M src/symbols.c (11) M src/tagmanager/tm_parser.c (10) M src/tagmanager/tm_parser.h (2) M src/tagmanager/tm_workspace.c (307) M src/tagmanager/tm_workspace.h (6)
-- Patch Links --
https://github.com/geany/geany/pull/3175.patch https://github.com/geany/geany/pull/3175.diff
Neat!!! Have not looked at it in detail but comments below.
Disables local variables for the symbol tree (it becomes too crowded when these are shown IMO).
Totally agree, I enabled them in the past using your patch and its waaay too busy.
Disables local variables for generated tag files - these aren't interesting for what we use global tags for. This however also means that unit tests don't cover local variables
Agree that global tags usage is for names accessible outside the scope, function names and struct members, but locals and parameters are only visible inside the function scope.
No tests!!! Well almost all the rest of Geany has no tests so its not like it stands out :smile:
Update goto tag definition/declaration to ignore local tags from other functions than the current one and also ignoring local variables defined on a line which is behind the current line.
Limiting it to only locals/parameters of the current function is great.
Nice idea about the following declarations, fine for languages that are C, but be careful, at least Julia violates it ([see](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope) "This is true even if the outer local is declared after (in the sense of textually below) an inner block.") and other languages may too (I think Lisp). Or is this feature filetype specific to C/C++ only?
Update non-scope autocompletion ignoring local variables like in (3).
What about object data members in member functions, data members (and functions as well actually) from all parent classes are available as unqualified names automatically visible in the member function (ignoring complications like "private" and "protected").
Update scope autocompletion ignoring local variables like in (3).
Isn't scope autocompletion automatically limited to the applicable scope?
Or are you talking about limiting the candidate set of composite declarations that are considered as scopes to provide potential names? ie when typing `x.` first apply (3) to find the possible types of `x` then for those that are composite types (things like `int` are irrelevant) find their member names and present that list?
Removing some keywords like "const", "struct" from the type, also removing & and contents of <> braces and [] braces so we only get the "pure" type without additional garbage.
I presume by <> you mean C++ template parameters? If so, although the parameters are actually part of the typename, technically the members (and so completions) can vary between specialisations. What do you do when there are several, show only the original declaration members, or combine members from all specialisations?
Supporting (multiple) inheritance and including members of parent classes in the result.
Neat!! Does it ripple up through grandparents and great grandparents etc? This also applies to non-scope autocompletion inside member functions as mentioned above.
Actually "Neat!!!" is not sufficient, this is massive, most modern code is written using parameters and locals almost exclusively, globals are only functions, and C++ moves many of them to members. So global autocompletes have significantly reduced in usefullness. Adding locals and parameters to autocomplete is a significant upgrade.
Nice idea about the following declarations, fine for languages that are C, but be careful, at least Julia violates it ([see](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope) "This is true even if the outer local is declared after (in the sense of textually below) an inner block.") and other languages may too (I think Lisp). Or is this feature filetype specific to C/C++ only?
[Edit: and inside C++ struct/class declarations all data member names are visible everywhere, even if declared after.]
I probably wasn't clear enough here but this is about local variables only and there's no change for other tag types. I think for variables declared inside functions it's safe to say that those declared after the current line are not usable.
What about object data members in member functions, data members (and functions as well actually) from all parent classes are available as unqualified names automatically visible in the member function (ignoring complications like "private" and "protected").
I'm not sure if I understand but non-scope autocompletion in Geany just simply takes all the symbols having the typed string as a prefix and shows them. This includes all members of all classes, enums, etc. What I did is that in addition to that, I also included function parameters and local variables from the current function (but again, just those defined on the previous lines).
Isn't scope autocompletion automatically limited to the applicable scope?
Despite being called "scope autocompletion" the way it works is more like "nesting-aware autocompletion". The scope information is used just to know what members various types have. The scope reported by ctags is more or less just the lexical scope not taking into account various scope-manipulation features of languages like `using namespace` and by just looking at what the `scope` field contains we wouldn't get correct results.
... when typing x. first apply (3) to find the possible types of x ...
This is basically the moment we are talking about - finding possible types of `x`. The way it works is that scope autocompletion finds all tags named `x` and then examines whether its `var_type` is a tag of a type that can contain some members. When searching for tags named `x`, scope autocompletion goes in this order: 1. Local variable tags preceding the current line 2. Tags appearing in the current file 2a. (For C/C++ it might be a good idea to improve this by looking for a header file with the same name and continue by looking for the tags there) 4. Workspace tags 5. Global tags
This way we simulate the true scope search and variable visibility (local variables shadowing variables declared in the file which in turn shadow variables declared in other files).
I presume by <> you mean C++ template parameters? If so, although the parameters are actually part of the typename, technically the members (and so completions) can vary between specialisations. What do you do when there are several, show only the original declaration members, or combine members from all specialisations?
ctags knows basically just the declarations and doesn't track template parameters. When there is `void foo(T t) {}`, for ctags it's the same thing whether `T` is a template parameter or some type. You will see `T` in the symbol tree tooltip or in function parameter calltip.
Neat!! Does it ripple up through grandparents and great grandparents etc?
Yes, to depth 10. Just added some hard-limit to avoid infinite recursion for things like ``` class C : C { }; ```
This also applies to non-scope autocompletion inside member functions as mentioned above.
As noted above, non-scope autocompletion is just primitive prefix-matching autocompletion including all tags and those member tags are already included.
I probably wasn't clear enough here but this is about local variables only and there's no change for other tag types. I think for variables declared inside functions it's safe to say that those declared after the current line are not usable.
This may be true for well-written, valid code. But we deal with code that's just being written, and in that case it can absolutely be useful to autocomplete later declarations, perhaps knowing that I need to move the declaration upwards after finishing this line.
I don't think we apply that logic to global tags like static variables, do we? Like, I can autocomplete a call to `foo()` even if its declaration is later in the file?
I'm not saying the "only tags declared before the cursor" is right or wrong, but that it's not so clear as you might think.
I would probably remove that logic from the patches for now and see what the feedback is.
Actually "Neat!!!" is not sufficient, this is massive, most modern code is written using parameters and locals almost exclusively, globals are only functions, and C++ moves many of them to members. So global autocompletes have significantly reduced in usefullness. Adding locals and parameters to autocomplete is a significant upgrade.
If you have some C++ code, please test how it behaves - I mostly tested it just with Geany's C (plus tried Boost to see how types are reported and what needs to be stripped from them).
One thing I noticed that doesn't work very well is multiple member accesses in a row like ``` a.b. ``` Geany starts from scratch when looking for a type when `.` is typed so for `b` it doesn't look at the particular `b` which is a member of `a` but it searches `b` globally. Unfortunately if we wanted to generalize this, we'd have to parse possibly complex parts of code in front of `.` by ourselves.
This may be true for well-written, valid code. But we deal with code that's just being written, and in that case it can absolutely be useful to autocomplete later declarations, perhaps knowing that I need to move the declaration upwards after finishing this line.
Can do that. On the one hand I don't think it's so common to have a variable declared after its use (I typically forget to declare it altogether), on the other hand there will hopefully not be too many variables with the same name declared in the same function that this would cause problems.
Also consider this: ``` void foo() { Foo a; if (true) { Bar a; if (true) { Baz a; } } // <-- cursor here if (true) { Bar2 a; if (true) { Baz2 a; } } } ``` We don't get nesting information for local variables by ctags - all the `a` variables in the above code have the same scope returned by ctags. So by removing some of them we may at least reduce the danger that the wrong one is used.
I don't think we apply that logic to global tags like static variables, do we? Like, I can autocomplete a call to foo() even if its declaration is later in the file?
No, we don't, I added it just for the local variables.
@techee pushed 2 commits.
5134b0c93c4b950424d7783a4691f92016392faf Sort tags so tags from source file's header are preferred to other files 503edf8dd3e2347a9faf39923abad6ae7d3aa92e Rewrite member_at_method_scope() to handle more situations
Have tried this, and first impressions its a big improvement on previously.
On the one hand I don't think it's so common to have a variable declared after its use
As I said above, its allowed and somewhat common in C++ inside class declarations.
Since types must be declared before use, members that use public types need to go after that definition, and if the type is public and the data member private its a common idiom to put those data members in one private section at the end of the class declaration rather than swapping back and forth all the time.
That means that public constructors and inline functions use the variable name before it is declared as in the example below (with comments about how well autocomplete works in various contexts).
``` class Foo { public: Foo():iiiii(1){} // autocompletes iiiii correctly void f(){ int pit; iiiii = 2; // autocompletes iiiii correctly if(p){ // autocompletes p first but with lots of C library crap p->i = p->j; // autocompletes ->i and j correctly } pit = 1; // autocompletes with ctrl space after p // but with pid_t before pit in list } struct Bar { int i, j; }; int operator ()(){ // autocompletes operator return iiiii; // autocompletes iiiii when ctrl space after just i // but with i, id, id_t before iiiii in list } ~Foo(){delete p;} private: int iiiii; Bar *p; };
main(){ Foo* p; p->f(); // autocompletes p but with Foo first, tooltip shows for f( correctly Foo foo; foo(); // no tooltip for foo( } ```
As noted there are some places where the sorting seems questionable.
Also constructors, `Foo()` above, should not show in . or -> completions lists (p-> in main() above), they can't be called like that. Destructors can and show ok.
I also opened the above file in vscode and (I guess unsurprisingly) it doesn't have the noted issues.
Now for _real_ evil :imp: code ...
note to self, don't ever autocomplete "get" :smile:
but a big improvement, seems to not get too scrambled by templates.
I have no issue with this being merged, its a great improvement on previous capabilities. Thanks @techee
Since types must be declared before use, members that use public types need to go after that definition, and if the type is public and the data member private, its a common idiom to put those data members in one private section at the end of the class declaration rather than swapping back and forth all the time.
Once again - the "ignore variables after the current line" thing is for _local variables only_ (that is, variables declared inside a single function). It doesn't apply to members. Anyway, no problem to remove it. As @kugel- pointed out, the possible problem could be when refactoring/writing a not yet compiled code and having the variable declared after the current location by accident. I'm still a bit hesitant about how common problem this is and if we should support invalid code (which we don't already, a single extra `{` breaks ctags parsing). But OK, let's remove this condition. ``` if(p){ // autocompletes p first but with lots of C library crap ... pit = 1; // autocompletes with ctrl space after p // but with pid_t before pit in list ... ``` This is normal autocompletion (scope autocompletion only happens when you type `.` or `->`) where the result contains all tags.
``` foo(); // no tooltip for foo( ``` I haven't done anything regarding tooltips. Tooltips right now just look at corresponding function calls which `foo` isn't. Could probably be improved.
As noted there are some places where the sorting seems questionable.
The sorting is alphabetical, like in the symbol tree (capitals first). I haven't done anything regarding the sorting of the results and I don't really have any smart idea how to (simply) guess what the user wants.
Also constructors, Foo() above, should not show in . or -> completions lists (p-> in main() above), they can't be called like that. Destructors can and show ok.
Constructors are reported by ctags as methods so we see them in the same way as methods. We could probably detect them by checking if the "function" name is the same as the name of the class and filter them out.
_local variables only_
Oh, _local variables only_ :smile: my bad. Agree with @kugel-, removing the forward limitation is better for _local variables only_ as well.
This is normal autocompletion (scope autocompletion only happens when you type . or ->) where the result contains all tags.
`pit` is a local, I thought you had sorted them first (my understanding from (5) in the OP), so I was pointing out `pid_t` showed before it, and its definitely not a local, in fact its from the C/C++ global tagfile IIUC.
Tooltips right now just look at corresponding function calls which foo isn't.
Well, its not a C function call, but it is a C++ function call, (have I mentioned not all languages are C?). If the problem is in determining function calls and not in finding the operator function tag then for sure its not part of this PR.
Constructors are reported by ctags as methods so we see them in the same way as methods. We could probably detect them by checking if the "function" name is the same as the name of the class and filter them out.
Ok, if ctags reports them as normal member functions then its understandable, and yes they are a member function where the name matches the class name so that is indeed how to filter them. Its just my idiom to Title case class names making the constructor sort first due to ASCII order and making them visible :stuck_out_tongue_winking_eye: .
pit is a local, I thought you had sorted them first (my understanding from (5) in the OP), so I was pointing out pid_t showed before it, and its definitely not a local, in fact its from the C/C++ global tagfile IIUC.
It was about ordering tags before processing them by the scope autocompletion code, not about ordering results. The biggest problem for larger projects is to pick the right tag, especially for often used names like "data", "id", "name", etc. and the heuristic tries to pick the nearest one to the current position (i.e. local > from current file > from its header > workspace tags > global tags).
(If you have some bigger C++ project around it would be interesting to see how the autocompletion behaves for it when you load all its tags e.g. using ProjectOrganizer.)
Sorting local variables above the rest of the tags would be possible for non-scope autocompletion (with scope autocompletion you get members which are never local). On the other hand this is the "stupid but predicable" autocompletion which always pops up a list of all tags sorted alphabetically and I don't know if having 2 groups each sorted alphabetically in the list wouldn't be confusing.
Well, its not a C function call, but it is a C++ function call, (have I mentioned not all languages are C?). If the problem is in determining function calls and not in finding the operator function tag then for sure its not part of this PR.
It's not really a function code, it's an object with operator () that is callable thanks to this. And the tooltip code doesn't take this into account.
It was about ordering tags before processing them by the scope autocompletion code, not about ordering results.
Ahhhhh, gotcha.
If you have some bigger C++ project around it would be interesting to see how the autocompletion behaves for it when you load all its tags.
I tried my current project, I just loaded all the .hpp files (just select all in the `include` directory so no ProjectOrganizer needed) and a bunch of cpp files.
The problem is almost no locals have a type because they are inferred (ie declared `auto`) and that is way above ctags pay grade to get those types, and so no scope autocomplete on . or -> to find out which tag was chosen. I guess that means the local was chosen, but its impossible to be sure.
Also my local names and member names tend not to overlap, (members have long names like `current_token` but locals are short like `a`) but deliberately creating a local the same name as a member does indeed give scope autocomplete for the local, not the member of the same name, and for the member when the local declaration is removed, which is correct.
Sorting local variables above the rest of the tags would be possible for non-scope autocompletion (with scope autocompletion you get members which are never local).
That would be good.
An example in the project I tested is that inside a function I have a local `count` so typing `co` ctrl+space gives a list including things like `conj`, `conjf`, ... `cookie_close_function_t`, `cookie_io_function_t` ...`cos`, `cosf`, `cosh`, `coshf`, `coshl`, `cosl`, `count`. The one I want is dead last. What the `cookie_..._function_t` is about I don't know, it must be from the C/C++ global tags file where `cos` etc come from. So sorting locals, then members, then globals would be much more usable.
Typing `co` ctrl+space at exactly the same place in the same file in Eclipse gets many of the same names plus some more, (including the cookie monsters), but grouped by a whole lot of groups like local var, global var, typedef, class, struct, member var, member function, global function etc each sorted alphabetical, but it has an icon on each name making the groups obvious. I believe Scintilla can [display them too](https://www.scintilla.org/ScintillaDoc.html#SCI_REGISTERIMAGE). Eclipse also has an option to alphabetise the autocomplete list ignoring groups, but the icon, and the fact the type is shown for variables (the inferred type, but Geany can't do that, we would just have "auto"), makes it easier to find what I want when its plain alphabetic.
Showing icons would help to reduce possible confusion about groups.
It's not really a function code, it's an object with operator () that is callable thanks to this. And the tooltip code doesn't take this into account.
Its just a member function like any other, but with a funny name. Thats what I mean by "determining function calls". I presume at the moment the tooltips code finds the tag for `foo`, and it ignores all but function/method tags. But for C++ it should also to notice it is a variable of a class with an operator() member function and tooltip that. And also if the tag says its a class name, then the tooltip should show the constructor if it has one. But as I said, so long as the tags support that then its tooltip code not this PR. We really should separate some of this language specific stuff into a plugin "someday".
@techee pushed 1 commit.
0c6d315431b7ae336ea16f8f2ec6e9ce84e3d462 Allow local variable autocompletion also before variable declaration
The problem is almost no locals have a type because they are inferred (ie declared auto) and that is way above ctags pay grade to get those types, and so no scope autocomplete on . or -> to find out which tag was chosen. I guess that means the local was chosen, but its impossible to be sure.
That's something that will unfortunately never work with ctags and will have to wait for LSP (aka the post-ctags time consumer if I or someone else is brave enough).
(sorting locals before other tags) That would be good.
OK, can try that.
Typing co ctrl+space at exactly the same place in the same file in Eclipse gets many of the same names plus some more, (including the cookie monsters), but grouped by a whole lot of groups like local var, global var, typedef, class, struct, member var, member function, global function etc each sorted alphabetical, but it has an icon on each name making the groups obvious.
The question is what we want - whether icons corresponding to groups or icons corresponding to tag types like in the symbol tree - see #3176. I suggest to try the sorting only first and see how it behaves.
Its just a member function like any other, but with a funny name. Thats what I mean by "determining function calls". I presume at the moment the tooltips code finds the tag for foo, and it ignores all but function/method tags. But for C++ it should also to notice it is a variable of a class with an operator() member function and tooltip that. And also if the tag says its a class name, then the tooltip should show the constructor if it has one. But as I said, so long as the tags support that then its tooltip code not this PR. We really should separate some of this language specific stuff into a plugin "someday".
For now I'll just keep it as it is - it didn't work before, it won't work now - and can be improved later.
That's something that will unfortunately never work with ctags and will have to wait for LSP (aka the post-ctags time consumer if I or someone else is brave enough).
Yeah, that would make Geany into a "full fat" IDE, not sure we want that. But inference is why I moved my C++ work to one. I guess (presuming "somebody" offers to do it) that is a decision that will be needed some day as more languages use inference, but not now.
The question is what we want - whether icons corresponding to groups or icons corresponding to tag types like in the symbol tree - see https://github.com/geany/geany/pull/3176. I suggest to try the sorting only first and see how it behaves.
I thought I saw something about icons recently!!! Yeah, its not this PR, sorting for a start.
For now I'll just keep it as it is - it didn't work before, it won't work now - and can be improved later.
Agreed, as I said "not this PR".
@techee pushed 2 commits.
58e0d4af1773a5420c610345e5fb8753737d3b0e Move sort find_header() and sort_found_tags() 1acd16b4bbce2e792d2003367781dc3868fc6e40 Sort non-scope autocompletion results by locality
@elextr I've just pushed the sort patch - please give it a try. When searching for tags Geany for non-scope autocompletion Geany now has to go through all the tags, not just the MAX_NUM tags inside the workspace array as local tags may be alphabetically behind the MAX_NUM number. This could possibly be slow but even for 1-letter autocompletion popup trigger I didn't see any slowness on my machine with big projects.
@techee pushed 1 commit.
a36cf376d557e4392fc949026934a1f6bfbe39a9 fixup! Sort tags so tags from source file's header are preferred to other files
I tried it in the same place as described above, typing `c` ctrl+space gives `count` first, yay, and other more likely things near the top.
But it introduces a problem when continuing typing with the autocomplete list open, when adding `o` instead of leaving the `count` entry highlighted the highlight is moved to the `code` entry further down the list, then adding `u` closes the autocomplete list. Ctrl+space brings it back much reduced as expected. It would seem that with continued typing the selection is purely alphabetic (selecting `code` over `count`) and/or it doesn't include the current entry. Is this selection done by us or Scintilla? If its Scintilla maybe we need https://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETORDER set to custom?
I tried it in the same place as described above, typing c ctrl+space gives count first, yay, and other more likely things near the top.
OK, I didn't notice it but you are right, looking at the documentation it seems the list either has to be sorted or using custom sorting. I would have to check what exactly ``` This requires extra processing in SCI_AUTOCSHOW to create a sorted index. ``` means (SCI_AUTOCSHOW documentation doesn't seem to mention anything about this index). For this PR I'd suggest to revert back to the original behavior and possibly address this in the future.
SCI_AUTOCSHOW documentation doesn't seem to mention anything about this index
Well its an implementation detail internal to Scintilla, nothing the user sees, so no need to mention it here.
It only relates to the value set by the `SCI_AUTOCSETORDER` function, so thats where its mentioned.
I just put `SSM(sci, SCI_AUTOCSETORDER, 2, 0);` before the call to `SCI_AUTOSHOW` at editor.c:604 and it indeed seemed to fix the problem.
I just put SSM(sci, SCI_AUTOCSETORDER, 2, 0); before the call to SCI_AUTOSHOW at editor.c:604 and it indeed seemed to fix the problem.
Ah, OK, if it's that simple, let's do that.
@techee pushed 2 commits.
3e375d5e91fbc5992943409d47a056fa52354065 fixup! Sort tags so tags from source file's header are preferred to other files 0c37d5ac4f44cd08f936b10e08751da76948348f Sort non-scope autocompletion results by locality
I fixed the Scintilla problem and also noticed one more problem in filtering non-scope autocompletion entries so I force-pushed 2 past patches fixing the problem.
@techee pushed 1 commit.
8973b53209790be506427a9895b6e5bdca114bb6 fixup! Sort tags so tags from source file's header are preferred to other files
@techee please do not force push unless _absolutely_ necessary, especially when you know testers have copied your branch, git pull now fails to merge with a conflict in tm_workspace.c.
@techee please do not force push unless absolutely necessary, especially when you know testers have copied your branch, git pull now fails to merge with a conflict in tm_workspace.c.
Yeah, sorry, I wanted to update also a commit message which wouldn't have been possible with simple fixup but should have created a separate commit instead.
Anyway made a new clone (lazy conflict fix) and it seems to work as advertised now.
I can't see any hint of the possible slowness issue noted above with all files in the biggest C++ project I have open, so I think its only likely to affect people with the kernal or chromium symbols open.
LGBT (test :-)
Probably best to merge this soon so it can get more testers. Will leave you to decide whats squashable.
@techee pushed 1 commit.
6aff32b42e40d2f1cea924a7518efeee0d73ad3e fixup! Enable local tag generation for C/C++
I just committed one more minor change so we map also tm_tag_local_var_t to a root in symbols tree. Even though we don't display it in the symbols tree, we need to be able to get an icon of local variables for #3176.
The last change doesn't seem to have any visible effects which I assume is correct, the visual effect being in #3176.
The last change doesn't seem to have any visible effects which I assume is correct, the visual effect being in https://github.com/geany/geany/pull/3176.
Exactly. But when #3176 is applied on top of this PR, without the patch local variables wouldn't get any icon in the autocompletion popup.
Great, so if it works is a #3176 question, but it doesn't break anything in this PR so this is still mergable.
Great, so if it works is a https://github.com/geany/geany/pull/3176 question, but it doesn't break anything in this PR so this is still mergable.
Yeah, it doesn't affect anything in this PR.
I can't see any hint of the possible slowness issue noted above with all files in the biggest C++ project I have open, so I think its only likely to affect people with the kernal or chromium symbols open.
This is something I'd still like to look at - I think I could optimize the non-scope autocompletion a bit so it doesn't have to govthrough so many symbols (and sort those). The biggest danger is libraries like `glib` or `gtk` where all the symbols have the same prefix `g_` or `gtk_` and are possible candidates for the autocompletion popup.
The biggest danger is libraries like glib or gtk where all the symbols have the same prefix g_ or gtk_ and are possible candidates for the autocompletion popup.
If Geany were C++ I would say stick 'em in a std::map but its not :(
@techee pushed 1 commit.
d6cc62f116406f328610a71e1aa522a1306f3c4a Speed up non-scope autocompletion
This is something I'd still like to look at - I think I could optimize the non-scope autocompletion a bit so it doesn't have to govthrough so many symbols (and sort those). The biggest danger is libraries like glib or gtk where all the symbols have the same prefix g_ or gtk_ and are possible candidates for the autocompletion popup.
OK, it's hopefully fixed in the latest commit.
@elextr I still find it a little strange that I get autocompletion results for variables declared after the current line in the function (I would say it's more annoying to see these invalid suggestions than the rare problem when you have variables declared later in the code by mistake). If you use some other editors for C/C++, would you check how they behave in this respect?
@techee pushed 1 commit.
3c9d3b0183c5ad5e304a44130f3f7ac5df78f31e Fix non-scope autocompletion deduplication
It was @kugel- who wanted variables declared after available during his manipulations, I wanted to be sure:
1. it only applied to variables, remember types can be forwarded and uctags doesn't emit tags for the forward declaration 2. it only applied to function (or lambda?) local variables, class member variables (and function names) are available backward 3. it only applied to C/C++, at least Julia allows use before declare, other languages would need their scope rules examining
Both Eclipse and vscode properly obey C/C++ visibility rules, so they don't show function local names (or globals but who uses those?) declared after.
@techee pushed 1 commit.
c41a84c026df0b8061bc4a4d8204c76834df35d8 Enable local variable and parameter tag reporting for Python and GDScript
@techee please move the Python/GDscript to another PR, this one is C/C++ and we have by far enough to test with that, adding more languages is just likely to slow it all down.
@techee pushed 1 commit.
188fef9dc2b222dcac94c1e87d94d70e963d54d1 Revert "Enable local variable and parameter tag reporting for Python and GDScript"
@techee please move the Python/GDscript to another PR, this one is C/C++ and we have by far enough to test with that, adding more languages is just likely to slow it all down.
Yeah, there was actually a problem with the current Python parser (which is fixed upstream) so I reverted the last commit and will post it separately.
Thanks, maybe split Python and gdscript, although we have plenty of Pythonistas here you would need to engage a GDscriptist to check it.
examining
It only applies to local variables (and function parameters which are however always at function beginning so always visible within function). It only applies to languages where we use the `tm_tag_local_var_t` mapping - currently it is C/C++, could also be Python and GDScript, the rest of parsers don't report local variables.
Both Eclipse and vscode properly obey C/C++ visibility rules, so they don't show function local names (or globals but who uses those?) declared after.
Then I'd suggest to respect the order. The problem is this: <img width="538" alt="Screen Shot 2022-04-29 at 1 35 38" src="https://user-images.githubusercontent.com/713965/165864725-e2698465-c568-44be-acd5-c383aef4dd8f.png"> Here you get invalid autocompletion for `header` which is declared in the block below when one could get `header_exts` directly at the top.
@techee pushed 1 commit.
98638827a4b8192bdfd4b42d7ef8fe7a22cf9d40 Revert "Allow local variable autocompletion also before variable declaration"
It only applies to languages where we use the tm_tag_local_var_t mapping - currently it is C/C++, could also be Python and GDScript, the rest of parsers don't report local variables.
Ok, well I just checked and Python also allows use before "declare" (assignment), eg
```
for i in range(2):
... if i == 1: ... print(j) ... else: ... j = 55; ... 55 ```
Statically j is used before its declaring assignment, but not at runtime which is what matters to Python, so clipping later declarations will need to be language specific.
Ok, well I just checked and Python also allows use before "declare" (assignment)
Yeah, makes sense with dynamic language like Python.
Well, we could have one more callback function in `tm_parser.c` like ``` gboolean tm_parser_var_valid_after_declare(TMParserType lang) { if (lang == TM_PARSER_PYTHON) return FALSE; return TRUE; } ``` and make the check based on the return value of this function.
Can you pass the kind and any other information thats relevant to the decision and localise the whole logic in the one function?
FWIW, I didn't **want** the "declared after" rule to be removed, I simply suggested to get feedback first before implementing the rule. Now you have experience with both sides and can make a decision, and we learned that it needs to be language specific.
All fine, go ahead :-)
Can you pass the kind and any other information thats relevant to the decision and localise the whole logic in the one function?
We now store the kind letter in `TMTag` but the letter is language-specific and not necessary in this case. This logic only applies to `tm_tag_local_var_t` tags and we don't need to pass the same value to this function.
Well, I was just thinking that I bet there are other languages with other visibility rules, not just for locals, (not all languages are C) but I guess expanding it can be left as an exercise for future @techee :-)
Well, I was just thinking that I bet there are other languages with other visibility rules, not just for locals, (not all languages are C) but I guess expanding it can be left as an exercise for future @techee :-)
I think I'll leave it to future generations of Geany coders :-).
OK if I rebase this PR a little? There have been many back and forth commits and rewrites of some previous implementations and the history is quite messy now. Or I could also post the result as a separate PR.
Yeah, as I [said](https://github.com/geany/geany/pull/3175#issuecomment-1111544942) I'll leave that to you to sort out. In a separate PR and branch would be nice since it wouldn't need to be force pushed and should just apply and you can delete the messy branch.
@techee pushed 1 commit.
09f361dbabd1a8739064d8a527d1016fdd3dd074 Make validity of local variables configurable based on used language
Closed #3175.
Closing in favor of #3185.
github-comments@lists.geany.org