@@ -347,14 +347,14 @@ func runWithoutResolvedSignatureCaching[T any](c *Checker, node *ast.Node, fn fu
347347
348348func (c * Checker ) GetRootSymbols (symbol * ast.Symbol ) []* ast.Symbol {
349349 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 }
356352 }
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
358358}
359359
360360func (c * Checker ) getImmediateRootSymbols (symbol * ast.Symbol ) []* ast.Symbol {
@@ -364,7 +364,8 @@ func (c *Checker) getImmediateRootSymbols(symbol *ast.Symbol) []*ast.Symbol {
364364 func (t * Type ) * ast.Symbol {
365365 return c .getPropertyOfType (t , symbol .Name )
366366 })
367- } else if symbol .Flags & ast .SymbolFlagsTransient != 0 {
367+ }
368+ if symbol .Flags & ast .SymbolFlagsTransient != 0 {
368369 if c .spreadLinks .Has (symbol ) {
369370 leftSpread := c .spreadLinks .Get (symbol ).leftSpread
370371 rightSpread := c .spreadLinks .Get (symbol ).rightSpread
@@ -382,9 +383,7 @@ func (c *Checker) getImmediateRootSymbols(symbol *ast.Symbol) []*ast.Symbol {
382383 if target != nil {
383384 return []* ast.Symbol {target }
384385 }
385- return nil
386386 }
387-
388387 return nil
389388}
390389
@@ -418,20 +417,16 @@ func (c *Checker) GetExportSpecifierLocalTargetSymbol(node *ast.Node) *ast.Symbo
418417 if node .Parent .Parent .AsExportDeclaration ().ModuleSpecifier != nil {
419418 return c .getExternalModuleMember (node .Parent .Parent , node , false /*dontResolveAlias*/ )
420419 }
421- name := node .PropertyName ()
422- if name == nil {
423- name = node .Name ()
424- }
420+ name := node .PropertyNameOrName ()
425421 if name .Kind == ast .KindStringLiteral {
426422 // Skip for invalid syntax like this: export { "x" }
427423 return nil
428424 }
425+ return c .resolveEntityName (name , ast .SymbolFlagsValue | ast .SymbolFlagsType | ast .SymbolFlagsNamespace | ast .SymbolFlagsAlias , true /*ignoreErrors*/ , false , nil )
429426 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 )
433428 }
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" )
435430}
436431
437432func (c * Checker ) GetShorthandAssignmentValueSymbol (location * ast.Node ) * ast.Symbol {
@@ -683,3 +678,122 @@ func (c *Checker) GetFirstTypeArgumentFromKnownType(t *Type) *Type {
683678 }
684679 return nil
685680}
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