-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve type completion #16875
base: master
Are you sure you want to change the base?
Improve type completion #16875
Conversation
@MartinGC94 Is it possible to split the PR on some more simple and small to speed up the code review? |
@iSazonov Not in a meaningful way IMO. The code is basically doing this:
Aside from step 3, every step relies on the previous steps so a PR for step 2 would either not compile, or require the code from step 1 to be included which would just end up making step 5 look exactly like this PR. It would probably also be hard to judge the cache design on its own without seeing how it gets used. Maybe a deeper explanation of what I've done and the design will help:
TypeNameMap groups short type names by the first character in the short type name, then the short name itself and finally all the full names with that same type name. The basic idea is to quickly be able to look up necessary data when I have a full name and to limit the scope of searches when I only have a partial name. Here's a quick summary of the order I would review the methods in and what they do: |
@MartinGC94 Thanks for depth explanation! Does InitializeTypeCache start in startup time? My ask is about makes sense prepopulate the cache in build time? |
@iSazonov when you attempt to complete a namespace or type the cache is initialized if the cache is null. The cache is invalidated AKA changed to null whenever a new assembly is loaded. |
@MartinGC94 My main concern is whether the cache initialized in non-interactive scenarios like schedule task and at startup time in other scenarios - all these could be cause noticeable delay. If yes it makes sense to prepopulate the cache otherwise it is initialized at first tab-completion and I guess users will see no delay really and we have no need to complicate. |
@iSazonov Non-interactive scenarios are not affected. As mentioned, it's only initialized when tab completing a namespace/type for the first time, which is the same way it works today. |
Since you rebuild all type cache code it already makes no sense :-) I suggest you consider to create Source Generator. You can use follow examples:
Also I suggest you consider to have two type cache - (1) prepopulated with SG, (2) created at run time for new loaded dll-s. |
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
I've thought of something, currently type accelerators use the resolved shortname as the list item text, for example |
This seems like overcomplicating. |
@iSazonov What do you mean overcomplicating? Assuming it's in response to my last comment, it's just a matter of changing a single line to use a different property when building the completion result. |
Yes, it is for your comment. Personally I don't like this - looks weird and mislead me. |
I agree that it would have made sense to have That said, it will create confusion in some places. Like if you go to complete Edit: And I see you point out the issue that would create in PSRL as well where it would only ever complete |
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
PR Summary
Fixes #16798
Fixes #3277
Fixes #14146
Fixes #7287
Fixes the issue where namespaces would be removed from typenames with no regard for type name conflicts:
Now it will tab complete to the shortest non ambiguous name, in this case it would just be the full name but if a namespace alias or "using system" had been defined it would use that instead. Note it won't fall back to type accelerators or type aliases even if they would have been shorter. IMO It would be confusing if the entered type name changed, for example "System.Sing" turning info "float" and it would be annoying not being able to tab complete the real name if you for whatever reason wanted to use it.
Fixes the issue where using statements in $profile had no effect on the tab completion.
This is done by first checking the script text for using statements and if none are found, fall back to the session state. The idea here is that if you are writing a script inside an editor the using statements there should have priority over whatever is in your session state.
Fixes the issue where powershell defined types are only considered for tab completion if they are defined in the script text.
Now it will also include types from
using module
statements in the tab completion and types loaded into the session state.Adds the ability to find types/namespaces based on subnamespaces.
For example you can type in
Generic.List<Tab>
to tab complete toSystem.Collections.Generic.List
instead of either having to type the full name, or justlist
and select it from a long list of names.Fixes the issue where quotes around using namespace statements aren't considered when removing the namespace from completion, for example:
currently completes to
[tomation.Language.Token]
instead of the proper [Automation.Language.Token]Limit the type completion suggestions to Attribute types when completing an attribute token, for example:
Increases and decreases the type completion performance a bit
Using the following snippet to test:
Measure-Command { TabExpansion2 [s} | select Milliseconds
on fresh console launches it takes on average 177ms to complete. In my normal pwsh install it takes an average of 164.2ms.
Tab completing after the type cache has been built averages about 5,46ms with my new code and 9ms with my normal pwsh install. Interestingly there's a lot more variance in my code VS the old code. The old code sits consistently on 9ms while mine fluctuates between 4 and 6.
These results make sense to me because my type cache does more work in advance and saves more data but maybe some C# genius can optimize it so it's always faster?
The code was designed and tested around the type/namespace alias support that is currently waiting to get reviewed and hopefully merged here: #16734 the code specific to that change has been commented out, depending on what gets merged first it may need to get uncommented in a different PR.
On a side note, testing this code has made this PSReadline issue: PowerShell/PSReadLine#722 much more apparent to me because there's so many completion items with the same ListItemText for example, tab completing
language
gets meMicrosoft.PowerShell.Commands.Language
instead of my desiredSystem.Management.Automation.Language
. It should really look at the CompletionText instead, at least for types/namespaces since "apparent" duplicates are a lot more common here.PR Context
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.(which runs in a different PS Host).