aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-07 23:35:20 +0100
committerAleksey Kladov <[email protected]>2018-09-07 23:35:20 +0100
commit127814d9a7f62c834c0893ff05e933aac4be89e9 (patch)
tree412432e0308c8b22b28e3b84776b44b311b283da
parentff1c82216cc05f2621a301e30ab7a1102dea9d2b (diff)
nested mod completion
-rw-r--r--crates/libeditor/src/completion.rs58
-rw-r--r--crates/libeditor/src/scope/mod_scope.rs11
-rw-r--r--crates/libsyntax2/src/ast/generated.rs13
-rw-r--r--crates/libsyntax2/src/ast/mod.rs24
-rw-r--r--crates/libsyntax2/src/grammar.ron8
5 files changed, 68 insertions, 46 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs
index c25b4c217..52df6fd10 100644
--- a/crates/libeditor/src/completion.rs
+++ b/crates/libeditor/src/completion.rs
@@ -2,7 +2,7 @@ use std::collections::{HashSet, HashMap};
2 2
3use libsyntax2::{ 3use libsyntax2::{
4 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*, 4 File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*,
5 ast::{self, LoopBodyOwner}, 5 ast::{self, LoopBodyOwner, ModuleItemOwner},
6 algo::{ 6 algo::{
7 ancestors, 7 ancestors,
8 visit::{visitor, Visitor, visitor_ctx, VisitorCtx}, 8 visit::{visitor, Visitor, visitor_ctx, VisitorCtx},
@@ -58,22 +58,34 @@ fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<Completi
58 if !is_node::<ast::Path>(name_ref.syntax()) { 58 if !is_node::<ast::Path>(name_ref.syntax()) {
59 return; 59 return;
60 } 60 }
61 if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() { 61 let mut visited_fn = false;
62 complete_expr_keywords(&file, fn_def, name_ref, acc); 62 for node in ancestors(name_ref.syntax()) {
63 let scopes = FnScopes::new(fn_def); 63 if let Some(items) = visitor()
64 complete_fn(name_ref, &scopes, acc); 64 .visit::<ast::Root, _>(|it| Some(it.items()))
65 } 65 .visit::<ast::Module, _>(|it| Some(it.item_list()?.items()))
66 if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() { 66 .accept(node) {
67 let scope = ModuleScope::new(root); 67 if let Some(items) = items {
68 acc.extend( 68 let scope = ModuleScope::new(items);
69 scope.entries().iter() 69 acc.extend(
70 .filter(|entry| entry.syntax() != name_ref.syntax()) 70 scope.entries().iter()
71 .map(|entry| CompletionItem { 71 .filter(|entry| entry.syntax() != name_ref.syntax())
72 label: entry.name().to_string(), 72 .map(|entry| CompletionItem {
73 lookup: None, 73 label: entry.name().to_string(),
74 snippet: None, 74 lookup: None,
75 }) 75 snippet: None,
76 ); 76 })
77 );
78 }
79 break;
80
81 } else if !visited_fn {
82 if let Some(fn_def) = ast::FnDef::cast(node) {
83 visited_fn = true;
84 complete_expr_keywords(&file, fn_def, name_ref, acc);
85 let scopes = FnScopes::new(fn_def);
86 complete_fn(name_ref, &scopes, acc);
87 }
88 }
77 } 89 }
78} 90}
79 91
@@ -300,6 +312,18 @@ mod tests {
300 } 312 }
301 313
302 #[test] 314 #[test]
315 fn test_completion_mod_scope_nested() {
316 check_scope_completion(r"
317 struct Foo;
318 mod m {
319 struct Bar;
320 fn quux() { <|> }
321 }
322 ", r#"[CompletionItem { label: "Bar", lookup: None, snippet: None },
323 CompletionItem { label: "quux", lookup: None, snippet: None }]"#);
324 }
325
326 #[test]
303 fn test_complete_type() { 327 fn test_complete_type() {
304 check_scope_completion(r" 328 check_scope_completion(r"
305 struct Foo; 329 struct Foo;
diff --git a/crates/libeditor/src/scope/mod_scope.rs b/crates/libeditor/src/scope/mod_scope.rs
index 67baa8678..0ec56a206 100644
--- a/crates/libeditor/src/scope/mod_scope.rs
+++ b/crates/libeditor/src/scope/mod_scope.rs
@@ -1,5 +1,6 @@
1use libsyntax2::{ 1use libsyntax2::{
2 AstNode, SyntaxNode, SyntaxNodeRef, SmolStr, ast 2 AstNode, SyntaxNode, SyntaxNodeRef, SmolStr,
3 ast::{self, AstChildren},
3}; 4};
4 5
5pub struct ModuleScope { 6pub struct ModuleScope {
@@ -16,9 +17,9 @@ enum EntryKind {
16} 17}
17 18
18impl ModuleScope { 19impl ModuleScope {
19 pub fn new(m: ast::Root) -> ModuleScope { 20 pub fn new(items: AstChildren<ast::ModuleItem>) -> ModuleScope {
20 let mut entries = Vec::new(); 21 let mut entries = Vec::new();
21 for item in m.items() { 22 for item in items {
22 let entry = match item { 23 let entry = match item {
23 ast::ModuleItem::StructDef(item) => Entry::new(item), 24 ast::ModuleItem::StructDef(item) => Entry::new(item),
24 ast::ModuleItem::EnumDef(item) => Entry::new(item), 25 ast::ModuleItem::EnumDef(item) => Entry::new(item),
@@ -85,11 +86,11 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
85#[cfg(test)] 86#[cfg(test)]
86mod tests { 87mod tests {
87 use super::*; 88 use super::*;
88 use libsyntax2::File; 89 use libsyntax2::{File, ast::ModuleItemOwner};
89 90
90 fn do_check(code: &str, expected: &[&str]) { 91 fn do_check(code: &str, expected: &[&str]) {
91 let file = File::parse(&code); 92 let file = File::parse(&code);
92 let scope = ModuleScope::new(file.ast()); 93 let scope = ModuleScope::new(file.ast().items());
93 let actual = scope.entries 94 let actual = scope.entries
94 .iter() 95 .iter()
95 .map(|it| it.name()) 96 .map(|it| it.name())
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs
index a239f0630..c945c094a 100644
--- a/crates/libsyntax2/src/ast/generated.rs
+++ b/crates/libsyntax2/src/ast/generated.rs
@@ -699,11 +699,8 @@ impl<'a> AstNode<'a> for ItemList<'a> {
699} 699}
700 700
701impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {} 701impl<'a> ast::FnDefOwner<'a> for ItemList<'a> {}
702impl<'a> ItemList<'a> { 702impl<'a> ast::ModuleItemOwner<'a> for ItemList<'a> {}
703 pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { 703impl<'a> ItemList<'a> {}
704 super::children(self)
705 }
706}
707 704
708// Label 705// Label
709#[derive(Debug, Clone, Copy)] 706#[derive(Debug, Clone, Copy)]
@@ -979,7 +976,6 @@ impl<'a> AstNode<'a> for Module<'a> {
979 976
980impl<'a> ast::NameOwner<'a> for Module<'a> {} 977impl<'a> ast::NameOwner<'a> for Module<'a> {}
981impl<'a> ast::AttrsOwner<'a> for Module<'a> {} 978impl<'a> ast::AttrsOwner<'a> for Module<'a> {}
982impl<'a> ast::FnDefOwner<'a> for Module<'a> {}
983impl<'a> Module<'a> {pub fn item_list(self) -> Option<ItemList<'a>> { 979impl<'a> Module<'a> {pub fn item_list(self) -> Option<ItemList<'a>> {
984 super::child_opt(self) 980 super::child_opt(self)
985 } 981 }
@@ -1616,12 +1612,9 @@ impl<'a> AstNode<'a> for Root<'a> {
1616 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 1612 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1617} 1613}
1618 1614
1615impl<'a> ast::ModuleItemOwner<'a> for Root<'a> {}
1619impl<'a> ast::FnDefOwner<'a> for Root<'a> {} 1616impl<'a> ast::FnDefOwner<'a> for Root<'a> {}
1620impl<'a> Root<'a> { 1617impl<'a> Root<'a> {
1621 pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a {
1622 super::children(self)
1623 }
1624
1625 pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a { 1618 pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a {
1626 super::children(self) 1619 super::children(self)
1627 } 1620 }
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs
index 0b6868547..a6da82957 100644
--- a/crates/libsyntax2/src/ast/mod.rs
+++ b/crates/libsyntax2/src/ast/mod.rs
@@ -36,7 +36,13 @@ pub trait ArgListOwner<'a>: AstNode<'a> {
36} 36}
37 37
38pub trait FnDefOwner<'a>: AstNode<'a> { 38pub trait FnDefOwner<'a>: AstNode<'a> {
39 fn functions(self) -> AstNodeChildren<'a, FnDef<'a>> { 39 fn functions(self) -> AstChildren<'a, FnDef<'a>> {
40 children(self)
41 }
42}
43
44pub trait ModuleItemOwner<'a>: AstNode<'a> {
45 fn items(self) -> AstChildren<'a, ModuleItem<'a>> {
40 children(self) 46 children(self)
41 } 47 }
42} 48}
@@ -52,7 +58,7 @@ pub trait TypeParamsOwner<'a>: AstNode<'a> {
52} 58}
53 59
54pub trait AttrsOwner<'a>: AstNode<'a> { 60pub trait AttrsOwner<'a>: AstNode<'a> {
55 fn attrs(self) -> AstNodeChildren<'a, Attr<'a>> { 61 fn attrs(self) -> AstChildren<'a, Attr<'a>> {
56 children(self) 62 children(self)
57 } 63 }
58} 64}
@@ -158,7 +164,7 @@ impl<'a> IfExpr<'a> {
158 pub fn else_branch(self) -> Option<Block<'a>> { 164 pub fn else_branch(self) -> Option<Block<'a>> {
159 self.blocks().nth(1) 165 self.blocks().nth(1)
160 } 166 }
161 fn blocks(self) -> AstNodeChildren<'a, Block<'a>> { 167 fn blocks(self) -> AstChildren<'a, Block<'a>> {
162 children(self) 168 children(self)
163 } 169 }
164} 170}
@@ -167,27 +173,27 @@ fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
167 children(parent).next() 173 children(parent).next()
168} 174}
169 175
170fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstNodeChildren<'a, C> { 176fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstChildren<'a, C> {
171 AstNodeChildren::new(parent.syntax()) 177 AstChildren::new(parent.syntax())
172} 178}
173 179
174 180
175#[derive(Debug)] 181#[derive(Debug)]
176pub struct AstNodeChildren<'a, N> { 182pub struct AstChildren<'a, N> {
177 inner: SyntaxNodeChildren<RefRoot<'a>>, 183 inner: SyntaxNodeChildren<RefRoot<'a>>,
178 ph: PhantomData<N>, 184 ph: PhantomData<N>,
179} 185}
180 186
181impl<'a, N> AstNodeChildren<'a, N> { 187impl<'a, N> AstChildren<'a, N> {
182 fn new(parent: SyntaxNodeRef<'a>) -> Self { 188 fn new(parent: SyntaxNodeRef<'a>) -> Self {
183 AstNodeChildren { 189 AstChildren {
184 inner: parent.children(), 190 inner: parent.children(),
185 ph: PhantomData, 191 ph: PhantomData,
186 } 192 }
187 } 193 }
188} 194}
189 195
190impl<'a, N: AstNode<'a>> Iterator for AstNodeChildren<'a, N> { 196impl<'a, N: AstNode<'a>> Iterator for AstChildren<'a, N> {
191 type Item = N; 197 type Item = N;
192 fn next(&mut self) -> Option<N> { 198 fn next(&mut self) -> Option<N> {
193 loop { 199 loop {
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron
index 6ed658daa..77ae4c7db 100644
--- a/crates/libsyntax2/src/grammar.ron
+++ b/crates/libsyntax2/src/grammar.ron
@@ -238,9 +238,8 @@ Grammar(
238 ], 238 ],
239 ast: { 239 ast: {
240 "Root": ( 240 "Root": (
241 traits: [ "FnDefOwner" ], 241 traits: [ "ModuleItemOwner", "FnDefOwner" ],
242 collections: [ 242 collections: [
243 ["items", "ModuleItem"],
244 ["modules", "Module"], 243 ["modules", "Module"],
245 ] 244 ]
246 ), 245 ),
@@ -271,12 +270,11 @@ Grammar(
271 ] ), 270 ] ),
272 "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ), 271 "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ),
273 "Module": ( 272 "Module": (
274 traits: ["NameOwner", "AttrsOwner", "FnDefOwner" ], 273 traits: ["NameOwner", "AttrsOwner" ],
275 options: [ "ItemList" ] 274 options: [ "ItemList" ]
276 ), 275 ),
277 "ItemList": ( 276 "ItemList": (
278 traits: [ "FnDefOwner" ], 277 traits: [ "FnDefOwner", "ModuleItemOwner" ],
279 collections: [ ["items", "ModuleItem"] ]
280 ), 278 ),
281 "ConstDef": ( traits: [ 279 "ConstDef": ( traits: [
282 "NameOwner", 280 "NameOwner",