diff --git a/crates/oxc_parser/src/diagnostics.rs b/crates/oxc_parser/src/diagnostics.rs index 7a1ce56761087..05d93172ba936 100644 --- a/crates/oxc_parser/src/diagnostics.rs +++ b/crates/oxc_parser/src/diagnostics.rs @@ -504,10 +504,17 @@ pub fn modifier_cannot_be_used_here(modifier: &Modifier) -> OxcDiagnostic { .with_label(modifier.span) } +/// TS(1028) +#[cold] +pub fn accessibility_modifier_already_seen(modifier: &Modifier) -> OxcDiagnostic { + ts_error("1028", "Accessibility modifier already seen.") + .with_label(modifier.span) + .with_help("Remove the duplicate modifier.") +} + /// TS(1030) #[cold] pub fn modifier_already_seen(modifier: &Modifier) -> OxcDiagnostic { - // OxcDiagnostic::error(format!("TS1030: '{}' modifier already seen.", modifier.kind)) ts_error("1030", format!("{}' modifier already seen.", modifier.kind)) .with_label(modifier.span) .with_help("Remove the duplicate modifier.") diff --git a/crates/oxc_parser/src/ts/types.rs b/crates/oxc_parser/src/ts/types.rs index 3f3e7eb547904..99eba60233fee 100644 --- a/crates/oxc_parser/src/ts/types.rs +++ b/crates/oxc_parser/src/ts/types.rs @@ -1328,8 +1328,13 @@ impl<'a> ParserImpl<'a> { if let Ok(kind) = ModifierKind::try_from(self.cur_kind()) { let modifier = Modifier { kind, span: self.cur_token().span() }; - flags.set(kind.into(), true); - modifiers.push(modifier); + let new_flag = ModifierFlags::from(kind); + if flags.contains(new_flag) { + self.error(diagnostics::accessibility_modifier_already_seen(&modifier)); + } else { + flags.insert(new_flag); + modifiers.push(modifier); + } } else { break; } diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index c8be9aa211ed0..0794909111b11 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -3,7 +3,7 @@ commit: 15392346 parser_typescript Summary: AST Parsed : 6522/6531 (99.86%) Positive Passed: 6511/6531 (99.69%) -Negative Passed: 1287/5754 (22.37%) +Negative Passed: 1288/5754 (22.38%) Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration24.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts @@ -409,7 +409,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constantEnum Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constraintErrors1.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constraintWithIndexedAccess.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constraints0.ts -Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constructorArgsErrors3.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constructorArgsErrors4.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constructorAsType.ts Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/constructorInvocationWithTooFewTypeArgs.ts @@ -6965,6 +6964,15 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private 3 │ } ╰──── + × TS(1028): Accessibility modifier already seen. + ╭─[typescript/tests/cases/compiler/constructorArgsErrors3.ts:2:25] + 1 │ class foo { + 2 │ constructor (public public a: number) { + · ────── + 3 │ } + ╰──── + help: Remove the duplicate modifier. + × TS(1090): 'export' modifier cannot appear on a parameter. ╭─[typescript/tests/cases/compiler/constructorArgsErrors5.ts:2:18] 1 │ class foo { @@ -14664,6 +14672,15 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private ╰──── help: Remove the duplicate modifier. + × TS(1028): Accessibility modifier already seen. + ╭─[typescript/tests/cases/conformance/classes/constructorDeclarations/constructorParameters/readonlyReadonly.ts:3:26] + 2 │ readonly readonly x: number; + 3 │ constructor(readonly readonly y: number) {} + · ──────── + 4 │ } + ╰──── + help: Remove the duplicate modifier. + × Super calls are not permitted outside constructors or in nested functions inside constructors. ╭─[typescript/tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassConstructorWithoutSuperCall.ts:24:31] 23 │ constructor() { // error