-
Notifications
You must be signed in to change notification settings - Fork 51
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
Introduce CodeActions #499
Introduce CodeActions #499
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.
I haven't gone deep into the implementation details yet since it's still WIP, but I've left a few comments/questions about the high level approach here. Thank you so much for taking this on, @chadhietala!
2e1f128
to
e64241a
Compare
1b6e779
to
c9a07b4
Compare
@dfreeman I think this is ready for review now. I ended up removing all the prettier things, simplified the config manager, consolidated the document related stuff. I wrote smoke tests for all the environments except loose mode. It isn't clear to me if its even possible to correctly apply the text changes due to how transformation works. Screen.Recording.2023-01-06.at.5.25.57.PM.mov |
Great, thank you! I should have time to give this a review tomorrow. |
c9a07b4
to
ab589c9
Compare
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 wrote smoke tests for all the environments except loose mode. It isn't clear to me if its even possible to correctly apply the text changes due to how transformation works.
Can you say more about what it is that makes actions for loose-mode templates complex? Is it that they're (usually) in a separate file from their backing class?
My uneducated guess would have been that doing things like inserting a {{! @glint-ignore }}
would be possible, even if there are reasons that more complex actions like "add missing field bar
" may be more difficult to account for.
@chadhietala I want to reiterate that I'm excited to see this land, and I'm super grateful for your work on it! 🙏 If there's anything here you want to talk through, feel free to ping me on Discord as well if that's easier 🙂 |
1b207a8
to
01b0771
Compare
This introduces CodeActions to the GlintLanguageServer. It is responsible for translating LSP requests into TS lanaguage server CodeFixActions and then back CodeActions
90b3324
to
c361d88
Compare
c361d88
to
7789876
Compare
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.
@dfreeman Sorry for the back and forth on this. I went back over all your comments and I think I've landed pretty close to what you had in mind. I was also able to get loose mode working. I have noted a couple areas that I think require your thoughts.
|
||
// The ConfigManager holds TypeScript/JS formating and user preferences. | ||
// It is only needed for the vscode binding | ||
export class ConfigManager { |
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 now just used for the binding. I noticed that this could be used for completions as well but it would need to be pulled through.
|
||
return server.getCodeActions( | ||
textDocument.uri, | ||
type, | ||
CodeActionKind.QuickFix, |
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.
Generally curious about your thoughts here about passing the kind. For the vscode binding we only let QuickFixs requests but I'm trying to balance the fact that you can call getCodeActions
programmatically. Since we don't support all codefix types it seems like we need something like this. Over time this can be dynamic.
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.
If I'm reading this right, this means that when the editor sends a request for any kind of code actions, we'll always respond with quickfixes?
You've spent a lot more time thinking about this than I have, so I'm probably missing something, but my kneejerk reaction would be to say it's better to return an empty response for an action request we don't support than to give back something that the editor didn't ask for. Why doesn't the short-circuit you have in the language server already handle this the way we'd want?
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.
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.
If a well-behaved editor will only ever ask us for quickfixes, why do we need to hard-code QuickFix
here?
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 spent a day looking as to why context.only
is optional and not always passed for CodeFix requests but found nothing. All implementations of language servers that I found (Svelte, Vue), that provide codefixes do a narrowing like:
let kind = '';
if (context.only === undefined) {
kind = CodeActionKind.QuickFix;
} else if (context.only.includes(CodeActionKind.QuickFix)) {
kind = CodeActionKind.QuickFix;
}
I can add this if you think it will be clearer.
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.
Thanks, that's super helpful context! I think something along those lines would help make it clearer for anyone (read: me in the future when I've forgotten this conversation 😅) who comes along and reads it later
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.
Sounds good. I pushed another commit that does ^ and explains whats going on with context.only
I think once we get #499 (comment) settled this will be ready to go. I should have better availability for a while from here forward, so hopefully we can land this in the next day or two—apologies again for how long it's taken! |
🎉 Thank you again for all your hard work here! |
What Does This Do?
In practice Glint is language server that translates Ember templates and concepts into TypeScript code that then is typechecked using the off shelf TypeScript typechecker. If there are errors during the checking, text offsets of those errors are translated back into the original text offsets (in Ember templates and concepts) so that the developer can resolve the type errors.
This PR starts to plumb through more capabilities for the Glint language server, specifically we're starting with CodeActions. CodeActions Requests are sent from the client to server to get for fixes for problems in code including type fixes. Since Glint utilizes the underlying TypeScript infrastructure we can leverage it to ask for CodeFixes that can then be applied to Ember code. This PR addresses 3 tricky areas:
ts.CodeFix
andlsp.CodeAction
This PR sets the ground work for these 3 areas.