Skip to content

Commit

Permalink
refactor(semantic): add binder for FormalParameters and RestElement, …
Browse files Browse the repository at this point in the history
…replacing the binder for FormalParameters (#2114)

Similar with #2013.

This way we will be able to find the corresponding Ast accurately.

The snapshots look a little strange but the change is expected.
  • Loading branch information
Dunqing authored Jan 22, 2024
1 parent 5ca07bc commit 8bccdab
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 21 deletions.
6 changes: 6 additions & 0 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,12 @@ pub enum FormalParameterKind {
Signature,
}

impl FormalParameterKind {
pub fn is_signature(&self) -> bool {
matches!(self, Self::Signature)
}
}

impl<'a> FormalParameters<'a> {
pub fn is_empty(&self) -> bool {
self.items.is_empty()
Expand Down
10 changes: 4 additions & 6 deletions crates/oxc_linter/src/rules/eslint/no_redeclare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,10 @@ impl Rule for NoRedeclare {
}
}
}
AstKind::FormalParameters(params) => {
for item in &params.items {
if let BindingPatternKind::BindingIdentifier(ident) = &item.pattern.kind {
if *symbol_table.get_name(variable.symbol_id) == ident.name {
self.report_diagnostic(ctx, variable, ident);
}
AstKind::FormalParameter(param) => {
if let BindingPatternKind::BindingIdentifier(ident) = &param.pattern.kind {
if *symbol_table.get_name(variable.symbol_id) == ident.name {
self.report_diagnostic(ctx, variable, ident);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ impl Rule for NoAccumulatingSpread {
let reference = symbols.get_reference(reference_id);
let Some(referenced_symbol_id) = reference.symbol_id() else { return };
let declaration_id = symbols.get_declaration(referenced_symbol_id);
let declaration = ctx.semantic().nodes().get_node(declaration_id);
let AstKind::FormalParameters(params) = declaration.kind() else { return };
let Some(declaration) = ctx.semantic().nodes().parent_node(declaration_id) else { return };
let AstKind::FormalParameters(params) = declaration.kind() else {
return;
};

// We're only looking for the first parameter, since that's where acc is.
// Skip non-parameter or non-first-parameter declarations.
Expand Down
49 changes: 38 additions & 11 deletions crates/oxc_semantic/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,42 @@ impl<'a> Binder for Function<'a> {
}
}

impl<'a> Binder for FormalParameters<'a> {
// Binds the formal parameters of a function or method.
impl<'a> Binder for RestElement<'a> {
// Binds the FormalParameters's rest of a function or method.
fn bind(&self, builder: &mut SemanticBuilder) {
let parent_kind = builder.nodes.parent_kind(builder.current_node_id).unwrap();
let AstKind::FormalParameters(parameters) = parent_kind else {
return;
};

if parameters.kind.is_signature() {
return;
}

let includes = SymbolFlags::FunctionScopedVariable;
let excludes =
SymbolFlags::FunctionScopedVariable | SymbolFlags::FunctionScopedVariableExcludes;
self.bound_names(&mut |ident| {
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
});
}
}

impl<'a> Binder for FormalParameter<'a> {
// Binds the FormalParameter of a function or method.
fn bind(&self, builder: &mut SemanticBuilder) {
let parent_kind = builder.nodes.parent_kind(builder.current_node_id).unwrap();
let AstKind::FormalParameters(parameters) = parent_kind else { unreachable!() };

if parameters.kind.is_signature() {
return;
}

let includes = SymbolFlags::FunctionScopedVariable;

let is_not_allowed_duplicate_parameters = matches!(
self.kind,
parameters.kind,
// ArrowFormalParameters: UniqueFormalParameters
FormalParameterKind::ArrowFormalParameters |
// UniqueFormalParameters : FormalParameters
Expand All @@ -199,20 +228,18 @@ impl<'a> Binder for FormalParameters<'a> {
builder.strict_mode() ||
// FormalParameters : FormalParameterList
// * It is a Syntax Error if IsSimpleParameterList of FormalParameterList is false and BoundNames of FormalParameterList contains any duplicate elements.
!self.is_simple_parameter_list();
!parameters.is_simple_parameter_list();

let excludes = if is_not_allowed_duplicate_parameters {
SymbolFlags::FunctionScopedVariable | SymbolFlags::FunctionScopedVariableExcludes
} else {
SymbolFlags::FunctionScopedVariableExcludes
};
let is_signature = self.kind == FormalParameterKind::Signature;
if !is_signature {
self.bound_names(&mut |ident| {
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
});
}

self.bound_names(&mut |ident| {
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
});
}
}

Expand Down
7 changes: 5 additions & 2 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,11 @@ impl<'a> SemanticBuilder<'a> {
&self.nodes,
);
}
AstKind::FormalParameters(params) => {
params.bind(self);
AstKind::RestElement(element) => {
element.bind(self);
}
AstKind::FormalParameter(param) => {
param.bind(self);
}
AstKind::CatchClause(clause) => {
clause.bind(self);
Expand Down

0 comments on commit 8bccdab

Please sign in to comment.