Skip to content

Commit 671fbca

Browse files
committed
refactor(traverse): indicate scope entry point with scope(enter_before) attr
1 parent 24979c9 commit 671fbca

File tree

4 files changed

+37
-9
lines changed

4 files changed

+37
-9
lines changed

crates/oxc_ast/src/ast/js.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1228,14 +1228,15 @@ pub struct WithStatement<'a> {
12281228
}
12291229

12301230
/// Switch Statement
1231-
#[visited_node(scope(ScopeFlags::empty()), enter_scope_before(cases))]
1231+
#[visited_node(scope(ScopeFlags::empty()))]
12321232
#[derive(Debug)]
12331233
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
12341234
#[cfg_attr(feature = "serialize", serde(tag = "type"))]
12351235
pub struct SwitchStatement<'a> {
12361236
#[cfg_attr(feature = "serialize", serde(flatten))]
12371237
pub span: Span,
12381238
pub discriminant: Expression<'a>,
1239+
#[scope(enter_before)]
12391240
pub cases: Vec<'a, SwitchCase<'a>>,
12401241
pub scope_id: Cell<Option<ScopeId>>,
12411242
}
@@ -1566,7 +1567,7 @@ pub struct YieldExpression<'a> {
15661567
}
15671568

15681569
/// Class Definitions
1569-
#[visited_node(scope(ScopeFlags::StrictMode), enter_scope_before(id))]
1570+
#[visited_node(scope(ScopeFlags::StrictMode))]
15701571
#[derive(Debug)]
15711572
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
15721573
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
@@ -1575,6 +1576,7 @@ pub struct Class<'a> {
15751576
#[cfg_attr(feature = "serialize", serde(flatten))]
15761577
pub span: Span,
15771578
pub decorators: Vec<'a, Decorator<'a>>,
1579+
#[scope(enter_before)]
15781580
pub id: Option<BindingIdentifier<'a>>,
15791581
pub super_class: Option<Expression<'a>>,
15801582
pub body: Box<'a, ClassBody<'a>>,

crates/oxc_ast/src/ast/ts.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ pub struct TSThisParameter<'a> {
4646
/// Enum Declaration
4747
///
4848
/// `const_opt` enum `BindingIdentifier` { `EnumBody_opt` }
49-
#[visited_node(scope(ScopeFlags::empty()), enter_scope_before(members))]
49+
#[visited_node(scope(ScopeFlags::empty()))]
5050
#[derive(Debug)]
5151
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
5252
#[cfg_attr(feature = "serialize", serde(tag = "type"))]
5353
pub struct TSEnumDeclaration<'a> {
5454
#[cfg_attr(feature = "serialize", serde(flatten))]
5555
pub span: Span,
5656
pub id: BindingIdentifier<'a>,
57+
#[scope(enter_before)]
5758
pub members: Vec<'a, TSEnumMember<'a>>,
5859
pub r#const: bool,
5960
pub declare: bool,
@@ -784,7 +785,6 @@ pub enum TSTypePredicateName<'a> {
784785

785786
#[visited_node(
786787
scope(ScopeFlags::TsModuleBlock),
787-
enter_scope_before(body),
788788
strict_if(self.body.as_ref().is_some_and(|body| body.is_strict())),
789789
)]
790790
#[derive(Debug)]
@@ -794,6 +794,7 @@ pub struct TSModuleDeclaration<'a> {
794794
#[cfg_attr(feature = "serialize", serde(flatten))]
795795
pub span: Span,
796796
pub id: TSModuleDeclarationName<'a>,
797+
#[scope(enter_before)]
797798
pub body: Option<TSModuleDeclarationBody<'a>>,
798799
/// The keyword used to define this module declaration
799800
/// ```text

crates/oxc_ast_macros/src/lib.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,28 @@
11
use proc_macro::TokenStream;
2+
use std::str::FromStr;
23

34
/// Attach to AST node type (struct or enum), to signal to codegen to create visitor for this type.
4-
/// Macro itself does nothing - just passes through the token stream unchanged.
5+
///
6+
/// Macro does not generate any code - it's purely a means to communicate information to the codegen.
7+
///
8+
/// Only thing macro does is add `#[derive(VisitedNode)]` to the item.
9+
/// Deriving `VisitedNode` does nothing, but supports the `#[scope]` attr on struct fields.
10+
/// This is a workaround for Rust not supporting helper attributes for `proc_macro_attribute` macros,
11+
/// so we need to use a derive macro to get that support.
12+
///
13+
/// Use native Rust `TokenStream`, to avoid dependency on slow-compiling crates like `syn` and `quote`.
514
#[proc_macro_attribute]
15+
#[allow(clippy::missing_panics_doc)]
616
pub fn visited_node(_args: TokenStream, input: TokenStream) -> TokenStream {
7-
input
17+
let mut stream = TokenStream::from_str("#[derive(::oxc_ast_macros::VisitedNode)]").unwrap();
18+
stream.extend(input);
19+
stream
20+
}
21+
22+
/// Dummy derive macro for a non-existent trait `VisitedNode`.
23+
///
24+
/// Does not generate any code, only purpose is to allow using `#[scope]` attr in the type def.
25+
#[proc_macro_derive(VisitedNode, attributes(scope))]
26+
pub fn visited_node_derive(_item: TokenStream) -> TokenStream {
27+
TokenStream::new()
828
}

crates/oxc_traverse/scripts/lib/parse.mjs

+8-3
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ function parseFile(code, filename, types) {
6868
function parseStruct(name, rawName, lines, scopeArgs, filename, startLineIndex) {
6969
const fields = [];
7070
for (let i = 0; i < lines.length; i++) {
71-
const line = lines[i];
72-
if (line.startsWith('#[')) {
71+
let line = lines[i];
72+
const isScopeEntry = line === '#[scope(enter_before)]';
73+
if (isScopeEntry) {
74+
line = lines[++i];
75+
} else if (line.startsWith('#[')) {
7376
while (!lines[i].endsWith(']')) {
7477
i++;
7578
}
@@ -86,6 +89,8 @@ function parseStruct(name, rawName, lines, scopeArgs, filename, startLineIndex)
8689
{name: innerTypeName, wrappers} = typeAndWrappers(typeName);
8790

8891
fields.push({name, typeName, rawName, rawTypeName, innerTypeName, wrappers});
92+
93+
if (isScopeEntry) scopeArgs.enterScopeBefore = name;
8994
}
9095
return {kind: 'struct', name, rawName, fields, scopeArgs};
9196
}
@@ -128,7 +133,7 @@ function parseScopeArgs(argsStr, filename, lineIndex) {
128133
while (true) {
129134
const [key] = matchAndConsume(/^([a-z_]+)\(/);
130135
assert(
131-
['scope', 'scope_if', 'strict_if', 'enter_scope_before'].includes(key),
136+
['scope', 'scope_if', 'strict_if'].includes(key),
132137
`Unexpected visited_node macro arg: ${key}`
133138
);
134139

0 commit comments

Comments
 (0)