Skip to content

Commit 9b92919

Browse files
committed
feat(semantic): check redeclaration of function declaration and class declaration (#10093)
Preparing for #10094. This will lead to a duplicate error of redeclaration of function and class, but it will be removed in #10094.
1 parent 84a3490 commit 9b92919

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

crates/oxc_semantic/src/checker/javascript.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,21 @@ pub fn check_function_redeclaration(func: &Function, ctx: &SemanticBuilder<'_>)
492492
ctx.error(redeclaration(&id.name, prev.span, id.span));
493493
}
494494

495+
pub fn check_class_redeclaration(class: &Class, ctx: &SemanticBuilder<'_>) {
496+
let Some(id) = &class.id else { return };
497+
let symbol_id = id.symbol_id();
498+
499+
let redeclarations = ctx.scoping.symbol_redeclarations(symbol_id);
500+
let Some(prev) = redeclarations.iter().nth_back(1) else {
501+
// No redeclarations
502+
return;
503+
};
504+
505+
if prev.flags.contains(SymbolFlags::Function) {
506+
ctx.error(redeclaration(&id.name, prev.span, id.span));
507+
}
508+
}
509+
495510
fn reg_exp_flag_u_and_v(span: Span) -> OxcDiagnostic {
496511
OxcDiagnostic::error(
497512
"The 'u' and 'v' regular expression flags cannot be enabled at the same time",

crates/oxc_semantic/src/checker/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
7676
}
7777
AstKind::Class(class) => {
7878
js::check_class(class, node, ctx);
79+
if !is_typescript {
80+
js::check_class_redeclaration(class, ctx);
81+
}
7982
ts::check_class(class, ctx);
8083
}
8184
AstKind::Function(func) if !is_typescript => {

tasks/coverage/snapshots/parser_test262.snap

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,6 +2691,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
26912691
× Identifier `f` has already been declared
26922692
╭─[test262/test/language/block-scope/syntax/redeclaration/async-function-name-redeclaration-attempt-with-class.js:24:18]
26932693
23 │
2694+
24 │ { async function f() {} class f {} }
2695+
· ┬ ┬
2696+
· │ ╰── It can not be redeclared here
2697+
· ╰── `f` has already been declared here
2698+
╰────
2699+
2700+
× Identifier `f` has already been declared
2701+
╭─[test262/test/language/block-scope/syntax/redeclaration/async-function-name-redeclaration-attempt-with-class.js:24:18]
2702+
23 │
26942703
24 │ { async function f() {} class f {} }
26952704
· ┬ ┬
26962705
· │ ╰── It can not be redeclared here
@@ -2763,6 +2772,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
27632772
× Identifier `f` has already been declared
27642773
╭─[test262/test/language/block-scope/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-class.js:24:19]
27652774
23 │
2775+
24 │ { async function* f() {} class f {} }
2776+
· ┬ ┬
2777+
· │ ╰── It can not be redeclared here
2778+
· ╰── `f` has already been declared here
2779+
╰────
2780+
2781+
× Identifier `f` has already been declared
2782+
╭─[test262/test/language/block-scope/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-class.js:24:19]
2783+
23 │
27662784
24 │ { async function* f() {} class f {} }
27672785
· ┬ ┬
27682786
· │ ╰── It can not be redeclared here
@@ -3064,6 +3082,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
30643082
× Identifier `f` has already been declared
30653083
╭─[test262/test/language/block-scope/syntax/redeclaration/function-name-redeclaration-attempt-with-class.js:23:12]
30663084
22 │
3085+
23 │ { function f() {} class f {} }
3086+
· ┬ ┬
3087+
· │ ╰── It can not be redeclared here
3088+
· ╰── `f` has already been declared here
3089+
╰────
3090+
3091+
× Identifier `f` has already been declared
3092+
╭─[test262/test/language/block-scope/syntax/redeclaration/function-name-redeclaration-attempt-with-class.js:23:12]
3093+
22 │
30673094
23 │ { function f() {} class f {} }
30683095
· ┬ ┬
30693096
· │ ╰── It can not be redeclared here
@@ -3136,6 +3163,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
31363163
× Identifier `f` has already been declared
31373164
╭─[test262/test/language/block-scope/syntax/redeclaration/generator-name-redeclaration-attempt-with-class.js:24:13]
31383165
23 │
3166+
24 │ { function* f() {} class f {} }
3167+
· ┬ ┬
3168+
· │ ╰── It can not be redeclared here
3169+
· ╰── `f` has already been declared here
3170+
╰────
3171+
3172+
× Identifier `f` has already been declared
3173+
╭─[test262/test/language/block-scope/syntax/redeclaration/generator-name-redeclaration-attempt-with-class.js:24:13]
3174+
23 │
31393175
24 │ { function* f() {} class f {} }
31403176
· ┬ ┬
31413177
· │ ╰── It can not be redeclared here
@@ -38252,6 +38288,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
3825238288
× Identifier `f` has already been declared
3825338289
╭─[test262/test/language/statements/switch/syntax/redeclaration/async-function-name-redeclaration-attempt-with-class.js:24:37]
3825438290
23 │
38291+
24 │ switch (0) { case 1: async function f() {} default: class f {} }
38292+
· ┬ ┬
38293+
· │ ╰── It can not be redeclared here
38294+
· ╰── `f` has already been declared here
38295+
╰────
38296+
38297+
× Identifier `f` has already been declared
38298+
╭─[test262/test/language/statements/switch/syntax/redeclaration/async-function-name-redeclaration-attempt-with-class.js:24:37]
38299+
23 │
3825538300
24 │ switch (0) { case 1: async function f() {} default: class f {} }
3825638301
· ┬ ┬
3825738302
· │ ╰── It can not be redeclared here
@@ -38324,6 +38369,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
3832438369
× Identifier `f` has already been declared
3832538370
╭─[test262/test/language/statements/switch/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-class.js:24:38]
3832638371
23 │
38372+
24 │ switch (0) { case 1: async function* f() {} default: class f {} }
38373+
· ┬ ┬
38374+
· │ ╰── It can not be redeclared here
38375+
· ╰── `f` has already been declared here
38376+
╰────
38377+
38378+
× Identifier `f` has already been declared
38379+
╭─[test262/test/language/statements/switch/syntax/redeclaration/async-generator-name-redeclaration-attempt-with-class.js:24:38]
38380+
23 │
3832738381
24 │ switch (0) { case 1: async function* f() {} default: class f {} }
3832838382
· ┬ ┬
3832938383
· │ ╰── It can not be redeclared here
@@ -38540,6 +38594,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
3854038594
× Identifier `f` has already been declared
3854138595
╭─[test262/test/language/statements/switch/syntax/redeclaration/function-name-redeclaration-attempt-with-class.js:23:31]
3854238596
22 │
38597+
23 │ switch (0) { case 1: function f() {} default: class f {} }
38598+
· ┬ ┬
38599+
· │ ╰── It can not be redeclared here
38600+
· ╰── `f` has already been declared here
38601+
╰────
38602+
38603+
× Identifier `f` has already been declared
38604+
╭─[test262/test/language/statements/switch/syntax/redeclaration/function-name-redeclaration-attempt-with-class.js:23:31]
38605+
22 │
3854338606
23 │ switch (0) { case 1: function f() {} default: class f {} }
3854438607
· ┬ ┬
3854538608
· │ ╰── It can not be redeclared here
@@ -38612,6 +38675,15 @@ Expect to Parse: tasks/coverage/test262/test/language/statements/function/S14_A5
3861238675
× Identifier `f` has already been declared
3861338676
╭─[test262/test/language/statements/switch/syntax/redeclaration/generator-name-redeclaration-attempt-with-class.js:24:32]
3861438677
23 │
38678+
24 │ switch (0) { case 1: function* f() {} default: class f {} }
38679+
· ┬ ┬
38680+
· │ ╰── It can not be redeclared here
38681+
· ╰── `f` has already been declared here
38682+
╰────
38683+
38684+
× Identifier `f` has already been declared
38685+
╭─[test262/test/language/statements/switch/syntax/redeclaration/generator-name-redeclaration-attempt-with-class.js:24:32]
38686+
23 │
3861538687
24 │ switch (0) { case 1: function* f() {} default: class f {} }
3861638688
· ┬ ┬
3861738689
· │ ╰── It can not be redeclared here

0 commit comments

Comments
 (0)