From ecd3b6167a2e00f23bb1b3ae6b6923ce70e338f0 Mon Sep 17 00:00:00 2001 From: Roland Grunberg Date: Tue, 5 Nov 2024 14:45:07 -0500 Subject: [PATCH] Add code action for unused pattern variable / unused lambda parameter. - Also add as clean up - Add testcase for clean up functionality Signed-off-by: Roland Grunberg --- .../internal/cleanup/CleanUpRegistry.java | 3 +- .../RenameUnusedLocalVariableCleanup.java | 49 +++++++++++++++++++ .../corrections/QuickFixProcessor.java | 1 + .../LocalCorrectionsSubProcessor.java | 17 +++++++ .../core/internal/cleanup/CleanUpsTest.java | 37 +++++++++++++- 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/RenameUnusedLocalVariableCleanup.java diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpRegistry.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpRegistry.java index e605de886c..0d153ef0d5 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpRegistry.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpRegistry.java @@ -55,7 +55,8 @@ public CleanUpRegistry() { new LambdaExpressionCleanup(), new TryWithResourceCleanUp(), new LambdaExpressionAndMethodRefCleanUp(), - new OrganizeImportsCleanup()); + new OrganizeImportsCleanup(), + new RenameUnusedLocalVariableCleanup()); // Store in a Map so that they can be accessed by ID quickly cleanUps = new HashMap<>(); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/RenameUnusedLocalVariableCleanup.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/RenameUnusedLocalVariableCleanup.java new file mode 100644 index 0000000000..4984cb0b33 --- /dev/null +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/RenameUnusedLocalVariableCleanup.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2024 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.ls.core.internal.cleanup; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.internal.corext.fix.CleanUpConstants; +import org.eclipse.jdt.internal.corext.fix.RenameUnusedVariableFixCore; +import org.eclipse.jdt.ui.cleanup.CleanUpContext; +import org.eclipse.jdt.ui.cleanup.ICleanUpFix; + +/** + * Represents a clean up that renames unused lambda parameter identifier to an + * underscore (_) + */ +public class RenameUnusedLocalVariableCleanup implements ISimpleCleanUp { + + private static final List COMPILER_OPTS = Arrays.asList(JavaCore.COMPILER_PB_UNUSED_LAMBDA_PARAMETER, JavaCore.COMPILER_PB_UNUSED_LOCAL); + + @Override + public Collection getIdentifiers() { + return List.of("removeUnusedLambdaParameters", CleanUpConstants.REMOVE_UNUSED_CODE_LOCAL_VARIABLES); + } + + @Override + public ICleanUpFix createFix(CleanUpContext context) throws CoreException { + return RenameUnusedVariableFixCore.createCleanUp(context.getAST(), true); + } + + @Override + public List getRequiredCompilerMarkers() { + return COMPILER_OPTS; + } + +} diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/QuickFixProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/QuickFixProcessor.java index c5c1aa2f2d..fb74dd45eb 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/QuickFixProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/QuickFixProcessor.java @@ -342,6 +342,7 @@ private void process(CodeActionParams params, IInvocationContext context, IProbl case IProblem.UnusedPrivateType: case IProblem.LocalVariableIsNeverUsed: case IProblem.ArgumentIsNeverUsed: + case IProblem.LambdaParameterIsNeverUsed: case IProblem.UnusedPrivateField: LocalCorrectionsSubProcessor.addUnusedMemberProposal(context, problem, proposals); break; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/LocalCorrectionsSubProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/LocalCorrectionsSubProcessor.java index ce9890fb17..29bbf92613 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/LocalCorrectionsSubProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/LocalCorrectionsSubProcessor.java @@ -92,6 +92,7 @@ import org.eclipse.jdt.internal.corext.fix.CleanUpConstants; import org.eclipse.jdt.internal.corext.fix.CodeStyleFixCore; import org.eclipse.jdt.internal.corext.fix.IProposableFix; +import org.eclipse.jdt.internal.corext.fix.RenameUnusedVariableFixCore; import org.eclipse.jdt.internal.corext.fix.SealedClassFixCore; import org.eclipse.jdt.internal.corext.fix.UnimplementedCodeFixCore; import org.eclipse.jdt.internal.corext.fix.UnusedCodeFixCore; @@ -434,6 +435,22 @@ public static void addUnimplementedMethodsProposals(IInvocationContext context, public static void addUnusedMemberProposal(IInvocationContext context, IProblemLocation problem, Collection proposals) { int problemId = problem.getProblemId(); + if (JavaModelUtil.is22OrHigher(context.getCompilationUnit().getJavaProject()) && (problemId == IProblem.LocalVariableIsNeverUsed || problemId == IProblem.LambdaParameterIsNeverUsed)) { + RenameUnusedVariableFixCore fix = RenameUnusedVariableFixCore.createRenameToUnnamedFix(context.getASTRoot(), problem); + if (fix != null) { + try { + CompilationUnitChange change = fix.createChange(null); + CUCorrectionProposalCore proposal = new CUCorrectionProposalCore(change.getName(), change.getCompilationUnit(), change, IProposalRelevance.UNUSED_MEMBER); + proposals.add(CodeActionHandler.wrap(proposal, CodeActionKind.QuickFix)); + } catch (CoreException e) { + JavaLanguageServerPlugin.log(e); + } + } + } + if (problemId == IProblem.LambdaParameterIsNeverUsed) { + return; + } + UnusedCodeFixCore fix = UnusedCodeFixCore.createUnusedMemberFix(context.getASTRoot(), problem, false); if (fix != null) { try { diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpsTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpsTest.java index 696d185d47..2a15d17116 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpsTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/cleanup/CleanUpsTest.java @@ -58,7 +58,7 @@ public void setup() throws Exception { javaProject = JavaCore.create(project); Hashtable options = TestOptions.getDefaultOptions(); - JavaCore.setComplianceOptions(JavaCore.VERSION_19, options); + JavaCore.setComplianceOptions(JavaCore.VERSION_22, options); options.put(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, String.valueOf(99)); javaProject.setOptions(options); @@ -640,4 +640,39 @@ public void test() { assertEquals(expected, actual); } + @Test + public void testRenameUnusedLambdaParameterCleanup() throws Exception { + String contents = """ + package test1; + public class A { + private interface J { + public void run(String a, String b); + } + public void test() { + J j = (a, b) -> System.out.println(a); + j.run("a", "b"); + } + } + """; + + ICompilationUnit unit = pack1.createCompilationUnit("A.java", contents, false, monitor); + String uri = unit.getUnderlyingResource().getLocationURI().toString(); + + String expected = """ + package test1; + public class A { + private interface J { + public void run(String a, String b); + } + public void test() { + J j = (a, _) -> System.out.println(a); + j.run("a", "b"); + } + } + """; + List textEdits = registry.getEditsForAllActiveCleanUps(new TextDocumentIdentifier(uri), Arrays.asList("removeUnusedLambdaParameters"), monitor); + String actual = TextEditUtil.apply(unit, textEdits); + assertEquals(expected, actual); + } + }