refactor(semantic): improve check function declaration implementation (#1854)

This commit is contained in:
Dunqing 2023-12-31 22:17:56 +08:00 committed by GitHub
parent 8f27a98468
commit bfd5cd92a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -24,7 +24,6 @@ pub struct EarlyErrorJavaScript;
impl EarlyErrorJavaScript { impl EarlyErrorJavaScript {
pub fn run<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) { pub fn run<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
let kind = node.kind(); let kind = node.kind();
check_function_declaration(kind, node, ctx);
match kind { match kind {
AstKind::BindingIdentifier(ident) => { AstKind::BindingIdentifier(ident) => {
@ -47,13 +46,36 @@ impl EarlyErrorJavaScript {
} }
AstKind::MetaProperty(prop) => check_meta_property(prop, node, ctx), AstKind::MetaProperty(prop) => check_meta_property(prop, node, ctx),
AstKind::WithStatement(stmt) => check_with_statement(stmt, ctx), AstKind::WithStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_with_statement(stmt, ctx);
}
AstKind::SwitchStatement(stmt) => check_switch_statement(stmt, ctx), AstKind::SwitchStatement(stmt) => check_switch_statement(stmt, ctx),
AstKind::BreakStatement(stmt) => check_break_statement(stmt, node, ctx), AstKind::BreakStatement(stmt) => check_break_statement(stmt, node, ctx),
AstKind::ContinueStatement(stmt) => check_continue_statement(stmt, node, ctx), AstKind::ContinueStatement(stmt) => check_continue_statement(stmt, node, ctx),
AstKind::LabeledStatement(stmt) => check_labeled_statement(stmt, node, ctx), AstKind::LabeledStatement(stmt) => {
AstKind::ForInStatement(stmt) => check_for_statement_left(&stmt.left, true, node, ctx), check_function_declaration(&stmt.body, true, ctx);
AstKind::ForOfStatement(stmt) => check_for_statement_left(&stmt.left, false, node, ctx), check_labeled_statement(stmt, node, ctx);
}
AstKind::ForInStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_for_statement_left(&stmt.left, true, node, ctx);
}
AstKind::ForOfStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_for_statement_left(&stmt.left, false, node, ctx);
}
AstKind::WhileStatement(WhileStatement { body, .. })
| AstKind::DoWhileStatement(DoWhileStatement { body, .. })
| AstKind::ForStatement(ForStatement { body, .. }) => {
check_function_declaration(body, false, ctx);
}
AstKind::IfStatement(stmt) => {
check_function_declaration(&stmt.consequent, true, ctx);
if let Some(alternate) = &stmt.alternate {
check_function_declaration(alternate, true, ctx);
}
}
AstKind::Class(class) => check_class(class, ctx), AstKind::Class(class) => check_class(class, ctx),
AstKind::Super(sup) => check_super(sup, node, ctx), AstKind::Super(sup) => check_super(sup, node, ctx),
@ -504,8 +526,8 @@ fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &Semant
} }
fn check_function_declaration<'a>( fn check_function_declaration<'a>(
kind: AstKind<'a>, stmt: &Statement<'a>,
_node: &AstNode<'a>, is_if_stmt_or_labeled_stmt: bool,
ctx: &SemanticBuilder<'a>, ctx: &SemanticBuilder<'a>,
) { ) {
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
@ -523,34 +545,13 @@ fn check_function_declaration<'a>(
struct FunctionDeclarationNonStrict(#[label] Span); struct FunctionDeclarationNonStrict(#[label] Span);
// Function declaration not allowed in statement position // Function declaration not allowed in statement position
let check = |stmt: &Statement<'a>| {
if let Statement::Declaration(Declaration::FunctionDeclaration(decl)) = stmt { if let Statement::Declaration(Declaration::FunctionDeclaration(decl)) = stmt {
if ctx.strict_mode() { if ctx.strict_mode() {
ctx.error(FunctionDeclarationStrict(decl.span)); ctx.error(FunctionDeclarationStrict(decl.span));
} else if !matches!(kind, AstKind::IfStatement(_) | AstKind::LabeledStatement(_)) { } else if !is_if_stmt_or_labeled_stmt {
ctx.error(FunctionDeclarationNonStrict(decl.span)); ctx.error(FunctionDeclarationNonStrict(decl.span));
} }
}
}; };
match kind {
AstKind::WithStatement(WithStatement { body, .. })
| AstKind::WhileStatement(WhileStatement { body, .. })
| AstKind::DoWhileStatement(DoWhileStatement { body, .. })
| AstKind::ForStatement(ForStatement { body, .. })
| AstKind::ForInStatement(ForInStatement { body, .. })
| AstKind::ForOfStatement(ForOfStatement { body, .. })
| AstKind::LabeledStatement(LabeledStatement { body, .. }) => {
check(body);
}
AstKind::IfStatement(if_stmt) => {
check(&if_stmt.consequent);
if let Some(alternate) = &if_stmt.alternate {
check(alternate);
}
}
_ => {}
}
} }
fn check_regexp_literal(lit: &RegExpLiteral, ctx: &SemanticBuilder<'_>) { fn check_regexp_literal(lit: &RegExpLiteral, ctx: &SemanticBuilder<'_>) {