@@ -2581,10 +2581,33 @@ namespace ts {
2581
2581
isFunctionLike ( node . parent ) && ( < FunctionLikeDeclaration > node . parent ) . name === node ;
2582
2582
}
2583
2583
2584
- /** Returns true if node is a name of an object literal property, e.g. "a" in x = { "a": 1 } */
2585
- function isNameOfPropertyAssignment ( node : Node ) : boolean {
2586
- return ( node . kind === SyntaxKind . Identifier || node . kind === SyntaxKind . StringLiteral || node . kind === SyntaxKind . NumericLiteral ) &&
2587
- ( node . parent . kind === SyntaxKind . PropertyAssignment || node . parent . kind === SyntaxKind . ShorthandPropertyAssignment ) && ( < PropertyDeclaration > node . parent ) . name === node ;
2584
+ function isObjectLiteralPropertyDeclaration ( node : Node ) : node is ObjectLiteralElement {
2585
+ switch ( node . kind ) {
2586
+ case SyntaxKind . PropertyAssignment :
2587
+ case SyntaxKind . ShorthandPropertyAssignment :
2588
+ case SyntaxKind . MethodDeclaration :
2589
+ case SyntaxKind . GetAccessor :
2590
+ case SyntaxKind . SetAccessor :
2591
+ return true ;
2592
+ }
2593
+ return false ;
2594
+ }
2595
+
2596
+ /**
2597
+ * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
2598
+ */
2599
+ function getContainingObjectLiteralElement ( node : Node ) : ObjectLiteralElement {
2600
+ switch ( node . kind ) {
2601
+ case SyntaxKind . StringLiteral :
2602
+ case SyntaxKind . NumericLiteral :
2603
+ if ( node . parent . kind === SyntaxKind . ComputedPropertyName ) {
2604
+ return isObjectLiteralPropertyDeclaration ( node . parent . parent ) ? node . parent . parent : undefined ;
2605
+ }
2606
+ // intential fall through
2607
+ case SyntaxKind . Identifier :
2608
+ return isObjectLiteralPropertyDeclaration ( node . parent ) && node . parent . name === node ? node . parent : undefined ;
2609
+ }
2610
+ return undefined ;
2588
2611
}
2589
2612
2590
2613
function isLiteralNameOfPropertyDeclarationOrIndexAccess ( node : Node ) : boolean {
@@ -2602,6 +2625,8 @@ namespace ts {
2602
2625
return ( < Declaration > node . parent ) . name === node ;
2603
2626
case SyntaxKind . ElementAccessExpression :
2604
2627
return ( < ElementAccessExpression > node . parent ) . argumentExpression === node ;
2628
+ case SyntaxKind . ComputedPropertyName :
2629
+ return true ;
2605
2630
}
2606
2631
}
2607
2632
@@ -6208,7 +6233,8 @@ namespace ts {
6208
6233
// If the location is name of property symbol from object literal destructuring pattern
6209
6234
// Search the property symbol
6210
6235
// for ( { property: p2 } of elems) { }
6211
- if ( isNameOfPropertyAssignment ( location ) && location . parent . kind !== SyntaxKind . ShorthandPropertyAssignment ) {
6236
+ const containingObjectLiteralElement = getContainingObjectLiteralElement ( location ) ;
6237
+ if ( containingObjectLiteralElement && containingObjectLiteralElement . kind !== SyntaxKind . ShorthandPropertyAssignment ) {
6212
6238
const propertySymbol = getPropertySymbolOfDestructuringAssignment ( location ) ;
6213
6239
if ( propertySymbol ) {
6214
6240
result . push ( propertySymbol ) ;
@@ -6234,8 +6260,8 @@ namespace ts {
6234
6260
// If the location is in a context sensitive location (i.e. in an object literal) try
6235
6261
// to get a contextual type for it, and add the property symbol from the contextual
6236
6262
// type to the search set
6237
- if ( isNameOfPropertyAssignment ( location ) ) {
6238
- forEach ( getPropertySymbolsFromContextualType ( location ) , contextualSymbol => {
6263
+ if ( containingObjectLiteralElement ) {
6264
+ forEach ( getPropertySymbolsFromContextualType ( containingObjectLiteralElement ) , contextualSymbol => {
6239
6265
addRange ( result , typeChecker . getRootSymbols ( contextualSymbol ) ) ;
6240
6266
} ) ;
6241
6267
@@ -6362,8 +6388,9 @@ namespace ts {
6362
6388
// If the reference location is in an object literal, try to get the contextual type for the
6363
6389
// object literal, lookup the property symbol in the contextual type, and use this symbol to
6364
6390
// compare to our searchSymbol
6365
- if ( isNameOfPropertyAssignment ( referenceLocation ) ) {
6366
- const contextualSymbol = forEach ( getPropertySymbolsFromContextualType ( referenceLocation ) , contextualSymbol => {
6391
+ const containingObjectLiteralElement = getContainingObjectLiteralElement ( referenceLocation ) ;
6392
+ if ( containingObjectLiteralElement ) {
6393
+ const contextualSymbol = forEach ( getPropertySymbolsFromContextualType ( containingObjectLiteralElement ) , contextualSymbol => {
6367
6394
return forEach ( typeChecker . getRootSymbols ( contextualSymbol ) , s => searchSymbols . indexOf ( s ) >= 0 ? s : undefined ) ;
6368
6395
} ) ;
6369
6396
@@ -6409,37 +6436,38 @@ namespace ts {
6409
6436
} ) ;
6410
6437
}
6411
6438
6412
- function getPropertySymbolsFromContextualType ( node : Node ) : Symbol [ ] {
6413
- if ( isNameOfPropertyAssignment ( node ) ) {
6414
- const objectLiteral = < ObjectLiteralExpression > node . parent . parent ;
6415
- const contextualType = typeChecker . getContextualType ( objectLiteral ) ;
6416
- const name = ( < Identifier > node ) . text ;
6417
- if ( contextualType ) {
6418
- if ( contextualType . flags & TypeFlags . Union ) {
6419
- // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types)
6420
- // if not, search the constituent types for the property
6421
- const unionProperty = contextualType . getProperty ( name ) ;
6422
- if ( unionProperty ) {
6423
- return [ unionProperty ] ;
6424
- }
6425
- else {
6426
- const result : Symbol [ ] = [ ] ;
6427
- forEach ( ( < UnionType > contextualType ) . types , t => {
6428
- const symbol = t . getProperty ( name ) ;
6429
- if ( symbol ) {
6430
- result . push ( symbol ) ;
6431
- }
6432
- } ) ;
6433
- return result ;
6434
- }
6435
- }
6436
- else {
6437
- const symbol = contextualType . getProperty ( name ) ;
6439
+ function getNameFromObjectLiteralElement ( node : ObjectLiteralElement ) {
6440
+ if ( node . name . kind === SyntaxKind . ComputedPropertyName ) {
6441
+ const nameExpression = ( < ComputedPropertyName > node . name ) . expression ;
6442
+ // treat computed property names where expression is string/numeric literal as just string/numeric literal
6443
+ if ( isStringOrNumericLiteral ( nameExpression . kind ) ) {
6444
+ return ( < LiteralExpression > nameExpression ) . text ;
6445
+ }
6446
+ return undefined ;
6447
+ }
6448
+ return ( < Identifier | LiteralExpression > node . name ) . text ;
6449
+ }
6450
+
6451
+ function getPropertySymbolsFromContextualType ( node : ObjectLiteralElement ) : Symbol [ ] {
6452
+ const objectLiteral = < ObjectLiteralExpression > node . parent ;
6453
+ const contextualType = typeChecker . getContextualType ( objectLiteral ) ;
6454
+ const name = getNameFromObjectLiteralElement ( node ) ;
6455
+ if ( name && contextualType ) {
6456
+ const result : Symbol [ ] = [ ] ;
6457
+ const symbol = contextualType . getProperty ( name ) ;
6458
+ if ( symbol ) {
6459
+ result . push ( symbol ) ;
6460
+ }
6461
+
6462
+ if ( contextualType . flags & TypeFlags . Union ) {
6463
+ forEach ( ( < UnionType > contextualType ) . types , t => {
6464
+ const symbol = t . getProperty ( name ) ;
6438
6465
if ( symbol ) {
6439
- return [ symbol ] ;
6466
+ result . push ( symbol ) ;
6440
6467
}
6441
- }
6468
+ } ) ;
6442
6469
}
6470
+ return result ;
6443
6471
}
6444
6472
return undefined ;
6445
6473
}
@@ -7901,7 +7929,8 @@ namespace ts {
7901
7929
// "a['propname']" then we want to store "propname" in the name table.
7902
7930
if ( isDeclarationName ( node ) ||
7903
7931
node . parent . kind === SyntaxKind . ExternalModuleReference ||
7904
- isArgumentOfElementAccessExpression ( node ) ) {
7932
+ isArgumentOfElementAccessExpression ( node ) ||
7933
+ isLiteralComputedPropertyDeclarationName ( node ) ) {
7905
7934
7906
7935
nameTable [ ( < LiteralExpression > node ) . text ] = nameTable [ ( < LiteralExpression > node ) . text ] === undefined ? node . pos : - 1 ;
7907
7936
}
0 commit comments