Skip to content

Commit e3effc6

Browse files
Boshenclaude
andcommitted
feat(parser): add ts error 1540 for TSModuleDeclaration
Report TS1540 when using the `module` keyword with an identifier name instead of a string literal: - `module M {}` → error - `declare module M {}` → error - `namespace M {}` → ok - `declare module "foo" {}` → ok Ref: microsoft/TypeScript#62876 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1778055 commit e3effc6

4 files changed

Lines changed: 60 additions & 8 deletions

File tree

crates/oxc_parser/src/diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,16 @@ pub fn optional_element_cannot_follow_rest_element(span: Span, rest_span: Span)
374374
])
375375
}
376376

377+
/// A 'namespace' declaration should not be declared using the 'module' keyword. ts(1540)
378+
#[cold]
379+
pub fn module_declaration_must_have_string_name(span: Span) -> OxcDiagnostic {
380+
ts_error(
381+
"1540",
382+
"A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.",
383+
)
384+
.with_label(span)
385+
}
386+
377387
// A type-only import can specify a default import or named bindings, but not both. ts(1363)
378388
#[cold]
379389
pub fn type_only_import_default_and_named(specifier_span: Span) -> OxcDiagnostic {

crates/oxc_parser/src/ts/statement.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,12 @@ impl<'a> ParserImpl<'a> {
305305
let kind = if self.eat(Kind::Namespace) {
306306
TSModuleDeclarationKind::Namespace
307307
} else {
308+
let module_span = self.cur_token().span();
308309
self.expect(Kind::Module);
309310
if self.at(Kind::Str) {
310311
return self.parse_ambient_external_module_declaration(span, modifiers);
311312
}
313+
self.error(diagnostics::module_declaration_must_have_string_name(module_span));
312314
TSModuleDeclarationKind::Module
313315
};
314316
self.parse_module_or_namespace_declaration(span, kind, modifiers)

tasks/coverage/snapshots/parser_babel.snap

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: fc58af40
33
parser_babel Summary:
44
AST Parsed : 2223/2229 (99.73%)
55
Positive Passed: 2206/2229 (98.97%)
6-
Negative Passed: 1651/1695 (97.40%)
6+
Negative Passed: 1652/1695 (97.46%)
77
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-for-using-of-no-initializer/input.js
88

99
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-property/typescript-invalid-abstract/input.ts
@@ -74,8 +74,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty
7474

7575
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/interface/get-set-invalid-this-parameters/input.ts
7676

77-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/module-namespace/module-identifier-invalid/input.ts
78-
7977
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/regression/keyword-qualified-type-2/input.ts
8078

8179
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/regression/keyword-qualified-type-disallowed/input.ts
@@ -13708,6 +13706,12 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
1370813706
╰────
1370913707
help: Try inserting a semicolon here
1371013708

13709+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
13710+
╭─[babel/packages/babel-parser/test/fixtures/typescript/module-namespace/module-identifier-invalid/input.ts:1:1]
13711+
1 │ module M {}
13712+
· ──────
13713+
╰────
13714+
1371113715
× Expected a semicolon or an implicit semicolon after a statement, but found none
1371213716
╭─[babel/packages/babel-parser/test/fixtures/typescript/module-namespace/module-new-line-error/input.ts:2:4]
1371313717
1 │ module

tasks/coverage/snapshots/parser_typescript.snap

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: f5ccf434
33
parser_typescript Summary:
44
AST Parsed : 9844/9845 (99.99%)
55
Positive Passed: 9836/9845 (99.91%)
6-
Negative Passed: 1498/2549 (58.77%)
6+
Negative Passed: 1500/2549 (58.85%)
77
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts
88

99
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
@@ -342,8 +342,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/es6ModuleInt
342342

343343
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/es6ModuleInternalNamedImports2.ts
344344

345-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/escapedIdentifiers.ts
346-
347345
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/esmNoSynthesizedDefault.ts
348346

349347
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/excessPropertyCheckIntersectionWithRecursiveType.ts
@@ -664,8 +662,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/moduleAugmen
664662

665663
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/moduleAugmentationImportsAndExports3.ts
666664

667-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/moduleKeywordDeprecated.ts
668-
669665
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/moduleProperty2.ts
670666

671667
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/moduleResolutionWithExtensions_unexpected2.ts
@@ -5808,6 +5804,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/statements/Va
58085804
· ────────────────
58095805
╰────
58105806

5807+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
5808+
╭─[typescript/tests/cases/compiler/escapedIdentifiers.ts:25:9]
5809+
24 │ }
5810+
25 │ declare module moduleType\u0032 {
5811+
· ──────
5812+
26 │ export var baz2: number;
5813+
╰────
5814+
58115815
× TS(1030): 'export' modifier already seen.
58125816
╭─[typescript/tests/cases/compiler/exportAlreadySeen.ts:2:12]
58135817
1 │ namespace M {
@@ -8078,6 +8082,38 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/statements/Va
80788082
13 │
80798083
╰────
80808084

8085+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
8086+
╭─[typescript/tests/cases/compiler/moduleKeywordDeprecated.ts:2:1]
8087+
1 │ // Error
8088+
2 │ module notok { }
8089+
· ──────
8090+
3 │ module not.ok { }
8091+
╰────
8092+
8093+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
8094+
╭─[typescript/tests/cases/compiler/moduleKeywordDeprecated.ts:3:1]
8095+
2 │ module notok { }
8096+
3 │ module not.ok { }
8097+
· ──────
8098+
4 │ declare module bad { }
8099+
╰────
8100+
8101+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
8102+
╭─[typescript/tests/cases/compiler/moduleKeywordDeprecated.ts:4:9]
8103+
3 │ module not.ok { }
8104+
4 │ declare module bad { }
8105+
· ──────
8106+
5 │ declare module also.bad { }
8107+
╰────
8108+
8109+
× TS(1540): A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
8110+
╭─[typescript/tests/cases/compiler/moduleKeywordDeprecated.ts:5:9]
8111+
4 │ declare module bad { }
8112+
5 │ declare module also.bad { }
8113+
· ──────
8114+
6 │
8115+
╰────
8116+
80818117
× Expected a semicolon or an implicit semicolon after a statement, but found none
80828118
╭─[typescript/tests/cases/compiler/moduleKeywordRepeatError.ts:3:14]
80838119
2 │

0 commit comments

Comments
 (0)