Skip to content

Commit 0def080

Browse files
committed
fix expansion of namespaces with non-id names
1 parent 14d8405 commit 0def080

3 files changed

Lines changed: 212 additions & 13 deletions

File tree

src/compiler/checker.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,7 @@ import {
11341134
WithStatement,
11351135
WriterContextOut,
11361136
YieldExpression,
1137+
ModuleName,
11371138
} from "./_namespaces/ts.js";
11381139
import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js";
11391140
import * as performance from "./_namespaces/ts.performance.js";
@@ -9802,7 +9803,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
98029803
// than whatever scope we traverse to them in. That's a bit of a complex rewrite, since we're not _actually_ tracking privates at all in advance,
98039804
// so we don't even have placeholders to fill in.
98049805
if (length(realMembers) || unfolding) {
9805-
const localName = getInternalSymbolName(symbol, symbolName);
9806+
let localName: ModuleName;
9807+
if (unfolding) {
9808+
// Use the same name as symbol display.
9809+
const oldFlags = context.flags;
9810+
context.flags |= NodeBuilderFlags.WriteTypeParametersInQualifiedName | SymbolFormatFlags.UseOnlyExternalAliasing;
9811+
localName = symbolToNode(symbol, context, /*meaning*/ SymbolFlags.All) as ModuleName;
9812+
context.flags = oldFlags;
9813+
}
9814+
else {
9815+
const localText = getInternalSymbolName(symbol, symbolName);
9816+
localName = factory.createIdentifier(localText);
9817+
context.approximateLength += localText.length;
9818+
}
98069819
serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment)));
98079820
}
98089821
if (length(mergedMembers)) {
@@ -9898,7 +9911,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
98989911
// Module symbol emit will take care of module-y members, provided it has exports
98999912
if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) {
99009913
const props = filter(getPropertiesOfType(type), isNamespaceMember);
9901-
serializeAsNamespaceDeclaration(props, localName, modifierFlags, /*suppressNewPrivateContext*/ true);
9914+
context.approximateLength += localName.length;
9915+
serializeAsNamespaceDeclaration(props, factory.createIdentifier(localName), modifierFlags, /*suppressNewPrivateContext*/ true);
99029916
}
99039917
}
99049918

@@ -9919,10 +9933,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
99199933
return signature.declaration;
99209934
}
99219935

