Skip to content

Commit fbb2755

Browse files
Copilotjakebailey
andauthored
Error on modules-as-namespaces (#2760)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
1 parent b61c4fa commit fbb2755

13 files changed

Lines changed: 159 additions & 140 deletions

internal/checker/checker.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5013,10 +5013,6 @@ func (c *Checker) checkModuleDeclaration(node *ast.Node) {
50135013
}
50145014
if ast.IsIdentifier(node.Name()) {
50155015
c.checkCollisionsForDeclarationName(node, node.Name())
5016-
if node.AsModuleDeclaration().Keyword == ast.KindModuleKeyword {
5017-
tokenRange := getNonModifierTokenRangeOfNode(node)
5018-
c.suggestionDiagnostics.Add(ast.NewDiagnostic(ast.GetSourceFileOfNode(node), tokenRange, diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead))
5019-
}
50205016
}
50215017
c.checkExportsOnMergedDeclarations(node)
50225018
symbol := c.getSymbolOfDeclaration(node)

internal/checker/utilities.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,14 +1262,6 @@ func minAndMax[T any](slice []T, getValue func(value T) int) (int, int) {
12621262
return minValue, maxValue
12631263
}
12641264

1265-
func getNonModifierTokenRangeOfNode(node *ast.Node) core.TextRange {
1266-
pos := node.Pos()
1267-
if last := ast.FindLastVisibleNode(node.ModifierNodes()); last != nil {
1268-
pos = last.Pos()
1269-
}
1270-
return scanner.GetRangeOfTokenAtPosition(ast.GetSourceFileOfNode(node), pos)
1271-
}
1272-
12731265
type FeatureMapEntry struct {
12741266
lib string
12751267
props []string

internal/parser/parser.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,19 +2082,20 @@ func (p *Parser) parseEnumDeclaration(pos int, jsdoc jsdocScannerInfo, modifiers
20822082
}
20832083

20842084
func (p *Parser) parseModuleDeclaration(pos int, jsdoc jsdocScannerInfo, modifiers *ast.ModifierList) *ast.Statement {
2085-
keyword := ast.KindModuleKeyword
20862085
if p.token == ast.KindGlobalKeyword {
20872086
// global augmentation
20882087
return p.parseAmbientExternalModuleDeclaration(pos, jsdoc, modifiers)
20892088
} else if p.parseOptional(ast.KindNamespaceKeyword) {
2090-
keyword = ast.KindNamespaceKeyword
2089+
// namespace keyword always produces a namespace declaration
2090+
return p.parseModuleOrNamespaceDeclaration(pos, jsdoc, modifiers, false /*nested*/, false /*isIllegalModuleKeyword*/)
20912091
} else {
20922092
p.parseExpected(ast.KindModuleKeyword)
20932093
if p.token == ast.KindStringLiteral {
20942094
return p.parseAmbientExternalModuleDeclaration(pos, jsdoc, modifiers)
20952095
}
2096+
// `module X {}` is illegal; use `namespace` instead
2097+
return p.parseModuleOrNamespaceDeclaration(pos, jsdoc, modifiers, false /*nested*/, true /*isIllegalModuleKeyword*/)
20962098
}
2097-
return p.parseModuleOrNamespaceDeclaration(pos, jsdoc, modifiers, false /*nested*/, keyword)
20982099
}
20992100

21002101
func (p *Parser) parseAmbientExternalModuleDeclaration(pos int, jsdoc jsdocScannerInfo, modifiers *ast.ModifierList) *ast.Node {
@@ -2133,25 +2134,29 @@ func (p *Parser) parseModuleBlock() *ast.Node {
21332134
return p.finishNode(p.factory.NewModuleBlock(statements), pos)
21342135
}
21352136

2136-
func (p *Parser) parseModuleOrNamespaceDeclaration(pos int, jsdoc jsdocScannerInfo, modifiers *ast.ModifierList, nested bool, keyword ast.Kind) *ast.Node {
2137+
func (p *Parser) parseModuleOrNamespaceDeclaration(pos int, jsdoc jsdocScannerInfo, modifiers *ast.ModifierList, nested bool, isIllegalModuleKeyword bool) *ast.Node {
21372138
saveHasAwaitIdentifier := p.statementHasAwaitIdentifier
21382139
var name *ast.Node
21392140
if nested {
21402141
name = p.parseIdentifierName()
21412142
} else {
21422143
name = p.parseIdentifier()
21432144
}
2145+
if isIllegalModuleKeyword && !nested {
2146+
errorStart := scanner.SkipTrivia(p.sourceText, name.Pos())
2147+
p.parseErrorAt(errorStart, name.End(), diagnostics.A_namespace_declaration_should_not_be_declared_using_the_module_keyword_Please_use_the_namespace_keyword_instead)
2148+
}
21442149
var body *ast.Node
21452150
if p.parseOptional(ast.KindDotToken) {
21462151
implicitExport := p.factory.NewModifier(ast.KindExportKeyword)
21472152
implicitExport.Loc = core.NewTextRange(p.nodePos(), p.nodePos())
21482153
implicitExport.Flags = ast.NodeFlagsReparsed
21492154
implicitModifiers := p.newModifierList(implicitExport.Loc, p.nodeSlicePool.NewSlice1(implicitExport))
2150-
body = p.parseModuleOrNamespaceDeclaration(p.nodePos(), 0 /*jsdoc*/, implicitModifiers, true /*nested*/, keyword)
2155+
body = p.parseModuleOrNamespaceDeclaration(p.nodePos(), 0 /*jsdoc*/, implicitModifiers, true /*nested*/, isIllegalModuleKeyword)
21512156
} else {
21522157
body = p.parseModuleBlock()
21532158
}
2154-
result := p.finishNode(p.factory.NewModuleDeclaration(modifiers, keyword, name, body), pos)
2159+
result := p.finishNode(p.factory.NewModuleDeclaration(modifiers, ast.KindNamespaceKeyword, name, body), pos)
21552160
p.withJSDoc(result, jsdoc)
21562161
p.checkJSSyntax(result)
21572162
p.statementHasAwaitIdentifier = saveHasAwaitIdentifier

internal/printer/printer_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,6 @@ func TestEmit(t *testing.T) {
255255
{title: "EnumDeclaration#1", input: `enum a{}`, output: "enum a {\n}"},
256256
{title: "EnumDeclaration#2", input: `enum a{b}`, output: "enum a {\n b\n}"},
257257
{title: "EnumDeclaration#3", input: `enum a{b=c}`, output: "enum a {\n b = c\n}"},
258-
{title: "ModuleDeclaration#1", input: `module a{}`, output: "module a { }"},
259-
{title: "ModuleDeclaration#2", input: `module a.b{}`, output: "module a.b { }"},
260258
{title: "ModuleDeclaration#3", input: `module "a";`, output: "module \"a\";"},
261259
{title: "ModuleDeclaration#4", input: `module "a"{}`, output: "module \"a\" { }"},
262260
{title: "ModuleDeclaration#5", input: `namespace a{}`, output: "namespace a { }"},

testdata/baselines/reference/compiler/reachabilityChecks11.errors.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,40 @@ reachabilityChecks11.ts(69,5): error TS7027: Unreachable code detected.
1111
// while (true);
1212
var x = 1;
1313

14-
module A {
14+
namespace A {
1515
while (true);
1616
let x;
1717
~~~~~~
1818
!!! error TS7027: Unreachable code detected.
1919
}
2020

21-
module A1 {
21+
namespace A1 {
2222
do {} while(true);
23-
module A {
23+
namespace A {
2424
interface F {}
2525
}
2626
}
2727

28-
module A2 {
28+
namespace A2 {
2929
while (true);
30-
module A {
31-
~~~~~~~~~~
30+
namespace A {
31+
~~~~~~~~~~~~~
3232
var x = 1;
3333
~~~~~~~~~~~~~~~~~~
3434
}
3535
~~~~~
3636
!!! error TS7027: Unreachable code detected.
3737
}
3838

39-
module A3 {
39+
namespace A3 {
4040
while (true);
4141
type T = string;
4242
}
4343

44-
module A4 {
44+
namespace A4 {
4545
while (true);
46-
module A {
47-
~~~~~~~~~~
46+
namespace A {
47+
~~~~~~~~~~~~~
4848
const enum E { X }
4949
~~~~~~~~~~~~~~~~~~~~~~~~~~
5050
}
@@ -73,9 +73,9 @@ reachabilityChecks11.ts(69,5): error TS7027: Unreachable code detected.
7373
!!! error TS7027: Unreachable code detected.
7474
}
7575

76-
module B {
76+
namespace B {
7777
for (; ;);
78-
module C {
78+
namespace C {
7979
}
8080
}
8181

testdata/baselines/reference/compiler/reachabilityChecks11.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,33 @@
44
// while (true);
55
var x = 1;
66

7-
module A {
7+
namespace A {
88
while (true);
99
let x;
1010
}
1111

12-
module A1 {
12+
namespace A1 {
1313
do {} while(true);
14-
module A {
14+
namespace A {
1515
interface F {}
1616
}
1717
}
1818

19-
module A2 {
19+
namespace A2 {
2020
while (true);
21-
module A {
21+
namespace A {
2222
var x = 1;
2323
}
2424
}
2525

26-
module A3 {
26+
namespace A3 {
2727
while (true);
2828
type T = string;
2929
}
3030

31-
module A4 {
31+
namespace A4 {
3232
while (true);
33-
module A {
33+
namespace A {
3434
const enum E { X }
3535
}
3636
}
@@ -51,9 +51,9 @@ function f2() {
5151
}
5252
}
5353

54-
module B {
54+
namespace B {
5555
for (; ;);
56-
module C {
56+
namespace C {
5757
}
5858
}
5959

testdata/baselines/reference/compiler/reachabilityChecks11.symbols

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,55 +5,55 @@
55
var x = 1;
66
>x : Symbol(x, Decl(reachabilityChecks11.ts, 1, 3))
77

8-
module A {
8+
namespace A {
99
>A : Symbol(A, Decl(reachabilityChecks11.ts, 1, 10))
1010

1111
while (true);
1212
let x;
1313
>x : Symbol(x, Decl(reachabilityChecks11.ts, 5, 7))
1414
}
1515

16-
module A1 {
16+
namespace A1 {
1717
>A1 : Symbol(A1, Decl(reachabilityChecks11.ts, 6, 1))
1818

1919
do {} while(true);
20-
module A {
20+
namespace A {
2121
>A : Symbol(A, Decl(reachabilityChecks11.ts, 9, 22))
2222

2323
interface F {}
24-
>F : Symbol(F, Decl(reachabilityChecks11.ts, 10, 14))
24+
>F : Symbol(F, Decl(reachabilityChecks11.ts, 10, 17))
2525
}
2626
}
2727

28-
module A2 {
28+
namespace A2 {
2929
>A2 : Symbol(A2, Decl(reachabilityChecks11.ts, 13, 1))
3030

3131
while (true);
32-
module A {
32+
namespace A {
3333
>A : Symbol(A, Decl(reachabilityChecks11.ts, 16, 17))
3434

3535
var x = 1;
3636
>x : Symbol(x, Decl(reachabilityChecks11.ts, 18, 11))
3737
}
3838
}
3939

40-
module A3 {
40+
namespace A3 {
4141
>A3 : Symbol(A3, Decl(reachabilityChecks11.ts, 20, 1))
4242

4343
while (true);
4444
type T = string;
4545
>T : Symbol(T, Decl(reachabilityChecks11.ts, 23, 17))
4646
}
4747

48-
module A4 {
48+
namespace A4 {
4949
>A4 : Symbol(A4, Decl(reachabilityChecks11.ts, 25, 1))
5050

5151
while (true);
52-
module A {
52+
namespace A {
5353
>A : Symbol(A, Decl(reachabilityChecks11.ts, 28, 17))
5454

5555
const enum E { X }
56-
>E : Symbol(E, Decl(reachabilityChecks11.ts, 29, 14))
56+
>E : Symbol(E, Decl(reachabilityChecks11.ts, 29, 17))
5757
>X : Symbol(E.X, Decl(reachabilityChecks11.ts, 30, 22))
5858
}
5959
}
@@ -84,11 +84,11 @@ function f2() {
8484
}
8585
}
8686

87-
module B {
87+
namespace B {
8888
>B : Symbol(B, Decl(reachabilityChecks11.ts, 48, 1))
8989

9090
for (; ;);
91-
module C {
91+
namespace C {
9292
>C : Symbol(C, Decl(reachabilityChecks11.ts, 51, 14))
9393
}
9494
}

testdata/baselines/reference/compiler/reachabilityChecks11.types

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var x = 1;
66
>x : number
77
>1 : 1
88

9-
module A {
9+
namespace A {
1010
>A : typeof A
1111

1212
while (true);
@@ -16,24 +16,24 @@ module A {
1616
>x : any
1717
}
1818

19-
module A1 {
19+
namespace A1 {
2020
>A1 : typeof A1
2121

2222
do {} while(true);
2323
>true : true
2424

25-
module A {
25+
namespace A {
2626
interface F {}
2727
}
2828
}
2929

30-
module A2 {
30+
namespace A2 {
3131
>A2 : typeof A2
3232

3333
while (true);
3434
>true : true
3535

36-
module A {
36+
namespace A {
3737
>A : typeof A
3838

3939
var x = 1;
@@ -42,7 +42,7 @@ module A2 {
4242
}
4343
}
4444

45-
module A3 {
45+
namespace A3 {
4646
>A3 : typeof A3
4747

4848
while (true);
@@ -52,13 +52,13 @@ module A3 {
5252
>T : string
5353
}
5454

55-
module A4 {
55+
namespace A4 {
5656
>A4 : typeof A4
5757

5858
while (true);
5959
>true : true
6060

61-
module A {
61+
namespace A {
6262
const enum E { X }
6363
>E : E
6464
>X : E.X
@@ -93,11 +93,11 @@ function f2() {
9393
}
9494
}
9595

96-
module B {
96+
namespace B {
9797
>B : typeof B
9898

9999
for (; ;);
100-
module C {
100+
namespace C {
101101
}
102102
}
103103

testdata/baselines/reference/submodule/compiler/escapedIdentifiers.errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
escapedIdentifiers.ts(25,16): error TS1540: A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
12
escapedIdentifiers.ts(37,12): error TS2564: Property 'foo1' has no initializer and is not definitely assigned in the constructor.
23
escapedIdentifiers.ts(40,12): error TS2564: Property 'foo2' has no initializer and is not definitely assigned in the constructor.
34

45

5-
==== escapedIdentifiers.ts (2 errors) ====
6+
==== escapedIdentifiers.ts (3 errors) ====
67
/*
78
0 .. \u0030
89
9 .. \u0039
@@ -28,6 +29,8 @@ escapedIdentifiers.ts(40,12): error TS2564: Property 'foo2' has no initializer a
2829
export var baz1: number;
2930
}
3031
declare module moduleType\u0032 {
32+
~~~~~~~~~~~~~~~~
33+
!!! error TS1540: A 'namespace' declaration should not be declared using the 'module' keyword. Please use the 'namespace' keyword instead.
3134
export var baz2: number;
3235
}
3336

0 commit comments

Comments
 (0)