From c4080437b2b765bdc9fab3efb03ee8fe5bbed088 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 3 Aug 2021 21:31:56 +0300 Subject: [PATCH] fix(45102): do not suggest refactoring for functions contains arguments reference (#45116) --- src/compiler/checker.ts | 1 + src/compiler/types.ts | 2 ++ .../convertArrowFunctionOrFunctionExpression.ts | 5 +++-- ...OrFunctionExpression_Availability_Anon_arguments.ts | 10 ++++++++++ ...rFunctionExpression_Availability_Arrow_arguments.ts | 10 ++++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_arguments.ts create mode 100644 tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_arguments.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a5809854fee..95001807b6a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -555,6 +555,7 @@ namespace ts { getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp), getExpandedParameters, hasEffectiveRestParameter, + containsArgumentsReference, getConstantValue: nodeIn => { const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3918e770efa..951316eb866 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4205,6 +4205,8 @@ namespace ts { /* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; /* @internal */ getExpandedParameters(sig: Signature): readonly (readonly Symbol[])[]; /* @internal */ hasEffectiveRestParameter(sig: Signature): boolean; + /* @internal */ containsArgumentsReference(declaration: SignatureDeclaration): boolean; + getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; diff --git a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts index 75cf29f9d79..4165cbfcc07 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -141,7 +141,7 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { const token = getTokenAtPosition(file, startPosition); const typeChecker = program.getTypeChecker(); const func = tryGetFunctionFromVariableDeclaration(file, typeChecker, token.parent); - if (func && !containingThis(func.body)) { + if (func && !containingThis(func.body) && !typeChecker.containsArgumentsReference(func)) { return { selectedVariableDeclaration: true, func }; } @@ -150,7 +150,8 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression { maybeFunc && (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) && !rangeContainsRange(maybeFunc.body, token) && - !containingThis(maybeFunc.body) + !containingThis(maybeFunc.body) && + !typeChecker.containsArgumentsReference(maybeFunc) ) { if (isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined; return { selectedVariableDeclaration: false, func: maybeFunc }; diff --git a/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_arguments.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_arguments.ts new file mode 100644 index 00000000000..dec33abe25b --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Anon_arguments.ts @@ -0,0 +1,10 @@ +/// + +////function foo() { +//// return /*a*/(/*b*/) => arguments; +////} + +goTo.select("a", "b"); +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_arguments.ts b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_arguments.ts new file mode 100644 index 00000000000..49056d7e57b --- /dev/null +++ b/tests/cases/fourslash/refactorConvertArrowFunctionOrFunctionExpression_Availability_Arrow_arguments.ts @@ -0,0 +1,10 @@ +/// + +////function foo() { +//// return /*a*/f/*b*/unction () { arguments } +////} + +goTo.select("a", "b"); +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");