Fix variable name collisions (#37761)

This commit is contained in:
Andrew Branch
2020-04-02 14:12:19 -08:00
committed by GitHub
parent 527f467926
commit 2187ba1f84
5 changed files with 35 additions and 24 deletions

View File

@@ -36,11 +36,6 @@ namespace ts.codefix {
hasBeenDeclared: boolean;
}
interface SymbolAndIdentifier {
readonly identifier: Identifier;
readonly symbol: Symbol;
}
interface Transformer {
readonly checker: TypeChecker;
readonly synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
@@ -139,12 +134,6 @@ namespace ts.codefix {
return !!(nodeType && checker.getPromisedTypeOfPromise(nodeType));
}
function isParameterOfPromiseCallback(node: Node, checker: TypeChecker): node is ParameterDeclaration {
return isParameter(node) && (
isPromiseReturningCallExpression(node.parent.parent, checker, "then") ||
isPromiseReturningCallExpression(node.parent.parent, checker, "catch"));
}
function isPromiseTypedExpression(node: Node, checker: TypeChecker): node is Expression {
if (!isExpression(node)) return false;
return !!checker.getPromisedTypeOfPromise(checker.getTypeAtLocation(node));
@@ -160,7 +149,6 @@ namespace ts.codefix {
It then checks for any collisions and renames them through getSynthesizedDeepClone
*/
function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map<SynthIdentifier>, sourceFile: SourceFile): FunctionLikeDeclaration {
const variableNames: SymbolAndIdentifier[] = [];
const identsToRenameMap = createMap<Identifier>(); // key is the symbol id
const collidingSymbolMap = createMultiMap<Symbol>();
forEachChild(nodeToRename, function visit(node: Node) {
@@ -188,7 +176,6 @@ namespace ts.codefix {
const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
const synthName = getNewNameIfConflict(ident, collidingSymbolMap);
synthNamesMap.set(symbolIdString, synthName);
variableNames.push({ identifier: synthName.identifier, symbol });
collidingSymbolMap.add(ident.text, symbol);
}
// We only care about identifiers that are parameters, variable declarations, or binding elements
@@ -201,17 +188,12 @@ namespace ts.codefix {
const newName = getNewNameIfConflict(node, collidingSymbolMap);
identsToRenameMap.set(symbolIdString, newName.identifier);
synthNamesMap.set(symbolIdString, newName);
variableNames.push({ identifier: newName.identifier, symbol });
collidingSymbolMap.add(originalName, symbol);
}
else {
const identifier = getSynthesizedDeepClone(node);
identsToRenameMap.set(symbolIdString, identifier);
synthNamesMap.set(symbolIdString, createSynthIdentifier(identifier));
if (isParameterOfPromiseCallback(node.parent, checker) || isVariableDeclaration(node.parent)) {
variableNames.push({ identifier, symbol });
collidingSymbolMap.add(originalName, symbol);
}
collidingSymbolMap.add(originalName, symbol);
}
}
}

View File

@@ -1113,7 +1113,16 @@ function rej(reject): a{
`
);
_testConvertToAsyncFunction("convertToAsyncFunction_ParameterNameCollision", `
async function foo<T>(x: T): Promise<T> {
return x;
}
function [#|bar|]<T>(x: T): Promise<T> {
return foo(x).then(foo)
}
`
);
_testConvertToAsyncFunction("convertToAsyncFunction_LocalReturn", `