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: enable automatically fix diagnostics #16715

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Young-Flash
Copy link
Member

@Young-Flash Young-Flash commented Feb 29, 2024

Change

  • server side: add specified_diagnostic_code field into AssistConfig, which use to filter out unreleated fixes to the diagnostic. add handle_code_action_for_specified_diagnostic based on the implementation of handle_code_action, which use to handle the rust-analyzer/codeActionForDiagnostic LSP request, it will return the only code action fix corrsponding to the specified diagnostic
  • client side: listen the onWillSaveTextDocument event and apply the fix corrsponding to the diagnostics which config by rust-analyzer.autoFixDiagnostics

Demo

demo-20240229113602-9x1ji67

based on the following config in settings.josn

"rust-analyzer.autoFixDiagnostics": [
    "unused_braces",
    "redundant_field_names",
    "non_snake_case",
],

Todo

  • server side: currently we only support native diagnostic fix from rust-analyzer(crates/ide-diagnostics/src/handlers/), ideally we should support fix from cargo check also. we should also add more native diagnostics and fix in rust-analyzer, but it require a lot of work
  • client side: expose a config for other event to trigger autoFixDiagnostics, like format file?

close #12960

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 29, 2024
Copy link
Member

@Veykril Veykril left a comment

Choose a reason for hiding this comment

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

Some thoughts, specified_diagnostic_code seems unnecessary. Instead of picking the first quickfix when there are multiple, autofixing shouldn't be applicable imo. If there are multiple options we can't reason about which one to pick so that's left to the user.

As such I don't believe implementing this needs to touch the server code at all.

With that out of the way, I feel like this isn't necessarily rust-analyzer specific but could be a generic configurable vscode extension that consumes a config of diagnostics with quickfixes that should be autofixed on save that is language agnostic?

@Young-Flash
Copy link
Member Author

Some thoughts, specified_diagnostic_code seems unnecessary. Instead of picking the first quickfix when there are multiple, autofixing shouldn't be applicable imo. If there are multiple options we can't reason about which one to pick so that's left to the user.

As such I don't believe implementing this needs to touch the server code at all.

The reason why I pick the first one in the returned CodeAction list is(for simplicity) that I reuse the response format of textDocument/codeAction as rust-analyzer/codeActionForDiagnostic's response format.

In fact, the response for rust-analyzer/codeActionForDiagnostic LSP request will contains at most one CodeAction, since we use specified_diagnostic_code to filter out diagnostic which is unrelated

.filter(|it| {
    specific_diagnostic_code.map_or(true, |specific_diagnostic_code| {
        &it.code.as_str() == specific_diagnostic_code
    })
})

and use CodeActionParams.range to filter out CodeAction which is out of the currentDiagnostic's range

.filter(|it| it.target.intersect(frange.range).is_some())

@Young-Flash
Copy link
Member Author

With that out of the way, I feel like this isn't necessarily rust-analyzer specific but could be a generic configurable vscode extension that consumes a config of diagnostics with quickfixes that should be autofixed on save that is language agnostic?

It may be, but that generic configurable vscode extension for all kind of language requires more work(since we cannot guarantee that the diagnosis and CodeAction of every language will respect the LSP protocol and vscode api?), currently I just want to support auto fix diagnostic for rust-analyzer

@Veykril
Copy link
Member

Veykril commented Mar 5, 2024

It may be, but that generic configurable vscode extension for all kind of language requires more work(since we cannot guarantee that the diagnosis and CodeAction of every language will respect the LSP protocol and vscode api?), currently I just want to support auto fix diagnostic for rust-analyzer

The LSP shouldn't really matter here at all. I'd expect that this functionality should be completely implementable with just vscode's diagnostics API

@Veykril Veykril added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 5, 2024
@bors
Copy link
Collaborator

bors commented Mar 5, 2024

☔ The latest upstream changes (presumably #16662) made this pull request unmergeable. Please resolve the merge conflicts.

@Young-Flash
Copy link
Member Author

I'd expect that this functionality should be completely implementable with just vscode's diagnostics API

Is it really possible to make this without touching rust-analyzer server side? If we don't filter out some unreleated CodeAction in server side, we will always get more than one CodeAction everytime we emit textDocument/codeAction, thus can't determine which to apply.

#16715 (comment)

@Veykril
Copy link
Member

Veykril commented Mar 11, 2024

The client should be able to associate code actions with diagnostics, so that filtering should happen on the client side, see https://code.visualstudio.com/api/references/vscode-api#CodeAction having a

diagnostics field:

Diagnostics that this code action resolves.

@Young-Flash
Copy link
Member Author

The client should be able to associate code actions with diagnostics

yeah, but that diagnostics?: [Diagnostic] field is allowed to undefined, and rust-analyzer server side don't attach diagnostics info for CodeAction

@Veykril
Copy link
Member

Veykril commented Mar 11, 2024

and rust-analyzer server side don't attach diagnostics info for CodeAction

Then we should fix that (that probably didn't exist back when code actions were implemented in r-a).

And them being possibly undefined comes from code actions not necessarily being associated with a diagnostic, so those are irrelevant to the feature here in the first place. Note that I am fine with us having this for r-a specifically for now, but my requirement is that this should not require changes to the server (aside from implementing the diagnostics field for CodeActions)

@Young-Flash
Copy link
Member Author

seems tricky
we have ide_db::assists::Assist in ide_diagnostics::Diagnostic

pub struct Diagnostic {
pub code: DiagnosticCode,
pub message: String,
pub range: FileRange,
pub severity: Severity,
pub unused: bool,
pub experimental: bool,
pub fixes: Option<Vec<Assist>>,
// The node that will be affected by `#[allow]` and similar attributes.
pub main_node: Option<InFile<SyntaxNodePtr>>,
}

attach Diagnostic in Assist casue cycle dependency ?

@Veykril
Copy link
Member

Veykril commented Mar 18, 2024

We have it inverted in comparison to the LSP (that is our diagnostics contain the assist that resolves them), but that is fine. We can flip that in the protocol conversion layer. We probably just need to restructure things slightly there so we don't lose the information before

@Veykril Veykril marked this pull request as draft April 15, 2024 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix diagnostics on save or on format
4 participants