-
-
Notifications
You must be signed in to change notification settings - Fork 509
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(oxc_language_server): implement
oxc.fixAll
workspace command (#…
…8858) This pull request focuses on optimizing the implementation of the `oxlint.applyAllFixesFile` vscode command by adding the command interface to the LSP instead of requesting all code actions and executing the preferred ones. This PR contains an abstraction above the LSP workspace commands, the `oxc.fixAll` command itself and minor changes to the vscode extension. Since the `workspace/executeCommand` handler is new, I've created an abstraction to register the commands and parse their arguments. While it isn't necessary, I feel like it makes future additions to the LS easier. I tested the command in both vscode and neovim, doubt it will be hard to use this in the zed / intellij projects. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
d6d80f7
commit f4662a9
Showing
6 changed files
with
248 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
use log::error; | ||
use serde::Deserialize; | ||
use tower_lsp::{ | ||
jsonrpc::{self, Error}, | ||
lsp_types::{ | ||
request::ApplyWorkspaceEdit, ApplyWorkspaceEditParams, TextEdit, Url, WorkspaceEdit, | ||
}, | ||
}; | ||
|
||
use crate::{capabilities::Capabilities, Backend}; | ||
|
||
pub const LSP_COMMANDS: [WorkspaceCommands; 1] = [WorkspaceCommands::FixAll(FixAllCommand)]; | ||
|
||
pub trait WorkspaceCommand { | ||
fn command_id(&self) -> String; | ||
fn available(&self, cap: Capabilities) -> bool; | ||
type CommandArgs<'a>: serde::Deserialize<'a>; | ||
async fn execute( | ||
&self, | ||
backend: &Backend, | ||
args: Self::CommandArgs<'_>, | ||
) -> jsonrpc::Result<Option<serde_json::Value>>; | ||
} | ||
|
||
pub enum WorkspaceCommands { | ||
FixAll(FixAllCommand), | ||
} | ||
|
||
impl WorkspaceCommands { | ||
pub fn command_id(&self) -> String { | ||
match self { | ||
WorkspaceCommands::FixAll(c) => c.command_id(), | ||
} | ||
} | ||
pub fn available(&self, cap: Capabilities) -> bool { | ||
match self { | ||
WorkspaceCommands::FixAll(c) => c.available(cap), | ||
} | ||
} | ||
pub async fn execute( | ||
&self, | ||
backend: &Backend, | ||
args: Vec<serde_json::Value>, | ||
) -> jsonrpc::Result<Option<serde_json::Value>> { | ||
match self { | ||
WorkspaceCommands::FixAll(c) => { | ||
let arg: Result< | ||
<FixAllCommand as WorkspaceCommand>::CommandArgs<'_>, | ||
serde_json::Error, | ||
> = serde_json::from_value(serde_json::Value::Array(args)); | ||
if let Err(e) = arg { | ||
error!("Invalid args passed to {:?}: {e}", c.command_id()); | ||
return Err(Error::invalid_request()); | ||
} | ||
let arg = arg.unwrap(); | ||
|
||
c.execute(backend, arg).await | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub struct FixAllCommand; | ||
|
||
#[derive(Deserialize)] | ||
pub struct FixAllCommandArg { | ||
uri: String, | ||
} | ||
|
||
impl WorkspaceCommand for FixAllCommand { | ||
fn command_id(&self) -> String { | ||
"oxc.fixAll".into() | ||
} | ||
fn available(&self, cap: Capabilities) -> bool { | ||
cap.workspace_apply_edit | ||
} | ||
type CommandArgs<'a> = (FixAllCommandArg,); | ||
|
||
async fn execute( | ||
&self, | ||
backend: &Backend, | ||
args: Self::CommandArgs<'_>, | ||
) -> jsonrpc::Result<Option<serde_json::Value>> { | ||
let url = Url::parse(&args.0.uri); | ||
if let Err(e) = url { | ||
error!("Invalid uri passed to {:?}: {e}", self.command_id()); | ||
return Err(Error::invalid_request()); | ||
} | ||
let url = url.unwrap(); | ||
|
||
let mut edits = vec![]; | ||
if let Some(value) = backend.diagnostics_report_map.get(&url.to_string()) { | ||
for report in value.iter() { | ||
if let Some(fixed) = &report.fixed_content { | ||
edits.push(TextEdit { range: fixed.range, new_text: fixed.code.clone() }); | ||
} | ||
} | ||
let _ = backend | ||
.client | ||
.send_request::<ApplyWorkspaceEdit>(ApplyWorkspaceEditParams { | ||
label: Some(match edits.len() { | ||
1 => "Oxlint: 1 fix applied".into(), | ||
n => format!("Oxlint: {n} fixes applied"), | ||
}), | ||
edit: WorkspaceEdit { | ||
#[expect(clippy::disallowed_types)] | ||
changes: Some(std::collections::HashMap::from([(url, edits)])), | ||
..WorkspaceEdit::default() | ||
}, | ||
}) | ||
.await; | ||
} | ||
|
||
Ok(None) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.