Skip to content

Commit

Permalink
fix(40469): suggest QF convert 'Convert to named function' to functio…
Browse files Browse the repository at this point in the history
…n expressions (#40476)
  • Loading branch information
a-tarasyuk authored Nov 5, 2020
1 parent 98aaeb7 commit 899e2d0
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 20 deletions.
31 changes: 19 additions & 12 deletions src/services/refactors/convertArrowFunctionOrFunctionExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,20 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {

function getFunctionInfo(file: SourceFile, startPosition: number, program: Program): FunctionInfo | undefined {
const token = getTokenAtPosition(file, startPosition);

const arrowFunc = getArrowFunctionFromVariableDeclaration(token.parent);
if (arrowFunc && !containingThis(arrowFunc.body)) return { selectedVariableDeclaration: true, func: arrowFunc };

const maybeFunc = getContainingFunction(token);
const typeChecker = program.getTypeChecker();
const func = tryGetFunctionFromVariableDeclaration(file, typeChecker, token.parent);
if (func && !containingThis(func.body)) {
return { selectedVariableDeclaration: true, func };
}

const maybeFunc = getContainingFunction(token);
if (
maybeFunc &&
(isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) &&
!rangeContainsRange(maybeFunc.body, token) &&
!containingThis(maybeFunc.body)
) {
if ((isFunctionExpression(maybeFunc) && maybeFunc.name && FindAllReferences.Core.isSymbolReferencedInFile(maybeFunc.name, typeChecker, file))) return undefined;
if (isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined;
return { selectedVariableDeclaration: false, func: maybeFunc };
}

Expand All @@ -136,13 +136,16 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
return isVariableDeclaration(parent) || (isVariableDeclarationList(parent) && parent.declarations.length === 1);
}

function getArrowFunctionFromVariableDeclaration(parent: Node): ArrowFunction | undefined {
if (!isSingleVariableDeclaration(parent)) return undefined;
const variableDeclaration = isVariableDeclaration(parent) ? parent : parent.declarations[0];

function tryGetFunctionFromVariableDeclaration(sourceFile: SourceFile, typeChecker: TypeChecker, parent: Node): ArrowFunction | FunctionExpression | undefined {
if (!isSingleVariableDeclaration(parent)) {
return undefined;
}
const variableDeclaration = isVariableDeclaration(parent) ? parent : first(parent.declarations);
const initializer = variableDeclaration.initializer;
if (!initializer || !isArrowFunction(initializer)) return undefined;
return initializer;
if (initializer && (isArrowFunction(initializer) || isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer))) {
return initializer;
}
return undefined;
}

function convertToBlock(body: ConciseBody): Block {
Expand Down Expand Up @@ -213,4 +216,8 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
function canBeConvertedToExpression(body: Block, head: Statement): head is ReturnStatement {
return body.statements.length === 1 && ((isReturnStatement(head) && !!head.expression));
}

function isFunctionReferencedInFile(sourceFile: SourceFile, typeChecker: TypeChecker, node: FunctionExpression): boolean {
return !!node.name && FindAllReferences.Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
//// /*z*/c/*y*/onst /*x*/f/*w*/oo = /*v*/f/*u*/unction() /*t*/{/*s*/ /*r*/r/*q*/eturn 42;};

goTo.select("z", "y");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to anonymous function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");

goTo.select("x", "w");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to anonymous function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");

goTo.select("v", "u");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
//// /*z*/c/*y*/onst /*x*/f/*w*/oo = /*v*/f/*u*/unction bar() /*t*/{/*s*/ /*r*/r/*q*/eturn 42;};

goTo.select("z", "y");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to anonymous function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");

goTo.select("x", "w");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to anonymous function");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
verify.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function");

goTo.select("v", "u");
verify.not.refactorAvailable("Convert arrow function or function expression", "Convert to named function");
Expand Down

0 comments on commit 899e2d0

Please sign in to comment.