Skip to content

Commit b6f7dd7

Browse files
committed
More PR feedback
1 parent 4a37fd7 commit b6f7dd7

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

src/harness/fourslash.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,12 +1681,14 @@ namespace FourSlash {
16811681
}
16821682

16831683
public verifyImplementationListIsEmpty(negative: boolean) {
1684-
const assertFn = negative ? assert.notEqual : assert.equal;
1685-
16861684
const implementations = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition);
1687-
const actualCount = implementations && implementations.length || 0;
16881685

1689-
assertFn(actualCount, 0, this.messageAtLastKnownMarker("Implementations Count"));
1686+
if (negative) {
1687+
assert.isTrue(implementations && implementations.length > 0, "Expected at least one implementation but got 0");
1688+
}
1689+
else {
1690+
assert.isUndefined(implementations, "Expected implementation list to be empty but implementations returned");
1691+
}
16901692
}
16911693

16921694
public verifyGoToDefinitionName(expectedName: string, expectedContainerName: string) {

src/services/services.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)