All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.java.cleanup.RemoveUnusedLocalVariablesTest.kt Maven / Gradle / Ivy

/*
 * Copyright 2021 the original author or authors.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openrewrite.java.cleanup import org.junit.jupiter.api.Test import org.openrewrite.Issue import org.openrewrite.Recipe import org.openrewrite.java.JavaRecipeTest @Suppress( "ConstantConditions", "StatementWithEmptyBody", "EmptyTryBlock", "CatchMayIgnoreException", "UnusedAssignment", "ResultOfMethodCallIgnored", "BooleanMethodNameMustStartWithQuestion", "PointlessBooleanExpression", "UseOfObsoleteCollectionType", "UnnecessaryLocalVariable", "EmptyFinallyBlock", "ClassInitializerMayBeStatic" ) interface RemoveUnusedLocalVariablesTest : JavaRecipeTest { override val recipe: Recipe get() = RemoveUnusedLocalVariables() @Test @Issue("https://github.com/openrewrite/rewrite/issues/841") fun ignoreSuppressWarnings() = assertUnchanged( before = """ class Test { static int method(int x) { int a = 0; @SuppressWarnings("unused") int b = 0; return a + 1; } } """ ) @Test fun removeUnusedLocalVariables() = assertChanged( before = """ class Test { static int method(int x) { int a = 0; int b = 0; return a; } } """, after = """ class Test { static int method(int x) { int a = 0; return a; } } """ ) @Test fun removeUnusedLocalVariablesReassignedButNeverUsed() = assertChanged( before = """ class Test { static int method() { int isRead = -1; int notRead = 0; notRead = 1; notRead += 1; notRead = isRead + 1; return isRead + 1; } } """, after = """ class Test { static int method() { int isRead = -1; return isRead + 1; } } """ ) @Test fun ignoreClassFields() = assertUnchanged( before = """ class Test { int a = 0; int b = 1; int method(int x) { b = 2; return x + 1; } } """ ) @Test fun removeUnusedLocalVariablesInClassInitializer() = assertChanged( before = """ class Test { static { int unused = 0; int used = 1; System.out.println(used); } { int unused = 0; int used = 1; System.out.println(used); } } """, after = """ class Test { static { int used = 1; System.out.println(used); } { int used = 1; System.out.println(used); } } """ ) @Test fun handleLocalVariablesShadowingClassFields() = assertChanged( before = """ class Test { int a = 0; int unused = 1; static int method(int x) { int unused = 2; return x + 1; } } """, after = """ class Test { int a = 0; int unused = 1; static int method(int x) { return x + 1; } } """ ) @Test fun localVariableUnusedIncrementOperation() = assertChanged( before = """ class Test { static boolean isTrue() { return false; } static int method(int x) { int a = 0; int b = 99; a++; for (int i = 0; isTrue(); i++) { a++; } return b++; } } """, after = """ class Test { static boolean isTrue() { return false; } static int method(int x) { int b = 99; for (int i = 0; isTrue(); i++) { } return b++; } } """ ) @Test @Issue("https://github.com/apache/dubbo/blob/747282cdf851c144af562d3f92e10349cc315e36/dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/model/GooglePB.java#L938-L944") fun keepLocalVariablesAssignmentOperationToOtherVariables() = assertUnchanged( before = """ class Test { static int method() { int dataSize = 0; int size = 0; for (int j = 0; j < 10; j++) { dataSize += 1; } size += dataSize; return size; } } """ ) @Test @Issue("https://github.com/openrewrite/rewrite/blob/706a172ed5449214a4a08637a27dbe768fb4eecd/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java#L55-L65") fun keepLocalVariableAssignmentOperation() = assertUnchanged( before = """ class Test { static boolean method() { boolean a = false; return a |= false; } } """ ) @Test @Issue("https://github.com/openrewrite/rewrite/blob/706a172ed5449214a4a08637a27dbe768fb4eecd/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java#L55-L65") fun removeUnusedLocalVariableBitwiseAssignmentOperation() = assertChanged( before = """ class Test { static boolean method() { boolean a = false; boolean b = false; b &= true; return a |= false; } } """, after = """ class Test { static boolean method() { boolean a = false; return a |= false; } } """ ) @Test @Issue("https://github.com/openrewrite/rewrite/blob/706a172ed5449214a4a08637a27dbe768fb4eecd/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java#L55-L65") fun keepLocalVariableBitwiseAssignmentOperationWithinExpression() = assertUnchanged( before = """ class Test { static boolean method(String string) { boolean a = false; for (char c : string.toCharArray()) { if (false || (a |= !Character.isWhitespace(c))) { break; } } return a; } } """ ) @Test @Issue("https://github.com/openrewrite/rewrite/blob/706a172ed5449214a4a08637a27dbe768fb4eecd/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java#L55-L65") fun handleInstanceOf() = assertUnchanged( before = """ import java.util.Stack; class Test { static boolean method(Stack typeStack) { for (Object e = typeStack.pop(); ; e = typeStack.pop()) { if (e instanceof String) { break; } } return true; } } """ ) @Test fun removeUnusedLocalVariablesFromMultiVariablesDeclaration() = assertChanged( before = """ class Test { static int method(int x) { int a = 0, b = 0, c = 0, d = 0; return b + c; } } """, after = """ class Test { static int method(int x) { int b = 0, c = 0; return b + c; } } """ ) @Test fun keepLocalVariablesWhenUsedAsMethodInvocationArgument() = assertUnchanged( before = """ class Test { static void method() { int a = 0; System.out.println(a); } } """ ) @Test fun keepLocalVariablesWhenMethodInvocationsCalledOnThem() = assertUnchanged( before = """ class Test { void method() { Worker worker = new Worker(); worker.doWork(); } class Worker { void doWork() { // } } } """ ) @Test fun ignoreClassVariables() = assertUnchanged( before = """ class Test { static int someClassVariable = 0; int someInstanceVariable = 0; static void method() { // do nothing } } """ ) @Test fun ignoreAnonymousClassVariables() = assertUnchanged( before = """ import java.io.File; class Test { static File method(File dir) { final File src = new File(dir, "child") { private static final long serialVersionUID = 1L; }; return src; } } """ ) @Test @Issue("https://github.com/apache/dubbo/blob/747282cdf851c144af562d3f92e10349cc315e36/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcStatus.java#L108-L118") fun forLoopWithExternalIncrementLogic() = assertUnchanged( before = """ class Test { static void method() { for (int i; ; ) { i = 41; if (i == 42) { break; } } } } """ ) @Test fun forLoopIncrementVariableReadInEvaluationCondition() = assertUnchanged( before = """ class Test { static void method() { for (int j = 0; j < 10; j++) { } } } """ ) @Test fun removeUnusedLocalVariablesWithinTryCatch() = assertChanged( before = """ class Test { static void method() { try { int a = 0; int b = 1; System.out.println(b); } catch (Exception e) { int a = 3; int b = 4; System.out.println(a); } finally { int a = 5; int b = 6; } } } """, after = """ class Test { static void method() { try { int b = 1; System.out.println(b); } catch (Exception e) { int a = 3; System.out.println(a); } finally { } } } """ ) @Test fun ignoreTryWithResourceUnusedVariables() = assertUnchanged( before = """ import java.util.stream.Stream; class Test { static void method() { try (Stream unused = Stream.of()) { // do nothing } catch (Exception e) { // do nothing } } } """ ) @Test fun handleVariablesReadWithinTry() = assertChanged( before = """ class Test { static void assertEquals(Object expected, Object actual) { // do nothing } static void method() { Object used, unused; try { used = new Object(); assertEquals(used, null); unused = new Object(); } catch (Exception e) { // do nothing } } } """, after = """ class Test { static void assertEquals(Object expected, Object actual) { // do nothing } static void method() { Object used; try { used = new Object(); assertEquals(used, null); } catch (Exception e) { // do nothing } } } """ ) @Test fun ignoreUnusedTryCatchExceptionVariableDeclaration() = assertUnchanged( before = """ class Test { static void method() { try { // do nothing } catch (Exception e) { // do nothing } } } """ ) @Test fun ignoreUnusedLambdaExpressionParameters() = assertUnchanged( before = """ import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; class Test { static BinaryOperator> method() { return (a, b) -> input -> { Object o = a.apply(input); o.toString(); return o; }; } } """ ) @Test fun ignoreUnusedLambdaExpressionParametersForEach() = assertUnchanged( before = """ import java.util.List; class Test { static void method(List list) { list.forEach(item -> { // do nothing with "item" }); } } """ ) @Test @Issue("https://github.com/txazo/spring-cloud-sourcecode/blob/5ffe615558e76f3bb37f19026ece5cbaff4d0404/eureka-client/src/main/java/com/netflix/discovery/converters/jackson/builder/StringInterningAmazonInfoBuilder.java#L114-L124") fun recognizeUsedVariableWithinWhileLoop() = assertChanged( before = """ class Test { TestToken testToken; static void method(Test tp) { int isUsed = 0; TestToken token = tp.nextToken(); while ((token = tp.nextToken()) != TestToken.END_TOKEN) { // do anything except read the value of "token" tp.nextToken(); int unused = 11; unused = isUsed; System.out.println(isUsed); } } TestToken nextToken() { return this.testToken; } enum TestToken { START_TOKEN, END_TOKEN } } """, after = """ class Test { TestToken testToken; static void method(Test tp) { int isUsed = 0; TestToken token = tp.nextToken(); while ((token = tp.nextToken()) != TestToken.END_TOKEN) { // do anything except read the value of "token" tp.nextToken(); System.out.println(isUsed); } } TestToken nextToken() { return this.testToken; } enum TestToken { START_TOKEN, END_TOKEN } } """ ) @Test @Issue("This still causes SonarQube to warn, but there isn't much that can be done in these cases. Maybe change to a while loop?") fun ignoreForLoopIncrementVariableNeverRead() = assertUnchanged( before = """ class Test { static boolean isTrue() { return true; } static void method() { for (int j = 0; isTrue(); j++) { } } } """ ) @Test @Issue("This still causes SonarQube to warn, but there isn't much that can be done in these cases. Maybe change to a forEach?") fun ignoreEnhancedForLoops() = assertUnchanged( before = """ import java.util.List; class Test { static void method(List list) { for (String s : list) { // do nothing } } } """ ) }