@@ -1844,6 +1844,13 @@ namespace ts {
18441844 owners : string [ ] ;
18451845 }
18461846
1847+ // Internal interface used for tracking state in find all references when checking
1848+ // the inheritance hierarchy of property access expressions
1849+ interface SymbolInheritanceState {
1850+ symbol : Symbol ;
1851+ cachedInheritanceResults : Map < boolean > ;
1852+ }
1853+
18471854 export interface DisplayPartsSymbolWriter extends SymbolWriter {
18481855 displayParts ( ) : SymbolDisplayPart [ ] ;
18491856 }
@@ -6546,13 +6553,17 @@ namespace ts {
65466553 // symbol of the local type of the symbol the property is being accessed on. This is because our search
65476554 // symbol may have a different parent symbol if the local type's symbol does not declare the property
65486555 // being accessed (i.e. it is declared in some parent class or interface)
6549- let parentSymbol : Symbol = undefined ;
6550- let inheritanceCache : Map < boolean > = undefined ;
6551- if ( implementations && searchLocation . parent && searchLocation . parent . kind === SyntaxKind . PropertyAccessExpression && searchLocation === ( < PropertyAccessExpression > searchLocation . parent ) . name ) {
6556+ let parentSymbols : SymbolInheritanceState [ ] = undefined ;
6557+
6558+ if ( implementations && isRightSideOfPropertyAccess ( searchLocation ) ) {
65526559 const localParentType = typeChecker . getTypeAtLocation ( ( < PropertyAccessExpression > searchLocation . parent ) . expression ) ;
6553- if ( localParentType && localParentType . symbol && localParentType . symbol . getFlags ( ) & ( SymbolFlags . Interface | SymbolFlags . Class ) && localParentType . symbol . parent !== searchSymbol . parent ) {
6554- parentSymbol = localParentType . symbol ;
6555- inheritanceCache = createMap < boolean > ( ) ;
6560+ if ( localParentType ) {
6561+ if ( localParentType . symbol && isClassOrInterfaceReference ( localParentType . symbol ) && localParentType . symbol . parent !== searchSymbol . parent ) {
6562+ parentSymbols = [ createSymbolInheritanceState ( localParentType . symbol ) ] ;
6563+ }
6564+ else if ( localParentType . getFlags ( ) & TypeFlags . UnionOrIntersection ) {
6565+ parentSymbols = map ( getSymbolsForComponentTypes ( < UnionOrIntersectionType > localParentType ) , createSymbolInheritanceState ) ;
6566+ }
65566567 }
65576568 }
65586569
@@ -6596,7 +6607,7 @@ namespace ts {
65966607 if ( referenceSymbol ) {
65976608 const referenceSymbolDeclaration = referenceSymbol . valueDeclaration ;
65986609 const shorthandValueSymbol = typeChecker . getShorthandAssignmentValueSymbol ( referenceSymbolDeclaration ) ;
6599- const relatedSymbol = getRelatedSymbol ( searchSymbols , referenceSymbol , referenceLocation , parentSymbol , inheritanceCache ) ;
6610+ const relatedSymbol = getRelatedSymbol ( searchSymbols , referenceSymbol , referenceLocation , parentSymbols ) ;
66006611
66016612 if ( relatedSymbol ) {
66026613 const referenceEntry = implementations ? getImplementationReferenceEntryForNode ( referenceLocation ) : getReferenceEntryFromNode ( referenceLocation ) ;
@@ -6691,6 +6702,18 @@ namespace ts {
66916702 }
66926703 }
66936704
6705+ function getSymbolsForComponentTypes ( type : UnionOrIntersectionType , result : Symbol [ ] = [ ] ) : Symbol [ ] {
6706+ for ( const componentType of type . types ) {
6707+ if ( componentType . symbol && componentType . symbol . getFlags ( ) & ( SymbolFlags . Class | SymbolFlags . Interface ) ) {
6708+ result . push ( componentType . symbol ) ;
6709+ }
6710+ if ( componentType . getFlags ( ) & TypeFlags . UnionOrIntersection ) {
6711+ getSymbolsForComponentTypes ( < UnionOrIntersectionType > componentType , result ) ;
6712+ }
6713+ }
6714+ return result ;
6715+ }
6716+
66946717 function getContainingTypeReference ( node : Node ) : Node {
66956718 if ( node ) {
66966719 if ( node . kind === SyntaxKind . TypeReference ) {
@@ -6786,7 +6809,7 @@ namespace ts {
67866809 return inherits ;
67876810 }
67886811
6789- function searchTypeReference ( typeReference : ExpressionWithTypeArguments , cachedResults : Map < boolean > ) {
6812+ function searchTypeReference ( typeReference : ExpressionWithTypeArguments , cachedResults : Map < boolean > ) : boolean {
67906813 if ( typeReference ) {
67916814 const type = typeChecker . getTypeAtLocation ( typeReference ) ;
67926815 if ( type && type . symbol ) {
@@ -6797,6 +6820,13 @@ namespace ts {
67976820 }
67986821 }
67996822
6823+ function createSymbolInheritanceState ( symbol : Symbol ) : SymbolInheritanceState {
6824+ return {
6825+ symbol,
6826+ cachedInheritanceResults : createMap < boolean > ( )
6827+ } ;
6828+ }
6829+
68006830 function getReferencesForSuperKeyword ( superKeyword : Node ) : ReferencedSymbol [ ] {
68016831 let searchSpaceNode = getSuperContainer ( superKeyword , /*stopOnFunctions*/ false ) ;
68026832 if ( ! searchSpaceNode ) {
@@ -7144,7 +7174,7 @@ namespace ts {
71447174 }
71457175 }
71467176
7147- function getRelatedSymbol ( searchSymbols : Symbol [ ] , referenceSymbol : Symbol , referenceLocation : Node , parentSymbol : Symbol , inheritanceCache : Map < boolean > ) : Symbol {
7177+ function getRelatedSymbol ( searchSymbols : Symbol [ ] , referenceSymbol : Symbol , referenceLocation : Node , parentSymbols : SymbolInheritanceState [ ] ) : Symbol {
71487178 if ( searchSymbols . indexOf ( referenceSymbol ) >= 0 ) {
71497179 return referenceSymbol ;
71507180 }
@@ -7153,7 +7183,7 @@ namespace ts {
71537183 // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
71547184 const aliasSymbol = getAliasSymbolForPropertyNameSymbol ( referenceSymbol , referenceLocation ) ;
71557185 if ( aliasSymbol ) {
7156- return getRelatedSymbol ( searchSymbols , aliasSymbol , referenceLocation , parentSymbol , inheritanceCache ) ;
7186+ return getRelatedSymbol ( searchSymbols , aliasSymbol , referenceLocation , parentSymbols ) ;
71577187 }
71587188
71597189 // If the reference location is in an object literal, try to get the contextual type for the
@@ -7198,7 +7228,13 @@ namespace ts {
71987228 // Finally, try all properties with the same name in any type the containing type extended or implemented, and
71997229 // see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the
72007230 // parent symbol
7201- if ( rootSymbol . parent && rootSymbol . parent . flags & ( SymbolFlags . Class | SymbolFlags . Interface ) && ( ! parentSymbol || inheritsFrom ( rootSymbol . parent , parentSymbol , inheritanceCache ) ) ) {
7231+ if ( rootSymbol . parent && rootSymbol . parent . flags & ( SymbolFlags . Class | SymbolFlags . Interface ) ) {
7232+ if ( parentSymbols ) {
7233+ if ( ! forEach ( parentSymbols , ( { symbol, cachedInheritanceResults} ) => inheritsFrom ( rootSymbol . parent , symbol , cachedInheritanceResults ) ) ) {
7234+ return undefined ;
7235+ }
7236+ }
7237+
72027238 const result : Symbol [ ] = [ ] ;
72037239 getPropertySymbolsFromBaseTypes ( rootSymbol . parent , rootSymbol . getName ( ) , result , /*previousIterationSymbolsCache*/ createMap < Symbol > ( ) ) ;
72047240 return forEach ( result , s => searchSymbols . indexOf ( s ) >= 0 ? s : undefined ) ;
0 commit comments