diff --git a/crates/oxc_semantic/src/post_transform_checker.rs b/crates/oxc_semantic/src/post_transform_checker.rs index 01036ca3b0503f..c300a58a5c0711 100644 --- a/crates/oxc_semantic/src/post_transform_checker.rs +++ b/crates/oxc_semantic/src/post_transform_checker.rs @@ -93,9 +93,9 @@ use std::{ use oxc_allocator::{Allocator, CloneIn}; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ast::*, visit::walk, Visit}; +use oxc_ast::{ast::*, ast_kind::AstKind, visit::walk, Visit}; use oxc_diagnostics::OxcDiagnostic; -use oxc_span::CompactStr; +use oxc_span::{CompactStr, GetSpan}; use oxc_syntax::{ reference::ReferenceId, scope::{ScopeFlags, ScopeId}, @@ -314,11 +314,6 @@ impl<'s> PostTransformChecker<'s> { for (&scope_id_after_transform, &scope_id_rebuilt) in self.after_transform.ids.scope_ids.iter().zip(self.rebuilt.ids.scope_ids.iter()) { - let (Some(scope_id_after_transform), Some(scope_id_rebuilt)) = - (scope_id_after_transform, scope_id_rebuilt) - else { - continue; - }; self.scope_ids_map.insert(scope_id_after_transform, scope_id_rebuilt); } @@ -360,44 +355,17 @@ impl<'s> PostTransformChecker<'s> { binding_names } - let scope_ids = match scope_ids.into_parts() { - (None, None) => continue, - (Some(scope_id_after_transform), Some(scope_id_rebuilt)) => { - let scope_ids = Pair::new(scope_id_after_transform, scope_id_rebuilt); - let binding_names = self.get_pair(scope_ids, get_sorted_binding_names); - if binding_names.is_mismatch() { - self.errors.push_mismatch("Bindings mismatch", scope_ids, binding_names); - } else { - let symbol_ids = self.get_pair(scope_ids, |data, scope_id| { - data.scopes.get_bindings(scope_id).values().copied().collect::>() - }); - if self.remap_symbol_ids_sets(&symbol_ids).is_mismatch() { - self.errors.push_mismatch( - "Binding symbols mismatch", - scope_ids, - symbol_ids, - ); - } - } - scope_ids - } - (Some(scope_id), None) => { - let binding_names = get_sorted_binding_names(&self.after_transform, scope_id); - self.errors.push_mismatch_strs( - "Bindings mismatch", - Pair::new(format!("{scope_id:?}: {binding_names:?}").as_str(), "No scope"), - ); - continue; - } - (None, Some(scope_id)) => { - let binding_names = get_sorted_binding_names(&self.rebuilt, scope_id); - self.errors.push_mismatch_strs( - "Bindings mismatch", - Pair::new("No scope", format!("{scope_id:?}: {binding_names:?}").as_str()), - ); - continue; + let binding_names = self.get_pair(scope_ids, get_sorted_binding_names); + if binding_names.is_mismatch() { + self.errors.push_mismatch("Bindings mismatch", scope_ids, binding_names); + } else { + let symbol_ids = self.get_pair(scope_ids, |data, scope_id| { + data.scopes.get_bindings(scope_id).values().copied().collect::>() + }); + if self.remap_symbol_ids_sets(&symbol_ids).is_mismatch() { + self.errors.push_mismatch("Binding symbols mismatch", scope_ids, symbol_ids); } - }; + } // Check flags match let flags = self.get_pair(scope_ids, |data, scope_id| data.scopes.get_flags(scope_id)); @@ -635,7 +603,7 @@ impl<'s> PostTransformChecker<'s> { /// `scope_ids`, `symbol_ids` and `reference_ids` lists are filled in visitation order. #[derive(Default)] pub struct SemanticIds { - scope_ids: Vec>, + scope_ids: Vec, symbol_ids: Vec, reference_ids: Vec, } @@ -655,20 +623,35 @@ impl SemanticIds { } } -struct SemanticIdsCollector<'c> { +struct SemanticIdsCollector<'a, 'c> { ids: &'c mut SemanticIds, errors: Vec, + kinds: Vec>, } -impl<'c> SemanticIdsCollector<'c> { +impl<'a, 'c> SemanticIdsCollector<'a, 'c> { fn new(ids: &'c mut SemanticIds) -> Self { - Self { ids, errors: vec![] } + Self { ids, errors: vec![], kinds: vec![] } } } -impl<'a, 'c> Visit<'a> for SemanticIdsCollector<'c> { +impl<'a, 'c> Visit<'a> for SemanticIdsCollector<'a, 'c> { + fn enter_node(&mut self, kind: AstKind<'a>) { + self.kinds.push(kind); + } + + fn leave_node(&mut self, _kind: AstKind<'a>) { + self.kinds.pop(); + } + fn enter_scope(&mut self, _flags: ScopeFlags, scope_id: &Cell>) { - self.ids.scope_ids.push(scope_id.get()); + if let Some(scope_id) = scope_id.get() { + self.ids.scope_ids.push(scope_id); + } else { + let message = "Missing ScopeId".to_string(); + self.errors + .push(OxcDiagnostic::error(message).with_label(self.kinds.last().unwrap().span())); + } } fn visit_identifier_reference(&mut self, ident: &IdentifierReference<'a>) { diff --git a/tasks/transform_conformance/oxc.snap.md b/tasks/transform_conformance/oxc.snap.md index e38db8d1a3911c..f70ea4bdfdba18 100644 --- a/tasks/transform_conformance/oxc.snap.md +++ b/tasks/transform_conformance/oxc.snap.md @@ -446,91 +446,32 @@ Passed: 10/36 * refresh/generates-valid-signature-for-exotic-ways-to-call-hooks/input.jsx - x Bindings mismatch: - | after transform: No scope - | rebuilt : ScopeId(3): [] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(10): [ReferenceId(17), ReferenceId(18), - | ReferenceId(20)] - | rebuilt : SymbolId(0): [ReferenceId(1), ReferenceId(16)] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(9): [ReferenceId(12), ReferenceId(13), - | ReferenceId(15)] - | rebuilt : SymbolId(4): [ReferenceId(3), ReferenceId(7)] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(7): [ReferenceId(9), ReferenceId(21), - | ReferenceId(22)] - | rebuilt : SymbolId(10): [ReferenceId(19), ReferenceId(22)] - - x Reference symbol mismatch: - | after transform: ReferenceId(17): Some("_s2") - | rebuilt : ReferenceId(0): None - - x Reference symbol mismatch: - | after transform: ReferenceId(12): Some("_s") - | rebuilt : ReferenceId(2): None - - x Reference symbol mismatch: - | after transform: ReferenceId(21): Some("_c") - | rebuilt : ReferenceId(21): None + x Semantic Collector failed after transform - x Unresolved references mismatch: - | after transform: ["React", "useFancyEffect", "useThePlatform"] - | rebuilt : ["$RefreshReg$", "$RefreshSig$", "React", - | "useFancyEffect", "useThePlatform"] + x Missing ScopeId + ,-[tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/generates-valid-signature-for-exotic-ways-to-call-hooks/input.jsx:1:1] + 1 | import FancyHook from 'fancy'; + : ^ + 2 | + `---- * refresh/includes-custom-hooks-into-the-signatures/input.jsx - x Bindings mismatch: - | after transform: No scope - | rebuilt : ScopeId(2): [] - - x Bindings mismatch: - | after transform: No scope - | rebuilt : ScopeId(6): [] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(8): [ReferenceId(10), ReferenceId(11), - | ReferenceId(13)] - | rebuilt : SymbolId(1): [ReferenceId(3), ReferenceId(7)] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(9): [ReferenceId(14), ReferenceId(15), - | ReferenceId(17)] - | rebuilt : SymbolId(2): [ReferenceId(10), ReferenceId(12)] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(10): [ReferenceId(19), ReferenceId(20), - | ReferenceId(22)] - | rebuilt : SymbolId(3): [ReferenceId(14), ReferenceId(18)] - - x Symbol reference IDs mismatch: - | after transform: SymbolId(6): [ReferenceId(6), ReferenceId(23), - | ReferenceId(24)] - | rebuilt : SymbolId(10): [ReferenceId(21), ReferenceId(24)] - - x Reference symbol mismatch: - | after transform: ReferenceId(10): Some("_s") - | rebuilt : ReferenceId(0): None - - x Reference symbol mismatch: - | after transform: ReferenceId(14): Some("_s2") - | rebuilt : ReferenceId(1): None - - x Reference symbol mismatch: - | after transform: ReferenceId(19): Some("_s3") - | rebuilt : ReferenceId(2): None + x Semantic Collector failed after transform - x Reference symbol mismatch: - | after transform: ReferenceId(23): Some("_c") - | rebuilt : ReferenceId(23): None + x Missing ScopeId + ,-[tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/includes-custom-hooks-into-the-signatures/input.jsx:1:1] + 1 | function useFancyState() { + : ^ + 2 | const [foo, setFoo] = React.useState(0); + `---- - x Unresolved references mismatch: - | after transform: ["React"] - | rebuilt : ["$RefreshReg$", "$RefreshSig$", "React"] + x Missing ScopeId + ,-[tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/includes-custom-hooks-into-the-signatures/input.jsx:1:1] + 1 | function useFancyState() { + : ^ + 2 | const [foo, setFoo] = React.useState(0); + `---- * refresh/registers-capitalized-identifiers-in-hoc-calls/input.jsx