Skip to content

Implement completionItem/resolve #3204

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

Merged
merged 5 commits into from
Dec 19, 2022
Merged

Implement completionItem/resolve #3204

merged 5 commits into from
Dec 19, 2022

Conversation

wz1000
Copy link
Collaborator

@wz1000 wz1000 commented Sep 21, 2022

Implement completionItem/resolve to lazily resolve types and documentation for completion items.
This results in very big memory usage improvments while also improving the responsiveness of completions.
Usually when GHC typechecks code, it reads in and deserializes interfaces lazily, so if the code imports
a bunch of modules, the interfaces will only be read in and deserialized if a particular name is actually
required for typechecking.

However, when we greedily generate completion lists, the act of querying for types and documentation results
in sucking in and deserializing interface sections for every single name in scope. This is very bad for
memory usage as it negates virtually all the benefits of lazy deserialization.

Instead, we can compute types and documentation on demand for individual completion items using the completionItem/resolve
LSP functionality.

A downside to this is that we can no longer generate snippets for functions
arguments with placeholders mentioning the types because we no longer have this
information available when we generate the original completion, and it is not
supported by LSP to resolve the actual completion snippet using completionItem/resolve.

However, I don't personally consider this to be a very big deal because this
feature was unreliable (eg for things from the export map which weren't in
scope) and I found it to be quite annoying when it did work.

@michaelpj
Copy link
Collaborator

Wow, this is a big deal!

Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good! I'm going to do my usual routine and question whether it's really the case that adding a complex feature like this requires 0 lines of explanatory comments :)

docs <- getDocumentationTryGhc packageState curMod n
toCompItem :: Parent -> Module -> T.Text -> Name -> Maybe (LImportDecl GhcPs) -> [CompItem]
toCompItem par m mn n imp' =
-- docs <- getDocumentationTryGhc packageState curMod n
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented out code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wz1000 is this the line causing the eager deserialization of interfaces?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This along with lookupName (the lookupName is slightly worse since it forces typechecking the iface which is also done lazily, getDocumentation will still load in the interface if it wasn't needed before and deserialize the documentation part).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still commented out

mdkm <- liftIO $ runAction "Completion resolve" ide $ use GetDocMap file
case mdkm of
Nothing -> pure (Right comp)
Just (DKMap dm km) -> liftIO $ runAction "Completion resolve" ide $ do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can make this kind of pattern simpler using the pattern we use elsewhere in the codebase using pluginResponse at the top level and maybeToEither and friends.

@michaelpj
Copy link
Collaborator

Also: tests?

@michaelpj
Copy link
Collaborator

Oh one last thing: we definitely want a cautionary comment on the main completion handler warning people not to accidentally pull in information from interface files in future!

@michaelpj
Copy link
Collaborator

#3080 gets the HIE file during completions, is that acceptable?

@pepeiborra
Copy link
Collaborator

#3080 gets the HIE file during completions, is that acceptable?

I am pretty confident getting the HIE file is 👍

@michaelpj
Copy link
Collaborator

I merged the record dot completions PR, which has introduced some conflicts.

Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous comments still need addressing also.

-- the NameCache.
-- Reason: this may the first occurrence of (say) Foo.bar we have encountered.
-- If we need to explore its value we will load Foo.hi; but meanwhile all we
-- need is a Name for it.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is that all we need? surely it will be the wrong Name and then we could get into trouble later? 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular it looks like you look it up in the module environment later, how can that work if they're fresh?

@wz1000 wz1000 force-pushed the wip/completion-resolve branch 2 times, most recently from 1e1ad22 to c983c6b Compare November 23, 2022 13:40
@wz1000 wz1000 force-pushed the wip/completion-resolve branch 8 times, most recently from dee48c1 to e7073d6 Compare December 14, 2022 09:59
@wz1000 wz1000 requested a review from isovector as a code owner December 14, 2022 09:59
Copy link
Collaborator

@isovector isovector left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm for wingman

@wz1000 wz1000 force-pushed the wip/completion-resolve branch 4 times, most recently from b367ca7 to cf0e3c3 Compare December 16, 2022 09:12
@wz1000 wz1000 enabled auto-merge (rebase) December 16, 2022 09:22
@wz1000 wz1000 force-pushed the wip/completion-resolve branch 9 times, most recently from cc06936 to 7cf643b Compare December 16, 2022 12:59
@wz1000 wz1000 requested a review from santiweight as a code owner December 16, 2022 12:59
@wz1000 wz1000 force-pushed the wip/completion-resolve branch from 7988b03 to fe7d852 Compare December 16, 2022 17:58
Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine, although I do think there were a few more comments that could be addressed.

@@ -221,7 +221,7 @@ jobs:
name: Test hls-explicit-imports-plugin test suite
run: cabal test hls-explicit-imports-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-explicit-imports-plugin --test-options="$TEST_OPTS"

- if: matrix.test
- if: matrix.test && matrix.os != 'windows-latest'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? is there an issue?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call-hierarchy tests were very flaky, I've fixed the problem I think and removed this.

docs <- getDocumentationTryGhc packageState curMod n
toCompItem :: Parent -> Module -> T.Text -> Name -> Maybe (LImportDecl GhcPs) -> [CompItem]
toCompItem par m mn n imp' =
-- docs <- getDocumentationTryGhc packageState curMod n
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still commented out

Wait for index instead of compliation before making requests
as indexing happens in the background in parallel with everything
else, so we have to synchronize on the database being ready before
making any call hierarchy requests.
@wz1000 wz1000 force-pushed the wip/completion-resolve branch from fe7d852 to 2d58fe1 Compare December 18, 2022 21:25
@wz1000 wz1000 requested a review from July541 as a code owner December 18, 2022 21:25
@wz1000 wz1000 disabled auto-merge December 18, 2022 23:26
@wz1000 wz1000 enabled auto-merge (rebase) December 18, 2022 23:26
@michaelpj
Copy link
Collaborator

pre-commit check is also failing, I think you're missing formatting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants