@@ -347,14 +347,14 @@ func runWithoutResolvedSignatureCaching[T any](c *Checker, node *ast.Node, fn fu
347
347
348
348
func (c * Checker ) GetRootSymbols (symbol * ast.Symbol ) []* ast.Symbol {
349
349
roots := c .getImmediateRootSymbols (symbol )
350
- if roots != nil {
351
- var result []* ast.Symbol
352
- for _ , root := range roots {
353
- result = append (result , c .GetRootSymbols (root )... )
354
- }
355
- return result
350
+ if len (roots ) == 0 {
351
+ return []* ast.Symbol {symbol }
356
352
}
357
- return []* ast.Symbol {symbol }
353
+ var result []* ast.Symbol
354
+ for _ , root := range roots {
355
+ result = append (result , c .GetRootSymbols (root )... )
356
+ }
357
+ return result
358
358
}
359
359
360
360
func (c * Checker ) getImmediateRootSymbols (symbol * ast.Symbol ) []* ast.Symbol {
@@ -364,7 +364,8 @@ func (c *Checker) getImmediateRootSymbols(symbol *ast.Symbol) []*ast.Symbol {
364
364
func (t * Type ) * ast.Symbol {
365
365
return c .getPropertyOfType (t , symbol .Name )
366
366
})
367
- } else if symbol .Flags & ast .SymbolFlagsTransient != 0 {
367
+ }
368
+ if symbol .Flags & ast .SymbolFlagsTransient != 0 {
368
369
if c .spreadLinks .Has (symbol ) {
369
370
leftSpread := c .spreadLinks .Get (symbol ).leftSpread
370
371
rightSpread := c .spreadLinks .Get (symbol ).rightSpread
@@ -382,9 +383,7 @@ func (c *Checker) getImmediateRootSymbols(symbol *ast.Symbol) []*ast.Symbol {
382
383
if target != nil {
383
384
return []* ast.Symbol {target }
384
385
}
385
- return nil
386
386
}
387
-
388
387
return nil
389
388
}
390
389
@@ -418,20 +417,16 @@ func (c *Checker) GetExportSpecifierLocalTargetSymbol(node *ast.Node) *ast.Symbo
418
417
if node .Parent .Parent .AsExportDeclaration ().ModuleSpecifier != nil {
419
418
return c .getExternalModuleMember (node .Parent .Parent , node , false /*dontResolveAlias*/ )
420
419
}
421
- name := node .PropertyName ()
422
- if name == nil {
423
- name = node .Name ()
424
- }
420
+ name := node .PropertyNameOrName ()
425
421
if name .Kind == ast .KindStringLiteral {
426
422
// Skip for invalid syntax like this: export { "x" }
427
423
return nil
428
424
}
425
+ return c .resolveEntityName (name , ast .SymbolFlagsValue | ast .SymbolFlagsType | ast .SymbolFlagsNamespace | ast .SymbolFlagsAlias , true /*ignoreErrors*/ , false , nil )
429
426
case ast .KindIdentifier :
430
- // do nothing (don't panic)
431
- default :
432
- panic ("Unhandled case in getExportSpecifierLocalTargetSymbol, node should be ExportSpecifier | Identifier" )
427
+ return c .resolveEntityName (node , ast .SymbolFlagsValue | ast .SymbolFlagsType | ast .SymbolFlagsNamespace | ast .SymbolFlagsAlias , true /*ignoreErrors*/ , false , nil )
433
428
}
434
- return c . resolveEntityName ( node , ast . SymbolFlagsValue | ast . SymbolFlagsType | ast . SymbolFlagsNamespace | ast . SymbolFlagsAlias , true /*ignoreErrors*/ , false , nil )
429
+ panic ( "Unhandled case in getExportSpecifierLocalTargetSymbol, node should be ExportSpecifier | Identifier" )
435
430
}
436
431
437
432
func (c * Checker ) GetShorthandAssignmentValueSymbol (location * ast.Node ) * ast.Symbol {
@@ -683,3 +678,122 @@ func (c *Checker) GetFirstTypeArgumentFromKnownType(t *Type) *Type {
683
678
}
684
679
return nil
685
680
}
681
+
682
+ // Gets all symbols for one property. Does not get symbols for every property.
683
+ func (c * Checker ) GetPropertySymbolsFromContextualType (node * ast.Node , contextualType * Type , unionSymbolOk bool ) []* ast.Symbol {
684
+ name := ast .GetTextOfPropertyName (node .Name ())
685
+ if name == "" {
686
+ return nil
687
+ }
688
+ if contextualType .flags & TypeFlagsUnion == 0 {
689
+ if symbol := c .getPropertyOfType (contextualType , name ); symbol != nil {
690
+ return []* ast.Symbol {symbol }
691
+ }
692
+ return nil
693
+ }
694
+ filteredTypes := contextualType .Types ()
695
+ if ast .IsObjectLiteralExpression (node .Parent ) || ast .IsJsxAttributes (node .Parent ) {
696
+ filteredTypes = core .Filter (filteredTypes , func (t * Type ) bool {
697
+ return ! c .IsTypeInvalidDueToUnionDiscriminant (t , node .Parent )
698
+ })
699
+ }
700
+ discriminatedPropertySymbols := core .MapNonNil (filteredTypes , func (t * Type ) * ast.Symbol {
701
+ return c .getPropertyOfType (t , name )
702
+ })
703
+ if unionSymbolOk && (len (discriminatedPropertySymbols ) == 0 || len (discriminatedPropertySymbols ) == len (contextualType .Types ())) {
704
+ if symbol := c .getPropertyOfType (contextualType , name ); symbol != nil {
705
+ return []* ast.Symbol {symbol }
706
+ }
707
+ }
708
+ if len (filteredTypes ) == 0 && len (discriminatedPropertySymbols ) == 0 {
709
+ // Bad discriminant -- do again without discriminating
710
+ return core .MapNonNil (contextualType .Types (), func (t * Type ) * ast.Symbol {
711
+ return c .getPropertyOfType (t , name )
712
+ })
713
+ }
714
+ // by eliminating duplicates we might even end up with a single symbol
715
+ // that helps with displaying better quick infos on properties of union types
716
+ return core .Deduplicate (discriminatedPropertySymbols )
717
+ }
718
+
719
+ // Gets the property symbol corresponding to the property in destructuring assignment
720
+ // 'property1' from
721
+ //
722
+ // for ( { property1: a } of elems) {
723
+ // }
724
+ //
725
+ // 'property1' at location 'a' from:
726
+ //
727
+ // [a] = [ property1, property2 ]
728
+ func (c * Checker ) GetPropertySymbolOfDestructuringAssignment (location * ast.Node ) * ast.Symbol {
729
+ if isArrayLiteralOrObjectLiteralDestructuringPattern (location .Parent .Parent ) {
730
+ // Get the type of the object or array literal and then look for property of given name in the type
731
+ if typeOfObjectLiteral := c .getTypeOfAssignmentPattern (location .Parent .Parent ); typeOfObjectLiteral != nil {
732
+ return c .getPropertyOfType (typeOfObjectLiteral , location .Text ())
733
+ }
734
+ }
735
+ return nil
736
+ }
737
+
738
+ // Gets the type of object literal or array literal of destructuring assignment.
739
+ // { a } from
740
+ //
741
+ // for ( { a } of elems) {
742
+ // }
743
+ //
744
+ // [ a ] from
745
+ //
746
+ // [a] = [ some array ...]
747
+ func (c * Checker ) getTypeOfAssignmentPattern (expr * ast.Node ) * Type {
748
+ // If this is from "for of"
749
+ // for ( { a } of elems) {
750
+ // }
751
+ if ast .IsForOfStatement (expr .Parent ) {
752
+ iteratedType := c .checkRightHandSideOfForOf (expr .Parent )
753
+ return c .checkDestructuringAssignment (expr , core .OrElse (iteratedType , c .errorType ), CheckModeNormal , false )
754
+ }
755
+ // If this is from "for" initializer
756
+ // for ({a } = elems[0];.....) { }
757
+ if ast .IsBinaryExpression (expr .Parent ) {
758
+ iteratedType := c .getTypeOfExpression (expr .Parent .AsBinaryExpression ().Right )
759
+ return c .checkDestructuringAssignment (expr , core .OrElse (iteratedType , c .errorType ), CheckModeNormal , false )
760
+ }
761
+ // If this is from nested object binding pattern
762
+ // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) {
763
+ if ast .IsPropertyAssignment (expr .Parent ) {
764
+ node := expr .Parent .Parent
765
+ typeOfParentObjectLiteral := core .OrElse (c .getTypeOfAssignmentPattern (node ), c .errorType )
766
+ propertyIndex := slices .Index (node .AsObjectLiteralExpression ().Properties .Nodes , expr .Parent )
767
+ return c .checkObjectLiteralDestructuringPropertyAssignment (node , typeOfParentObjectLiteral , propertyIndex , nil , false )
768
+ }
769
+ // Array literal assignment - array destructuring pattern
770
+ node := expr .Parent
771
+ // [{ property1: p1, property2 }] = elems;
772
+ typeOfArrayLiteral := core .OrElse (c .getTypeOfAssignmentPattern (node ), c .errorType )
773
+ elementType := core .OrElse (c .checkIteratedTypeOrElementType (IterationUseDestructuring , typeOfArrayLiteral , c .undefinedType , expr .Parent ), c .errorType )
774
+ return c .checkArrayLiteralDestructuringElementAssignment (node , typeOfArrayLiteral , slices .Index (node .AsArrayLiteralExpression ().Elements .Nodes , expr ), elementType , CheckModeNormal )
775
+ }
776
+
777
+ func isArrayLiteralOrObjectLiteralDestructuringPattern (node * ast.Node ) bool {
778
+ if ! (ast .IsArrayLiteralExpression (node ) || ast .IsObjectLiteralExpression (node )) {
779
+ return false
780
+ }
781
+ parent := node .Parent
782
+ // [a,b,c] from:
783
+ // [a, b, c] = someExpression;
784
+ if ast .IsBinaryExpression (parent ) && parent .AsBinaryExpression ().Left == node && parent .AsBinaryExpression ().OperatorToken .Kind == ast .KindEqualsToken {
785
+ return true
786
+ }
787
+ // [a, b, c] from:
788
+ // for([a, b, c] of expression)
789
+ if ast .IsForOfStatement (parent ) && parent .Initializer () == node {
790
+ return true
791
+ }
792
+ // {x, a: {a, b, c} } = someExpression
793
+ if ast .IsPropertyAssignment (parent ) {
794
+ return isArrayLiteralOrObjectLiteralDestructuringPattern (parent .Parent )
795
+ }
796
+ // [a, b, c] of
797
+ // [x, [a, b, c] ] = someExpression
798
+ return isArrayLiteralOrObjectLiteralDestructuringPattern (parent )
799
+ }
0 commit comments