aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-28 16:22:52 +0100
committerAleksey Kladov <[email protected]>2018-08-28 16:22:59 +0100
commitd34588bf83898870d7f9b4b49ac2a5f71c77dabb (patch)
treea0b6eb7b41cb586d1c10e408a4791edf7c341a1f /crates/libeditor/src
parent748a4cacd24d9ecdca995e66117a10a1562e7d5d (diff)
create module smartly
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r--crates/libeditor/src/scope/fn_scope.rs (renamed from crates/libeditor/src/scope.rs)178
-rw-r--r--crates/libeditor/src/scope/mod.rs3
2 files changed, 92 insertions, 89 deletions
diff --git a/crates/libeditor/src/scope.rs b/crates/libeditor/src/scope/fn_scope.rs
index 3d398a74c..e807c6c71 100644
--- a/crates/libeditor/src/scope.rs
+++ b/crates/libeditor/src/scope/fn_scope.rs
@@ -9,6 +9,95 @@ use libsyntax2::{
9 algo::{ancestors, generate, walk::preorder} 9 algo::{ancestors, generate, walk::preorder}
10}; 10};
11 11
12type ScopeId = usize;
13
14#[derive(Debug)]
15pub struct FnScopes {
16 scopes: Vec<ScopeData>,
17 scope_for: HashMap<SyntaxNode, ScopeId>,
18}
19
20impl FnScopes {
21 pub fn new(fn_def: ast::FnDef) -> FnScopes {
22 let mut scopes = FnScopes {
23 scopes: Vec::new(),
24 scope_for: HashMap::new()
25 };
26 let root = scopes.root_scope();
27 fn_def.param_list().into_iter()
28 .flat_map(|it| it.params())
29 .filter_map(|it| it.pat())
30 .for_each(|it| scopes.add_bindings(root, it));
31
32 if let Some(body) = fn_def.body() {
33 compute_block_scopes(body, &mut scopes, root)
34 }
35 scopes
36 }
37 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
38 &self.scopes[scope].entries
39 }
40 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item=ScopeId> + 'a {
41 generate(self.scope_for(node), move |&scope| self.scopes[scope].parent)
42 }
43 fn root_scope(&mut self) -> ScopeId {
44 let res = self.scopes.len();
45 self.scopes.push(ScopeData { parent: None, entries: vec![] });
46 res
47 }
48 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
49 let res = self.scopes.len();
50 self.scopes.push(ScopeData { parent: Some(parent), entries: vec![] });
51 res
52 }
53 fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) {
54 let entries = preorder(pat.syntax())
55 .filter_map(ast::BindPat::cast)
56 .filter_map(ScopeEntry::new);
57 self.scopes[scope].entries.extend(entries);
58 }
59 fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) {
60 self.scope_for.insert(node.owned(), scope);
61 }
62 fn scope_for(&self, node: SyntaxNodeRef) -> Option<ScopeId> {
63 ancestors(node)
64 .filter_map(|it| self.scope_for.get(&it.owned()).map(|&scope| scope))
65 .next()
66 }
67}
68
69pub struct ScopeEntry {
70 syntax: SyntaxNode
71}
72
73impl ScopeEntry {
74 fn new(pat: ast::BindPat) -> Option<ScopeEntry> {
75 if pat.name().is_some() {
76 Some(ScopeEntry { syntax: pat.syntax().owned() })
77 } else {
78 None
79 }
80 }
81 pub fn name(&self) -> SmolStr {
82 self.ast().name()
83 .unwrap()
84 .text()
85 }
86 fn ast(&self) -> ast::BindPat {
87 ast::BindPat::cast(self.syntax.borrowed())
88 .unwrap()
89 }
90}
91
92impl fmt::Debug for ScopeEntry {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 f.debug_struct("ScopeEntry")
95 .field("name", &self.name())
96 .field("syntax", &self.syntax)
97 .finish()
98 }
99}
100
12fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) { 101fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) {
13 for stmt in block.statements() { 102 for stmt in block.statements() {
14 match stmt { 103 match stmt {
@@ -95,97 +184,8 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) {
95 } 184 }
96} 185}
97 186
98type ScopeId = usize;
99
100#[derive(Debug)]
101pub struct FnScopes {
102 scopes: Vec<ScopeData>,
103 scope_for: HashMap<SyntaxNode, ScopeId>,
104}
105
106impl FnScopes {
107 pub fn new(fn_def: ast::FnDef) -> FnScopes {
108 let mut scopes = FnScopes {
109 scopes: Vec::new(),
110 scope_for: HashMap::new()
111 };
112 let root = scopes.root_scope();
113 fn_def.param_list().into_iter()
114 .flat_map(|it| it.params())
115 .filter_map(|it| it.pat())
116 .for_each(|it| scopes.add_bindings(root, it));
117
118 if let Some(body) = fn_def.body() {
119 compute_block_scopes(body, &mut scopes, root)
120 }
121 scopes
122 }
123 pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
124 &self.scopes[scope].entries
125 }
126 pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item=ScopeId> + 'a {
127 generate(self.scope_for(node), move |&scope| self.scopes[scope].parent)
128 }
129 fn root_scope(&mut self) -> ScopeId {
130 let res = self.scopes.len();
131 self.scopes.push(ScopeData { parent: None, entries: vec![] });
132 res
133 }
134 fn new_scope(&mut self, parent: ScopeId) -> ScopeId {
135 let res = self.scopes.len();
136 self.scopes.push(ScopeData { parent: Some(parent), entries: vec![] });
137 res
138 }
139 fn add_bindings(&mut self, scope: ScopeId, pat: ast::Pat) {
140 let entries = preorder(pat.syntax())
141 .filter_map(ast::BindPat::cast)
142 .filter_map(ScopeEntry::new);
143 self.scopes[scope].entries.extend(entries);
144 }
145 fn set_scope(&mut self, node: SyntaxNodeRef, scope: ScopeId) {
146 self.scope_for.insert(node.owned(), scope);
147 }
148 fn scope_for(&self, node: SyntaxNodeRef) -> Option<ScopeId> {
149 ancestors(node)
150 .filter_map(|it| self.scope_for.get(&it.owned()).map(|&scope| scope))
151 .next()
152 }
153}
154
155#[derive(Debug)] 187#[derive(Debug)]
156struct ScopeData { 188struct ScopeData {
157 parent: Option<ScopeId>, 189 parent: Option<ScopeId>,
158 entries: Vec<ScopeEntry> 190 entries: Vec<ScopeEntry>
159} 191}
160
161pub struct ScopeEntry {
162 syntax: SyntaxNode
163}
164
165impl ScopeEntry {
166 fn new(pat: ast::BindPat) -> Option<ScopeEntry> {
167 if pat.name().is_some() {
168 Some(ScopeEntry { syntax: pat.syntax().owned() })
169 } else {
170 None
171 }
172 }
173 pub fn name(&self) -> SmolStr {
174 self.ast().name()
175 .unwrap()
176 .text()
177 }
178 fn ast(&self) -> ast::BindPat {
179 ast::BindPat::cast(self.syntax.borrowed())
180 .unwrap()
181 }
182}
183
184impl fmt::Debug for ScopeEntry {
185 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 f.debug_struct("ScopeEntry")
187 .field("name", &self.name())
188 .field("syntax", &self.syntax)
189 .finish()
190 }
191}
diff --git a/crates/libeditor/src/scope/mod.rs b/crates/libeditor/src/scope/mod.rs
new file mode 100644
index 000000000..1a77a8b6e
--- /dev/null
+++ b/crates/libeditor/src/scope/mod.rs
@@ -0,0 +1,3 @@
1mod fn_scope;
2
3pub use self::fn_scope::FnScopes;