diff --git a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts index d79a0561bd5..78d2127ac01 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -93,16 +93,36 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { return { renameFilename: undefined, renameLocation: undefined, edits }; } + function containingThis(node: Node): boolean { + let containsThis = false; + node.forEachChild(function checkThis(child) { + + if (isThis(child)) { + containsThis = true; + return; + } + + forEachChild(child, checkThis); + }); + + return containsThis; + } + 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 }; + if (arrowFunc && !containingThis(arrowFunc.body)) return { selectedVariableDeclaration: true, func: arrowFunc }; const maybeFunc = getContainingFunction(token); const typeChecker = program.getTypeChecker(); - if (maybeFunc && (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) && !rangeContainsRange(maybeFunc.body, 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; return { selectedVariableDeclaration: false, func: maybeFunc }; } diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_this.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_this.ts new file mode 100644 index 00000000000..5ea85798bdd --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_this.ts @@ -0,0 +1,9 @@ +/// + +//// const bar = 42; +//// const foo = /*x*/f/*w*/unction() {return this.bar;}; + +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"); diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_this.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_this.ts new file mode 100644 index 00000000000..d1905c48f35 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_this.ts @@ -0,0 +1,9 @@ +/// + +//// const bar = 42; +//// const foo = /*x*/(/*w*/) => this.bar; + +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"); diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_FnArgument.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_FnArgument.ts index 28ad1354991..c07a741f1ab 100644 --- a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_FnArgument.ts +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_FnArgument.ts @@ -10,6 +10,6 @@ edit.applyRefactor({ actionDescription: "Convert to anonymous function", newContent: `function doSomething(a){} doSomething(function() { - return 1 + 1; -});`, + return 1 + 1; + });`, }); diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_MapArgument.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_MapArgument.ts index d1919cf5d7c..8d53517d7ea 100644 --- a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_MapArgument.ts +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_ToAnon_MapArgument.ts @@ -8,6 +8,6 @@ edit.applyRefactor({ actionName: "Convert to anonymous function", actionDescription: "Convert to anonymous function", newContent: `[9,8,7].map(function(n) { - return n + 418; -});`, + return n + 418; + });`, });