refactor(ast): pass final ScopeFlags into visit_function (#4283)

We have a strange workaround for `visit_function` where we pass in `ScopeFlags`, to support creating the scope inside `Function`, but setting different flags for `MethodDefinition`s.

Previously `visit_function` took `Option<ScopeFlags>` and then did `flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function` to it. Personally, I found this confusing. When I was looking at `MethodDefinition`, I was wondering "It's a function, why doesn't it set Function flag too?"

This changes makes it more explicit and clear what `ScopeFlags` everything has.
This commit is contained in:
overlookmotel 2024-07-16 07:22:06 +00:00
parent bf3d8d3e8f
commit 2c7bb9f6c8
11 changed files with 44 additions and 48 deletions

View file

@ -79,7 +79,7 @@ pub enum Expression<'a> {
ChainExpression(Box<'a, ChainExpression<'a>>) = 16,
ClassExpression(Box<'a, Class<'a>>) = 17,
ConditionalExpression(Box<'a, ConditionalExpression<'a>>) = 18,
#[visit_args(flags = None)]
#[visit_args(flags = ScopeFlags::Function)]
FunctionExpression(Box<'a, Function<'a>>) = 19,
ImportExpression(Box<'a, ImportExpression<'a>>) = 20,
LogicalExpression(Box<'a, LogicalExpression<'a>>) = 21,
@ -970,7 +970,7 @@ pub struct BlockStatement<'a> {
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum Declaration<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 32,
#[visit_args(flags = None)]
#[visit_args(flags = ScopeFlags::Function)]
FunctionDeclaration(Box<'a, Function<'a>>) = 33,
ClassDeclaration(Box<'a, Class<'a>>) = 34,
UsingDeclaration(Box<'a, UsingDeclaration<'a>>) = 35,
@ -1437,8 +1437,8 @@ pub struct BindingRestElement<'a> {
/// Function Definitions
#[visited_node]
#[scope(
// TODO: `ScopeFlags::Function` is not correct if this is a `MethodDefinition`
flags(flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function),
// `flags` passed in to visitor via parameter defined by `#[visit_args(flags = ...)]` on parents
flags(flags),
strict_if(self.is_strict()),
)]
#[derive(Debug)]
@ -1642,12 +1642,12 @@ pub struct MethodDefinition<'a> {
pub span: Span,
pub decorators: Vec<'a, Decorator<'a>>,
pub key: PropertyKey<'a>,
#[visit_args(flags = Some(match self.kind {
MethodDefinitionKind::Get => ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::empty(),
}))]
#[visit_args(flags = match self.kind {
MethodDefinitionKind::Get => ScopeFlags::Function | ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::Function | ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Function | ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::Function,
})]
pub value: Box<'a, Function<'a>>, // FunctionExpression
pub kind: MethodDefinitionKind,
pub computed: bool,
@ -1959,7 +1959,7 @@ inherit_variants! {
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(untagged))]
pub enum ExportDefaultDeclarationKind<'a> {
#[visit_args(flags = None)]
#[visit_args(flags = ScopeFlags::Function)]
FunctionDeclaration(Box<'a, Function<'a>>) = 64,
ClassDeclaration(Box<'a, Class<'a>>) = 65,

View file

