Skip to content

Commit 7be7cba

Browse files
andrewbranchweswigham
authored andcommitted
Fixes binding well known symbol assignment via element access (#33687)
* Fix binding well-known symbols by element access * Add navigationBar test * Revert settings.json change * Accept baselines * Actually make it bind * Accept API baselines * Dont use internal name in API
1 parent 7c50bcc commit 7be7cba

10 files changed

+105
-8
lines changed

src/compiler/binder.ts

+3
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ namespace ts {
344344
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
345345
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));
346346
}
347+
if (isWellKnownSymbolSyntactically(name)) {
348+
return getPropertyNameForKnownSymbolName(idText(name.name));
349+
}
347350
return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
348351
}
349352
switch (node.kind) {

src/compiler/types.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,14 @@ namespace ts {
820820

821821
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
822822

823-
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
823+
export type DeclarationName =
824+
| Identifier
825+
| StringLiteralLike
826+
| NumericLiteral
827+
| ComputedPropertyName
828+
| ElementAccessExpression
829+
| BindingPattern
830+
| EntityNameExpression;
824831

825832
export interface Declaration extends Node {
826833
_declarationBrand: any;
@@ -1886,13 +1893,17 @@ namespace ts {
18861893
| CallChainRoot
18871894
;
18881895

1896+
/** @internal */
1897+
export interface WellKnownSymbolExpression extends PropertyAccessExpression {
1898+
expression: Identifier & { escapedText: "Symbol" };
1899+
}
18891900
/** @internal */
18901901
export type BindableObjectDefinePropertyCall = CallExpression & { arguments: { 0: BindableStaticNameExpression, 1: StringLiteralLike | NumericLiteral, 2: ObjectLiteralExpression } };
18911902
/** @internal */
18921903
export type BindableStaticNameExpression = EntityNameExpression | BindableStaticElementAccessExpression;
18931904
/** @internal */
18941905
export type LiteralLikeElementAccessExpression = ElementAccessExpression & Declaration & {
1895-
argumentExpression: StringLiteralLike | NumericLiteral;
1906+
argumentExpression: StringLiteralLike | NumericLiteral | WellKnownSymbolExpression;
18961907
};
18971908
/** @internal */
18981909
export type BindableStaticElementAccessExpression = LiteralLikeElementAccessExpression & {

src/compiler/utilities.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -2075,7 +2075,9 @@ namespace ts {
20752075
}
20762076

20772077
export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
2078-
return isElementAccessExpression(node) && isStringOrNumericLiteralLike(node.argumentExpression);
2078+
return isElementAccessExpression(node) && (
2079+
isStringOrNumericLiteralLike(node.argumentExpression) ||
2080+
isWellKnownSymbolSyntactically(node.argumentExpression));
20792081
}
20802082

20812083
export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression {
@@ -2908,7 +2910,7 @@ namespace ts {
29082910
* Symbol.name
29092911
* where Symbol is literally the word "Symbol", and name is any identifierName
29102912
*/
2911-
export function isWellKnownSymbolSyntactically(node: Expression): boolean {
2913+
export function isWellKnownSymbolSyntactically(node: Node): node is WellKnownSymbolExpression {
29122914
return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression);
29132915
}
29142916

src/services/navigationBar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ namespace ts.NavigationBar {
136136
for (let i = 0; i < depth; i++) endNode();
137137
}
138138
function startNestedNodes(targetNode: Node, entityName: BindableStaticNameExpression) {
139-
const names: PropertyNameLiteral[] = [];
139+
const names: (PropertyNameLiteral | WellKnownSymbolExpression)[] = [];
140140
while (!isPropertyNameLiteral(entityName)) {
141141
const name = getNameOrArgument(entityName);
142142
const nameText = getElementOrPropertyAccessName(entityName);
@@ -334,7 +334,7 @@ namespace ts.NavigationBar {
334334
assignmentTarget;
335335

336336
let depth = 0;
337-
let className: PropertyNameLiteral;
337+
let className: PropertyNameLiteral | WellKnownSymbolExpression;
338338
// If we see a prototype assignment, start tracking the target as a class
339339
// This is only done for simple classes not nested assignments.
340340
if (isIdentifier(prototypeAccess.expression)) {

tests/baselines/reference/api/tsserverlibrary.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ declare namespace ts {
549549
}
550550
export type EntityName = Identifier | QualifiedName;
551551
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
552-
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
552+
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
553553
export interface Declaration extends Node {
554554
_declarationBrand: any;
555555
}

tests/baselines/reference/api/typescript.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ declare namespace ts {
549549
}
550550
export type EntityName = Identifier | QualifiedName;
551551
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
552-
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
552+
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
553553
export interface Declaration extends Node {
554554
_declarationBrand: any;
555555
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/compiler/wellKnownSymbolExpando.ts ===
2+
function f() {}
3+
>f : Symbol(f, Decl(wellKnownSymbolExpando.ts, 0, 0), Decl(wellKnownSymbolExpando.ts, 0, 15))
4+
5+
f[Symbol.iterator] = function() {}
6+
>f : Symbol(f, Decl(wellKnownSymbolExpando.ts, 0, 0), Decl(wellKnownSymbolExpando.ts, 0, 15))
7+
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
8+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
9+
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/compiler/wellKnownSymbolExpando.ts ===
2+
function f() {}
3+
>f : typeof f
4+
5+
f[Symbol.iterator] = function() {}
6+
>f[Symbol.iterator] = function() {} : () => void
7+
>f[Symbol.iterator] : () => void
8+
>f : typeof f
9+
>Symbol.iterator : symbol
10+
>Symbol : SymbolConstructor
11+
>iterator : symbol
12+
>function() {} : () => void
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// @noEmit: true
2+
// @target: esnext
3+
4+
function f() {}
5+
f[Symbol.iterator] = function() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////function f() {}
4+
////f[Symbol.iterator] = function() {}
5+
6+
verify.navigationTree({
7+
"text": "<global>",
8+
"kind": "script",
9+
"childItems": [
10+
{
11+
"text": "f",
12+
"kind": "class",
13+
"childItems": [
14+
{
15+
"text": "constructor",
16+
"kind": "constructor"
17+
},
18+
{
19+
"text": "[Symbol.iterator]",
20+
"kind": "function"
21+
}
22+
]
23+
}
24+
]
25+
});
26+
27+
verify.navigationBar([
28+
{
29+
"text": "<global>",
30+
"kind": "script",
31+
"childItems": [
32+
{
33+
"text": "f",
34+
"kind": "class"
35+
}
36+
]
37+
},
38+
{
39+
"text": "f",
40+
"kind": "class",
41+
"childItems": [
42+
{
43+
"text": "constructor",
44+
"kind": "constructor"
45+
},
46+
{
47+
"text": "[Symbol.iterator]",
48+
"kind": "function"
49+
}
50+
],
51+
"indent": 1
52+
}
53+
]);

0 commit comments

Comments
 (0)