-
-
Notifications
You must be signed in to change notification settings - Fork 367
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
Auto complete definitions within imports #2152
Conversation
Thanks for the fix, great to see tests to exercise it |
I am not sure if this fixes #2082. Afaics tests are demonstrating that completions works inside imports lists but the issue is about completions over qualified imports in the body of the module:
|
Sorry, I misunderstood the ticket. Will remove from the description. |
To clarify the expected behaviour is functions from MyModule followed by functions from all modules. |
buildModouleExportMap:: Maybe (ExportsMap) -> DM.Map T.Text [T.Text] | ||
buildModouleExportMap (Just exportsMap) = do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this function do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a typo in the name, however, it builds a map of "module.name" -> ["functions" .. ]
which I use to look up the available functions for that module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And why is it needed? Can't you use the ExportsMap as it is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I need it because I have to group on "module.name"
and use that as the key to look up all functions within that module. ExportsMap
as it is seems to be a map of "function-name" -> [{moduleNameText: "module-name", name: "function-name" ...} ]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, you are right.
But why build a map to do only one lookup and then throw it away?
- Cost of building the map: O(NlogN)
- Cost of doing the lookup by scanning the original exports map: O(N)
Neither is good enough, you want O(logN). How? Probably by changing the representation of the exports map to add a second index, the module name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think the first suggestion would be a good first pass? With potential follow up commits to pull out a plugin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ExportsMap only indexes package modules. You will need to fetch the ModIface for local modules. So both changes are needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took a first pass at this. There is still more work to do. As of this comment, I am just generating the map based on the already existing map. I also see that this does not work for local modules, as you suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second pass - I generate the map from the modIface rather than the existing map.. This still does not account for local modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I now generate the map for local modules as well. I will take a look at your other comments.
dont worry, the pr looks great anyways, lets see if we had a opened issue about |
Afaics this fixes #797 (cc @ndmitchell) |
…l-language-server into import-func-completions
160a017
to
f53cc5a
Compare
f53cc5a
to
863a483
Compare
stack builds are failing:
|
…l-language-server into import-func-completions
thank you - this is fixed |
…l-language-server into import-func-completions
…l-language-server into import-func-completions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there! Just some minor performance improvements requested
…l-language-server into import-func-completions
This looks all good, but let's take a look at the Completion benchmark experiments before landing. |
@pepeiborra - What is involved with this step? Is this part of CI or is it a manual step that I should run and report on? Happy to work through it |
There's a CI job that runs the benchmarks, renders the results summary, and produces downloadable artifacts. See https://github.com/haskell/haskell-language-server/actions/runs/1211084983 However the CI results are not entirely reliable, so you can run locally with |
Running locally in gitpod, I get the following results :
There is a substantial regression in userTime for the "completions after edit" experiment, which takes almost 3 times longer. This is really bad considering that the experiment doesn't actually try to complete within imports - it's just completing on a random identifier inside the module body. Bummer!
Therefore the way forward is to extract import completion out to a new plugin - we don't need a new package, it can stay within ghcide the same way that we split code actions into multiple plugins recently. |
Ah, the other thing worth trying is switching from |
Ahh ok, glad this was caught by the experiments! My original implementation made many calls to useWithStaleFast, we still don't want to use that approach, right? One other thought I had would be to pass in I am also happy to separate it out into a separate plugin |
It's not ideal, but would be good to benchmark. Overhead will be seen in the delayedTime column |
…l-language-server into import-func-completions
Just pushed up a commit with this. I am still figuring out how to run the benchmark |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And that's why benchmarks are important.
Marking this as ready to merge now, follow ups are optional and can be done in future PRs.
Thanks @alexnaspo for your dedication, this was an awesome effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing tour the force from you both @pepeiborra and @alexnaspo, congrats!
This fixed (hopefully) #314 |
AutoComplete functions inside a module import
import Control.Applicative (A<cursor-position>)
Will auto complete to Alternative, Applicative... etc