Simplify getPropertySymbolsFromBaseTypes (#23004)

This commit is contained in:
Andy 2018-03-30 09:42:49 -07:00 committed by GitHub
parent 31c3ef51d3
commit a5df301dec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1438,7 +1438,7 @@ namespace ts.FindAllReferences.Core {
// Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker);
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, result);
}
}
}
@ -1458,27 +1458,22 @@ namespace ts.FindAllReferences.Core {
* @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol.
* The value of previousIterationSymbol is undefined when the function is first called.
*/
function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Push<Symbol>, previousIterationSymbolsCache: SymbolTable, checker: TypeChecker): void {
// If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited
// This is particularly important for the following cases, so that we do not infinitely visit the same symbol.
// For example:
// interface C extends C {
// /*findRef*/propName: string;
// }
// The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName,
// the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined,
// the function will add any found symbol of the property-name, then its sub-routine will call
// getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already
// visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol.
if (!symbol || previousIterationSymbolsCache.has(symbol.escapedName)) {
return;
}
function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, checker: TypeChecker, result: Symbol[] = []): Symbol[] {
const seen = createMap<true>();
recur(symbol);
return result;
function recur(symbol: Symbol): void {
// Use `addToSeen` to ensure we don't infinitely recurse in this situation:
// interface C extends C {
// /*findRef*/propName: string;
// }
if (!(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, getSymbolId(symbol))) return;
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
for (const declaration of symbol.declarations) {
for (const typeReference of getAllSuperTypeNodes(declaration)) {
const type = checker.getTypeAtLocation(typeReference);
if (!type) continue;
if (!(type && type.symbol)) continue;
const propertySymbol = checker.getPropertyOfType(type, propertyName);
if (propertySymbol) {
@ -1486,8 +1481,7 @@ namespace ts.FindAllReferences.Core {
}
// Visit the typeReference as well to see if it directly or indirectly use that property
previousIterationSymbolsCache.set(symbol.escapedName, symbol);
getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache, checker);
recur(type.symbol);
}
}
}
@ -1559,9 +1553,7 @@ namespace ts.FindAllReferences.Core {
return undefined;
}
const result: Symbol[] = [];
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker);
return result.some(search.includes) ? rootSymbol : undefined;
return getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker).some(search.includes) ? rootSymbol : undefined;
}
return undefined;
@ -1667,20 +1659,11 @@ namespace ts.FindAllReferences.Core {
*/
function getParentSymbolsOfPropertyAccess(location: Node, symbol: Symbol, checker: TypeChecker): Symbol[] | undefined {
const propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(location);
if (!propertyAccessExpression) {
return undefined;
}
const localParentType = checker.getTypeAtLocation(propertyAccessExpression.expression);
if (!localParentType) {
return undefined;
}
if (localParentType.symbol && localParentType.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) && localParentType.symbol !== symbol.parent) {
return [localParentType.symbol];
}
else if (localParentType.flags & TypeFlags.UnionOrIntersection) {
return getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType);
}
const localParentType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression);
return localParentType && localParentType.symbol && localParentType.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) && localParentType.symbol !== symbol.parent
? [localParentType.symbol]
: localParentType && localParentType.flags & TypeFlags.UnionOrIntersection
? getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType)
: undefined;
}
}