[rust][sema] Only create one scope per function/class
Fixes up function and class handling to not create nested scopes in some cases. Doesn't affect name resolution otherwise.
Joe Savona committed
Aug 17, 2023 at 10:03 UTC
3ce41169303eceb47b4a5147e8fceeea23a145e8
3 files changed
+142
-144
compiler/forget/crates/forget_semantic_analysis/src/analyzer.rs
+72
-53
@@ -149,53 +149,49 @@ impl Analyzer {
149
}
150
151
fn visit_function<T: IntoFunction>(&mut self, node: &T) {
152
+ assert_eq!(self.manager.scope(self.current).kind, ScopeKind::Function);
153
let function = node.function();
153
- let scope = self.enter(ScopeKind::Function, |visitor| {
154
- for param in &function.params {
155
- // `this` parameters don't declare variables, nor can they have
156
- // default values
157
- if let Pattern::Identifier(param) = param {
158
- if ¶m.name == "this" {
159
- continue;
160
- }
154
+ for param in &function.params {
155
+ // `this` parameters don't declare variables, nor can they have
156
+ // default values
157
+ if let Pattern::Identifier(param) = param {
158
+ if ¶m.name == "this" {
159
+ continue;
160
}
162
- Analyzer::visit_declaration_pattern(
163
- visitor,
164
- param,
165
- Some(DeclarationKind::Function),
166
- );
161
}
162
+ Analyzer::visit_declaration_pattern(self, param, Some(DeclarationKind::Function));
163
+ }
164
169
- if let Some(body) = &function.body {
170
- match body {
171
- FunctionBody::BlockStatement(body) => {
172
- // Skip calling visit_block_statement to avoid creating an extra
173
- // block scope
174
- for item in &body.body {
175
- visitor.visit_statement(item);
176
- }
177
- }
178
- FunctionBody::Expression(body) => {
179
- visitor.visit_expression(body);
165
+ if let Some(body) = &function.body {
166
+ match body {
167
+ FunctionBody::BlockStatement(body) => {
168
+ // Skip calling visit_block_statement to avoid creating an extra
169
+ // block scope
170
+ for item in &body.body {
171
+ self.visit_statement(item);
172
}
173
}
174
+ FunctionBody::Expression(body) => {
175
+ self.visit_expression(body);
176
+ }
177
}
183
- });
178
+ }
179
self.manager
180
.node_scopes
186
- .insert(AstNode::from(function), scope);
181
+ .insert(AstNode::from(function), self.current);
182
}
183
184
fn visit_class<T: IntoClass>(&mut self, node: &T) {
185
+ assert_eq!(self.manager.scope(self.current).kind, ScopeKind::Class);
186
let class = node.class();
191
- let scope = self.enter(ScopeKind::Class, |visitor| {
192
- if let Some(super_class) = &class.super_class {
193
- visitor.visit_expression(super_class);
194
- }
187
+ if let Some(super_class) = &class.super_class {
188
+ self.visit_expression(super_class);
189
+ }
190
196
- visitor.visit_class_body(&class.body);
197
- });
198
- self.manager.node_scopes.insert(AstNode::from(class), scope);
191
+ self.visit_class_body(&class.body);
192
+ self.manager
193
+ .node_scopes
194
+ .insert(AstNode::from(class), self.current);
195
}
196
197
fn visit_reference_identifier(
@@ -361,7 +357,28 @@ impl Visitor for Analyzer {
357
.node_declarations
358
.insert(AstNode::from(id), declaration);
359
}
364
- Analyzer::visit_class(self, ast);
360
+ self.enter(ScopeKind::Class, |visitor| {
361
+ Analyzer::visit_class(visitor, ast);
362
+ });
363
+ }
364
+
365
+ fn visit_class_expression(&mut self, ast: &forget_estree::ClassExpression) {
366
+ self.enter(ScopeKind::Class, |visitor| {
367
+ if let Some(id) = &ast.class.id {
368
+ let declaration = visitor.manager.add_declaration(
369
+ visitor.current,
370
+ id.name.clone(),
371
+ DeclarationKind::Function,
372
+ id.range,
373
+ );
374
+ visitor
375
+ .manager
376
+ .node_declarations
377
+ .insert(AstNode::from(id), declaration);
378
+ }
379
+
380
+ Analyzer::visit_class(visitor, ast);
381
+ });
382
}
383
384
fn visit_class_property(&mut self, ast: &forget_estree::ClassProperty) {
@@ -419,32 +436,34 @@ impl Visitor for Analyzer {
436
.node_declarations
437
.insert(AstNode::from(id), declaration);
438
}
422
- Analyzer::visit_function(self, ast);
439
+ self.enter(ScopeKind::Function, |visitor| {
440
+ Analyzer::visit_function(visitor, ast);
441
+ });
442
}
443
444
fn visit_function_expression(&mut self, ast: &forget_estree::FunctionExpression) {
426
- let mut function_scope: Option<ScopeId> = None;
427
- if let Some(id) = &ast.function.id {
428
- function_scope = Some(self.enter_scope(ScopeKind::Function));
429
- let declaration = self.manager.add_declaration(
430
- self.current,
431
- id.name.clone(),
432
- DeclarationKind::Function,
433
- id.range,
434
- );
435
- self.manager
436
- .node_declarations
437
- .insert(AstNode::from(id), declaration);
438
- }
445
+ self.enter(ScopeKind::Function, |visitor| {
446
+ if let Some(id) = &ast.function.id {
447
+ let declaration = visitor.manager.add_declaration(
448
+ visitor.current,
449
+ id.name.clone(),
450
+ DeclarationKind::Function,
451
+ id.range,
452
+ );
453
+ visitor
454
+ .manager
455
+ .node_declarations
456
+ .insert(AstNode::from(id), declaration);
457
+ }
458
440
- Analyzer::visit_function(self, ast);
441
- if let Some(function_scope) = function_scope {
442
- self.close_scope(function_scope);
443
- }
459
+ Analyzer::visit_function(visitor, ast);
460
+ });
461
}
462
463
fn visit_arrow_function_expression(&mut self, ast: &forget_estree::ArrowFunctionExpression) {
447
- Analyzer::visit_function(self, ast);
464
+ self.enter(ScopeKind::Function, |visitor| {
465
+ Analyzer::visit_function(visitor, ast);
466
+ });
467
}
468
469
fn visit_assignment_expression(&mut self, ast: &forget_estree::AssignmentExpression) {
compiler/forget/crates/forget_semantic_analysis/tests/snapshots/analysis_test__fixtures@function-hoisting.js.snap
+1
-11
@@ -255,17 +255,7 @@ ScopeManager {
255
},
256
},
257
references: [],
258
- children: [
259
- Scope {
260
- id: ScopeId(
261
- 10,
262
- ),
263
- kind: Function,
264
- declarations: {},
265
- references: [],
266
- children: [],
267
- },
268
- ],
258
+ children: [],
259
},
260
],
261
},
compiler/forget/crates/forget_semantic_analysis/tests/snapshots/analysis_test__fixtures@simple-function.js.snap
+69
-80
@@ -169,91 +169,80 @@ ScopeManager {
169
2,
170
),
171
},
172
+ "c": Declaration {
173
+ id: DeclarationId(
174
+ 14,
175
+ ),
176
+ kind: Function,
177
+ scope: ScopeId(
178
+ 2,
179
+ ),
180
+ },
181
+ "d": Declaration {
182
+ id: DeclarationId(
183
+ 15,
184
+ ),
185
+ kind: Let,
186
+ scope: ScopeId(
187
+ 2,
188
+ ),
189
+ },
190
},
173
- references: [],
174
- children: [
175
- Scope {
176
- id: ScopeId(
191
+ references: [
192
+ Reference {
193
+ id: ReferenceId(
194
+ 1,
195
+ ),
196
+ kind: Read,
197
+ declaration: DeclarationId(
198
+ 10,
199
+ ),
200
+ declaration (name): "a",
201
+ scope: ScopeId(
202
+ 2,
203
+ ),
204
+ },
205
+ Reference {
206
+ id: ReferenceId(
207
+ 2,
208
+ ),
209
+ kind: Read,
210
+ declaration: DeclarationId(
211
+ 11,
212
+ ),
213
+ declaration (name): "b",
214
+ scope: ScopeId(
215
+ 2,
216
+ ),
217
+ },
218
+ Reference {
219
+ id: ReferenceId(
220
3,
221
),
179
- kind: Function,
180
- declarations: {
181
- "c": Declaration {
182
- id: DeclarationId(
183
- 14,
184
- ),
185
- kind: Function,
186
- scope: ScopeId(
187
- 3,
188
- ),
189
- },
190
- "d": Declaration {
191
- id: DeclarationId(
192
- 15,
193
- ),
194
- kind: Let,
195
- scope: ScopeId(
196
- 3,
197
- ),
198
- },
199
- },
200
- references: [
201
- Reference {
202
- id: ReferenceId(
203
- 1,
204
- ),
205
- kind: Read,
206
- declaration: DeclarationId(
207
- 10,
208
- ),
209
- declaration (name): "a",
210
- scope: ScopeId(
211
- 3,
212
- ),
213
- },
214
- Reference {
215
- id: ReferenceId(
216
- 2,
217
- ),
218
- kind: Read,
219
- declaration: DeclarationId(
220
- 11,
221
- ),
222
- declaration (name): "b",
223
- scope: ScopeId(
224
- 3,
225
- ),
226
- },
227
- Reference {
228
- id: ReferenceId(
229
- 3,
230
- ),
231
- kind: Read,
232
- declaration: DeclarationId(
233
- 14,
234
- ),
235
- declaration (name): "c",
236
- scope: ScopeId(
237
- 3,
238
- ),
239
- },
240
- Reference {
241
- id: ReferenceId(
242
- 4,
243
- ),
244
- kind: Read,
245
- declaration: DeclarationId(
246
- 15,
247
- ),
248
- declaration (name): "d",
249
- scope: ScopeId(
250
- 3,
251
- ),
252
- },
253
- ],
254
- children: [],
222
+ kind: Read,
223
+ declaration: DeclarationId(
224
+ 14,
225
+ ),
226
+ declaration (name): "c",
227
+ scope: ScopeId(
228
+ 2,
229
+ ),
230
+ },
231
+ Reference {
232
+ id: ReferenceId(
233
+ 4,
234
+ ),
235
+ kind: Read,
236
+ declaration: DeclarationId(
237
+ 15,
238
+ ),
239
+ declaration (name): "d",
240
+ scope: ScopeId(
241
+ 2,
242
+ ),
243
},
244
],
245
+ children: [],
246
},
247
],
248
},