mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
Enable ruff-specific source actions (#10916)
## Summary Fixes #10780. The server now send code actions to the client with a Ruff-specific kind, `source.*.ruff`. The kind filtering logic has also been reworked to support this. ## Test Plan Add this to your `settings.json` in VS Code: ```json { "[python]": { "editor.codeActionsOnSave": { "source.organizeImports.ruff": "explicit", }, } } ``` Imports should be automatically organized when you manually save with `Ctrl/Cmd+S`.
This commit is contained in:
parent
cffc55576f
commit
eab3c4e334
3 changed files with 40 additions and 47 deletions
|
@ -224,7 +224,7 @@ impl Server {
|
|||
CodeActionOptions {
|
||||
code_action_kinds: Some(
|
||||
SupportedCodeAction::all()
|
||||
.flat_map(|action| action.kinds().into_iter())
|
||||
.map(SupportedCodeAction::to_kind)
|
||||
.collect(),
|
||||
),
|
||||
work_done_progress_options: WorkDoneProgressOptions {
|
||||
|
@ -284,18 +284,21 @@ pub(crate) enum SupportedCodeAction {
|
|||
}
|
||||
|
||||
impl SupportedCodeAction {
|
||||
/// Returns the possible LSP code action kind(s) that map to this code action.
|
||||
fn kinds(self) -> Vec<CodeActionKind> {
|
||||
/// Returns the LSP code action kind that map to this code action.
|
||||
fn to_kind(self) -> CodeActionKind {
|
||||
match self {
|
||||
Self::QuickFix => vec![CodeActionKind::QUICKFIX],
|
||||
Self::SourceFixAll => vec![CodeActionKind::SOURCE_FIX_ALL, crate::SOURCE_FIX_ALL_RUFF],
|
||||
Self::SourceOrganizeImports => vec![
|
||||
CodeActionKind::SOURCE_ORGANIZE_IMPORTS,
|
||||
crate::SOURCE_ORGANIZE_IMPORTS_RUFF,
|
||||
],
|
||||
Self::QuickFix => CodeActionKind::QUICKFIX,
|
||||
Self::SourceFixAll => crate::SOURCE_FIX_ALL_RUFF,
|
||||
Self::SourceOrganizeImports => crate::SOURCE_ORGANIZE_IMPORTS_RUFF,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_kind(kind: CodeActionKind) -> impl Iterator<Item = Self> {
|
||||
Self::all().filter(move |supported_kind| {
|
||||
supported_kind.to_kind().as_str().starts_with(kind.as_str())
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns all code actions kinds that the server currently supports.
|
||||
fn all() -> impl Iterator<Item = Self> {
|
||||
[
|
||||
|
@ -306,16 +309,3 @@ impl SupportedCodeAction {
|
|||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<CodeActionKind> for SupportedCodeAction {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(kind: CodeActionKind) -> std::result::Result<Self, Self::Error> {
|
||||
for supported_kind in Self::all() {
|
||||
if supported_kind.kinds().contains(&kind) {
|
||||
return Ok(supported_kind);
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,14 +112,14 @@ fn fix_all(snapshot: &DocumentSnapshot) -> crate::Result<CodeActionOrCommand> {
|
|||
None,
|
||||
)
|
||||
};
|
||||
let action = types::CodeAction {
|
||||
|
||||
Ok(CodeActionOrCommand::CodeAction(types::CodeAction {
|
||||
title: format!("{DIAGNOSTIC_NAME}: Fix all auto-fixable problems"),
|
||||
kind: Some(types::CodeActionKind::SOURCE_FIX_ALL),
|
||||
kind: Some(crate::SOURCE_FIX_ALL_RUFF),
|
||||
edit,
|
||||
data,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(types::CodeActionOrCommand::CodeAction(action))
|
||||
}))
|
||||
}
|
||||
|
||||
fn organize_imports(snapshot: &DocumentSnapshot) -> crate::Result<CodeActionOrCommand> {
|
||||
|
@ -147,14 +147,14 @@ fn organize_imports(snapshot: &DocumentSnapshot) -> crate::Result<CodeActionOrCo
|
|||
None,
|
||||
)
|
||||
};
|
||||
let action = types::CodeAction {
|
||||
|
||||
Ok(CodeActionOrCommand::CodeAction(types::CodeAction {
|
||||
title: format!("{DIAGNOSTIC_NAME}: Organize imports"),
|
||||
kind: Some(types::CodeActionKind::SOURCE_ORGANIZE_IMPORTS),
|
||||
kind: Some(crate::SOURCE_ORGANIZE_IMPORTS_RUFF),
|
||||
edit,
|
||||
data,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(types::CodeActionOrCommand::CodeAction(action))
|
||||
}))
|
||||
}
|
||||
|
||||
/// If `action_filter` is `None`, this returns [`SupportedCodeActionKind::all()`]. Otherwise,
|
||||
|
@ -166,14 +166,8 @@ fn supported_code_actions(
|
|||
return SupportedCodeAction::all().collect();
|
||||
};
|
||||
|
||||
SupportedCodeAction::all()
|
||||
.filter(move |action| {
|
||||
action_filter.iter().any(|filter| {
|
||||
action
|
||||
.kinds()
|
||||
.iter()
|
||||
.any(|kind| kind.as_str().starts_with(filter.as_str()))
|
||||
})
|
||||
})
|
||||
action_filter
|
||||
.into_iter()
|
||||
.flat_map(SupportedCodeAction::from_kind)
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -30,14 +30,23 @@ impl super::BackgroundDocumentRequestHandler for CodeActionResolve {
|
|||
) -> Result<types::CodeAction> {
|
||||
let document = snapshot.document();
|
||||
|
||||
let action_kind: SupportedCodeAction = action
|
||||
.kind
|
||||
.clone()
|
||||
.ok_or(anyhow::anyhow!("No kind was given for code action"))
|
||||
.with_failure_code(ErrorCode::InvalidParams)?
|
||||
.try_into()
|
||||
.map_err(|()| anyhow::anyhow!("Code action was of an invalid kind"))
|
||||
.with_failure_code(ErrorCode::InvalidParams)?;
|
||||
let code_actions = SupportedCodeAction::from_kind(
|
||||
action
|
||||
.kind
|
||||
.clone()
|
||||
.ok_or(anyhow::anyhow!("No kind was given for code action"))
|
||||
.with_failure_code(ErrorCode::InvalidParams)?,
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Ensure that the code action maps to _exactly one_ supported code action
|
||||
let [action_kind] = code_actions.as_slice() else {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Code action resolver did not expect code action kind {:?}",
|
||||
action.kind.as_ref().unwrap()
|
||||
))
|
||||
.with_failure_code(ErrorCode::InvalidParams);
|
||||
};
|
||||
|
||||
action.edit = match action_kind {
|
||||
SupportedCodeAction::SourceFixAll => Some(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue