From 1679a376f30c5ad8971c0f855074a3f489fee5fa Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 3 May 2021 18:03:28 +0300 Subject: Resolve single assist only --- crates/ide/src/diagnostics.rs | 6 ++--- crates/ide/src/diagnostics/fixes.rs | 16 ++++++------ crates/ide/src/diagnostics/unlinked_file.rs | 2 +- crates/ide/src/lib.rs | 8 +++--- crates/ide/src/ssr.rs | 4 +-- crates/ide_assists/src/lib.rs | 39 ++++++++++++++++++++++++++--- crates/rust-analyzer/src/handlers.rs | 29 +++++++++++++-------- crates/rust-analyzer/src/lsp_ext.rs | 2 ++ crates/rust-analyzer/src/to_proto.rs | 4 ++- 9 files changed, 78 insertions(+), 32 deletions(-) (limited to 'crates') diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 455f20c93..b14f908b7 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs @@ -85,7 +85,7 @@ pub struct DiagnosticsConfig { pub(crate) fn diagnostics( db: &RootDatabase, config: &DiagnosticsConfig, - resolve: AssistResolveStrategy, + resolve: &AssistResolveStrategy, file_id: FileId, ) -> Vec { let _p = profile::span("diagnostics"); @@ -213,7 +213,7 @@ pub(crate) fn diagnostics( fn diagnostic_with_fix( d: &D, sema: &Semantics, - resolve: AssistResolveStrategy, + resolve: &AssistResolveStrategy, ) -> Diagnostic { Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) .with_fix(d.fix(&sema, resolve)) @@ -223,7 +223,7 @@ fn diagnostic_with_fix( fn warning_with_fix( d: &D, sema: &Semantics, - resolve: AssistResolveStrategy, + resolve: &AssistResolveStrategy, ) -> Diagnostic { Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) .with_fix(d.fix(&sema, resolve)) diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index f23064eac..15821500f 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs @@ -39,7 +39,7 @@ pub(crate) trait DiagnosticWithFix: Diagnostic { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option; } @@ -47,7 +47,7 @@ impl DiagnosticWithFix for UnresolvedModule { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; let unresolved_module = self.decl.to_node(&root); @@ -71,7 +71,7 @@ impl DiagnosticWithFix for NoSuchField { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; missing_record_expr_field_fix( @@ -86,7 +86,7 @@ impl DiagnosticWithFix for MissingFields { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { // Note that although we could add a diagnostics to // fill the missing tuple field, e.g : @@ -126,7 +126,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; let tail_expr = self.expr.to_node(&root); @@ -143,7 +143,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; @@ -167,7 +167,7 @@ impl DiagnosticWithFix for IncorrectCase { fn fix( &self, sema: &Semantics, - resolve: AssistResolveStrategy, + resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; let name_node = self.ident.to_node(&root); @@ -191,7 +191,7 @@ impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { fn fix( &self, sema: &Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { let root = sema.db.parse_or_expand(self.file)?; let next_expr = self.next_expr.to_node(&root); diff --git a/crates/ide/src/diagnostics/unlinked_file.rs b/crates/ide/src/diagnostics/unlinked_file.rs index e48528bed..93fd25dea 100644 --- a/crates/ide/src/diagnostics/unlinked_file.rs +++ b/crates/ide/src/diagnostics/unlinked_file.rs @@ -54,7 +54,7 @@ impl DiagnosticWithFix for UnlinkedFile { fn fix( &self, sema: &hir::Semantics, - _resolve: AssistResolveStrategy, + _resolve: &AssistResolveStrategy, ) -> Option { // If there's an existing module that could add a `mod` item to include the unlinked file, // suggest that as a fix. diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 6847b7e83..6a88236e3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -522,7 +522,7 @@ impl Analysis { frange: FileRange, ) -> Cancelable> { self.with_db(|db| { - let ssr_assists = ssr::ssr_assists(db, resolve, frange); + let ssr_assists = ssr::ssr_assists(db, &resolve, frange); let mut acc = Assist::get(db, config, resolve, frange); acc.extend(ssr_assists.into_iter()); acc @@ -536,7 +536,7 @@ impl Analysis { resolve: AssistResolveStrategy, file_id: FileId, ) -> Cancelable> { - self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id)) + self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id)) } /// Convenience function to return assists + quick fixes for diagnostics @@ -553,9 +553,9 @@ impl Analysis { }; self.with_db(|db| { - let ssr_assists = ssr::ssr_assists(db, resolve, frange); + let ssr_assists = ssr::ssr_assists(db, &resolve, frange); let diagnostic_assists = if include_fixes { - diagnostics::diagnostics(db, diagnostics_config, resolve, frange.file_id) + diagnostics::diagnostics(db, diagnostics_config, &resolve, frange.file_id) .into_iter() .filter_map(|it| it.fix) .filter(|it| it.target.intersect(frange.range).is_some()) diff --git a/crates/ide/src/ssr.rs b/crates/ide/src/ssr.rs index 785ce3010..1695e52ec 100644 --- a/crates/ide/src/ssr.rs +++ b/crates/ide/src/ssr.rs @@ -7,7 +7,7 @@ use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, Root pub(crate) fn ssr_assists( db: &RootDatabase, - resolve: AssistResolveStrategy, + resolve: &AssistResolveStrategy, frange: FileRange, ) -> Vec { let mut ssr_assists = Vec::with_capacity(2); @@ -73,7 +73,7 @@ mod tests { let mut local_roots = FxHashSet::default(); local_roots.insert(ide_db::base_db::fixture::WORKSPACE); db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); - ssr_assists(&db, resolve, FileRange { file_id, range: range_or_offset.into() }) + ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() }) } #[test] diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs index 397d2a3d0..01addffe9 100644 --- a/crates/ide_assists/src/lib.rs +++ b/crates/ide_assists/src/lib.rs @@ -17,6 +17,8 @@ mod tests; pub mod utils; pub mod ast_transform; +use std::str::FromStr; + use hir::Semantics; use ide_db::base_db::FileRange; use ide_db::{label::Label, source_change::SourceChange, RootDatabase}; @@ -56,6 +58,35 @@ impl AssistKind { _ => return false, } } + + pub fn name(&self) -> &str { + match self { + AssistKind::None => "None", + AssistKind::QuickFix => "QuickFix", + AssistKind::Generate => "Generate", + AssistKind::Refactor => "Refactor", + AssistKind::RefactorExtract => "RefactorExtract", + AssistKind::RefactorInline => "RefactorInline", + AssistKind::RefactorRewrite => "RefactorRewrite", + } + } +} + +impl FromStr for AssistKind { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "None" => Ok(AssistKind::None), + "QuickFix" => Ok(AssistKind::QuickFix), + "Generate" => Ok(AssistKind::Generate), + "Refactor" => Ok(AssistKind::Refactor), + "RefactorExtract" => Ok(AssistKind::RefactorExtract), + "RefactorInline" => Ok(AssistKind::RefactorInline), + "RefactorRewrite" => Ok(AssistKind::RefactorRewrite), + unknown => Err(format!("Unknown AssistKind: '{}'", unknown)), + } + } } /// Unique identifier of the assist, should not be shown to the user @@ -64,11 +95,11 @@ impl AssistKind { pub struct AssistId(pub &'static str, pub AssistKind); // TODO kb docs -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub enum AssistResolveStrategy { None, All, - Single(AssistId), + Single(String, AssistKind), } impl AssistResolveStrategy { @@ -76,7 +107,9 @@ impl AssistResolveStrategy { match self { AssistResolveStrategy::None => false, AssistResolveStrategy::All => true, - AssistResolveStrategy::Single(id_to_resolve) => id_to_resolve == id, + AssistResolveStrategy::Single(id_to_resolve, kind) => { + id_to_resolve == id.0 && kind == &id.1 + } } } } diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index dc350c01f..cd6bbf303 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -8,9 +8,9 @@ use std::{ }; use ide::{ - AnnotationConfig, AssistResolveStrategy, FileId, FilePosition, FileRange, HoverAction, - HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, - TextEdit, + AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange, + HoverAction, HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope, + SourceChange, TextEdit, }; use ide_db::SymbolKind; use itertools::Itertools; @@ -28,7 +28,7 @@ use lsp_types::{ use project_model::TargetKind; use serde::{Deserialize, Serialize}; use serde_json::to_value; -use stdx::{format_to, split_once}; +use stdx::format_to; use syntax::{algo, ast, AstNode, TextRange, TextSize}; use crate::{ @@ -1058,18 +1058,27 @@ pub(crate) fn handle_code_action_resolve( .only .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); + let assist_kind: AssistKind = match params.kind.parse() { + Ok(kind) => kind, + Err(e) => { + return Err(LspError::new( + ErrorCode::InvalidParams as i32, + format!("For the assist to resolve, failed to parse the kind: {}", e), + ) + .into()) + } + }; + let assists = snap.analysis.assists_with_fixes( &assists_config, &snap.config.diagnostics(), - // TODO kb pass a certain id - AssistResolveStrategy::All, + AssistResolveStrategy::Single(params.id.clone(), assist_kind), frange, )?; - let (id, index) = split_once(¶ms.id, ':').unwrap(); - let index = index.parse::().unwrap(); - let assist = &assists[index]; - assert!(assist.id.0 == id); + let assist = &assists[params.index]; + assert!(assist.id.0 == params.id); + assert!(assist.id.1 == assist_kind); let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit; code_action.edit = edit; Ok(code_action) diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index b8835a534..292aedc9c 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -303,6 +303,8 @@ pub struct CodeAction { pub struct CodeActionData { pub code_action_params: lsp_types::CodeActionParams, pub id: String, + pub kind: String, + pub index: usize, } #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index c2361b32e..62e16680b 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -897,8 +897,10 @@ pub(crate) fn code_action( (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?), (None, Some((index, code_action_params))) => { res.data = Some(lsp_ext::CodeActionData { - id: format!("{}:{}", assist.id.0, index.to_string()), + id: assist.id.0.to_string(), code_action_params, + kind: assist.id.1.name().to_string(), + index, }); } (None, None) => { -- cgit v1.2.3