Skip to content

Commit a0a248c

Browse files
committed
test(transformer): transform checker output symbol name for mismatches
1 parent d953a6b commit a0a248c

File tree

7 files changed

+18040
-18009
lines changed

7 files changed

+18040
-18009
lines changed

crates/oxc_semantic/src/post_transform_checker.rs

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
113113
pub fn check_semantic_after_transform(
114114
symbols_after_transform: &SymbolTable,
115115
scopes_after_transform: &ScopeTree,
116-
program: &Program<'_>,
116+
program: &Program,
117117
) -> Option<Vec<OxcDiagnostic>> {
118118
let mut errors = Errors::default();
119119

@@ -125,8 +125,12 @@ pub fn check_semantic_after_transform(
125125
// Collect `ScopeId`s, `SymbolId`s and `ReferenceId`s from AST after transformer
126126
let scoping_after_transform =
127127
Scoping { symbols: symbols_after_transform, scopes: scopes_after_transform };
128-
let (scope_ids_after_transform, symbol_ids_after_transform, reference_ids_after_transform) =
129-
SemanticIdsCollector::new(&mut errors).collect(program);
128+
let (
129+
scope_ids_after_transform,
130+
symbol_ids_after_transform,
131+
reference_ids_after_transform,
132+
reference_names,
133+
) = SemanticIdsCollector::new(&mut errors).collect(program);
130134

131135
// Clone the post-transform AST, re-run semantic analysis on it, and collect `ScopeId`s,
132136
// `SymbolId`s and `ReferenceId`s from AST.
@@ -141,7 +145,7 @@ pub fn check_semantic_after_transform(
141145
.into_symbol_table_and_scope_tree();
142146
let scoping_rebuilt = Scoping { symbols: &symbols_rebuilt, scopes: &scopes_rebuilt };
143147

144-
let (scope_ids_rebuilt, symbol_ids_rebuilt, reference_ids_rebuilt) =
148+
let (scope_ids_rebuilt, symbol_ids_rebuilt, reference_ids_rebuilt, _) =
145149
SemanticIdsCollector::new(&mut errors).collect(&program);
146150

147151
// Create mappings from after transform IDs to rebuilt IDs
@@ -156,6 +160,7 @@ pub fn check_semantic_after_transform(
156160
scope_ids_map,
157161
symbol_ids_map,
158162
reference_ids_map,
163+
reference_names,
159164
errors,
160165
};
161166
checker.check_scopes();
@@ -167,19 +172,20 @@ pub fn check_semantic_after_transform(
167172
}
168173

169174
/// Check all AST nodes have scope, symbol and reference IDs
170-
pub fn check_semantic_ids(program: &Program<'_>) -> Option<Vec<OxcDiagnostic>> {
175+
pub fn check_semantic_ids(program: &Program) -> Option<Vec<OxcDiagnostic>> {
171176
let mut errors = Errors::default();
172177
SemanticIdsCollector::new(&mut errors).collect(program);
173178
errors.get()
174179
}
175180

176-
struct PostTransformChecker<'s> {
181+
struct PostTransformChecker<'a, 's> {
177182
scoping_after_transform: Scoping<'s>,
178183
scoping_rebuilt: Scoping<'s>,
179184
// Mappings from after transform ID to rebuilt ID
180185
scope_ids_map: IdMapping<ScopeId>,
181186
symbol_ids_map: IdMapping<SymbolId>,
182187
reference_ids_map: IdMapping<ReferenceId>,
188+
reference_names: Vec<Atom<'a>>,
183189
errors: Errors,
184190
}
185191

@@ -327,7 +333,7 @@ rebuilt : {value_rebuilt}
327333
}
328334
}
329335

330-
impl<'s> PostTransformChecker<'s> {
336+
impl<'a, 's> PostTransformChecker<'a, 's> {
331337
fn check_scopes(&mut self) {
332338
for scope_ids in self.scope_ids_map.pairs() {
333339
// Check bindings are the same
@@ -393,28 +399,30 @@ impl<'s> PostTransformChecker<'s> {
393399
scoping.symbols.names[symbol_id].clone()
394400
});
395401
if names.is_mismatch() {
396-
self.errors.push_mismatch("Symbol name mismatch", symbol_ids, names);
402+
self.errors.push_mismatch("Symbol name mismatch", symbol_ids, &names);
397403
}
404+
let symbol_name = names.rebuilt.as_str();
405+
let mismatch_title = |field| format!("Symbol {field} mismatch for {symbol_name:?}");
398406

399407
// Check flags match
400408
let flags =
401409
self.get_pair(symbol_ids, |scoping, symbol_id| scoping.symbols.flags[symbol_id]);
402410
if flags.is_mismatch() {
403-
self.errors.push_mismatch("Symbol flags mismatch", symbol_ids, flags);
411+
self.errors.push_mismatch(&mismatch_title("flags"), symbol_ids, flags);
404412
}
405413

406414
// Check spans match
407415
let spans =
408416
self.get_pair(symbol_ids, |scoping, symbol_id| scoping.symbols.spans[symbol_id]);
409417
if spans.is_mismatch() {
410-
self.errors.push_mismatch("Symbol span mismatch", symbol_ids, spans);
418+
self.errors.push_mismatch(&mismatch_title("span"), symbol_ids, spans);
411419
}
412420

413421
// Check scope IDs match
414422
let scope_ids = self
415423
.get_pair(symbol_ids, |scoping, symbol_id| scoping.symbols.scope_ids[symbol_id]);
416424
if self.remap_scope_ids(scope_ids).is_mismatch() {
417-
self.errors.push_mismatch("Symbol scope ID mismatch", symbol_ids, scope_ids);
425+
self.errors.push_mismatch(&mismatch_title("scope ID"), symbol_ids, scope_ids);
418426
}
419427

420428
// NB: Skip checking declarations match - transformer does not set `NodeId`s
@@ -425,7 +433,7 @@ impl<'s> PostTransformChecker<'s> {
425433
});
426434
if self.remap_reference_ids_sets(&reference_ids).is_mismatch() {
427435
self.errors.push_mismatch(
428-
"Symbol reference IDs mismatch",
436+
&mismatch_title("reference IDs"),
429437
symbol_ids,
430438
reference_ids,
431439
);
@@ -439,7 +447,7 @@ impl<'s> PostTransformChecker<'s> {
439447
});
440448
if redeclaration_spans.is_mismatch() {
441449
self.errors.push_mismatch(
442-
"Symbol redeclarations mismatch",
450+
&mismatch_title("redeclarations"),
443451
symbol_ids,
444452
redeclaration_spans,
445453
);
@@ -448,7 +456,7 @@ impl<'s> PostTransformChecker<'s> {
448456
}
449457

450458
fn check_references(&mut self) {
451-
for reference_ids in self.reference_ids_map.pairs() {
459+
for (reference_ids, name) in self.reference_ids_map.pairs().zip(&self.reference_names) {
452460
// Check symbol IDs match
453461
let symbol_ids = self.get_pair(reference_ids, |scoping, reference_id| {
454462
scoping.symbols.references[reference_id].symbol_id()
@@ -458,18 +466,31 @@ impl<'s> PostTransformChecker<'s> {
458466
symbol_ids.rebuilt.map(Option::Some),
459467
);
460468
if symbol_ids_remapped.is_mismatch() {
461-
let symbol_names = self.get_pair(symbol_ids, |scoping, symbol_id| {
462-
symbol_id.map(|symbol_id| scoping.symbols.names[symbol_id].clone())
469+
let mismatch_strs = self.get_pair(reference_ids, |scoping, reference_id| {
470+
match scoping.symbols.references[reference_id].symbol_id() {
471+
Some(symbol_id) => {
472+
let symbol_name = &scoping.symbols.names[symbol_id];
473+
format!("{symbol_id:?} {symbol_name:?}")
474+
}
475+
None => "<None>".to_string(),
476+
}
463477
});
464-
self.errors.push_mismatch("Reference symbol mismatch", reference_ids, symbol_names);
478+
self.errors.push_mismatch_strs(
479+
&format!("Reference symbol mismatch for {name:?}"),
480+
mismatch_strs,
481+
);
465482
}
466483

467484
// Check flags match
468485
let flags = self.get_pair(reference_ids, |scoping, reference_id| {
469486
scoping.symbols.references[reference_id].flags()
470487
});
471488
if flags.is_mismatch() {
472-
self.errors.push_mismatch("Reference flags mismatch", reference_ids, flags);
489+
self.errors.push_mismatch(
490+
&format!("Reference flags mismatch for {name:?}"),
491+
reference_ids,
492+
flags,
493+
);
473494
}
474495
}
475496
}
@@ -590,32 +611,40 @@ impl<'s> PostTransformChecker<'s> {
590611
/// Collector of `ScopeId`s, `SymbolId`s and `ReferenceId`s from an AST.
591612
///
592613
/// `scope_ids`, `symbol_ids` and `reference_ids` lists are filled in visitation order.
593-
struct SemanticIdsCollector<'e> {
614+
struct SemanticIdsCollector<'a, 'e> {
594615
scope_ids: Vec<Option<ScopeId>>,
595616
symbol_ids: Vec<Option<SymbolId>>,
596617
reference_ids: Vec<Option<ReferenceId>>,
618+
reference_names: Vec<Atom<'a>>,
597619
errors: &'e mut Errors,
598620
}
599621

600-
impl<'e> SemanticIdsCollector<'e> {
622+
impl<'a, 'e> SemanticIdsCollector<'a, 'e> {
601623
fn new(errors: &'e mut Errors) -> Self {
602-
Self { scope_ids: vec![], symbol_ids: vec![], reference_ids: vec![], errors }
624+
Self {
625+
scope_ids: vec![],
626+
symbol_ids: vec![],
627+
reference_ids: vec![],
628+
reference_names: vec![],
629+
errors,
630+
}
603631
}
604632

605633
/// Collect IDs and check for errors
606634
#[allow(clippy::type_complexity)]
607635
fn collect(
608636
mut self,
609-
program: &Program<'_>,
610-
) -> (Vec<Option<ScopeId>>, Vec<Option<SymbolId>>, Vec<Option<ReferenceId>>) {
637+
program: &Program<'a>,
638+
) -> (Vec<Option<ScopeId>>, Vec<Option<SymbolId>>, Vec<Option<ReferenceId>>, Vec<Atom<'a>>)
639+
{
611640
if !program.source_type.is_typescript_definition() {
612641
self.visit_program(program);
613642
}
614-
(self.scope_ids, self.symbol_ids, self.reference_ids)
643+
(self.scope_ids, self.symbol_ids, self.reference_ids, self.reference_names)
615644
}
616645
}
617646

618-
impl<'a, 'e> Visit<'a> for SemanticIdsCollector<'e> {
647+
impl<'a, 'e> Visit<'a> for SemanticIdsCollector<'a, 'e> {
619648
fn enter_scope(&mut self, _flags: ScopeFlags, scope_id: &Cell<Option<ScopeId>>) {
620649
let scope_id = scope_id.get();
621650
self.scope_ids.push(scope_id);
@@ -627,16 +656,18 @@ impl<'a, 'e> Visit<'a> for SemanticIdsCollector<'e> {
627656
fn visit_identifier_reference(&mut self, ident: &IdentifierReference<'a>) {
628657
let reference_id = ident.reference_id.get();
629658
self.reference_ids.push(reference_id);
630-
if reference_id.is_none() {
631-
self.errors.push(format!("Missing ReferenceId: {}", ident.name));
659+
if reference_id.is_some() {
660+
self.reference_names.push(ident.name.clone());
661+
} else {
662+
self.errors.push(format!("Missing ReferenceId: {:?}", ident.name));
632663
}
633664
}
634665

635666
fn visit_binding_identifier(&mut self, ident: &BindingIdentifier<'a>) {
636667
let symbol_id = ident.symbol_id.get();
637668
self.symbol_ids.push(symbol_id);
638669
if symbol_id.is_none() {
639-
self.errors.push(format!("Missing SymbolId: {}", ident.name));
670+
self.errors.push(format!("Missing SymbolId: {:?}", ident.name));
640671
}
641672
}
642673

0 commit comments

Comments
 (0)