@ -836,7 +836,7 @@ pub trait Visit<'a>: Sized {
}
#[inline]
fn visit_function(&mut self, it: &Function<'a>, flags: Option<ScopeFlags>) {
fn visit_function(&mut self, it: &Function<'a>, flags: ScopeFlags) {
walk_function(self, it, flags);
}
@ -1509,7 +1509,7 @@ pub mod walk {
Expression::ClassExpression(it) => visitor.visit_class(it),
Expression::ConditionalExpression(it) => visitor.visit_conditional_expression(it),
Expression::FunctionExpression(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
Expression::ImportExpression(it) => visitor.visit_import_expression(it),
@ -3014,27 +3014,23 @@ pub mod walk {
visitor.visit_decorators(&it.decorators);
visitor.visit_property_key(&it.key);
{
let flags = Some(match it.kind {
MethodDefinitionKind::Get => ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::empty(),
});
let flags = match it.kind {
MethodDefinitionKind::Get => ScopeFlags::Function | ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::Function | ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Function | ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::Function,
};
visitor.visit_function(&it.value, flags);
}
visitor.leave_node(kind);
}
pub fn walk_function<'a, V: Visit<'a>>(
visitor: &mut V,
it: &Function<'a>,
flags: Option<ScopeFlags>,
) {
pub fn walk_function<'a, V: Visit<'a>>(visitor: &mut V, it: &Function<'a>, flags: ScopeFlags) {
let kind = AstKind::Function(visitor.alloc(it));
visitor.enter_node(kind);
visitor.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
let mut flags = flags;
if it.is_strict() {
flags |= ScopeFlags::StrictMode;
}
@ -3738,7 +3734,7 @@ pub mod walk {
match it {
Declaration::VariableDeclaration(it) => visitor.visit_variable_declaration(it),
Declaration::FunctionDeclaration(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
Declaration::ClassDeclaration(it) => visitor.visit_class(it),
@ -4119,7 +4115,7 @@ pub mod walk {
) {
match it {
ExportDefaultDeclarationKind::FunctionDeclaration(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
ExportDefaultDeclarationKind::ClassDeclaration(it) => visitor.visit_class(it),

View file

@ -831,7 +831,7 @@ pub trait VisitMut<'a>: Sized {
}
#[inline]
fn visit_function(&mut self, it: &mut Function<'a>, flags: Option<ScopeFlags>) {
fn visit_function(&mut self, it: &mut Function<'a>, flags: ScopeFlags) {
walk_function(self, it, flags);
}
@ -1516,7 +1516,7 @@ pub mod walk_mut {
Expression::ClassExpression(it) => visitor.visit_class(it),
Expression::ConditionalExpression(it) => visitor.visit_conditional_expression(it),
Expression::FunctionExpression(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
Expression::ImportExpression(it) => visitor.visit_import_expression(it),
@ -3150,12 +3150,12 @@ pub mod walk_mut {
visitor.visit_decorators(&mut it.decorators);
visitor.visit_property_key(&mut it.key);
{
let flags = Some(match it.kind {
MethodDefinitionKind::Get => ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::empty(),
});
let flags = match it.kind {
MethodDefinitionKind::Get => ScopeFlags::Function | ScopeFlags::GetAccessor,
MethodDefinitionKind::Set => ScopeFlags::Function | ScopeFlags::SetAccessor,
MethodDefinitionKind::Constructor => ScopeFlags::Function | ScopeFlags::Constructor,
MethodDefinitionKind::Method => ScopeFlags::Function,
};
visitor.visit_function(&mut it.value, flags);
}
visitor.leave_node(kind);
@ -3164,13 +3164,13 @@ pub mod walk_mut {
pub fn walk_function<'a, V: VisitMut<'a>>(
visitor: &mut V,
it: &mut Function<'a>,
flags: Option<ScopeFlags>,
flags: ScopeFlags,
) {
let kind = AstType::Function;
visitor.enter_node(kind);
visitor.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
let mut flags = flags;
if it.is_strict() {
flags |= ScopeFlags::StrictMode;
}
@ -3946,7 +3946,7 @@ pub mod walk_mut {
match it {
Declaration::VariableDeclaration(it) => visitor.visit_variable_declaration(it),
Declaration::FunctionDeclaration(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
Declaration::ClassDeclaration(it) => visitor.visit_class(it),
@ -4357,7 +4357,7 @@ pub mod walk_mut {
) {
match it {
ExportDefaultDeclarationKind::FunctionDeclaration(it) => {
let flags = None;
let flags = ScopeFlags::Function;
visitor.visit_function(it, flags)
}
ExportDefaultDeclarationKind::ClassDeclaration(it) => visitor.visit_class(it),

View file

@ -136,7 +136,7 @@ impl<'a> Visit<'a> for FunctionReturnType<'a> {
}
}
fn visit_function(&mut self, _func: &Function<'a>, _flags: Option<ScopeFlags>) {
fn visit_function(&mut self, _func: &Function<'a>, _flags: ScopeFlags) {
// We don't care about nested functions
}

View file

@ -231,7 +231,7 @@ impl<'a> Visit<'a> for ScopeTree<'a> {
}
}
fn visit_function(&mut self, func: &Function<'a>, flags: Option<ScopeFlags>) {
fn visit_function(&mut self, func: &Function<'a>, flags: ScopeFlags) {
walk_function(self, func, flags);
if func.type_parameters.is_some() {
self.leave_scope();

View file

@ -105,7 +105,7 @@ impl<'a> Visit<'a> for AwaitFinder {
fn visit_arrow_function_expression(&mut self, _expr: &ArrowFunctionExpression<'a>) {}
fn visit_function(&mut self, _func: &Function<'a>, _flags: Option<ScopeFlags>) {}
fn visit_function(&mut self, _func: &Function<'a>, _flags: ScopeFlags) {}
}
#[test]

View file

@ -151,7 +151,7 @@ impl<'a> Visit<'a> for KeepVar<'a> {
}
}
fn visit_function(&mut self, _it: &Function<'a>, _flags: Option<ScopeFlags>) {
fn visit_function(&mut self, _it: &Function<'a>, _flags: ScopeFlags) {
/* skip functions */
}

View file

@ -46,7 +46,7 @@ struct CountASTNodes {
}
impl<'a> Visit<'a> for CountASTNodes {
fn visit_function(&mut self, func: &Function<'a>, flags: Option<ScopeFlags>) {
fn visit_function(&mut self, func: &Function<'a>, flags: ScopeFlags) {
self.functions += 1;
walk::walk_function(self, func, flags);
}

View file

@ -1441,7 +1441,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.leave_node(kind);
}
fn visit_function(&mut self, func: &Function<'a>, flags: Option<ScopeFlags>) {
fn visit_function(&mut self, func: &Function<'a>, flags: ScopeFlags) {
/* cfg */
let (before_function_graph_ix, error_harness, function_graph_ix) =
control_flow!(self, |cfg| {
@ -1460,7 +1460,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.enter_node(kind);
self.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
let mut flags = flags;
if func.is_strict() {
flags |= ScopeFlags::StrictMode;
}

View file

@ -549,7 +549,7 @@ impl<'a> Visit<'a> for ChildScopeCollector {
self.scope_ids.push(clause.scope_id.get().unwrap());
}
fn visit_function(&mut self, func: &Function<'a>, _flags: Option<ScopeFlags>) {
fn visit_function(&mut self, func: &Function<'a>, _flags: ScopeFlags) {
self.scope_ids.push(func.scope_id.get().unwrap());
}

View file

@ -254,7 +254,7 @@ impl<'a> VisitBuilder<'a> {
let as_param_type = self.with_ref_pat(&as_type);
let (extra_params, extra_args) = if ident == "Function" {
(quote!(, flags: Option<ScopeFlags>,), quote!(, flags))
(quote!(, flags: ScopeFlags,), quote!(, flags))
} else {
(TokenStream::default(), TokenStream::default())
};