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
This commit is contained in:
Andrew Branch 2019-09-30 18:14:07 -05:00 committed by Wesley Wigham
parent 7c50bccec2
commit 7be7cba050
10 changed files with 105 additions and 8 deletions

View file

@ -344,6 +344,9 @@ namespace ts {
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));
}
if (isWellKnownSymbolSyntactically(name)) {
return getPropertyNameForKnownSymbolName(idText(name.name));
}
return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
}
switch (node.kind) {

View file

@ -820,7 +820,14 @@ namespace ts {
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
export type DeclarationName =
| Identifier
| StringLiteralLike
| NumericLiteral
| ComputedPropertyName
| ElementAccessExpression
| BindingPattern
| EntityNameExpression;
export interface Declaration extends Node {
_declarationBrand: any;
@ -1886,13 +1893,17 @@ namespace ts {
| CallChainRoot
;
/** @internal */
export interface WellKnownSymbolExpression extends PropertyAccessExpression {
expression: Identifier & { escapedText: "Symbol" };
}
/** @internal */
export type BindableObjectDefinePropertyCall = CallExpression & { arguments: { 0: BindableStaticNameExpression, 1: StringLiteralLike | NumericLiteral, 2: ObjectLiteralExpression } };
/** @internal */
export type BindableStaticNameExpression = EntityNameExpression | BindableStaticElementAccessExpression;
/** @internal */
export type LiteralLikeElementAccessExpression = ElementAccessExpression & Declaration & {
argumentExpression: StringLiteralLike | NumericLiteral;
argumentExpression: StringLiteralLike | NumericLiteral | WellKnownSymbolExpression;
};
/** @internal */
export type BindableStaticElementAccessExpression = LiteralLikeElementAccessExpression & {

View file

@ -2075,7 +2075,9 @@ namespace ts {
}
export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
return isElementAccessExpression(node) && isStringOrNumericLiteralLike(node.argumentExpression);
return isElementAccessExpression(node) && (
isStringOrNumericLiteralLike(node.argumentExpression) ||
isWellKnownSymbolSyntactically(node.argumentExpression));
}
export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression {
@ -2908,7 +2910,7 @@ namespace ts {
* Symbol.name
* where Symbol is literally the word "Symbol", and name is any identifierName
*/
export function isWellKnownSymbolSyntactically(node: Expression): boolean {
export function isWellKnownSymbolSyntactically(node: Node): node is WellKnownSymbolExpression {
return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression);
}

View file

@ -136,7 +136,7 @@ namespace ts.NavigationBar {
for (let i = 0; i < depth; i++) endNode();
}
function startNestedNodes(targetNode: Node, entityName: BindableStaticNameExpression) {
const names: PropertyNameLiteral[] = [];
const names: (PropertyNameLiteral | WellKnownSymbolExpression)[] = [];
while (!isPropertyNameLiteral(entityName)) {
const name = getNameOrArgument(entityName);
const nameText = getElementOrPropertyAccessName(entityName);
@ -334,7 +334,7 @@ namespace ts.NavigationBar {
assignmentTarget;
let depth = 0;
let className: PropertyNameLiteral;
let className: PropertyNameLiteral | WellKnownSymbolExpression;
// If we see a prototype assignment, start tracking the target as a class
// This is only done for simple classes not nested assignments.
if (isIdentifier(prototypeAccess.expression)) {

View file

@ -549,7 +549,7 @@ declare namespace ts {
}
export type EntityName = Identifier | QualifiedName;
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
export interface Declaration extends Node {
_declarationBrand: any;
}

View file

@ -549,7 +549,7 @@ declare namespace ts {
}
export type EntityName = Identifier | QualifiedName;
export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern;
export type DeclarationName = Identifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
export interface Declaration extends Node {
_declarationBrand: any;
}

View file

@ -0,0 +1,10 @@
=== tests/cases/compiler/wellKnownSymbolExpando.ts ===
function f() {}
>f : Symbol(f, Decl(wellKnownSymbolExpando.ts, 0, 0), Decl(wellKnownSymbolExpando.ts, 0, 15))
f[Symbol.iterator] = function() {}
>f : Symbol(f, Decl(wellKnownSymbolExpando.ts, 0, 0), Decl(wellKnownSymbolExpando.ts, 0, 15))
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>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, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))

View file

@ -0,0 +1,13 @@
=== tests/cases/compiler/wellKnownSymbolExpando.ts ===
function f() {}
>f : typeof f
f[Symbol.iterator] = function() {}
>f[Symbol.iterator] = function() {} : () => void
>f[Symbol.iterator] : () => void
>f : typeof f
>Symbol.iterator : symbol
>Symbol : SymbolConstructor
>iterator : symbol
>function() {} : () => void

View file

@ -0,0 +1,5 @@
// @noEmit: true
// @target: esnext
function f() {}
f[Symbol.iterator] = function() {}

View file

@ -0,0 +1,53 @@
/// <reference path="fourslash.ts"/>
////function f() {}
////f[Symbol.iterator] = function() {}
verify.navigationTree({
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "f",
"kind": "class",
"childItems": [
{
"text": "constructor",
"kind": "constructor"
},
{
"text": "[Symbol.iterator]",
"kind": "function"
}
]
}
]
});
verify.navigationBar([
{
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "f",
"kind": "class"
}
]
},
{
"text": "f",
"kind": "class",
"childItems": [
{
"text": "constructor",
"kind": "constructor"
},
{
"text": "[Symbol.iterator]",
"kind": "function"
}
],
"indent": 1
}
]);