diff options
author | Aleksey Kladov <[email protected]> | 2018-08-30 18:37:33 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-30 18:37:33 +0100 |
commit | 80ab3433d3376b7c44787d63af6e7b3217ae41d8 (patch) | |
tree | acd067ca08c5155521444d3975f8ba016bcc8424 | |
parent | 49e14a99ed4d0baf849bbd5766f6c16e7d37930c (diff) |
complete imports
-rw-r--r-- | crates/libeditor/src/scope/mod_scope.rs | 88 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs | 85 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 26 |
3 files changed, 180 insertions, 19 deletions
diff --git a/crates/libeditor/src/scope/mod_scope.rs b/crates/libeditor/src/scope/mod_scope.rs index aa8dd93a7..25faee3b8 100644 --- a/crates/libeditor/src/scope/mod_scope.rs +++ b/crates/libeditor/src/scope/mod_scope.rs | |||
@@ -6,21 +6,38 @@ pub struct ModuleScope { | |||
6 | entries: Vec<Entry>, | 6 | entries: Vec<Entry>, |
7 | } | 7 | } |
8 | 8 | ||
9 | pub struct Entry { | ||
10 | node: SyntaxNode, | ||
11 | kind: EntryKind, | ||
12 | } | ||
13 | |||
14 | enum EntryKind { | ||
15 | Item, Import, | ||
16 | } | ||
17 | |||
9 | impl ModuleScope { | 18 | impl ModuleScope { |
10 | pub fn new(m: ast::Root) -> ModuleScope { | 19 | pub fn new(m: ast::Root) -> ModuleScope { |
11 | let entries = m.items().filter_map(|item| { | 20 | let mut entries = Vec::new(); |
12 | match item { | 21 | for item in m.items() { |
22 | let entry = match item { | ||
13 | ast::ModuleItem::StructDef(item) => Entry::new(item), | 23 | ast::ModuleItem::StructDef(item) => Entry::new(item), |
14 | ast::ModuleItem::EnumDef(item) => Entry::new(item), | 24 | ast::ModuleItem::EnumDef(item) => Entry::new(item), |
15 | ast::ModuleItem::FnDef(item) => Entry::new(item), | 25 | ast::ModuleItem::FnDef(item) => Entry::new(item), |
16 | ast::ModuleItem::ConstDef(item) => Entry::new(item), | 26 | ast::ModuleItem::ConstDef(item) => Entry::new(item), |
17 | ast::ModuleItem::StaticDef(item) => Entry::new(item), | 27 | ast::ModuleItem::StaticDef(item) => Entry::new(item), |
18 | ast::ModuleItem::TraitDef(item) => Entry::new(item), | 28 | ast::ModuleItem::TraitDef(item) => Entry::new(item), |
29 | ast::ModuleItem::Module(item) => Entry::new(item), | ||
30 | ast::ModuleItem::UseItem(item) => { | ||
31 | if let Some(tree) = item.use_tree() { | ||
32 | collect_imports(tree, &mut entries); | ||
33 | } | ||
34 | continue; | ||
35 | }, | ||
19 | ast::ModuleItem::ExternCrateItem(_) | | 36 | ast::ModuleItem::ExternCrateItem(_) | |
20 | ast::ModuleItem::ImplItem(_) | | 37 | ast::ModuleItem::ImplItem(_) => continue, |
21 | ast::ModuleItem::UseItem(_) => None | 38 | }; |
22 | } | 39 | entries.extend(entry) |
23 | }).collect(); | 40 | } |
24 | 41 | ||
25 | ModuleScope { entries } | 42 | ModuleScope { entries } |
26 | } | 43 | } |
@@ -30,20 +47,63 @@ impl ModuleScope { | |||
30 | } | 47 | } |
31 | } | 48 | } |
32 | 49 | ||
33 | pub struct Entry { | ||
34 | name: SyntaxNode, | ||
35 | } | ||
36 | |||
37 | impl Entry { | 50 | impl Entry { |
38 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> { | 51 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> { |
39 | let name = item.name()?; | 52 | let name = item.name()?; |
40 | Some(Entry { name: name.syntax().owned() }) | 53 | Some(Entry { node: name.syntax().owned(), kind: EntryKind::Item }) |
54 | } | ||
55 | fn new_import(path: ast::Path) -> Option<Entry> { | ||
56 | let name_ref = path.segment()?.name_ref()?; | ||
57 | Some(Entry { node: name_ref.syntax().owned(), kind: EntryKind::Import }) | ||
41 | } | 58 | } |
42 | pub fn name(&self) -> SmolStr { | 59 | pub fn name(&self) -> SmolStr { |
43 | self.ast().text() | 60 | match self.kind { |
61 | EntryKind::Item => | ||
62 | ast::Name::cast(self.node.borrowed()).unwrap() | ||
63 | .text(), | ||
64 | EntryKind::Import => | ||
65 | ast::NameRef::cast(self.node.borrowed()).unwrap() | ||
66 | .text(), | ||
67 | } | ||
44 | } | 68 | } |
45 | fn ast(&self) -> ast::Name { | 69 | } |
46 | ast::Name::cast(self.name.borrowed()).unwrap() | 70 | |
71 | fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) { | ||
72 | if let Some(use_tree_list) = tree.use_tree_list() { | ||
73 | return use_tree_list.use_trees().for_each(|it| collect_imports(it, acc)); | ||
74 | } | ||
75 | if let Some(path) = tree.path() { | ||
76 | acc.extend(Entry::new_import(path)); | ||
47 | } | 77 | } |
48 | } | 78 | } |
49 | 79 | ||
80 | |||
81 | #[cfg(test)] | ||
82 | mod tests { | ||
83 | use super::*; | ||
84 | use libsyntax2::File; | ||
85 | |||
86 | fn do_check(code: &str, expected: &[&str]) { | ||
87 | let file = File::parse(&code); | ||
88 | let scope = ModuleScope::new(file.ast()); | ||
89 | let actual = scope.entries | ||
90 | .iter() | ||
91 | .map(|it| it.name()) | ||
92 | .collect::<Vec<_>>(); | ||
93 | assert_eq!(expected, actual.as_slice()); | ||
94 | } | ||
95 | |||
96 | #[test] | ||
97 | fn test_module_scope() { | ||
98 | do_check(" | ||
99 | struct Foo; | ||
100 | enum Bar {} | ||
101 | mod baz {} | ||
102 | fn quux() {} | ||
103 | use x::{ | ||
104 | y::z, | ||
105 | t, | ||
106 | }; | ||
107 | ", &["Foo", "Bar", "baz", "quux", "z", "t"]) | ||
108 | } | ||
109 | } | ||
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index c2a22c8fc..1bb3b11d1 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -977,6 +977,7 @@ pub enum ModuleItem<'a> { | |||
977 | ExternCrateItem(ExternCrateItem<'a>), | 977 | ExternCrateItem(ExternCrateItem<'a>), |
978 | ConstDef(ConstDef<'a>), | 978 | ConstDef(ConstDef<'a>), |
979 | StaticDef(StaticDef<'a>), | 979 | StaticDef(StaticDef<'a>), |
980 | Module(Module<'a>), | ||
980 | } | 981 | } |
981 | 982 | ||
982 | impl<'a> AstNode<'a> for ModuleItem<'a> { | 983 | impl<'a> AstNode<'a> for ModuleItem<'a> { |
@@ -991,6 +992,7 @@ impl<'a> AstNode<'a> for ModuleItem<'a> { | |||
991 | EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })), | 992 | EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })), |
992 | CONST_DEF => Some(ModuleItem::ConstDef(ConstDef { syntax })), | 993 | CONST_DEF => Some(ModuleItem::ConstDef(ConstDef { syntax })), |
993 | STATIC_DEF => Some(ModuleItem::StaticDef(StaticDef { syntax })), | 994 | STATIC_DEF => Some(ModuleItem::StaticDef(StaticDef { syntax })), |
995 | MODULE => Some(ModuleItem::Module(Module { syntax })), | ||
994 | _ => None, | 996 | _ => None, |
995 | } | 997 | } |
996 | } | 998 | } |
@@ -1005,6 +1007,7 @@ impl<'a> AstNode<'a> for ModuleItem<'a> { | |||
1005 | ModuleItem::ExternCrateItem(inner) => inner.syntax(), | 1007 | ModuleItem::ExternCrateItem(inner) => inner.syntax(), |
1006 | ModuleItem::ConstDef(inner) => inner.syntax(), | 1008 | ModuleItem::ConstDef(inner) => inner.syntax(), |
1007 | ModuleItem::StaticDef(inner) => inner.syntax(), | 1009 | ModuleItem::StaticDef(inner) => inner.syntax(), |
1010 | ModuleItem::Module(inner) => inner.syntax(), | ||
1008 | } | 1011 | } |
1009 | } | 1012 | } |
1010 | } | 1013 | } |
@@ -1294,7 +1297,11 @@ impl<'a> AstNode<'a> for Path<'a> { | |||
1294 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | 1297 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } |
1295 | } | 1298 | } |
1296 | 1299 | ||
1297 | impl<'a> Path<'a> {} | 1300 | impl<'a> Path<'a> { |
1301 | pub fn segment(self) -> Option<PathSegment<'a>> { | ||
1302 | super::child_opt(self) | ||
1303 | } | ||
1304 | } | ||
1298 | 1305 | ||
1299 | // PathExpr | 1306 | // PathExpr |
1300 | #[derive(Debug, Clone, Copy)] | 1307 | #[derive(Debug, Clone, Copy)] |
@@ -1332,6 +1339,28 @@ impl<'a> AstNode<'a> for PathPat<'a> { | |||
1332 | 1339 | ||
1333 | impl<'a> PathPat<'a> {} | 1340 | impl<'a> PathPat<'a> {} |
1334 | 1341 | ||
1342 | // PathSegment | ||
1343 | #[derive(Debug, Clone, Copy)] | ||
1344 | pub struct PathSegment<'a> { | ||
1345 | syntax: SyntaxNodeRef<'a>, | ||
1346 | } | ||
1347 | |||
1348 | impl<'a> AstNode<'a> for PathSegment<'a> { | ||
1349 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
1350 | match syntax.kind() { | ||
1351 | PATH_SEGMENT => Some(PathSegment { syntax }), | ||
1352 | _ => None, | ||
1353 | } | ||
1354 | } | ||
1355 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
1356 | } | ||
1357 | |||
1358 | impl<'a> PathSegment<'a> { | ||
1359 | pub fn name_ref(self) -> Option<NameRef<'a>> { | ||
1360 | super::child_opt(self) | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1335 | // PathType | 1364 | // PathType |
1336 | #[derive(Debug, Clone, Copy)] | 1365 | #[derive(Debug, Clone, Copy)] |
1337 | pub struct PathType<'a> { | 1366 | pub struct PathType<'a> { |
@@ -1989,7 +2018,59 @@ impl<'a> AstNode<'a> for UseItem<'a> { | |||
1989 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | 2018 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } |
1990 | } | 2019 | } |
1991 | 2020 | ||
1992 | impl<'a> UseItem<'a> {} | 2021 | impl<'a> UseItem<'a> { |
2022 | pub fn use_tree(self) -> Option<UseTree<'a>> { | ||
2023 | super::child_opt(self) | ||
2024 | } | ||
2025 | } | ||
2026 | |||
2027 | // UseTree | ||
2028 | #[derive(Debug, Clone, Copy)] | ||
2029 | pub struct UseTree<'a> { | ||
2030 | syntax: SyntaxNodeRef<'a>, | ||
2031 | } | ||
2032 | |||
2033 | impl<'a> AstNode<'a> for UseTree<'a> { | ||
2034 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
2035 | match syntax.kind() { | ||
2036 | USE_TREE => Some(UseTree { syntax }), | ||
2037 | _ => None, | ||
2038 | } | ||
2039 | } | ||
2040 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
2041 | } | ||
2042 | |||
2043 | impl<'a> UseTree<'a> { | ||
2044 | pub fn path(self) -> Option<Path<'a>> { | ||
2045 | super::child_opt(self) | ||
2046 | } | ||
2047 | |||
2048 | pub fn use_tree_list(self) -> Option<UseTreeList<'a>> { | ||
2049 | super::child_opt(self) | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | // UseTreeList | ||
2054 | #[derive(Debug, Clone, Copy)] | ||
2055 | pub struct UseTreeList<'a> { | ||
2056 | syntax: SyntaxNodeRef<'a>, | ||
2057 | } | ||
2058 | |||
2059 | impl<'a> AstNode<'a> for UseTreeList<'a> { | ||
2060 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
2061 | match syntax.kind() { | ||
2062 | USE_TREE_LIST => Some(UseTreeList { syntax }), | ||
2063 | _ => None, | ||
2064 | } | ||
2065 | } | ||
2066 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
2067 | } | ||
2068 | |||
2069 | impl<'a> UseTreeList<'a> { | ||
2070 | pub fn use_trees(self) -> impl Iterator<Item = UseTree<'a>> + 'a { | ||
2071 | super::children(self) | ||
2072 | } | ||
2073 | } | ||
1993 | 2074 | ||
1994 | // WhereClause | 2075 | // WhereClause |
1995 | #[derive(Debug, Clone, Copy)] | 2076 | #[derive(Debug, Clone, Copy)] |
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index 0bb40f5ab..8267c2854 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -337,7 +337,7 @@ Grammar( | |||
337 | ), | 337 | ), |
338 | "ModuleItem": ( | 338 | "ModuleItem": ( |
339 | enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "ImplItem", | 339 | enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "ImplItem", |
340 | "UseItem", "ExternCrateItem", "ConstDef", "StaticDef" ] | 340 | "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ] |
341 | ), | 341 | ), |
342 | 342 | ||
343 | "TupleExpr": (), | 343 | "TupleExpr": (), |
@@ -507,13 +507,33 @@ Grammar( | |||
507 | "Param": ( | 507 | "Param": ( |
508 | options: [["pat", "Pat"]], | 508 | options: [["pat", "Pat"]], |
509 | ), | 509 | ), |
510 | "UseItem": (), | 510 | "UseItem": ( |
511 | options: [["use_tree", "UseTree"]] | ||
512 | ), | ||
513 | "UseTree": ( | ||
514 | options: [ | ||
515 | ["path", "Path"], | ||
516 | ["use_tree_list", "UseTreeList"], | ||
517 | ] | ||
518 | ), | ||
519 | "UseTreeList": ( | ||
520 | collections: [["use_trees", "UseTree"]] | ||
521 | ), | ||
511 | "ExternCrateItem": (), | 522 | "ExternCrateItem": (), |
512 | "ArgList": ( | 523 | "ArgList": ( |
513 | collections: [ | 524 | collections: [ |
514 | ["args", "Expr"] | 525 | ["args", "Expr"] |
515 | ] | 526 | ] |
516 | ), | 527 | ), |
517 | "Path": (), | 528 | "Path": ( |
529 | options: [ | ||
530 | ["segment", "PathSegment"] | ||
531 | ] | ||
532 | ), | ||
533 | "PathSegment": ( | ||
534 | options: [ | ||
535 | ["name_ref", "NameRef"] | ||
536 | ] | ||
537 | ), | ||
518 | }, | 538 | }, |
519 | ) | 539 | ) |