-
Notifications
You must be signed in to change notification settings - Fork 207
Conversation
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.
Completions related code is already a significant part of the HieExtras module, what do you think of splitting into another one for better readability?
instance Semigroup QualCompls where | ||
(QualCompls a) <> (QualCompls b) = QualCompls $ Map.unionWith (++) a b | ||
|
||
instance Monoid QualCompls where |
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.
Needs a mappend implementation for ghc 8.2
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 solution is to simply add here
mappend = (<>)
result <- lift $ lift $ Hoogle.infoCmd' query | ||
case result of | ||
Right x -> return $ Just x | ||
_ -> return Nothing |
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.
Nice cleanup!
} deriving (Typeable) | ||
|
||
-- The supported languages and extensions | ||
languagesAndExts :: [T.Text] | ||
languagesAndExts = map T.pack GHC.supportedLanguagesAndExtensions |
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.
This is great, was this previously cached for a reason? Helpful reading by the way https://stackoverflow.com/a/3951092/1320911
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.
This basically achieve the same as caching it. When I added it to the cache I just wanted to avoid the text packing on each use.
I agree with @lorenzo, I think the completion logic is significant enough to split out |
@bubba, @lorenzo any comments on the type lookup behaviour? If I restore the old behaviour, because looking up the type is anyway done in the |
@wz1000 I don’t think I fully understand the consequences of changing the behavior, superficially this looks ok to me. What do you think the consequences of not having the old behavior might be? |
This is how the new behaviour manifests itself in vscode: Before GHC has loaded the GHC.Enum interface file, the completion item looks like this: After I add a usage of If I revert to the old behaviour, just having the |
I think doing the expensive work in the resolve step is the right way to go. As I understand it, this is precisely why the resolve step exists. Completion needs to be a fast/unintrusive operation, so reducing the work done is a good step. |
I am happy with this approach, and agree we should move the stuff into its own file. But for traceability it would be better to land this one as a change to HieExtras, so we can see the diff, and then add a second administrative change to move the code around. |
@wz1000 relying on Hoogle for type information felt a bit dodgey, so I am happy that this is the correct way, even if it is a bit slower to resolve, which happens "asynchronously" so I am not concerned. But in your example posted, does this mean that completion won't show any types until that interface file is loaded by means of it being used inside the document? Or is a completion request alone able to force it to load the interface file? |
Yes, this. But I guess it won't be too bad to load the interface file on a completion resolve request. Btw, for a comparison of memory usage before and after this patch, see BEFORE and AFTER The test is loading the file 20 times, then loading it 20 times asking for completions every time. The bump in the middle in BEFORE is when we start asking for completions. |
I've changed it so that the interface file is loaded in when the client asks to resolve the completion, and the type/snippet is available for every symbol in the completion list. |
After @mpickering pointed this out yesterday, I noticed that completion was a lot more complicated than it needed to be. Instead of the convoluted wrangling we do with import declarations, all the information we need is in the
GlobalRdrEnv
.In addition to this, I've separated out the step of getting the type information/snippets for the completion into the LSP
CompletionItemResolve
request. Type information for local variables whichis readily at hand in the
TypecheckedModule
itself is still reported in the original completion request.A potential performance issue I've tried to fix is that looking up the types of all the possible completions would result in GHC loading a bunch of interface files it didn't need to.
For example, consider a module that imports
Prelude
, but doesn't use any functions fromGHC.Enum
(likeenumFrom
). Normally, GHC will not load the interface file forGHC.Enum
. However, when we try to get the type of theenumFrom
completion, this forces GHC to go and actually load the interface file for that module.I've implemented the function we used to look up the type information to just returnNothing
in this case and not try to load theGHC.Enum
interface file. You can see this in action in the"does not pull in unnecessary modules until needed"
test case I've added.The above behaviour is up for discussion, and I will re-implement the old/default behaviour forgetTypeForName
depending on the consensus.The interface file will now be pulled in when the client requests to "resolve" the completion.
The behavioural changes due to this PR are:
The types/snippets for some functions from modules that haven't been used previously may not be available, as described above.