@@ -5031,9 +5031,10 @@ namespace ts {
5031
5031
else {
5032
5032
// Perform "Find all References" and retrieve only those that are implementations
5033
5033
const referencedSymbols = getReferencedSymbolsForNode ( node , program . getSourceFiles ( ) , /*findInStrings*/ false , /*findInComments*/ false , /*implementations*/ true ) ;
5034
-
5035
- return flatMap ( referencedSymbols , symbol =>
5034
+ const result = flatMap ( referencedSymbols , symbol =>
5036
5035
map ( symbol . references , ( { textSpan, fileName } ) => ( { textSpan, fileName } ) ) ) ;
5036
+
5037
+ return result && result . length > 0 ? result : undefined ;
5037
5038
}
5038
5039
}
5039
5040
@@ -5060,9 +5061,7 @@ namespace ts {
5060
5061
}
5061
5062
else if ( node . kind === SyntaxKind . VariableDeclaration ) {
5062
5063
const parentStatement = getParentStatementOfVariableDeclaration ( < VariableDeclaration > node ) ;
5063
- if ( parentStatement && hasModifier ( parentStatement , ModifierFlags . Ambient ) ) {
5064
- return true ;
5065
- }
5064
+ return parentStatement && hasModifier ( parentStatement , ModifierFlags . Ambient ) ;
5066
5065
}
5067
5066
}
5068
5067
else if ( isFunctionLike ( node ) ) {
@@ -5081,8 +5080,10 @@ namespace ts {
5081
5080
}
5082
5081
5083
5082
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
+ }
5086
5087
}
5087
5088
5088
5089
function getOccurrencesAtPosition ( fileName : string , position : number ) : ReferenceEntry [ ] {
@@ -6491,16 +6492,23 @@ namespace ts {
6491
6492
/**
6492
6493
* Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
6493
6494
* 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
6495
6496
* necessary to avoid potential loops like so:
6496
6497
* class A extends B { }
6497
6498
* class B extends A { }
6498
6499
*
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
+ *
6499
6507
* @param child A class or interface Symbol
6500
6508
* @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
6502
6510
*/
6503
- function inheritsFrom ( child : Symbol , parent : Symbol , cachedResults : Map < boolean > ) : boolean {
6511
+ function explicitlyInheritsFrom ( child : Symbol , parent : Symbol , cachedResults : Map < boolean > ) : boolean {
6504
6512
const parentIsInterface = parent . getFlags ( ) & SymbolFlags . Interface ;
6505
6513
return searchHierarchy ( child ) ;
6506
6514
@@ -6966,7 +6974,7 @@ namespace ts {
6966
6974
if ( rootSymbol . parent && rootSymbol . parent . flags & ( SymbolFlags . Class | SymbolFlags . Interface ) ) {
6967
6975
// Parents will only be defined if implementations is true
6968
6976
if ( parents ) {
6969
- if ( ! forEach ( parents , parent => inheritsFrom ( rootSymbol . parent , parent , cache ) ) ) {
6977
+ if ( ! forEach ( parents , parent => explicitlyInheritsFrom ( rootSymbol . parent , parent , cache ) ) ) {
6970
6978
return undefined ;
6971
6979
}
6972
6980
}
0 commit comments