diff --git a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts index 50ab2fa3563..d79a0561bd5 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -26,8 +26,8 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { } function getAvailableActions(context: RefactorContext): ReadonlyArray { - const { file, startPosition } = context; - const info = getFunctionInfo(file, startPosition); + const { file, startPosition, program } = context; + const info = getFunctionInfo(file, startPosition, program); if (!info) return emptyArray; const { selectedVariableDeclaration, func } = info; @@ -62,8 +62,8 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { } function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { - const { file, startPosition } = context; - const info = getFunctionInfo(file, startPosition); + const { file, startPosition, program } = context; + const info = getFunctionInfo(file, startPosition, program); if (!info) return undefined; const { func } = info; @@ -93,14 +93,17 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { return { renameFilename: undefined, renameLocation: undefined, edits }; } - function getFunctionInfo(file: SourceFile, startPosition: number): FunctionInfo | undefined { + function getFunctionInfo(file: SourceFile, startPosition: number, program: Program): FunctionInfo | undefined { const token = getTokenAtPosition(file, startPosition); const arrowFunc = getArrowFunctionFromVariableDeclaration(token.parent); if (arrowFunc) return { selectedVariableDeclaration: true, func: arrowFunc }; const maybeFunc = getContainingFunction(token); + const typeChecker = program.getTypeChecker(); + if (maybeFunc && (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) && !rangeContainsRange(maybeFunc.body, token)) { + if ((isFunctionExpression(maybeFunc) && maybeFunc.name && FindAllReferences.Core.isSymbolReferencedInFile(maybeFunc.name, typeChecker, file))) return undefined; return { selectedVariableDeclaration: false, func: maybeFunc }; } diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_unusedName.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_unusedName.ts new file mode 100644 index 00000000000..480dd466ec2 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_unusedName.ts @@ -0,0 +1,28 @@ +/// + +//// /*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"); + +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"); + +goTo.select("v", "u"); +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.refactorAvailable("Convert arrow function or function expression", "Convert to arrow function"); + +goTo.select("t", "s"); +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"); + +goTo.select("r", "q"); +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"); diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_usedName.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_usedName.ts new file mode 100644 index 00000000000..ff87ca84714 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_usedName.ts @@ -0,0 +1,28 @@ +/// + +//// /*z*/c/*y*/onst /*x*/f/*w*/oo = /*v*/f/*u*/unction isEven(n) /*t*/{/*s*/ /*r*/r/*q*/eturn n === 0 ? true : n === 1 ? false : isEven(n - 2);}; + +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"); + +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"); + +goTo.select("v", "u"); +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"); + +goTo.select("t", "s"); +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"); + +goTo.select("r", "q"); +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");