Skip to content

Completions from non-imported modules #1327

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

Closed
michaelpj opened this issue Feb 8, 2021 · 8 comments · Fixed by #2040
Closed

Completions from non-imported modules #1327

michaelpj opened this issue Feb 8, 2021 · 8 comments · Fixed by #2040
Labels

Comments

@michaelpj
Copy link
Collaborator

A feature I remember from Java IDEs that was very nice was that completion would offer options from modules that were not (yet) imported, but were available. Selecting that completion would also insert the appropriate import. When combined with auto-organizing imports this lets you almost ignore imports and just work from the completion prompt.

I think we could do this, although there's a risk that we might end up returning a really large number of completions! Completions from other modules in the package, would be nice, but doing it for dependencies too would be great. I would love to be able to just complete Map and have it imported!

(The LSP protocol supports this: CompletionItems have a list of additionalTextEdits which even calls out "adding an additional import at the top of the file" as a example usecase.)

@konn
Copy link
Collaborator

konn commented Feb 8, 2021

Agreed. If I remember correctly, we once had this feature when the automatic import-list extension had been implemented.
This behaviour disappeared once the automatic extension got disabled due to misformatted import candidates.
The automatic extension of import lists has recently been revived in #1266 by @pepeiborra, but it seems that the proposed feature is still disabled. What prevented this from the revival, @pepeiborra?

@pepeiborra
Copy link
Collaborator

#1266 implements auto extending import lists - that is, for identifiers in modules that are already imported. additionalTextEdits did not work well for us, the reworked version uses a Command.

Providing completions from non-imported modules is a related but different feature.

@berberman
Copy link
Collaborator

Now we produce completion items (with auto extending mechanism) from module's import declarations, which means that the completion only works if the source module has already been imported. As @michaelpj said, Java IDE, in particular IntelliJ IDEA, is doing a great job in this. In this case users even don't have to focus on the imports. But name clashes in Haskell are extremely common: imagine that we input an unqualified identifer -- singleton in the editor, and which module should be imported? I think it would be a bit hard to figure this out, since we have Data.ByteString.singleton, Data.ByteString.Lazy.singleton, Data.IntMap.singleton, Data.Sequence.singleton, and so on...

@michaelpj
Copy link
Collaborator Author

But name clashes in Haskell are extremely common: imagine that we input an unqualified identifer -- singleton in the editor, and which module should be imported?

Personally, I would like:

  • All versions of singleton appear in the completions list, disambiguated (not sure how possible this is)
  • If you complete to an identifier from a non-imported module, we always add a qualified import by default and insert the identifier qualified.

If we paired this with a code action to "unqualify this module import if there are no name clashes", I think that would be a fairly nice flow. Complete a bunch of Map functions, getting them all qualified by default; if the qualification becomes annoying, run the action to try and unqualify them all.

@michaelpj
Copy link
Collaborator Author

additionalTextEdits did not work well for us, the reworked version uses a Command.

Just out of curiosity, why not?

@pepeiborra
Copy link
Collaborator

Because ghcide reuses stale completions. A stale completion is usually still valid, a stale text edit is not. Commands offer a solution to this, as the textedit is calculated when the completion is applied instead of when the completion is generated.

@jneira jneira added component: ghcide type: enhancement New feature or request labels Feb 9, 2021
@jneira
Copy link
Member

jneira commented Feb 9, 2021

Personally, I would like:

* All versions of `singleton` appear in the completions list, disambiguated (not sure how possible this is)

* If you complete to an identifier from a non-imported module, we always add a qualified import by default and insert the identifier qualified.

If we paired this with a code action to "unqualify this module import if there are no name clashes", I think that would be a fairly nice flow. Complete a bunch of Map functions, getting them all qualified by default; if the qualification becomes annoying, run the action to try and unqualify them all.

That seem a nice workflow to me too. The completion list could be filtered by the type (hey, this is haskell, right?), as requested in other issue: #754. That would give us the exact match for the singleton example and that is how java ide's work (at least my fav one, eclipse)

@alanz
Copy link
Collaborator

alanz commented Feb 10, 2021

Because ghcide reuses stale completions.

You can still do this, but then use completionItem/resolve to generate the detailed current additional edit if it is chosen

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

Successfully merging a pull request may close this issue.

6 participants