Skip to content
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

feat(lsp): Add Inlay types #2005

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

spotandjake
Copy link
Member

This pr adds inlay types which closes #1359.

This pr is marked as a draft as there is still some work that needs to be done:

  • We probably want to simplify some of the type signatures (i.e function types can get very complex, might be better to just say Function, and show the return type and param types on the actual lambda)
  • We probably want to add a config to the vscode extension to toggle inlay types, as you might want inlay hints like the module hints but not the types.
  • We should probably decide if we want to enable inlays on Tuple patterns, record patterns, constructor patterns

Current Demo Below:
image

@spotandjake spotandjake added the lsp Issues related to the language server. label Feb 2, 2024
@spotandjake spotandjake self-assigned this Feb 2, 2024
@spotandjake spotandjake marked this pull request as ready for review July 29, 2024 01:08
@spotandjake
Copy link
Member Author

image
This pr should be ready for review now.

@ospencer
Copy link
Member

Here I'd want us to hide hints for function definitions—they're long and get in the way of the function arguments, which already have hints on them/show much of the same information.

It'd also be cool to have hints on destructures, but that could maybe come in a later PR.

Copy link
Member

@marcusroberts marcusroberts left a comment

Choose a reason for hiding this comment

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

I'm going to approve because the code looks good, but subject to the request to be able to hide/show them as a setting

@spotandjake
Copy link
Member Author

spotandjake commented Aug 2, 2024

Here I'd want us to hide hints for function definitions—they're long and get in the way of the function arguments, which already have hints on them/show much of the same information.

It'd also be cool to have hints on destructures, but that could maybe come in a later PR.

I made that change, I also implemented a cli flag --disable-inlay-types which can be used to dissable the type hints when we release we can add a setting to the vscode extension that injects the flag.

I think we should leave the destructures for a future pr.

I also plan on coming back and adding type hints on function calls that show the label in a future pr.

@alex-snezhko
Copy link
Member

@spotandjake can't you just disable inlay hints in the client, and then users can decide if they want them or not? What is the purpose of the flag?

@spotandjake
Copy link
Member Author

spotandjake commented Aug 2, 2024

@spotandjake can't you just disable inlay hints in the client, and then users can decide if they want them or not? What is the purpose of the flag?

As we add more inlays, such as parameter hints. and other inlays I can see cases where the user might want to dissable the type hints but keep the others, because of how verbose the type hints are.

};

let enter_binding = ({vb_pat, vb_expr}: value_binding, toplevel: bool) =>
if (!toplevel) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: cut down on the condition nesting, perhaps if (!toplevel && toggle_type_hints) and then

switch (vb_pat) {
| {pat_extra: [], pat_desc: TPatVar(_, {loc}) => ...
| _ => ()
}

};
| _ => ()
}
| _ => ()
Copy link
Member

Choose a reason for hiding this comment

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

Would this ever be possible? If not should we do failwith("Impossible: ...")?

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems as though there is a case where it can be a constructor.

List.combine(args, argument_typs),
);
};
| _ => ()
Copy link
Member

Choose a reason for hiding this comment

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

I think this would never be possible. Should we do failwith("Impossible: ...")?

Copy link
Member Author

Choose a reason for hiding this comment

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

That case can be hit if we are omitting the annotation because typ is None

typ_args,
);
// Make Hints
if (List.length(argument_typs) == List.length(args)) {
Copy link
Member

Choose a reason for hiding this comment

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

Would this ever be false?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think so but I also think it makes sense to ensure we don't make a change somewhere else in the compiler and break this. I am going to add a failwith("Impossible") though if it is the not equal.

List.map(
((arg, typ: Types.type_expr)) =>
switch (arg) {
| Default(_) => None
Copy link
Member

Choose a reason for hiding this comment

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

Could you expand on this? I'm seeing in your screenshot that the default argument has an inline hint on it

Copy link
Member Author

Choose a reason for hiding this comment

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

The default hint comes from the binding pass, if this is enabled it shows : Option<_> after the value.

Copy link
Member

@ospencer ospencer left a comment

Choose a reason for hiding this comment

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

Played with this locally and I love how this looks and feels! I understand your point about having the command line flag, but I feel like we should wait to add that when we actually are adding more hints and want them to be controlled separately and not commit to having the flag right now.

compiler/src/language_server/inlayhint.re Outdated Show resolved Hide resolved
compiler/src/language_server/inlayhint.re Outdated Show resolved Hide resolved
compiler/src/language_server/inlayhint.re Outdated Show resolved Hide resolved
compiler/src/language_server/inlayhint.re Outdated Show resolved Hide resolved
@spotandjake
Copy link
Member Author

After discussion in discord instead of the command line flag it would make more sense to use: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize but I think we can defer it to a separate pr when we are going to add more inlay hint types.

The final thing this pr needs is test but I don't quite understand how the new lsp tests work yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lsp Issues related to the language server.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LSP: Add support for inlay hints
4 participants