@@ -5031,9 +5031,10 @@ namespace ts {
50315031 else {
50325032 // Perform "Find all References" and retrieve only those that are implementations
50335033 const referencedSymbols = getReferencedSymbolsForNode ( node , program . getSourceFiles ( ) , /*findInStrings*/ false , /*findInComments*/ false , /*implementations*/ true ) ;
5034-
5035- return flatMap ( referencedSymbols , symbol =>
5034+ const result = flatMap ( referencedSymbols , symbol =>
50365035 map ( symbol . references , ( { textSpan, fileName } ) => ( { textSpan, fileName } ) ) ) ;
5036+
5037+ return result && result . length > 0 ? result : undefined ;
50375038 }
50385039 }
50395040
@@ -5060,9 +5061,7 @@ namespace ts {
50605061 }
50615062 else if ( node . kind === SyntaxKind . VariableDeclaration ) {
50625063 const parentStatement = getParentStatementOfVariableDeclaration ( < VariableDeclaration > node ) ;
5063- if ( parentStatement && hasModifier ( parentStatement , ModifierFlags . Ambient ) ) {
5064- return true ;
5065- }
5064+ return parentStatement && hasModifier ( parentStatement , ModifierFlags . Ambient ) ;
50665065 }
50675066 }
50685067 else if ( isFunctionLike ( node ) ) {
@@ -5081,8 +5080,10 @@ namespace ts {
50815080 }
50825081
50835082 function getParentStatementOfVariableDeclaration ( node : VariableDeclaration ) : VariableStatement {
5084- return node . parent && node . parent . kind === SyntaxKind . VariableDeclarationList && node . parent . parent
5085- && node . parent . parent . kind === SyntaxKind . VariableStatement && < VariableStatement > node . parent . parent ;
5083+ if ( node . parent && node . parent . parent && node . parent . parent . kind === SyntaxKind . VariableStatement ) {
5084+ Debug . assert ( node . parent . kind === SyntaxKind . VariableDeclarationList ) ;
5085+ return < VariableStatement > node . parent . parent ;
5086+ }
50865087 }
50875088
50885089 function getOccurrencesAtPosition ( fileName : string , position : number ) : ReferenceEntry [ ] {
@@ -6491,16 +6492,23 @@ namespace ts {
64916492 /**
64926493 * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
64936494 * is an interface, determines if some ancestor of the child symbol extends or inherits from it.
6494- * This also takes in a cache of previous results which makes this slightly more efficient and is
6495+ * Also takes in a cache of previous results which makes this slightly more efficient and is
64956496 * necessary to avoid potential loops like so:
64966497 * class A extends B { }
64976498 * class B extends A { }
64986499 *
6500+ * We traverse the AST rather than using the type checker because users are typically only interested
6501+ * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling
6502+ * implementations of types that share a common ancestor with the type whose implementation we are
6503+ * searching for need to be filtered out of the results. The type checker doesn't let us make the
6504+ * distinction between structurally compatible implementations and explicit implementations, so we
6505+ * must use the AST.
6506+ *
64996507 * @param child A class or interface Symbol
65006508 * @param parent Another class or interface Symbol
6501- * @param cachedResults A map of symbol names to booleans indicating previous results
6509+ * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results
65026510 */
6503- function inheritsFrom ( child : Symbol , parent : Symbol , cachedResults : Map < boolean > ) : boolean {
6511+ function explicitlyInheritsFrom ( child : Symbol , parent : Symbol , cachedResults : Map < boolean > ) : boolean {
65046512 const parentIsInterface = parent . getFlags ( ) & SymbolFlags . Interface ;
65056513 return searchHierarchy ( child ) ;
65066514
@@ -6966,7 +6974,7 @@ namespace ts {
69666974 if ( rootSymbol . parent && rootSymbol . parent . flags & ( SymbolFlags . Class | SymbolFlags . Interface ) ) {
69676975 // Parents will only be defined if implementations is true
69686976 if ( parents ) {
6969- if ( ! forEach ( parents , parent => inheritsFrom ( rootSymbol . parent , parent , cache ) ) ) {
6977+ if ( ! forEach ( parents , parent => explicitlyInheritsFrom ( rootSymbol . parent , parent , cache ) ) ) {
69706978 return undefined ;
69716979 }
69726980 }
0 commit comments