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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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", `

View File

@ -12,13 +12,13 @@ function /*[#|*/innerPromise/*|]*/(): Promise<string> {
async function innerPromise(): Promise<string> {
const resp = await fetch("https://typescriptlang.org");
let blob: any;
let blob_1: any;
try {
const { blob } = await resp.blob();
blob = blob.byteOffset;
blob_1 = blob.byteOffset;
}
catch ({ message }) {
blob = 'Error ' + message;
blob_1 = 'Error ' + message;
}
return blob.toString();
return blob_1.toString();
}

View File

@ -0,0 +1,20 @@
// ==ORIGINAL==
async function foo<T>(x: T): Promise<T> {
return x;
}
function /*[#|*/bar/*|]*/<T>(x: T): Promise<T> {
return foo(x).then(foo)
}
// ==ASYNC FUNCTION::Convert to async function==
async function foo<T>(x: T): Promise<T> {
return x;
}
async function bar<T>(x: T): Promise<T> {
const x_1 = await foo(x);
return foo(x_1);
}

View File

@ -14,6 +14,6 @@ async function f(): Promise<void>{
// a
/*b*/ const result /*g*/ = await fetch(/*d*/ 'https://typescriptlang.org' /*e*/);
console.log(result); /*k*/
console.log(/*i*/ result /*j*/); /*k*/
// m
}