aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 455f20c93..b14f908b7 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -85,7 +85,7 @@ pub struct DiagnosticsConfig {
85pub(crate) fn diagnostics( 85pub(crate) fn diagnostics(
86 db: &RootDatabase, 86 db: &RootDatabase,
87 config: &DiagnosticsConfig, 87 config: &DiagnosticsConfig,
88 resolve: AssistResolveStrategy, 88 resolve: &AssistResolveStrategy,
89 file_id: FileId, 89 file_id: FileId,
90) -> Vec<Diagnostic> { 90) -> Vec<Diagnostic> {
91 let _p = profile::span("diagnostics"); 91 let _p = profile::span("diagnostics");
@@ -213,7 +213,7 @@ pub(crate) fn diagnostics(
213fn diagnostic_with_fix<D: DiagnosticWithFix>( 213fn diagnostic_with_fix<D: DiagnosticWithFix>(
214 d: &D, 214 d: &D,
215 sema: &Semantics<RootDatabase>, 215 sema: &Semantics<RootDatabase>,
216 resolve: AssistResolveStrategy, 216 resolve: &AssistResolveStrategy,
217) -> Diagnostic { 217) -> Diagnostic {
218 Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) 218 Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message())
219 .with_fix(d.fix(&sema, resolve)) 219 .with_fix(d.fix(&sema, resolve))
@@ -223,7 +223,7 @@ fn diagnostic_with_fix<D: DiagnosticWithFix>(
223fn warning_with_fix<D: DiagnosticWithFix>( 223fn warning_with_fix<D: DiagnosticWithFix>(
224 d: &D, 224 d: &D,
225 sema: &Semantics<RootDatabase>, 225 sema: &Semantics<RootDatabase>,
226 resolve: AssistResolveStrategy, 226 resolve: &AssistResolveStrategy,
227) -> Diagnostic { 227) -> Diagnostic {
228 Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) 228 Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message())
229 .with_fix(d.fix(&sema, resolve)) 229 .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 {
39 fn fix( 39 fn fix(
40 &self, 40 &self,
41 sema: &Semantics<RootDatabase>, 41 sema: &Semantics<RootDatabase>,
42 _resolve: AssistResolveStrategy, 42 _resolve: &AssistResolveStrategy,
43 ) -> Option<Assist>; 43 ) -> Option<Assist>;
44} 44}
45 45
@@ -47,7 +47,7 @@ impl DiagnosticWithFix for UnresolvedModule {
47 fn fix( 47 fn fix(
48 &self, 48 &self,
49 sema: &Semantics<RootDatabase>, 49 sema: &Semantics<RootDatabase>,
50 _resolve: AssistResolveStrategy, 50 _resolve: &AssistResolveStrategy,
51 ) -> Option<Assist> { 51 ) -> Option<Assist> {
52 let root = sema.db.parse_or_expand(self.file)?; 52 let root = sema.db.parse_or_expand(self.file)?;
53 let unresolved_module = self.decl.to_node(&root); 53 let unresolved_module = self.decl.to_node(&root);
@@ -71,7 +71,7 @@ impl DiagnosticWithFix for NoSuchField {
71 fn fix( 71 fn fix(
72 &self, 72 &self,
73 sema: &Semantics<RootDatabase>, 73 sema: &Semantics<RootDatabase>,
74 _resolve: AssistResolveStrategy, 74 _resolve: &AssistResolveStrategy,
75 ) -> Option<Assist> { 75 ) -> Option<Assist> {
76 let root = sema.db.parse_or_expand(self.file)?; 76 let root = sema.db.parse_or_expand(self.file)?;
77 missing_record_expr_field_fix( 77 missing_record_expr_field_fix(
@@ -86,7 +86,7 @@ impl DiagnosticWithFix for MissingFields {
86 fn fix( 86 fn fix(
87 &self, 87 &self,
88 sema: &Semantics<RootDatabase>, 88 sema: &Semantics<RootDatabase>,
89 _resolve: AssistResolveStrategy, 89 _resolve: &AssistResolveStrategy,
90 ) -> Option<Assist> { 90 ) -> Option<Assist> {
91 // Note that although we could add a diagnostics to 91 // Note that although we could add a diagnostics to
92 // fill the missing tuple field, e.g : 92 // fill the missing tuple field, e.g :
@@ -126,7 +126,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
126 fn fix( 126 fn fix(
127 &self, 127 &self,
128 sema: &Semantics<RootDatabase>, 128 sema: &Semantics<RootDatabase>,
129 _resolve: AssistResolveStrategy, 129 _resolve: &AssistResolveStrategy,
130 ) -> Option<Assist> { 130 ) -> Option<Assist> {
131 let root = sema.db.parse_or_expand(self.file)?; 131 let root = sema.db.parse_or_expand(self.file)?;
132 let tail_expr = self.expr.to_node(&root); 132 let tail_expr = self.expr.to_node(&root);
@@ -143,7 +143,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
143 fn fix( 143 fn fix(
144 &self, 144 &self,
145 sema: &Semantics<RootDatabase>, 145 sema: &Semantics<RootDatabase>,
146 _resolve: AssistResolveStrategy, 146 _resolve: &AssistResolveStrategy,
147 ) -> Option<Assist> { 147 ) -> Option<Assist> {
148 let root = sema.db.parse_or_expand(self.file)?; 148 let root = sema.db.parse_or_expand(self.file)?;
149 149
@@ -167,7 +167,7 @@ impl DiagnosticWithFix for IncorrectCase {
167 fn fix( 167 fn fix(
168 &self, 168 &self,
169 sema: &Semantics<RootDatabase>, 169 sema: &Semantics<RootDatabase>,
170 resolve: AssistResolveStrategy, 170 resolve: &AssistResolveStrategy,
171 ) -> Option<Assist> { 171 ) -> Option<Assist> {
172 let root = sema.db.parse_or_expand(self.file)?; 172 let root = sema.db.parse_or_expand(self.file)?;
173 let name_node = self.ident.to_node(&root); 173 let name_node = self.ident.to_node(&root);
@@ -191,7 +191,7 @@ impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
191 fn fix( 191 fn fix(
192 &self, 192 &self,
193 sema: &Semantics<RootDatabase>, 193 sema: &Semantics<RootDatabase>,
194 _resolve: AssistResolveStrategy, 194 _resolve: &AssistResolveStrategy,
195 ) -> Option<Assist> { 195 ) -> Option<Assist> {
196 let root = sema.db.parse_or_expand(self.file)?; 196 let root = sema.db.parse_or_expand(self.file)?;
197 let next_expr = self.next_expr.to_node(&root); 197 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 {
54 fn fix( 54 fn fix(
55 &self, 55 &self,
56 sema: &hir::Semantics<RootDatabase>, 56 sema: &hir::Semantics<RootDatabase>,
57 _resolve: AssistResolveStrategy, 57 _resolve: &AssistResolveStrategy,
58 ) -> Option<Assist> { 58 ) -> Option<Assist> {
59 // If there's an existing module that could add a `mod` item to include the unlinked file, 59 // If there's an existing module that could add a `mod` item to include the unlinked file,
60 // suggest that as a fix. 60 // 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 {
522 frange: FileRange, 522 frange: FileRange,
523 ) -> Cancelable<Vec<Assist>> { 523 ) -> Cancelable<Vec<Assist>> {
524 self.with_db(|db| { 524 self.with_db(|db| {
525 let ssr_assists = ssr::ssr_assists(db, resolve, frange); 525 let ssr_assists = ssr::ssr_assists(db, &resolve, frange);
526 let mut acc = Assist::get(db, config, resolve, frange); 526 let mut acc = Assist::get(db, config, resolve, frange);
527 acc.extend(ssr_assists.into_iter()); 527 acc.extend(ssr_assists.into_iter());
528 acc 528 acc
@@ -536,7 +536,7 @@ impl Analysis {
536 resolve: AssistResolveStrategy, 536 resolve: AssistResolveStrategy,
537 file_id: FileId, 537 file_id: FileId,
538 ) -> Cancelable<Vec<Diagnostic>> { 538 ) -> Cancelable<Vec<Diagnostic>> {
539 self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id)) 539 self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id))
540 } 540 }
541 541
542 /// Convenience function to return assists + quick fixes for diagnostics 542 /// Convenience function to return assists + quick fixes for diagnostics
@@ -553,9 +553,9 @@ impl Analysis {
553 }; 553 };
554 554
555 self.with_db(|db| { 555 self.with_db(|db| {
556 let ssr_assists = ssr::ssr_assists(db, resolve, frange); 556 let ssr_assists = ssr::ssr_assists(db, &resolve, frange);
557 let diagnostic_assists = if include_fixes { 557 let diagnostic_assists = if include_fixes {
558 diagnostics::diagnostics(db, diagnostics_config, resolve, frange.file_id) 558 diagnostics::diagnostics(db, diagnostics_config, &resolve, frange.file_id)
559 .into_iter() 559 .into_iter()
560 .filter_map(|it| it.fix) 560 .filter_map(|it| it.fix)
561 .filter(|it| it.target.intersect(frange.range).is_some()) 561 .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
7 7
8pub(crate) fn ssr_assists( 8pub(crate) fn ssr_assists(
9 db: &RootDatabase, 9 db: &RootDatabase,
10 resolve: AssistResolveStrategy, 10 resolve: &AssistResolveStrategy,
11 frange: FileRange, 11 frange: FileRange,
12) -> Vec<Assist> { 12) -> Vec<Assist> {
13 let mut ssr_assists = Vec::with_capacity(2); 13 let mut ssr_assists = Vec::with_capacity(2);
@@ -73,7 +73,7 @@ mod tests {
73 let mut local_roots = FxHashSet::default(); 73 let mut local_roots = FxHashSet::default();
74 local_roots.insert(ide_db::base_db::fixture::WORKSPACE); 74 local_roots.insert(ide_db::base_db::fixture::WORKSPACE);
75 db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); 75 db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
76 ssr_assists(&db, resolve, FileRange { file_id, range: range_or_offset.into() }) 76 ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() })
77 } 77 }
78 78
79 #[test] 79 #[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;
17pub mod utils; 17pub mod utils;
18pub mod ast_transform; 18pub mod ast_transform;
19 19
20use std::str::FromStr;
21
20use hir::Semantics; 22use hir::Semantics;
21use ide_db::base_db::FileRange; 23use ide_db::base_db::FileRange;
22use ide_db::{label::Label, source_change::SourceChange, RootDatabase}; 24use ide_db::{label::Label, source_change::SourceChange, RootDatabase};
@@ -56,6 +58,35 @@ impl AssistKind {
56 _ => return false, 58 _ => return false,
57 } 59 }
58 } 60 }
61
62 pub fn name(&self) -> &str {
63 match self {
64 AssistKind::None => "None",
65 AssistKind::QuickFix => "QuickFix",
66 AssistKind::Generate => "Generate",
67 AssistKind::Refactor => "Refactor",
68 AssistKind::RefactorExtract => "RefactorExtract",
69 AssistKind::RefactorInline => "RefactorInline",
70 AssistKind::RefactorRewrite => "RefactorRewrite",
71 }
72 }
73}
74
75impl FromStr for AssistKind {
76 type Err = String;
77
78 fn from_str(s: &str) -> Result<Self, Self::Err> {
79 match s {
80 "None" => Ok(AssistKind::None),
81 "QuickFix" => Ok(AssistKind::QuickFix),
82 "Generate" => Ok(AssistKind::Generate),
83 "Refactor" => Ok(AssistKind::Refactor),
84 "RefactorExtract" => Ok(AssistKind::RefactorExtract),
85 "RefactorInline" => Ok(AssistKind::RefactorInline),
86 "RefactorRewrite" => Ok(AssistKind::RefactorRewrite),
87 unknown => Err(format!("Unknown AssistKind: '{}'", unknown)),
88 }
89 }
59} 90}
60 91
61/// Unique identifier of the assist, should not be shown to the user 92/// Unique identifier of the assist, should not be shown to the user
@@ -64,11 +95,11 @@ impl AssistKind {
64pub struct AssistId(pub &'static str, pub AssistKind); 95pub struct AssistId(pub &'static str, pub AssistKind);
65 96
66// TODO kb docs 97// TODO kb docs
67#[derive(Debug, Clone, Copy)] 98#[derive(Debug, Clone)]
68pub enum AssistResolveStrategy { 99pub enum AssistResolveStrategy {
69 None, 100 None,
70 All, 101 All,
71 Single(AssistId), 102 Single(String, AssistKind),
72} 103}
73 104
74impl AssistResolveStrategy { 105impl AssistResolveStrategy {
@@ -76,7 +107,9 @@ impl AssistResolveStrategy {
76 match self { 107 match self {
77 AssistResolveStrategy::None => false, 108 AssistResolveStrategy::None => false,
78 AssistResolveStrategy::All => true, 109 AssistResolveStrategy::All => true,
79 AssistResolveStrategy::Single(id_to_resolve) => id_to_resolve == id, 110 AssistResolveStrategy::Single(id_to_resolve, kind) => {
111 id_to_resolve == id.0 && kind == &id.1
112 }
80 } 113 }
81 } 114 }
82} 115}
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::{
8}; 8};
9 9
10use ide::{ 10use ide::{
11 AnnotationConfig, AssistResolveStrategy, FileId, FilePosition, FileRange, HoverAction, 11 AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange,
12 HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SourceChange, 12 HoverAction, HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
13 TextEdit, 13 SourceChange, TextEdit,
14}; 14};
15use ide_db::SymbolKind; 15use ide_db::SymbolKind;
16use itertools::Itertools; 16use itertools::Itertools;
@@ -28,7 +28,7 @@ use lsp_types::{
28use project_model::TargetKind; 28use project_model::TargetKind;
29use serde::{Deserialize, Serialize}; 29use serde::{Deserialize, Serialize};
30use serde_json::to_value; 30use serde_json::to_value;
31use stdx::{format_to, split_once}; 31use stdx::format_to;
32use syntax::{algo, ast, AstNode, TextRange, TextSize}; 32use syntax::{algo, ast, AstNode, TextRange, TextSize};
33 33
34use crate::{ 34use crate::{
@@ -1058,18 +1058,27 @@ pub(crate) fn handle_code_action_resolve(
1058 .only 1058 .only
1059 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); 1059 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
1060 1060
1061 let assist_kind: AssistKind = match params.kind.parse() {
1062 Ok(kind) => kind,
1063 Err(e) => {
1064 return Err(LspError::new(
1065 ErrorCode::InvalidParams as i32,
1066 format!("For the assist to resolve, failed to parse the kind: {}", e),
1067 )
1068 .into())
1069 }
1070 };
1071
1061 let assists = snap.analysis.assists_with_fixes( 1072 let assists = snap.analysis.assists_with_fixes(
1062 &assists_config, 1073 &assists_config,
1063 &snap.config.diagnostics(), 1074 &snap.config.diagnostics(),
1064 // TODO kb pass a certain id 1075 AssistResolveStrategy::Single(params.id.clone(), assist_kind),
1065 AssistResolveStrategy::All,
1066 frange, 1076 frange,
1067 )?; 1077 )?;
1068 1078
1069 let (id, index) = split_once(&params.id, ':').unwrap(); 1079 let assist = &assists[params.index];
1070 let index = index.parse::<usize>().unwrap(); 1080 assert!(assist.id.0 == params.id);
1071 let assist = &assists[index]; 1081 assert!(assist.id.1 == assist_kind);
1072 assert!(assist.id.0 == id);
1073 let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit; 1082 let edit = to_proto::code_action(&snap, assist.clone(), None)?.edit;
1074 code_action.edit = edit; 1083 code_action.edit = edit;
1075 Ok(code_action) 1084 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 {
303pub struct CodeActionData { 303pub struct CodeActionData {
304 pub code_action_params: lsp_types::CodeActionParams, 304 pub code_action_params: lsp_types::CodeActionParams,
305 pub id: String, 305 pub id: String,
306 pub kind: String,
307 pub index: usize,
306} 308}
307 309
308#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] 310#[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(
897 (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?), 897 (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?),
898 (None, Some((index, code_action_params))) => { 898 (None, Some((index, code_action_params))) => {
899 res.data = Some(lsp_ext::CodeActionData { 899 res.data = Some(lsp_ext::CodeActionData {
900 id: format!("{}:{}", assist.id.0, index.to_string()), 900 id: assist.id.0.to_string(),
901 code_action_params, 901 code_action_params,
902 kind: assist.id.1.name().to_string(),
903 index,
902 }); 904 });
903 } 905 }
904 (None, None) => { 906 (None, None) => {