diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 66742c94f05..3d7e84321a5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1132,13 +1132,15 @@ import { walkUpBindingElementsAndPatterns, walkUpOuterExpressions, walkUpParenthesizedExpressions, - walkUpParenthesizedTypes, - walkUpParenthesizedTypesAndGetParentAndChild, - WhileStatement, - WideningContext, - WithStatement, - WriterContextOut, - YieldExpression, + walkUpParenthesizedTypes, + walkUpParenthesizedTypesAndGetParentAndChild, + Version, + versionMajorMinor, + WhileStatement, + WideningContext, + WithStatement, + WriterContextOut, + YieldExpression, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -47992,16 +47994,47 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - if (isIdentifier(node.name)) { - checkCollisionsForDeclarationName(node, node.name); - if (!(node.flags & (NodeFlags.Namespace | NodeFlags.GlobalAugmentation))) { - const sourceFile = getSourceFileOfNode(node); - const pos = getNonModifierTokenPosOfNode(node); - const span = getSpanOfTokenAtPosition(sourceFile, pos); - suggestionDiagnostics.add( - createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead), - ); - } + if (isIdentifier(node.name)) { + checkCollisionsForDeclarationName(node, node.name); + if (!(node.flags & (NodeFlags.Namespace | NodeFlags.GlobalAugmentation))) { + const sourceFile = getSourceFileOfNode(node); + const pos = getNonModifierTokenPosOfNode(node); + const span = getSpanOfTokenAtPosition(sourceFile, pos); + + // Check if we should generate an error (TS 6.0+) or suggestion (older versions) + const currentVersion = new Version(versionMajorMinor); + const errorVersion = new Version("6.0"); + const shouldError = currentVersion.compareTo(errorVersion) >= Comparison.EqualTo; + + // Check if ignoreDeprecations should suppress this error + let shouldSuppress = false; + if (shouldError && compilerOptions.ignoreDeprecations) { + // Only valid ignoreDeprecations values: "5.0" and "6.0" + if (compilerOptions.ignoreDeprecations === "6.0") { + shouldSuppress = true; + } + } + + if (shouldError && !shouldSuppress) { + // In TypeScript 6.0+, this is an error unless suppressed by ignoreDeprecations + const errorDiagnostic = createFileDiagnostic( + sourceFile, + span.start, + span.length, + Diagnostics.The_module_keyword_is_not_allowed_for_namespace_declarations_Use_the_namespace_keyword_instead + ); + diagnostics.add(errorDiagnostic); + } else { + // In older versions or when suppressed, keep as suggestion + const suggestionDiagnostic = createFileDiagnostic( + sourceFile, + span.start, + span.length, + Diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead + ); + suggestionDiagnostics.add(suggestionDiagnostic); + } + } } checkExportsOnMergedDeclarations(node); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 22ac200a0dc..d44e112cbbc 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1820,10 +1820,14 @@ "category": "Error", "code": 1539 }, - "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.": { - "category": "Suggestion", - "code": 1540, - "reportsDeprecated": true + "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.": { + "category": "Suggestion", + "code": 1540, + "reportsDeprecated": true + }, + "The 'module' keyword is not allowed for namespace declarations. Use the 'namespace' keyword instead.": { + "category": "Error", + "code": 1547 }, "Type-only import of an ECMAScript module from a CommonJS module must have a 'resolution-mode' attribute.": { "category": "Error", diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts new file mode 100644 index 00000000000..9c6a6315d20 --- /dev/null +++ b/tests/cases/fourslash/moduleDeclarationDeprecated_error1.ts @@ -0,0 +1,27 @@ +/// + +// @Filename: a.ts +////[|module|] mod1 { export let x: number } +////declare [|module|] mod2 { export let x: number } +////export [|module|] mod3 { export let x: number } +////export declare [|module|] mod4 { export let x: number } +////namespace mod5 { export let x: number } +////declare namespace mod6 { export let x: number } +////mod1.x = 1; +////mod2.x = 1; +////mod5.x = 1; +////mod6.x = 1; + +// @Filename: b.ts +////declare module "global-ambient-module" {} + +goTo.file("a.ts") +const errorDiagnostics = test.ranges().map(range => ({ + code: 1547, + message: "The 'module' keyword is not allowed for namespace declarations. Use the 'namespace' keyword instead.", + range, +})); +verify.getSemanticDiagnostics(errorDiagnostics) + +goTo.file("b.ts") +verify.getSemanticDiagnostics([]) \ No newline at end of file diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts new file mode 100644 index 00000000000..6ca2f2d05e2 --- /dev/null +++ b/tests/cases/fourslash/moduleDeclarationDeprecated_ignoreDeprecations.ts @@ -0,0 +1,31 @@ +/// + +// @ignoreDeprecations: 6.0 +// @Filename: a.ts +////[|module|] mod1 { export let x: number } +////declare [|module|] mod2 { export let x: number } +////export [|module|] mod3 { export let x: number } +////export declare [|module|] mod4 { export let x: number } +////namespace mod5 { export let x: number } +////declare namespace mod6 { export let x: number } +////declare module "module-augmentation" {} +////declare global {} +////mod1.x = 1; +////mod2.x = 1; +////mod5.x = 1; +////mod6.x = 1; + +// @Filename: b.ts +////module "global-ambient-module" {} + +goTo.file("a.ts") +const diagnostics = test.ranges().map(range => ({ + code: 1540, + message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.", + reportsDeprecated: true as true, + range, +})); +verify.getSuggestionDiagnostics(diagnostics) + +goTo.file("b.ts") +verify.getSuggestionDiagnostics([]) \ No newline at end of file diff --git a/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts b/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts index 5554300a5a0..96f34910f7d 100644 --- a/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts +++ b/tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts @@ -1,30 +1,31 @@ -/// -// @Filename: a.ts -////[|module|] mod1 { export let x: number } -////declare [|module|] mod2 { export let x: number } -////export [|module|] mod3 { export let x: number } -////export declare [|module|] mod4 { export let x: number } -////namespace mod5 { export let x: number } -////declare namespace mod6 { export let x: number } -////declare module "module-augmentation" {} -////declare global {} -////mod1.x = 1; -////mod2.x = 1; -////mod5.x = 1; -////mod6.x = 1; - -// @Filename: b.ts -////module "global-ambient-module" {} - -goTo.file("a.ts") -const diagnostics = test.ranges().map(range => ({ - code: 1540, - message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.", - reportsDeprecated: true, - range, -})); -verify.getSuggestionDiagnostics(diagnostics) - -goTo.file("b.ts") +/// +// @ignoreDeprecations: 6.0 +// @Filename: a.ts +////[|module|] mod1 { export let x: number } +////declare [|module|] mod2 { export let x: number } +////export [|module|] mod3 { export let x: number } +////export declare [|module|] mod4 { export let x: number } +////namespace mod5 { export let x: number } +////declare namespace mod6 { export let x: number } +////declare module "module-augmentation" {} +////declare global {} +////mod1.x = 1; +////mod2.x = 1; +////mod5.x = 1; +////mod6.x = 1; + +// @Filename: b.ts +////module "global-ambient-module" {} + +goTo.file("a.ts") +const diagnostics = test.ranges().map(range => ({ + code: 1540, + message: "A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.", + reportsDeprecated: true as true, + range, +})); +verify.getSuggestionDiagnostics(diagnostics) + +goTo.file("b.ts") verify.getSuggestionDiagnostics([])