diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index b7d948b3deb..59d19a1bd9b 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -121,9 +121,26 @@ namespace ts.codefix { break; case SyntaxKind.Parameter: - const functionDeclaration = parent.parent; - if (functionDeclaration.parameters.length === 1) { - changes.deleteNode(sourceFile, parent); + const oldFunction = parent.parent; + if (isArrowFunction(oldFunction) && oldFunction.parameters.length === 1) { + // Lambdas with exactly one parameter are special because, after removal, there + // must be an empty parameter list (i.e. `()`) and this won't necessarily be the + // case if the parameter is simply removed (e.g. in `x => 1`). + const newFunction = updateArrowFunction( + oldFunction, + oldFunction.modifiers, + oldFunction.typeParameters, + /*parameters*/ undefined, + oldFunction.type, + oldFunction.equalsGreaterThanToken, + oldFunction.body); + + // Drop leading and trailing trivia of the new function because we're only going + // to replace the span (vs the full span) of the old function - the old leading + // and trailing trivia will remain. + suppressLeadingAndTrailingTrivia(newFunction); + + changes.replaceRange(sourceFile, { pos: oldFunction.getStart(), end: oldFunction.end }, newFunction); } else { changes.deleteNodeInList(sourceFile, parent); diff --git a/tests/cases/fourslash/unusedParameterInLambda1.ts b/tests/cases/fourslash/unusedParameterInLambda1.ts index ace79adae46..fdb53a8a05f 100644 --- a/tests/cases/fourslash/unusedParameterInLambda1.ts +++ b/tests/cases/fourslash/unusedParameterInLambda1.ts @@ -2,12 +2,11 @@ // @noUnusedLocals: true // @noUnusedParameters: true -//// function f1() { -//// [|return (x:number) => {}|] -//// } +////[|/*~a*/(/*~b*/x/*~c*/:/*~d*/number/*~e*/)/*~f*/ => /*~g*/{/*~h*/}/*~i*/|] +// In a perfect world, /*~f*/ and /*~h*/ would probably be retained. verify.codeFix({ description: "Remove declaration for: 'x'", index: 0, - newRangeContent: "return () => {}", + newRangeContent: "/*~a*/() => /*~g*/ { }/*~i*/", }); diff --git a/tests/cases/fourslash/unusedParameterInLambda2.ts b/tests/cases/fourslash/unusedParameterInLambda2.ts new file mode 100644 index 00000000000..e2b1be346b8 --- /dev/null +++ b/tests/cases/fourslash/unusedParameterInLambda2.ts @@ -0,0 +1,12 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true +////[|/*~a*/x/*~b*/ /*~c*/=>/*~d*/ {/*~e*/}/*~f*/|] + +// In a perfect world, /*~c*/ and /*~e*/ would probably be retained. +verify.codeFix({ + description: "Remove declaration for: 'x'", + index: 0, + newRangeContent: "/*~a*/() => /*~d*/ { }/*~f*/", +}); diff --git a/tests/cases/fourslash/unusedParameterInLambda3.ts b/tests/cases/fourslash/unusedParameterInLambda3.ts new file mode 100644 index 00000000000..f95d142d436 --- /dev/null +++ b/tests/cases/fourslash/unusedParameterInLambda3.ts @@ -0,0 +1,12 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true +////[|/*~a*/(/*~b*/x/*~c*/,/*~d*/y/*~e*/)/*~f*/ => /*~g*/x/*~h*/|] + +// In a perfect world, /*~c*/ would probably be retained, rather than /*~e*/. +verify.codeFix({ + description: "Remove declaration for: 'y'", + index: 0, + newRangeContent: "/*~a*/(/*~b*/x/*~e*/)/*~f*/ => /*~g*/x/*~h*/", +}); diff --git a/tests/cases/fourslash/unusedParameterInLambda4.ts b/tests/cases/fourslash/unusedParameterInLambda4.ts new file mode 100644 index 00000000000..015f081891a --- /dev/null +++ b/tests/cases/fourslash/unusedParameterInLambda4.ts @@ -0,0 +1,11 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true +////[|/*~a*/(/*~b*/x/*~c*/,/*~d*/y/*~e*/)/*~f*/ => /*~g*/y/*~h*/|] + +verify.codeFix({ + description: "Remove declaration for: 'x'", + index: 0, + newRangeContent: "/*~a*/(/*~d*/y/*~e*/)/*~f*/ => /*~g*/y/*~h*/", +});