Skip to content
9 changes: 9 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ import {
getNamespaceDeclarationNode,
getNewTargetContainer,
getNonAugmentationDeclaration,
getNonModifierTokenPosOfNode,
getNormalizedAbsolutePath,
getObjectFlags,
getOriginalNode,
Expand Down Expand Up @@ -46011,6 +46012,14 @@ 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),
);
}
}

checkExportsOnMergedDeclarations(node);
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1645,6 +1645,11 @@
"category": "Error",
"code": 1498
},
"A namespace declaration should not be declared using the module keyword. Please use the namespace keyword instead.": {
"category": "Suggestion",
"code": 1499,
"reportsDeprecated": true
},

"The types of '{0}' are incompatible between these types.": {
"category": "Error",
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,16 @@ export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFil
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastDecorator.end);
}

/** @internal */
export function getNonModifierTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number {
const lastModifier = !nodeIsMissing(node) && canHaveModifiers(node) && node.modifiers ? last(node.modifiers) : undefined;
if (!lastModifier) {
return getTokenPosOfNode(node, sourceFile);
}

return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastModifier.end);
}

/** @internal */
export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia = false): string {
return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia);
Expand Down
41 changes: 41 additions & 0 deletions tests/cases/fourslash/moduleDeclarationDeprecated_suggestion1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
///<reference path="fourslash.ts" />
// @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 global {}
////mod1.x = 1;
////mod2.x = 1;
////mod5.x = 1;
////mod6.x = 1;

const ranges = test.ranges();
verify.getSuggestionDiagnostics([
{
"code": 1499,
"message": "A namespace declaration should not be declared using the module keyword. Please use the namespace keyword instead.",
"reportsDeprecated": true,
"range": ranges[0]
},
{
"code": 1499,
"message": "A namespace declaration should not be declared using the module keyword. Please use the namespace keyword instead.",
"reportsDeprecated": true,
"range": ranges[1]
},
{
"code": 1499,
"message": "A namespace declaration should not be declared using the module keyword. Please use the namespace keyword instead.",
"reportsDeprecated": true,
"range": ranges[2]
},
{
"code": 1499,
"message": "A namespace declaration should not be declared using the module keyword. Please use the namespace keyword instead.",
"reportsDeprecated": true,
"range": ranges[3]
},
])