diff options
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r-- | crates/ra_analysis/src/completion.rs | 39 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/complete_keyword.rs (renamed from crates/ra_analysis/src/completion/complete_keywords.rs) | 0 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/complete_snippet.rs | 78 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/reference_completion.rs | 82 |
4 files changed, 104 insertions, 95 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs index 39066d51f..883b3e851 100644 --- a/crates/ra_analysis/src/completion.rs +++ b/crates/ra_analysis/src/completion.rs | |||
@@ -2,7 +2,8 @@ mod completion_item; | |||
2 | mod reference_completion; | 2 | mod reference_completion; |
3 | 3 | ||
4 | mod complete_fn_param; | 4 | mod complete_fn_param; |
5 | mod complete_keywords; | 5 | mod complete_keyword; |
6 | mod complete_snippet; | ||
6 | 7 | ||
7 | use ra_editor::find_node_at_offset; | 8 | use ra_editor::find_node_at_offset; |
8 | use ra_text_edit::AtomTextEdit; | 9 | use ra_text_edit::AtomTextEdit; |
@@ -49,7 +50,9 @@ pub(crate) fn completions( | |||
49 | 50 | ||
50 | let ctx = ctry!(SyntaxContext::new(&original_file, position.offset)); | 51 | let ctx = ctry!(SyntaxContext::new(&original_file, position.offset)); |
51 | complete_fn_param::complete_fn_param(&mut acc, &ctx); | 52 | complete_fn_param::complete_fn_param(&mut acc, &ctx); |
52 | complete_keywords::complete_expr_keyword(&mut acc, &ctx); | 53 | complete_keyword::complete_expr_keyword(&mut acc, &ctx); |
54 | complete_snippet::complete_expr_snippet(&mut acc, &ctx); | ||
55 | complete_snippet::complete_item_snippet(&mut acc, &ctx); | ||
53 | 56 | ||
54 | Ok(Some(acc)) | 57 | Ok(Some(acc)) |
55 | } | 58 | } |
@@ -61,10 +64,12 @@ pub(super) struct SyntaxContext<'a> { | |||
61 | leaf: SyntaxNodeRef<'a>, | 64 | leaf: SyntaxNodeRef<'a>, |
62 | enclosing_fn: Option<ast::FnDef<'a>>, | 65 | enclosing_fn: Option<ast::FnDef<'a>>, |
63 | is_param: bool, | 66 | is_param: bool, |
64 | /// a single-indent path, like `foo`. | 67 | /// A single-indent path, like `foo`. |
65 | is_trivial_path: bool, | 68 | is_trivial_path: bool, |
66 | after_if: bool, | 69 | after_if: bool, |
67 | is_stmt: bool, | 70 | is_stmt: bool, |
71 | /// Something is typed at the "top" level, in module or impl/trait. | ||
72 | is_new_item: bool, | ||
68 | } | 73 | } |
69 | 74 | ||
70 | impl SyntaxContext<'_> { | 75 | impl SyntaxContext<'_> { |
@@ -77,6 +82,7 @@ impl SyntaxContext<'_> { | |||
77 | is_trivial_path: false, | 82 | is_trivial_path: false, |
78 | after_if: false, | 83 | after_if: false, |
79 | is_stmt: false, | 84 | is_stmt: false, |
85 | is_new_item: false, | ||
80 | }; | 86 | }; |
81 | ctx.fill(original_file, offset); | 87 | ctx.fill(original_file, offset); |
82 | Some(ctx) | 88 | Some(ctx) |
@@ -112,17 +118,22 @@ impl SyntaxContext<'_> { | |||
112 | } | 118 | } |
113 | } | 119 | } |
114 | fn classify_name_ref(&mut self, file: &SourceFileNode, name_ref: ast::NameRef) { | 120 | fn classify_name_ref(&mut self, file: &SourceFileNode, name_ref: ast::NameRef) { |
115 | // let name_range = name_ref.syntax().range(); | 121 | let name_range = name_ref.syntax().range(); |
116 | // let top_node = name_ref | 122 | let top_node = name_ref |
117 | // .syntax() | 123 | .syntax() |
118 | // .ancestors() | 124 | .ancestors() |
119 | // .take_while(|it| it.range() == name_range) | 125 | .take_while(|it| it.range() == name_range) |
120 | // .last() | 126 | .last() |
121 | // .unwrap(); | 127 | .unwrap(); |
122 | // match top_node.parent().map(|it| it.kind()) { | 128 | |
123 | // Some(SOURCE_FILE) | Some(ITEM_LIST) => return Some(NameRefKind::BareIdentInMod), | 129 | match top_node.parent().map(|it| it.kind()) { |
124 | // _ => (), | 130 | Some(SOURCE_FILE) | Some(ITEM_LIST) => { |
125 | // } | 131 | self.is_new_item = true; |
132 | return; | ||
133 | } | ||
134 | _ => (), | ||
135 | } | ||
136 | |||
126 | let parent = match name_ref.syntax().parent() { | 137 | let parent = match name_ref.syntax().parent() { |
127 | Some(it) => it, | 138 | Some(it) => it, |
128 | None => return, | 139 | None => return, |
diff --git a/crates/ra_analysis/src/completion/complete_keywords.rs b/crates/ra_analysis/src/completion/complete_keyword.rs index d0a6ec19e..d0a6ec19e 100644 --- a/crates/ra_analysis/src/completion/complete_keywords.rs +++ b/crates/ra_analysis/src/completion/complete_keyword.rs | |||
diff --git a/crates/ra_analysis/src/completion/complete_snippet.rs b/crates/ra_analysis/src/completion/complete_snippet.rs new file mode 100644 index 000000000..5d6cc5dc9 --- /dev/null +++ b/crates/ra_analysis/src/completion/complete_snippet.rs | |||
@@ -0,0 +1,78 @@ | |||
1 | use crate::{ | ||
2 | completion::{CompletionItem, Completions, CompletionKind::*, SyntaxContext}, | ||
3 | }; | ||
4 | |||
5 | pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &SyntaxContext) { | ||
6 | if !(ctx.is_trivial_path && ctx.enclosing_fn.is_some()) { | ||
7 | return; | ||
8 | } | ||
9 | CompletionItem::new("pd") | ||
10 | .snippet("eprintln!(\"$0 = {:?}\", $0);") | ||
11 | .kind(Snippet) | ||
12 | .add_to(acc); | ||
13 | CompletionItem::new("ppd") | ||
14 | .snippet("eprintln!(\"$0 = {:#?}\", $0);") | ||
15 | .kind(Snippet) | ||
16 | .add_to(acc); | ||
17 | } | ||
18 | |||
19 | pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &SyntaxContext) { | ||
20 | if !ctx.is_new_item { | ||
21 | return; | ||
22 | } | ||
23 | CompletionItem::new("Test function") | ||
24 | .lookup_by("tfn") | ||
25 | .snippet( | ||
26 | "\ | ||
27 | #[test] | ||
28 | fn ${1:feature}() { | ||
29 | $0 | ||
30 | }", | ||
31 | ) | ||
32 | .kind(Snippet) | ||
33 | .add_to(acc); | ||
34 | CompletionItem::new("pub(crate)") | ||
35 | .snippet("pub(crate) $0") | ||
36 | .kind(Snippet) | ||
37 | .add_to(acc); | ||
38 | } | ||
39 | |||
40 | #[cfg(test)] | ||
41 | mod tests { | ||
42 | use crate::completion::{CompletionKind, check_completion}; | ||
43 | fn check_snippet_completion(code: &str, expected_completions: &str) { | ||
44 | check_completion(code, expected_completions, CompletionKind::Snippet); | ||
45 | } | ||
46 | |||
47 | #[test] | ||
48 | fn completes_snippets_in_expressions() { | ||
49 | check_snippet_completion( | ||
50 | r"fn foo(x: i32) { <|> }", | ||
51 | r##" | ||
52 | pd "eprintln!(\"$0 = {:?}\", $0);" | ||
53 | ppd "eprintln!(\"$0 = {:#?}\", $0);" | ||
54 | "##, | ||
55 | ); | ||
56 | } | ||
57 | |||
58 | #[test] | ||
59 | fn completes_snippets_in_items() { | ||
60 | // check_snippet_completion(r" | ||
61 | // <|> | ||
62 | // ", | ||
63 | // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##, | ||
64 | // ); | ||
65 | check_snippet_completion( | ||
66 | r" | ||
67 | #[cfg(test)] | ||
68 | mod tests { | ||
69 | <|> | ||
70 | } | ||
71 | ", | ||
72 | r##" | ||
73 | tfn "Test function" "#[test]\nfn ${1:feature}() {\n $0\n}" | ||
74 | pub(crate) "pub(crate) $0" | ||
75 | "##, | ||
76 | ); | ||
77 | } | ||
78 | } | ||
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index 15ff4c5dd..46d381927 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs | |||
@@ -32,8 +32,6 @@ pub(super) fn completions( | |||
32 | if let Some(fn_def) = enclosing_fn { | 32 | if let Some(fn_def) = enclosing_fn { |
33 | let scopes = FnScopes::new(fn_def); | 33 | let scopes = FnScopes::new(fn_def); |
34 | complete_fn(name_ref, &scopes, acc); | 34 | complete_fn(name_ref, &scopes, acc); |
35 | // complete_expr_keywords(&file, fn_def, name_ref, acc); | ||
36 | complete_expr_snippets(acc); | ||
37 | } | 35 | } |
38 | 36 | ||
39 | let module_scope = module.scope(db)?; | 37 | let module_scope = module.scope(db)?; |
@@ -56,19 +54,7 @@ pub(super) fn completions( | |||
56 | }); | 54 | }); |
57 | } | 55 | } |
58 | NameRefKind::Path(path) => complete_path(acc, db, module, path)?, | 56 | NameRefKind::Path(path) => complete_path(acc, db, module, path)?, |
59 | NameRefKind::BareIdentInMod => { | 57 | NameRefKind::BareIdentInMod => (), |
60 | let name_range = name_ref.syntax().range(); | ||
61 | let top_node = name_ref | ||
62 | .syntax() | ||
63 | .ancestors() | ||
64 | .take_while(|it| it.range() == name_range) | ||
65 | .last() | ||
66 | .unwrap(); | ||
67 | match top_node.parent().map(|it| it.kind()) { | ||
68 | Some(SOURCE_FILE) | Some(ITEM_LIST) => complete_mod_item_snippets(acc), | ||
69 | _ => (), | ||
70 | } | ||
71 | } | ||
72 | } | 58 | } |
73 | Ok(()) | 59 | Ok(()) |
74 | } | 60 | } |
@@ -162,35 +148,6 @@ fn complete_path( | |||
162 | Ok(()) | 148 | Ok(()) |
163 | } | 149 | } |
164 | 150 | ||
165 | fn complete_mod_item_snippets(acc: &mut Completions) { | ||
166 | CompletionItem::new("Test function") | ||
167 | .lookup_by("tfn") | ||
168 | .snippet( | ||
169 | "\ | ||
170 | #[test] | ||
171 | fn ${1:feature}() { | ||
172 | $0 | ||
173 | }", | ||
174 | ) | ||
175 | .kind(Snippet) | ||
176 | .add_to(acc); | ||
177 | CompletionItem::new("pub(crate)") | ||
178 | .snippet("pub(crate) $0") | ||
179 | .kind(Snippet) | ||
180 | .add_to(acc); | ||
181 | } | ||
182 | |||
183 | fn complete_expr_snippets(acc: &mut Completions) { | ||
184 | CompletionItem::new("pd") | ||
185 | .snippet("eprintln!(\"$0 = {:?}\", $0);") | ||
186 | .kind(Snippet) | ||
187 | .add_to(acc); | ||
188 | CompletionItem::new("ppd") | ||
189 | .snippet("eprintln!(\"$0 = {:#?}\", $0);") | ||
190 | .kind(Snippet) | ||
191 | .add_to(acc); | ||
192 | } | ||
193 | |||
194 | #[cfg(test)] | 151 | #[cfg(test)] |
195 | mod tests { | 152 | mod tests { |
196 | use crate::completion::{CompletionKind, check_completion}; | 153 | use crate::completion::{CompletionKind, check_completion}; |
@@ -199,10 +156,6 @@ mod tests { | |||
199 | check_completion(code, expected_completions, CompletionKind::Reference); | 156 | check_completion(code, expected_completions, CompletionKind::Reference); |
200 | } | 157 | } |
201 | 158 | ||
202 | fn check_snippet_completion(code: &str, expected_completions: &str) { | ||
203 | check_completion(code, expected_completions, CompletionKind::Snippet); | ||
204 | } | ||
205 | |||
206 | #[test] | 159 | #[test] |
207 | fn test_completion_let_scope() { | 160 | fn test_completion_let_scope() { |
208 | check_reference_completion( | 161 | check_reference_completion( |
@@ -378,37 +331,4 @@ mod tests { | |||
378 | "Spam", | 331 | "Spam", |
379 | ); | 332 | ); |
380 | } | 333 | } |
381 | |||
382 | #[test] | ||
383 | fn completes_snippets_in_expressions() { | ||
384 | check_snippet_completion( | ||
385 | r"fn foo(x: i32) { <|> }", | ||
386 | r##" | ||
387 | pd "eprintln!(\"$0 = {:?}\", $0);" | ||
388 | ppd "eprintln!(\"$0 = {:#?}\", $0);" | ||
389 | "##, | ||
390 | ); | ||
391 | } | ||
392 | |||
393 | #[test] | ||
394 | fn completes_snippets_in_items() { | ||
395 | // check_snippet_completion(r" | ||
396 | // <|> | ||
397 | // ", | ||
398 | // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##, | ||
399 | // ); | ||
400 | check_snippet_completion( | ||
401 | r" | ||
402 | #[cfg(test)] | ||
403 | mod tests { | ||
404 | <|> | ||
405 | } | ||
406 | ", | ||
407 | r##" | ||
408 | tfn "Test function" "#[test]\nfn ${1:feature}() {\n $0\n}" | ||
409 | pub(crate) "pub(crate) $0" | ||
410 | "##, | ||
411 | ); | ||
412 | } | ||
413 | |||
414 | } | 334 | } |