14
pub fn analyze(ast: &Program) -> ScopeManager {
15
let mut analyzer = Analyzer::new(ast);
16
analyzer.visit_program(ast);
17
- analyzer.manager
17
+ analyzer.complete()
18
}
19
20
struct Analyzer {
21
manager: ScopeManager,
22
labels: Vec<LabelId>,
23
current: ScopeId,
24
+ unresolved: Vec<UnresolvedReference>,
25
+}
26
+
27
+#[derive(Debug, Clone)]
28
+pub struct UnresolvedReference {
29
+ pub scope: ScopeId,
30
+ pub ast: AstNode,
31
+ pub name: String,
32
+ pub kind: ReferenceKind,
33
+ pub range: Option<SourceRange>,
34
}
35
36
impl Analyzer {
42
manager,
43
labels,
44
current,
45
+ unresolved: Default::default(),
46
}
47
}
48
49
+ fn complete(mut self) -> ScopeManager {
50
+ for reference in self.unresolved {
51
+ if let Some(declaration) = self
52
+ .manager
53
+ .lookup_declaration(reference.scope, &reference.name)
54
+ {
55
+ let id =
56
+ self.manager
57
+ .add_reference(reference.scope, reference.kind, declaration.id);
58
+ self.manager.node_references.insert(reference.ast, id);
59
+ } else {
60
+ self.manager.diagnostics.push(Diagnostic::invalid_syntax(
61
+ "Undefined variable",
62
+ reference.range,
63
+ ));
64
+ }
65
+ }
66
+ self.manager
67
+ }
68
+
69
fn enter_label<F>(&mut self, id: LabelId, mut f: F)
70
where
71
F: FnMut(&mut Self) -> (),
134
assert_eq!(self.current, id, "Mismatched enter_scope/close_scope");
135
let scope = self.manager.mut_scope(self.current);
136
let parent = scope.parent.unwrap();
106
- let unresolved = std::mem::take(&mut scope.unresolved);
107
- drop(scope);
137
self.current = parent;
109
-
110
- // Lookup unresolved nodes from the child scope in the (now-current) parent scope
111
- for reference in unresolved {
112
- if let Some(declaration) = self
113
- .manager
114
- .lookup_declaration(reference.scope, &reference.name)
115
- {
116
- let id =
117
- self.manager
118
- .add_reference(reference.scope, reference.kind, declaration.id);
119
- self.manager.node_references.insert(reference.ast, id);
120
- } else {
121
- self.manager.push_unresolved_reference(parent, reference);
122
- }
123
- }
138
}
139
140
fn visit_function<T: IntoFunction>(&mut self, node: &T) {
182
kind: ReferenceKind,
183
range: Option<SourceRange>,
184
) {
171
- self.manager
172
- .add_unresolved_reference(self.current, ast, name.to_string(), kind, range);
185
+ self.unresolved.push(UnresolvedReference {
186
+ scope: self.current,
187
+ ast,
188
+ name: name.to_string(),
189
+ kind,
190
+ range,
191
+ });
192
}
193
194
fn visit_declaration_identifier(
218
.insert(AstNode::from(ast), id);
219
} else {
220
// Re-assigning a variable
202
- self.manager.add_unresolved_reference(
203
- self.current,
204
- AstNode::from(ast),
205
- ast.name.to_string(),
206
- ReferenceKind::Write,
207
- ast.range,
208
- );
221
+ self.unresolved.push(UnresolvedReference {
222
+ scope: self.current,
223
+ ast: AstNode::from(ast),
224
+ name: ast.name.to_string(),
225
+ kind: ReferenceKind::Write,
226
+ range: ast.range,
227
+ });
228
}
229
}
230
661
)
662
}
663
645
- fn visit_program(&mut self, ast: &forget_estree::Program) {
646
- for item in &ast.body {
647
- self.visit_module_item(item);
648
- }
649
- let scope = self.manager.mut_scope(self.current);
650
- let unresolved = std::mem::take(&mut scope.unresolved);
651
- for reference in unresolved {
652
- if let Some(declaration) = self
653
- .manager
654
- .lookup_declaration(reference.scope, &reference.name)
655
- {
656
- let id =
657
- self.manager
658
- .add_reference(reference.scope, reference.kind, declaration.id);
659
- self.manager.node_references.insert(reference.ast, id);
660
- } else {
661
- self.manager.diagnostics.push(Diagnostic::invalid_syntax(
662
- "Undefined variable",
663
- reference.range,
664
- ));
665
- }
666
- }
667
- }
668
-
664
fn visit_property(&mut self, ast: &forget_estree::Property) {
665
if ast.is_computed {
666
self.visit_expression(&ast.key);