Support indexing with known symbols

This commit is contained in:
Jason Freeman
2015-02-05 17:18:32 -08:00
parent df826de042
commit d07ed679a0
26 changed files with 495 additions and 14 deletions

View File

@@ -97,7 +97,7 @@ module ts {
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
var nameExpression = (<ComputedPropertyName>node.name).expression;
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return "__@" + (<PropertyAccessExpression>nameExpression).name.text;
return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
}
return (<Identifier | LiteralExpression>node.name).text;
}

View File

@@ -5787,8 +5787,8 @@ module ts {
// See if we can index as a property.
if (node.argumentExpression) {
if (node.argumentExpression.kind === SyntaxKind.StringLiteral || node.argumentExpression.kind === SyntaxKind.NumericLiteral) {
var name = (<LiteralExpression>node.argumentExpression).text;
var name = getPropertyNameForIndexedAccess(node.argumentExpression);
if (name !== undefined) {
var prop = getPropertyOfType(objectType, name);
if (prop) {
getNodeLinks(node).resolvedSymbol = prop;
@@ -5832,6 +5832,36 @@ module ts {
return unknownType;
}
/**
* If indexArgumentExpression is a string literal or number literal, returns its text.
* If indexArgumentExpression is a well known symbol, returns the property name corresponding
* to this symbol.
* Otherwise, returns undefined.
*/
function getPropertyNameForIndexedAccess(indexArgumentExpression: Expression) {
if (indexArgumentExpression.kind === SyntaxKind.StringLiteral || indexArgumentExpression.kind === SyntaxKind.NumericLiteral) {
return (<LiteralExpression>indexArgumentExpression).text;
}
if (isWellKnownSymbolSyntactically(indexArgumentExpression)) {
var leftHandSide = (<PropertyAccessExpression>indexArgumentExpression).expression;
Debug.assert((<Identifier>leftHandSide).text === "Symbol");
// The name is Symbol.<someName>, so make sure Symbol actually resolves to the
// global Symbol object
var leftHandSideSymbol = resolveName(indexArgumentExpression, (<Identifier>leftHandSide).text,
SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
if (leftHandSideSymbol === globalESSymbolConstructorSymbol) {
// Make sure the property type is the primitive symbol type
var rightHandSideName = (<Identifier>(<PropertyAccessExpression>indexArgumentExpression).name).text;
var esSymbolConstructorPropertyType = getTypeOfPropertyOfType(globalESSymbolConstructorType, rightHandSideName);
if (esSymbolConstructorPropertyType && esSymbolConstructorPropertyType.flags & TypeFlags.ESSymbol) {
return getPropertyNameForKnownSymbolName(rightHandSideName);
}
}
}
return undefined;
}
function resolveUntypedCall(node: CallLikeExpression): Signature {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
checkExpression((<TaggedTemplateExpression>node).template);
@@ -10334,7 +10364,7 @@ module ts {
globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
globalESSymbolType = getGlobalType("Symbol");
globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
globalESSymbolConstructorType = getTypeOfGlobalSymbol(globalESSymbolConstructorSymbol, /*arity*/ 0);
globalESSymbolConstructorType = getTypeOfSymbol(globalESSymbolConstructorSymbol);
}
else {
globalTemplateStringsArrayType = unknownType;

View File

@@ -852,6 +852,10 @@ module ts {
return node.kind === SyntaxKind.PropertyAccessExpression && isESSymbolIdentifier((<PropertyAccessExpression>node).expression);
}
export function getPropertyNameForKnownSymbolName(symbolName: string): string {
return "__@" + symbolName;
}
/**
* Includes the word "Symbol" with unicode escapes
*/