aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r--crates/ra_analysis/src/completion.rs39
-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.rs78
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs82
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;
2mod reference_completion; 2mod reference_completion;
3 3
4mod complete_fn_param; 4mod complete_fn_param;
5mod complete_keywords; 5mod complete_keyword;
6mod complete_snippet;
6 7
7use ra_editor::find_node_at_offset; 8use ra_editor::find_node_at_offset;
8use ra_text_edit::AtomTextEdit; 9use 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
70impl SyntaxContext<'_> { 75impl 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 @@
1use crate::{
2 completion::{CompletionItem, Completions, CompletionKind::*, SyntaxContext},
3};
4
5pub(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
19pub(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]
28fn ${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)]
41mod 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
165fn complete_mod_item_snippets(acc: &mut Completions) {
166 CompletionItem::new("Test function")
167 .lookup_by("tfn")
168 .snippet(
169 "\
170#[test]
171fn ${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
183fn 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)]
195mod tests { 152mod 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}