aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-03 13:46:14 +0100
committerAleksey Kladov <[email protected]>2018-09-03 13:46:14 +0100
commit2f2feef9afe8f1c75f743a56f945a1560ca85af4 (patch)
treee0c38474c39feaf4aae0de4ac2f4ec7d8ad91c79 /crates
parent4798a89a12f40af17174a160f6d6a2f1c53db8d6 (diff)
completion for trait params
Diffstat (limited to 'crates')
-rw-r--r--crates/libeditor/src/completion.rs41
-rw-r--r--crates/libsyntax2/src/ast/generated.rs1
-rw-r--r--crates/libsyntax2/src/grammar.ron1
3 files changed, 33 insertions, 10 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs
index 6c3775127..c25b4c217 100644
--- a/crates/libeditor/src/completion.rs
+++ b/crates/libeditor/src/completion.rs
@@ -35,11 +35,17 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI
35 let mut res = Vec::new(); 35 let mut res = Vec::new();
36 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), offset) { 36 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), offset) {
37 has_completions = true; 37 has_completions = true;
38 complete_name_ref(&file, name_ref, &mut res) 38 complete_name_ref(&file, name_ref, &mut res);
39 // special case, `trait T { fn foo(i_am_a_name_ref) {} }`
40 if is_node::<ast::Param>(name_ref.syntax()) {
41 param_completions(name_ref.syntax(), &mut res);
42 }
39 } 43 }
40 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) { 44 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) {
41 has_completions = true; 45 if is_node::<ast::Param>(name.syntax()) {
42 complete_name(&file, name, &mut res) 46 has_completions = true;
47 param_completions(name.syntax(), &mut res);
48 }
43 } 49 }
44 if has_completions { 50 if has_completions {
45 Some(res) 51 Some(res)
@@ -71,15 +77,12 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<Completi
71 } 77 }
72} 78}
73 79
74fn complete_name(_file: &File, name: ast::Name, acc: &mut Vec<CompletionItem>) { 80fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
75 if !is_node::<ast::Param>(name.syntax()) {
76 return;
77 }
78
79 let mut params = HashMap::new(); 81 let mut params = HashMap::new();
80 for node in ancestors(name.syntax()) { 82 for node in ancestors(ctx) {
81 let _ = visitor_ctx(&mut params) 83 let _ = visitor_ctx(&mut params)
82 .visit::<ast::Root, _>(process) 84 .visit::<ast::Root, _>(process)
85 .visit::<ast::ItemList, _>(process)
83 .accept(node); 86 .accept(node);
84 } 87 }
85 params.into_iter() 88 params.into_iter()
@@ -420,16 +423,34 @@ mod tests {
420 } 423 }
421 424
422 #[test] 425 #[test]
423 fn test_param_completion() { 426 fn test_param_completion_last_param() {
424 check_scope_completion(r" 427 check_scope_completion(r"
425 fn foo(file_id: FileId) {} 428 fn foo(file_id: FileId) {}
426 fn bar(file_id: FileId) {} 429 fn bar(file_id: FileId) {}
427 fn baz(file<|>) {} 430 fn baz(file<|>) {}
428 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); 431 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
432 }
433
434 #[test]
435 fn test_param_completion_nth_param() {
429 check_scope_completion(r" 436 check_scope_completion(r"
430 fn foo(file_id: FileId) {} 437 fn foo(file_id: FileId) {}
431 fn bar(file_id: FileId) {} 438 fn bar(file_id: FileId) {}
432 fn baz(file<|>, x: i32) {} 439 fn baz(file<|>, x: i32) {}
433 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); 440 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
434 } 441 }
442
443 #[test]
444 fn test_param_completion_trait_param() {
445 check_scope_completion(r"
446 pub(crate) trait SourceRoot {
447 pub fn contains(&self, file_id: FileId) -> bool;
448 pub fn module_map(&self) -> &ModuleMap;
449 pub fn lines(&self, file_id: FileId) -> &LineIndex;
450 pub fn syntax(&self, file<|>)
451 }
452 ", r#"[CompletionItem { label: "self", lookup: None, snippet: None },
453 CompletionItem { label: "SourceRoot", lookup: None, snippet: None },
454 CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
455 }
435} 456}
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs
index 4a57837df..a239f0630 100644
--- a/crates/libsyntax2/src/ast/generated.rs
+++ b/crates/libsyntax2/src/ast/generated.rs
@@ -698,6 +698,7 @@ impl<'a> AstNode<'a> for ItemList<'a> {
698 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 698 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
699} 699}
700 700
701impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {}
701impl<'a> ItemList<'a> { 702impl<'a> ItemList<'a> {
702 pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { 703 pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a {
703 super::children(self) 704 super::children(self)
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron
index 8a2b780f0..6ed658daa 100644
--- a/crates/libsyntax2/src/grammar.ron
+++ b/crates/libsyntax2/src/grammar.ron
@@ -275,6 +275,7 @@ Grammar(
275 options: [ "ItemList" ] 275 options: [ "ItemList" ]
276 ), 276 ),
277 "ItemList": ( 277 "ItemList": (
278 traits: [ "FnDefOwner" ],
278 collections: [ ["items", "ModuleItem"] ] 279 collections: [ ["items", "ModuleItem"] ]
279 ), 280 ),
280 "ConstDef": ( traits: [ 281 "ConstDef": ( traits: [