Skip to content

Commit 7e6f18d

Browse files
author
Andy Hanson
committed
Don't use constructor symbol for search -- use class symbol and filter out only 'new C()' uses.
1 parent f90d8dd commit 7e6f18d

File tree

3 files changed

+23
-34
lines changed

3 files changed

+23
-34
lines changed

src/compiler/core.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,5 +1515,4 @@ namespace ts {
15151515
? ((fileName) => fileName)
15161516
: ((fileName) => fileName.toLowerCase());
15171517
}
1518-
15191518
}

src/services/services.ts

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,7 +4614,6 @@ namespace ts {
46144614
let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location);
46154615
let hasAddedSymbolInfo: boolean;
46164616
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isExpression(location);
4617-
const isConstructor = location.kind === SyntaxKind.ConstructorKeyword;
46184617
let type: Type;
46194618

46204619
// Class at constructor site need to be shown as constructor apart from property,method, vars
@@ -4625,12 +4624,7 @@ namespace ts {
46254624
}
46264625

46274626
let signature: Signature;
4628-
type = isThisExpression
4629-
? typeChecker.getTypeAtLocation(location)
4630-
: isConstructor
4631-
// For constructor, get type of the class.
4632-
? typeChecker.getTypeOfSymbolAtLocation(symbol.parent, location)
4633-
: typeChecker.getTypeOfSymbolAtLocation(symbol, location);
4627+
type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location);
46344628
if (type) {
46354629
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
46364630
const right = (<PropertyAccessExpression>location.parent).name;
@@ -6067,11 +6061,9 @@ namespace ts {
60676061
return getReferencesForSuperKeyword(node);
60686062
}
60696063

6070-
const isConstructor = node.kind === SyntaxKind.ConstructorKeyword;
6071-
60726064
// `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword,
60736065
// so we have to specify that we want the constructor symbol.
6074-
let symbol = isConstructor ? node.parent.symbol : typeChecker.getSymbolAtLocation(node);
6066+
const symbol = typeChecker.getSymbolAtLocation(node);
60756067

60766068
if (!symbol && node.kind === SyntaxKind.StringLiteral) {
60776069
return getReferencesForStringLiteral(<StringLiteral>node, sourceFiles);
@@ -6097,8 +6089,7 @@ namespace ts {
60976089

60986090
// Get the text to search for.
60996091
// Note: if this is an external module symbol, the name doesn't include quotes.
6100-
const nameSymbol = isConstructor ? symbol.parent : symbol; // A constructor is referenced using the name of its class.
6101-
const declaredName = stripQuotes(getDeclaredName(typeChecker, nameSymbol, node));
6092+
const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node));
61026093

61036094
// Try to get the smallest valid scope that we can limit our search to;
61046095
// otherwise we'll need to search globally (i.e. include each file).
@@ -6112,7 +6103,7 @@ namespace ts {
61126103
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
61136104
}
61146105
else {
6115-
const internedName = isConstructor ? declaredName : getInternedName(symbol, node, declarations);
6106+
const internedName = getInternedName(symbol, node, declarations);
61166107
for (const sourceFile of sourceFiles) {
61176108
cancellationToken.throwIfCancellationRequested();
61186109

@@ -6145,7 +6136,7 @@ namespace ts {
61456136
};
61466137
}
61476138

6148-
function getAliasSymbolForPropertyNameSymbol(symbol: Symbol, location: Node): Symbol {
6139+
function getAliasSymbolForPropertyNameSymbol(symbol: Symbol, location: Node): Symbol | undefined {
61496140
if (symbol.flags & SymbolFlags.Alias) {
61506141
// Default import get alias
61516142
const defaultImport = getDeclarationOfKind(symbol, SyntaxKind.ImportClause);
@@ -6171,6 +6162,10 @@ namespace ts {
61716162
return undefined;
61726163
}
61736164

6165+
function followAliasIfNecessary(symbol: Symbol, location: Node): Symbol {
6166+
return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol;
6167+
}
6168+
61746169
function getPropertySymbolOfDestructuringAssignment(location: Node) {
61756170
return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) &&
61766171
typeChecker.getPropertySymbolOfDestructuringAssignment(<Identifier>location);
@@ -6434,7 +6429,8 @@ namespace ts {
64346429
if (referenceSymbol) {
64356430
const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
64366431
const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
6437-
const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation);
6432+
const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
6433+
/*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword);
64386434

64396435
if (relatedSymbol) {
64406436
const referencedSymbol = getReferencedSymbol(relatedSymbol);
@@ -6461,23 +6457,19 @@ namespace ts {
64616457

64626458
/** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */
64636459
function findAdditionalConstructorReferences(referenceSymbol: Symbol, referenceLocation: Node): void {
6464-
const searchClassSymbol = searchSymbol.parent;
6465-
Debug.assert(isClassLike(searchClassSymbol.valueDeclaration));
6460+
Debug.assert(isClassLike(searchSymbol.valueDeclaration));
64666461

64676462
const referenceClass = referenceLocation.parent;
6468-
if (referenceSymbol === searchClassSymbol && isClassLike(referenceClass)) {
6463+
if (referenceSymbol === searchSymbol && isClassLike(referenceClass)) {
6464+
Debug.assert(referenceClass.name === referenceLocation);
64696465
// This is the class declaration containing the constructor.
6470-
const calls = findOwnConstructorCalls(referenceSymbol, <ClassLikeDeclaration>referenceClass);
6471-
addReferences(calls);
6466+
addReferences(findOwnConstructorCalls(referenceSymbol, referenceClass));
64726467
}
64736468
else {
64746469
// If this class appears in `extends C`, then the extending class' "super" calls are references.
64756470
const classExtending = tryGetClassExtendingIdentifier(referenceLocation);
6476-
if (classExtending && isClassLike(classExtending)) {
6477-
if (getRelatedSymbol([searchClassSymbol], referenceSymbol, referenceLocation)) {
6478-
const supers = superConstructorAccesses(classExtending);
6479-
addReferences(supers);
6480-
}
6471+
if (classExtending && isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) {
6472+
addReferences(superConstructorAccesses(classExtending));
64816473
}
64826474
}
64836475
}
@@ -6915,21 +6907,17 @@ namespace ts {
69156907
}
69166908
}
69176909

6918-
function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol | undefined {
6910+
function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node, searchLocationIsConstructor: boolean): Symbol | undefined {
69196911
if (contains(searchSymbols, referenceSymbol)) {
6920-
return referenceSymbol;
6912+
// If we are searching for constructor uses, they must be 'new' expressions.
6913+
return !(searchLocationIsConstructor && !isNewExpressionTarget(referenceLocation)) && referenceSymbol;
69216914
}
69226915

69236916
// If the reference symbol is an alias, check if what it is aliasing is one of the search
69246917
// symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
69256918
const aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation);
69266919
if (aliasSymbol) {
6927-
return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation);
6928-
}
6929-
6930-
// If we are in a constructor and we didn't find the symbol yet, we should try looking for the constructor instead.
6931-
if (isNewExpressionTarget(referenceLocation) && referenceSymbol.members && referenceSymbol.members["__constructor"]) {
6932-
return getRelatedSymbol(searchSymbols, referenceSymbol.members["__constructor"], referenceLocation.parent);
6920+
return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor);
69336921
}
69346922

69356923
// If the reference location is in an object literal, try to get the contextual type for the

tests/cases/fourslash/findAllReferencesOfConstructor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
//// }
2929
//// method() { super(); }
3030
////}
31+
// Does not find 'super()' calls for a class that merely implements 'C',
32+
// since those must be calling a different constructor.
3133
////class E implements C {
3234
//// constructor() { super(); }
3335
////}

0 commit comments

Comments
 (0)