-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove finalizer from classes in util.zip (#233)
* recipe for removing finalizer from ZipFile, Deflater and Inflater * adding license header to recipe * Format textblocks and resolve ZipFile compilation issues * Format RemoveFinalizerFromZip * Add tests to show or prevent implementation issues * added preconditions and refactored the logic * fixing finalize removal recipe to handle edge cases * Apply formatter * Only override visitMethodInvocation Support case of empty select by looking at surrounding class declaration Use method matcher instead of String comparison to find finalize calls Use TypeUtils instead of String comparison to find extending classes * Also removeCallsToSelfFinalize * Limit to Java 12+ --------- Co-authored-by: Tim te Beek <tim@moderne.io>
- Loading branch information
1 parent
4241d47
commit 927b01d
Showing
2 changed files
with
373 additions
and
0 deletions.
There are no files selected for viewing
101 changes: 101 additions & 0 deletions
101
src/main/java/org/openrewrite/java/migrate/util/RemoveFinalizerFromZip.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Copyright 2023 the original author or authors. | ||
* <p> | ||
* 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 | ||
* <p> | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* <p> | ||
* 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.migrate.util; | ||
|
||
import lombok.EqualsAndHashCode; | ||
import lombok.Value; | ||
import org.openrewrite.ExecutionContext; | ||
import org.openrewrite.Preconditions; | ||
import org.openrewrite.Recipe; | ||
import org.openrewrite.TreeVisitor; | ||
import org.openrewrite.java.JavaVisitor; | ||
import org.openrewrite.java.MethodMatcher; | ||
import org.openrewrite.java.search.UsesJavaVersion; | ||
import org.openrewrite.java.search.UsesType; | ||
import org.openrewrite.java.tree.Expression; | ||
import org.openrewrite.java.tree.J; | ||
import org.openrewrite.java.tree.JavaType; | ||
import org.openrewrite.java.tree.TypeUtils; | ||
|
||
import java.util.List; | ||
|
||
@Value | ||
@EqualsAndHashCode(callSuper = true) | ||
public class RemoveFinalizerFromZip extends Recipe { | ||
|
||
private static final String JAVA_UTIL_ZIP_DEFLATER = "java.util.zip.Deflater"; | ||
private static final String JAVA_UTIL_ZIP_INFLATER = "java.util.zip.Inflater"; | ||
private static final String JAVA_UTIL_ZIP_ZIP_FILE = "java.util.zip.ZipFile"; | ||
|
||
private static final MethodMatcher METHOD_MATCHER = new MethodMatcher("java.lang.Object finalize()"); | ||
|
||
@Override | ||
public String getDisplayName() { | ||
return "Remove invocations of deprecated invocations from Deflater, Inflater, ZipFile "; | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "Remove invocations of finalize() deprecated invocations from Deflater, Inflater, ZipFile."; | ||
} | ||
|
||
@Override | ||
public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
return Preconditions.check(Preconditions.and( | ||
new UsesJavaVersion<>(12), | ||
Preconditions.or( | ||
new UsesType<>(JAVA_UTIL_ZIP_DEFLATER, false), | ||
new UsesType<>(JAVA_UTIL_ZIP_INFLATER, false), | ||
new UsesType<>(JAVA_UTIL_ZIP_ZIP_FILE, false))), | ||
new JavaVisitor<ExecutionContext>() { | ||
@Override | ||
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) { | ||
J.MethodInvocation mi = (J.MethodInvocation) super.visitMethodInvocation(method, executionContext); | ||
|
||
if (METHOD_MATCHER.matches(mi)) { | ||
Expression select = mi.getSelect(); | ||
if (select == null) { | ||
J.ClassDeclaration cd = getCursor().firstEnclosingOrThrow(J.ClassDeclaration.class); | ||
if (shouldRemoveFinalize(cd.getType())) { | ||
return null; | ||
} | ||
} else { | ||
if (shouldRemoveFinalize(select.getType())) { | ||
// Retain any side effects preceding the finalize() call | ||
List<J> sideEffects = select.getSideEffects(); | ||
if (sideEffects.isEmpty()) { | ||
return null; | ||
} | ||
if (sideEffects.size() == 1) { | ||
return sideEffects.get(0).withPrefix(mi.getPrefix()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return mi; | ||
} | ||
|
||
private boolean shouldRemoveFinalize(JavaType type) { | ||
return TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_DEFLATER, type) | ||
|| TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_INFLATER, type) | ||
|| TypeUtils.isAssignableTo(JAVA_UTIL_ZIP_ZIP_FILE, type); | ||
} | ||
}); | ||
} | ||
|
||
} |
272 changes: 272 additions & 0 deletions
272
src/test/java/org/openrewrite/java/migrate/util/RemoveFinalizerFromZipTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
/* | ||
* Copyright 2023 the original author or authors. | ||
* <p> | ||
* 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 | ||
* <p> | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* <p> | ||
* 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.migrate.util; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.openrewrite.DocumentExample; | ||
import org.openrewrite.test.RecipeSpec; | ||
import org.openrewrite.test.RewriteTest; | ||
|
||
import static org.openrewrite.java.Assertions.*; | ||
|
||
class RemoveFinalizerFromZipTest implements RewriteTest { | ||
|
||
@Override | ||
public void defaults(RecipeSpec spec) { | ||
spec.recipe(new RemoveFinalizerFromZip()).allSources(s -> s.markers(javaVersion(12))); | ||
} | ||
|
||
@Test | ||
@DocumentExample | ||
void removeFinalizerForInflater() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooInflater extends Inflater { | ||
public void test() { | ||
FooInflater obj = new FooInflater(); | ||
obj.finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.Inflater; | ||
class FooInflater extends Inflater { | ||
public void test() { | ||
FooInflater obj = new FooInflater(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void removeCallsToSelfFinalize() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void removeCallsToThisFinalize() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
this.finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void removeWhileKeepingSideEffects() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
new FooBar().finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithFinalizeOnObject() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
new Object().finalize(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithoutFinalizerForInflater() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Inflater; | ||
class FooBar extends Inflater { | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void removeFinalizerForDeflater() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Deflater; | ||
class FooBar extends Deflater { | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
obj.finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.Deflater; | ||
class FooBar extends Deflater { | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithoutFinalizerForDeflater() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.Deflater; | ||
class FooBar extends Deflater { | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void removeFinalizerForZipFile() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.ZipFile; | ||
class FooBar extends ZipFile { | ||
FooBar(){ | ||
super(""); | ||
} | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
obj.finalize(); | ||
} | ||
} | ||
""", """ | ||
import java.util.zip.ZipFile; | ||
class FooBar extends ZipFile { | ||
FooBar(){ | ||
super(""); | ||
} | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithoutFinalizerForZipFile() { | ||
//language=java | ||
rewriteRun(java(""" | ||
import java.util.zip.ZipFile; | ||
class FooBar extends ZipFile { | ||
FooBar(){ | ||
super(""); | ||
} | ||
public void test() { | ||
FooBar obj = new FooBar(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithoutExtends() { | ||
//language=java | ||
rewriteRun(java(""" | ||
class FooBar { | ||
public void test() { | ||
new Object().finalize(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeWithoutExtendsOrSelect() { | ||
//language=java | ||
rewriteRun(java(""" | ||
class FooBar { | ||
public void test() { | ||
finalize(); | ||
} | ||
} | ||
""")); | ||
} | ||
|
||
@Test | ||
void noChangeOnJava11() { | ||
//language=java | ||
rewriteRun(version(java(""" | ||
import java.util.zip.ZipFile; | ||
class FooBar extends ZipFile { | ||
FooBar(){ | ||
super(""); | ||
} | ||
public void test() { | ||
finalize(); | ||
} | ||
} | ||
"""), 11)); | ||
} | ||
} |