aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2021-05-03 15:08:09 +0100
committerKirill Bulatov <[email protected]>2021-05-03 15:14:49 +0100
commite5cdcb8b124f5b7d59950429787e760e46388f72 (patch)
tree8740336ea373603a48542d911da6765645a02627 /crates/ide_assists
parenteb741e895f1a73420a401f2495c711afe37d9d19 (diff)
Add a way to resolve certain assists
Diffstat (limited to 'crates/ide_assists')
-rw-r--r--crates/ide_assists/src/assist_context.rs10
-rw-r--r--crates/ide_assists/src/lib.rs24
-rw-r--r--crates/ide_assists/src/tests.rs21
3 files changed, 39 insertions, 16 deletions
diff --git a/crates/ide_assists/src/assist_context.rs b/crates/ide_assists/src/assist_context.rs
index 8714e4978..19e9f179e 100644
--- a/crates/ide_assists/src/assist_context.rs
+++ b/crates/ide_assists/src/assist_context.rs
@@ -19,7 +19,9 @@ use syntax::{
19}; 19};
20use text_edit::{TextEdit, TextEditBuilder}; 20use text_edit::{TextEdit, TextEditBuilder};
21 21
22use crate::{assist_config::AssistConfig, Assist, AssistId, AssistKind, GroupLabel}; 22use crate::{
23 assist_config::AssistConfig, Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel,
24};
23 25
24/// `AssistContext` allows to apply an assist or check if it could be applied. 26/// `AssistContext` allows to apply an assist or check if it could be applied.
25/// 27///
@@ -105,14 +107,14 @@ impl<'a> AssistContext<'a> {
105} 107}
106 108
107pub(crate) struct Assists { 109pub(crate) struct Assists {
108 resolve: bool,
109 file: FileId, 110 file: FileId,
111 resolve: AssistResolveStrategy,
110 buf: Vec<Assist>, 112 buf: Vec<Assist>,
111 allowed: Option<Vec<AssistKind>>, 113 allowed: Option<Vec<AssistKind>>,
112} 114}
113 115
114impl Assists { 116impl Assists {
115 pub(crate) fn new(ctx: &AssistContext, resolve: bool) -> Assists { 117 pub(crate) fn new(ctx: &AssistContext, resolve: AssistResolveStrategy) -> Assists {
116 Assists { 118 Assists {
117 resolve, 119 resolve,
118 file: ctx.frange.file_id, 120 file: ctx.frange.file_id,
@@ -158,7 +160,7 @@ impl Assists {
158 } 160 }
159 161
160 fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> { 162 fn add_impl(&mut self, mut assist: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
161 let source_change = if self.resolve { 163 let source_change = if self.resolve.should_resolve(&assist.id) {
162 let mut builder = AssistBuilder::new(self.file); 164 let mut builder = AssistBuilder::new(self.file);
163 f(&mut builder); 165 f(&mut builder);
164 Some(builder.finish()) 166 Some(builder.finish())
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 88ae5c9a9..397d2a3d0 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -26,7 +26,7 @@ pub(crate) use crate::assist_context::{AssistContext, Assists};
26 26
27pub use assist_config::AssistConfig; 27pub use assist_config::AssistConfig;
28 28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum AssistKind { 30pub enum AssistKind {
31 // FIXME: does the None variant make sense? Probably not. 31 // FIXME: does the None variant make sense? Probably not.
32 None, 32 None,
@@ -60,9 +60,27 @@ impl AssistKind {
60 60
61/// Unique identifier of the assist, should not be shown to the user 61/// Unique identifier of the assist, should not be shown to the user
62/// directly. 62/// directly.
63#[derive(Debug, Clone, Copy, PartialEq, Eq)] 63#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64pub struct AssistId(pub &'static str, pub AssistKind); 64pub struct AssistId(pub &'static str, pub AssistKind);
65 65
66// TODO kb docs
67#[derive(Debug, Clone, Copy)]
68pub enum AssistResolveStrategy {
69 None,
70 All,
71 Single(AssistId),
72}
73
74impl AssistResolveStrategy {
75 pub fn should_resolve(&self, id: &AssistId) -> bool {
76 match self {
77 AssistResolveStrategy::None => false,
78 AssistResolveStrategy::All => true,
79 AssistResolveStrategy::Single(id_to_resolve) => id_to_resolve == id,
80 }
81 }
82}
83
66#[derive(Clone, Debug)] 84#[derive(Clone, Debug)]
67pub struct GroupLabel(pub String); 85pub struct GroupLabel(pub String);
68 86
@@ -91,7 +109,7 @@ impl Assist {
91 pub fn get( 109 pub fn get(
92 db: &RootDatabase, 110 db: &RootDatabase,
93 config: &AssistConfig, 111 config: &AssistConfig,
94 resolve: bool, 112 resolve: AssistResolveStrategy,
95 range: FileRange, 113 range: FileRange,
96 ) -> Vec<Assist> { 114 ) -> Vec<Assist> {
97 let sema = Semantics::new(db); 115 let sema = Semantics::new(db);
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 6f4f97361..227687766 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -12,7 +12,10 @@ use stdx::{format_to, trim_indent};
12use syntax::TextRange; 12use syntax::TextRange;
13use test_utils::{assert_eq_text, extract_offset}; 13use test_utils::{assert_eq_text, extract_offset};
14 14
15use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; 15use crate::{
16 handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, AssistResolveStrategy,
17 Assists,
18};
16 19
17pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig { 20pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
18 snippet_cap: SnippetCap::new(true), 21 snippet_cap: SnippetCap::new(true),
@@ -65,14 +68,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
65 let before = db.file_text(file_id).to_string(); 68 let before = db.file_text(file_id).to_string();
66 let frange = FileRange { file_id, range: selection.into() }; 69 let frange = FileRange { file_id, range: selection.into() };
67 70
68 let assist = Assist::get(&db, &TEST_CONFIG, true, frange) 71 let assist = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::All, frange)
69 .into_iter() 72 .into_iter()
70 .find(|assist| assist.id.0 == assist_id) 73 .find(|assist| assist.id.0 == assist_id)
71 .unwrap_or_else(|| { 74 .unwrap_or_else(|| {
72 panic!( 75 panic!(
73 "\n\nAssist is not applicable: {}\nAvailable assists: {}", 76 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
74 assist_id, 77 assist_id,
75 Assist::get(&db, &TEST_CONFIG, false, frange) 78 Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange)
76 .into_iter() 79 .into_iter()
77 .map(|assist| assist.id.0) 80 .map(|assist| assist.id.0)
78 .collect::<Vec<_>>() 81 .collect::<Vec<_>>()
@@ -108,7 +111,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
108 let sema = Semantics::new(&db); 111 let sema = Semantics::new(&db);
109 let config = TEST_CONFIG; 112 let config = TEST_CONFIG;
110 let ctx = AssistContext::new(sema, &config, frange); 113 let ctx = AssistContext::new(sema, &config, frange);
111 let mut acc = Assists::new(&ctx, true); 114 let mut acc = Assists::new(&ctx, AssistResolveStrategy::All);
112 handler(&mut acc, &ctx); 115 handler(&mut acc, &ctx);
113 let mut res = acc.finish(); 116 let mut res = acc.finish();
114 117
@@ -186,7 +189,7 @@ fn assist_order_field_struct() {
186 let (before_cursor_pos, before) = extract_offset(before); 189 let (before_cursor_pos, before) = extract_offset(before);
187 let (db, file_id) = with_single_file(&before); 190 let (db, file_id) = with_single_file(&before);
188 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; 191 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
189 let assists = Assist::get(&db, &TEST_CONFIG, false, frange); 192 let assists = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange);
190 let mut assists = assists.iter(); 193 let mut assists = assists.iter();
191 194
192 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); 195 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
@@ -211,7 +214,7 @@ pub fn test_some_range(a: int) -> bool {
211"#, 214"#,
212 ); 215 );
213 216
214 let assists = Assist::get(&db, &TEST_CONFIG, false, frange); 217 let assists = Assist::get(&db, &TEST_CONFIG, AssistResolveStrategy::None, frange);
215 let expected = labels(&assists); 218 let expected = labels(&assists);
216 219
217 expect![[r#" 220 expect![[r#"
@@ -240,7 +243,7 @@ pub fn test_some_range(a: int) -> bool {
240 let mut cfg = TEST_CONFIG; 243 let mut cfg = TEST_CONFIG;
241 cfg.allowed = Some(vec![AssistKind::Refactor]); 244 cfg.allowed = Some(vec![AssistKind::Refactor]);
242 245
243 let assists = Assist::get(&db, &cfg, false, frange); 246 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange);
244 let expected = labels(&assists); 247 let expected = labels(&assists);
245 248
246 expect![[r#" 249 expect![[r#"
@@ -255,7 +258,7 @@ pub fn test_some_range(a: int) -> bool {
255 { 258 {
256 let mut cfg = TEST_CONFIG; 259 let mut cfg = TEST_CONFIG;
257 cfg.allowed = Some(vec![AssistKind::RefactorExtract]); 260 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
258 let assists = Assist::get(&db, &cfg, false, frange); 261 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange);
259 let expected = labels(&assists); 262 let expected = labels(&assists);
260 263
261 expect![[r#" 264 expect![[r#"
@@ -268,7 +271,7 @@ pub fn test_some_range(a: int) -> bool {
268 { 271 {
269 let mut cfg = TEST_CONFIG; 272 let mut cfg = TEST_CONFIG;
270 cfg.allowed = Some(vec![AssistKind::QuickFix]); 273 cfg.allowed = Some(vec![AssistKind::QuickFix]);
271 let assists = Assist::get(&db, &cfg, false, frange); 274 let assists = Assist::get(&db, &cfg, AssistResolveStrategy::None, frange);
272 let expected = labels(&assists); 275 let expected = labels(&assists);
273 276
274 expect![[r#""#]].assert_eq(&expected); 277 expect![[r#""#]].assert_eq(&expected);