about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKirill Bulatov <mail4score@gmail.com>2021-05-03 18:03:28 +0300
committerKirill Bulatov <mail4score@gmail.com>2021-05-03 18:03:28 +0300
commit1679a376f30c5ad8971c0f855074a3f489fee5fa (patch)
tree1ffe5d504426f6e1d9cbf1c56d9e6b91ab9ac43d
parente5cdcb8b124f5b7d59950429787e760e46388f72 (diff)
downloadrust-1679a376f30c5ad8971c0f855074a3f489fee5fa.tar.gz
rust-1679a376f30c5ad8971c0f855074a3f489fee5fa.zip
Resolve single assist only
-rw-r--r--crates/ide/src/diagnostics.rs6
-rw-r--r--crates/ide/src/diagnostics/fixes.rs16
-rw-r--r--crates/ide/src/diagnostics/unlinked_file.rs2
-rw-r--r--crates/ide/src/lib.rs8
-rw-r--r--crates/ide/src/ssr.rs4
-rw-r--r--crates/ide_assists/src/lib.rs39
-rw-r--r--crates/rust-analyzer/src/handlers.rs29
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs4
9 files changed, 78 insertions, 32 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 455f20c93f2..b14f908b75e 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<Diagnostic> {
     let _p = profile::span("diagnostics");
@@ -213,7 +213,7 @@ pub(crate) fn diagnostics(
 fn diagnostic_with_fix<D: DiagnosticWithFix>(
     d: &D,
     sema: &Semantics<RootDatabase>,
-    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<D: DiagnosticWithFix>(
 fn warning_with_fix<D: DiagnosticWithFix>(
     d: &D,
     sema: &Semantics<RootDatabase>,
-    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 f23064eac10..15821500f1a 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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist>;
 }
 
@@ -47,7 +47,7 @@ impl DiagnosticWithFix for UnresolvedModule {
     fn fix(
         &self,
         sema: &Semantics<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         // 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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         let root = sema.db.parse_or_expand(self.file)?;
 
@@ -167,7 +167,7 @@ impl DiagnosticWithFix for IncorrectCase {
     fn fix(
         &self,
         sema: &Semantics<RootDatabase>,
-        resolve: AssistResolveStrategy,
+        resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         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 e48528bed25..93fd25dea47 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<RootDatabase>,
-        _resolve: AssistResolveStrategy,
+        _resolve: &AssistResolveStrategy,
     ) -> Option<Assist> {
         // 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 6847b7e836a..6a88236e3f4 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -522,7 +522,7 @@ impl Analysis {
         frange: FileRange,
     ) -> Cancelable<Vec<Assist>> {
         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<Vec<Diagnostic>> {
-        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 785ce301099..1695e52ece8 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<Assist> {
     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 397d2a3d0ee..01addffe949 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<Self, Self::Err> {
+        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 dc350c01fb3..cd6bbf30333 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(&params.id, ':').unwrap();
-    let index = index.parse::<usize>().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 b8835a5349b..292aedc9c2c 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 c2361b32e73..62e16680b4a 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) => {