CodeAction groups
This commit is contained in:
@@ -102,6 +102,7 @@ pub struct ClientCapsConfig {
|
||||
pub hierarchical_symbols: bool,
|
||||
pub code_action_literals: bool,
|
||||
pub work_done_progress: bool,
|
||||
pub code_action_group: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -294,9 +295,13 @@ impl Config {
|
||||
|
||||
self.assist.allow_snippets(false);
|
||||
if let Some(experimental) = &caps.experimental {
|
||||
let enable =
|
||||
let snippet_text_edit =
|
||||
experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true);
|
||||
self.assist.allow_snippets(enable);
|
||||
self.assist.allow_snippets(snippet_text_edit);
|
||||
|
||||
let code_action_group =
|
||||
experimental.get("codeActionGroup").and_then(|it| it.as_bool()) == Some(true);
|
||||
self.client_caps.code_action_group = code_action_group
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ expression: diag
|
||||
fixes: [
|
||||
CodeAction {
|
||||
title: "return the expression directly",
|
||||
group: None,
|
||||
kind: Some(
|
||||
"quickfix",
|
||||
),
|
||||
|
||||
@@ -50,6 +50,7 @@ expression: diag
|
||||
fixes: [
|
||||
CodeAction {
|
||||
title: "consider prefixing with an underscore",
|
||||
group: None,
|
||||
kind: Some(
|
||||
"quickfix",
|
||||
),
|
||||
|
||||
@@ -145,6 +145,7 @@ fn map_rust_child_diagnostic(
|
||||
} else {
|
||||
MappedRustChildDiagnostic::SuggestedFix(lsp_ext::CodeAction {
|
||||
title: rd.message.clone(),
|
||||
group: None,
|
||||
kind: Some("quickfix".to_string()),
|
||||
edit: Some(lsp_ext::SnippetWorkspaceEdit {
|
||||
// FIXME: there's no good reason to use edit_map here....
|
||||
|
||||
@@ -133,14 +133,6 @@ pub struct Runnable {
|
||||
pub cwd: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SourceChange {
|
||||
pub label: String,
|
||||
pub workspace_edit: SnippetWorkspaceEdit,
|
||||
pub cursor_position: Option<lsp_types::TextDocumentPositionParams>,
|
||||
}
|
||||
|
||||
pub enum InlayHints {}
|
||||
|
||||
impl Request for InlayHints {
|
||||
@@ -196,6 +188,8 @@ impl Request for CodeActionRequest {
|
||||
pub struct CodeAction {
|
||||
pub title: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub group: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub kind: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub command: Option<lsp_types::Command>,
|
||||
|
||||
@@ -18,7 +18,7 @@ use lsp_types::{
|
||||
SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, Url, WorkspaceEdit,
|
||||
};
|
||||
use ra_ide::{
|
||||
Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
|
||||
FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
|
||||
TextEdit,
|
||||
};
|
||||
use ra_prof::profile;
|
||||
@@ -720,6 +720,7 @@ pub fn handle_code_action(
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let range = from_proto::text_range(&line_index, params.range);
|
||||
let frange = FileRange { file_id, range };
|
||||
|
||||
let diagnostics = world.analysis().diagnostics(file_id)?;
|
||||
let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
|
||||
@@ -733,7 +734,8 @@ pub fn handle_code_action(
|
||||
for source_edit in fixes_from_diagnostics {
|
||||
let title = source_edit.label.clone();
|
||||
let edit = to_proto::snippet_workspace_edit(&world, source_edit)?;
|
||||
let action = lsp_ext::CodeAction { title, kind: None, edit: Some(edit), command: None };
|
||||
let action =
|
||||
lsp_ext::CodeAction { title, group: None, kind: None, edit: Some(edit), command: None };
|
||||
res.push(action);
|
||||
}
|
||||
|
||||
@@ -745,53 +747,9 @@ pub fn handle_code_action(
|
||||
res.push(fix.action.clone());
|
||||
}
|
||||
|
||||
let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default();
|
||||
for assist in
|
||||
world.analysis().assists(&world.config.assist, FileRange { file_id, range })?.into_iter()
|
||||
{
|
||||
match &assist.group_label {
|
||||
Some(label) => grouped_assists
|
||||
.entry(label.to_owned())
|
||||
.or_insert_with(|| {
|
||||
let idx = res.len();
|
||||
let dummy = lsp_ext::CodeAction {
|
||||
title: String::new(),
|
||||
kind: None,
|
||||
command: None,
|
||||
edit: None,
|
||||
};
|
||||
res.push(dummy);
|
||||
(idx, Vec::new())
|
||||
})
|
||||
.1
|
||||
.push(assist),
|
||||
None => {
|
||||
res.push(to_proto::code_action(&world, assist)?.into());
|
||||
}
|
||||
}
|
||||
for assist in world.analysis().assists(&world.config.assist, frange)?.into_iter() {
|
||||
res.push(to_proto::code_action(&world, assist)?.into());
|
||||
}
|
||||
|
||||
for (group_label, (idx, assists)) in grouped_assists {
|
||||
if assists.len() == 1 {
|
||||
res[idx] = to_proto::code_action(&world, assists.into_iter().next().unwrap())?.into();
|
||||
} else {
|
||||
let title = group_label;
|
||||
|
||||
let mut arguments = Vec::with_capacity(assists.len());
|
||||
for assist in assists {
|
||||
let source_change = to_proto::source_change(&world, assist.source_change)?;
|
||||
arguments.push(to_value(source_change)?);
|
||||
}
|
||||
|
||||
let command = Some(Command {
|
||||
title: title.clone(),
|
||||
command: "rust-analyzer.selectAndApplySourceChange".to_string(),
|
||||
arguments: Some(vec![serde_json::Value::Array(arguments)]),
|
||||
});
|
||||
res[idx] = lsp_ext::CodeAction { title, kind: None, edit: None, command };
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
|
||||
@@ -478,15 +478,6 @@ pub(crate) fn resource_op(
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn source_change(
|
||||
world: &WorldSnapshot,
|
||||
source_change: SourceChange,
|
||||
) -> Result<lsp_ext::SourceChange> {
|
||||
let label = source_change.label.clone();
|
||||
let workspace_edit = self::snippet_workspace_edit(world, source_change)?;
|
||||
Ok(lsp_ext::SourceChange { label, workspace_edit, cursor_position: None })
|
||||
}
|
||||
|
||||
pub(crate) fn snippet_workspace_edit(
|
||||
world: &WorldSnapshot,
|
||||
source_change: SourceChange,
|
||||
@@ -606,6 +597,7 @@ fn main() <fold>{
|
||||
pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> {
|
||||
let res = lsp_ext::CodeAction {
|
||||
title: assist.label,
|
||||
group: if world.config.client_caps.code_action_group { assist.group_label } else { None },
|
||||
kind: Some(String::new()),
|
||||
edit: Some(snippet_workspace_edit(world, assist.source_change)?),
|
||||
command: None,
|
||||
|
||||
Reference in New Issue
Block a user