9922-
function serializeAsNamespaceDeclaration(props: readonly Symbol[], localName: string, modifierFlags: ModifierFlags, suppressNewPrivateContext: boolean) {
9936+
function serializeAsNamespaceDeclaration(props: readonly Symbol[], localName: ModuleName, modifierFlags: ModifierFlags, suppressNewPrivateContext: boolean) {
9937+
const nodeFlags = isIdentifier(localName) ? NodeFlags.Namespace : NodeFlags.None;
99239938
const unfolding = isUnfolding(context);
99249939
if (length(props)) {
9925-
context.approximateLength += localName.length + 14; // "namespace localName { }"
9940+
context.approximateLength += 14; // "namespace { }"
99269941
const localVsRemoteMap = arrayToMultiMap(props, p => !length(p.declarations) || some(p.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)) || unfolding ? "local" : "remote");
99279942
const localProps = localVsRemoteMap.get("local") || emptyArray;
99289943
// handle remote props first - we need to make an `import` declaration that points at the module containing each remote
@@ -9942,7 +9957,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
99429957

99439958
// Add a namespace
99449959
// Create namespace as non-synthetic so it is usable as an enclosing declaration
9945-
let fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace);
9960+
let fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, localName, factory.createModuleBlock([]), nodeFlags);
99469961
setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration);
99479962
fakespace.locals = createSymbolTable(props);
99489963
fakespace.symbol = props[0].parent!;
@@ -9977,13 +9992,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
99779992
addResult(fakespace, modifierFlags); // namespaces can never be default exported
99789993
}
99799994
else if (unfolding) {
9980-
context.approximateLength += localName.length + 14; // "namespace { }"
9995+
context.approximateLength += 14; // "namespace { }"
99819996
addResult(
99829997
factory.createModuleDeclaration(
99839998
/*modifiers*/ undefined,
9984-
factory.createIdentifier(localName),
9999+
localName,
998510000
factory.createModuleBlock([]),
9986-
NodeFlags.Namespace,
10001+
nodeFlags,
998710002
),
998810003
modifierFlags,
998910004
);

tests/baselines/reference/quickinfoVerbosityNamespace.baseline

Lines changed: 183 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@
7171
// var z = 2;
7272
// }
7373

74+
=== /tests/cases/fourslash/foo.ts ===
75+
// export function foo() { return "foo"; }
76+
// import("./foo")
77+
// ^^^^^^^
78+
// | ----------------------------------------------------------------------
79+
// | module "/tests/cases/fourslash/foo" {
80+
// | function foo(): string;
81+
// | namespace foo { }
82+
// | }
83+
// | (verbosity level: 1)
84+
// | ----------------------------------------------------------------------
85+
// ^^^^^^^
86+
// | ----------------------------------------------------------------------
87+
// | module "/tests/cases/fourslash/foo"
88+
// | (verbosity level: 0)
89+
// | ----------------------------------------------------------------------
90+
// var x = import("./foo")
91+
7492
=== /4.ts ===
7593
// class Foo<T> {
7694
// y!: T;
@@ -276,7 +294,7 @@
276294
},
277295
{
278296
"text": "Foo",
279-
"kind": "text"
297+
"kind": "className"
280298
},
281299
{
282300
"text": " ",
@@ -468,7 +486,7 @@
468486
},
469487
{
470488
"text": "ns",
471-
"kind": "text"
489+
"kind": "moduleName"
472490
},
473491
{
474492
"text": " ",
@@ -688,7 +706,7 @@
688706
},
689707
{
690708
"text": "ns",
691-
"kind": "text"
709+
"kind": "moduleName"
692710
},
693711
{
694712
"text": " ",
@@ -980,7 +998,7 @@
980998
},
981999
{
9821000
"text": "Two",
983-
"kind": "text"
1001+
"kind": "moduleName"
9841002
},
9851003
{
9861004
"text": " ",
@@ -1124,7 +1142,7 @@
11241142
},
11251143
{
11261144
"text": "Two",
1127-
"kind": "text"
1145+
"kind": "moduleName"
11281146
},
11291147
{
11301148
"text": " ",
@@ -1356,6 +1374,158 @@
13561374
},
13571375
{
13581376
"text": "OnlyLocal",
1377+
"kind": "moduleName"
1378+
},
1379+
{
1380+
"text": " ",
1381+
"kind": "space"
1382+
},
1383+
{
1384+
"text": "{",
1385+
"kind": "punctuation"
1386+
},
1387+
{
1388+
"text": " ",
1389+
"kind": "space"
1390+
},
1391+
{
1392+
"text": "}",
1393+
"kind": "punctuation"
1394+
}
1395+
],
1396+
"documentation": [],
1397+
"canIncreaseVerbosityLevel": false,
1398+
"verbosityLevel": 1
1399+
}
1400+
},
1401+
{
1402+
"marker": {
1403+
"fileName": "/tests/cases/fourslash/foo.ts",
1404+
"position": 48,
1405+
"name": "5"
1406+
},
1407+
"item": {
1408+
"kind": "module",
1409+
"kindModifiers": "",
1410+
"textSpan": {
1411+
"start": 47,
1412+
"length": 7
1413+
},
1414+
"displayParts": [
1415+
{
1416+
"text": "module",
1417+
"kind": "keyword"
1418+
},
1419+
{
1420+
"text": " ",
1421+
"kind": "space"
1422+
},
1423+
{
1424+
"text": "\"/tests/cases/fourslash/foo\"",
1425+
"kind": "stringLiteral"
1426+
}
1427+
],
1428+
"documentation": [],
1429+
"canIncreaseVerbosityLevel": true,
1430+
"verbosityLevel": 0
1431+
}
1432+
},
1433+
{
1434+
"marker": {
1435+
"fileName": "/tests/cases/fourslash/foo.ts",
1436+
"position": 48,
1437+
"name": "5"
1438+
},
1439+
"item": {
1440+
"kind": "module",
1441+
"kindModifiers": "",
1442+
"textSpan": {
1443+
"start": 47,
1444+
"length": 7
1445+
},
1446+
"displayParts": [
1447+
{
1448+
"text": "module",
1449+
"kind": "keyword"
1450+
},
1451+
{
1452+
"text": " ",
1453+
"kind": "space"
1454+
},
1455+
{
1456+
"text": "\"/tests/cases/fourslash/foo\"",
1457+
"kind": "stringLiteral"
1458+
},
1459+
{
1460+
"text": " ",
1461+
"kind": "space"
1462+
},
1463+
{
1464+
"text": "{",
1465+
"kind": "punctuation"
1466+
},
1467+
{
1468+
"text": "\n",
1469+
"kind": "lineBreak"
1470+
},
1471+
{
1472+
"text": " ",
1473+
"kind": "space"
1474+
},
1475+
{
1476+
"text": "function",
1477+
"kind": "keyword"
1478+
},
1479+
{
1480+
"text": " ",
1481+
"kind": "space"
1482+
},
1483+
{
1484+
"text": "foo",
1485+
"kind": "text"
1486+
},
1487+
{
1488+
"text": "(",
1489+
"kind": "punctuation"
1490+
},
1491+
{
1492+
"text": ")",
1493+
"kind": "punctuation"
1494+
},
1495+
{
1496+
"text": ":",
1497+
"kind": "punctuation"
1498+
},
1499+
{
1500+
"text": " ",
1501+
"kind": "space"
1502+
},
1503+
{
1504+
"text": "string",
1505+
"kind": "keyword"
1506+
},
1507+
{
1508+
"text": ";",
1509+
"kind": "punctuation"
1510+
},
1511+
{
1512+
"text": "\n",
1513+
"kind": "lineBreak"
1514+
},
1515+
{
1516+
"text": " ",
1517+
"kind": "space"
1518+
},
1519+
{
1520+
"text": "namespace",
1521+
"kind": "keyword"
1522+
},
1523+
{
1524+
"text": " ",
1525+
"kind": "space"
1526+
},
1527+
{
1528+
"text": "foo",
13591529
"kind": "text"
13601530
},
13611531
{
@@ -1370,6 +1540,14 @@
13701540
"text": " ",
13711541
"kind": "space"
13721542
},
1543+
{
1544+
"text": "}",
1545+
"kind": "punctuation"
1546+
},
1547+
{
1548+
"text": "\n",
1549+
"kind": "lineBreak"
1550+
},
13731551
{
13741552
"text": "}",
13751553
"kind": "punctuation"

tests/cases/fourslash/quickinfoVerbosityNamespace.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@
5050
//// const bar: number;
5151
//// }
5252

53+
// @filename: foo.ts
54+
//// export function foo() { return "foo"; }
55+
//// import("/*5*/./foo")
56+
//// var x = import("./foo")
57+
5358
verify.baselineQuickInfo({
5459
1: [0, 1],
5560
2: [0, 1, 2],
5661
3: [0, 1, 2],
5762
4: [0, 1],
63+
5: [0, 1],
5864
})

0 commit comments

Comments
 (0)