Improve find-all-references for redeclared property in a derived interface (#21002)

This commit is contained in:
Andy
2018-01-04 10:58:14 -08:00
committed by GitHub
parent e3a20e7f0a
commit db82a5604a
39 changed files with 85 additions and 240 deletions

View File

@@ -876,6 +876,8 @@ namespace ts.FindAllReferences.Core {
case SpecialSearchKind.Class:
addClassStaticThisReferences(referenceLocation, search, state);
break;
default:
Debug.assertNever(state.specialSearchKind);
}
getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
@@ -1436,7 +1438,7 @@ namespace ts.FindAllReferences.Core {
// This is not needed when searching for re-exports.
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, implementations: boolean): Symbol[] {
// The search set contains at least the current symbol
const result = [symbol];
const result: Symbol[] = [];
const containingObjectLiteralElement = getContainingObjectLiteralElement(location);
if (containingObjectLiteralElement) {
@@ -1453,9 +1455,9 @@ namespace ts.FindAllReferences.Core {
// If the location is in a context sensitive location (i.e. in an object literal) try
// to get a contextual type for it, and add the property symbol from the contextual
// type to the search set
forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), contextualSymbol => {
addRange(result, checker.getRootSymbols(contextualSymbol));
});
for (const contextualSymbol of getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker)) {
addRootSymbols(contextualSymbol);
}
/* Because in short-hand property assignment, location has two meaning : property name and as value of the property
* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
@@ -1496,9 +1498,7 @@ namespace ts.FindAllReferences.Core {
// If this is a union property, add all the symbols from all its source symbols in all unioned types.
// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
for (const rootSymbol of checker.getRootSymbols(sym)) {
if (rootSymbol !== sym) {
result.push(rootSymbol);
}
result.push(rootSymbol);
// 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)) {
@@ -1522,7 +1522,7 @@ 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: Symbol[], previousIterationSymbolsCache: SymbolTable, checker: TypeChecker): void {
function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, result: Push<Symbol>, previousIterationSymbolsCache: SymbolTable, checker: TypeChecker): void {
if (!symbol) {
return;
}
@@ -1591,9 +1591,7 @@ namespace ts.FindAllReferences.Core {
// compare to our searchSymbol
const containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation);
if (containingObjectLiteralElement) {
const contextualSymbol = forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), contextualSymbol =>
find(checker.getRootSymbols(contextualSymbol), search.includes));
const contextualSymbol = firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), findRootSymbol);
if (contextualSymbol) {
return contextualSymbol;
}
@@ -1622,7 +1620,7 @@ namespace ts.FindAllReferences.Core {
function findRootSymbol(sym: Symbol): Symbol | undefined {
// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
// Or a union property, use its underlying unioned symbols
return forEach(state.checker.getRootSymbols(sym), rootSymbol => {
return firstDefined(checker.getRootSymbols(sym), rootSymbol => {
// if it is in the list, then we are done
if (search.includes(rootSymbol)) {
return rootSymbol;
@@ -1633,12 +1631,12 @@ namespace ts.FindAllReferences.Core {
// parent symbol
if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
// Parents will only be defined if implementations is true
if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, state.checker))) {
if (search.parents && !some(search.parents, parent => explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker))) {
return undefined;
}
const result: Symbol[] = [];
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker);
getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker);
return find(result, search.includes);
}
@@ -1660,28 +1658,12 @@ namespace ts.FindAllReferences.Core {
}
/** Gets all symbols for one property. Does not get symbols for every property. */
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): Symbol[] | undefined {
const objectLiteral = <ObjectLiteralExpression>node.parent;
const contextualType = checker.getContextualType(objectLiteral);
function getPropertySymbolsFromContextualType(node: ObjectLiteralElement, checker: TypeChecker): ReadonlyArray<Symbol> {
const contextualType = checker.getContextualType(<ObjectLiteralExpression>node.parent);
const name = getNameFromObjectLiteralElement(node);
if (name && contextualType) {
const result: Symbol[] = [];
const symbol = contextualType.getProperty(name);
if (symbol) {
result.push(symbol);
}
if (contextualType.flags & TypeFlags.Union) {
forEach((<UnionType>contextualType).types, t => {
const symbol = t.getProperty(name);
if (symbol) {
result.push(symbol);
}
});
}
return result;
}
return undefined;
const symbol = contextualType && name && contextualType.getProperty(name);
return symbol ? [symbol] :
contextualType && contextualType.flags & TypeFlags.Union ? mapDefined((<UnionType>contextualType).types, t => t.getProperty(name)) : emptyArray;
}
/**