Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3c6f9b0
add: recipe for RSPEC-S1170, adding "static" to "public final" consta…
Oct 22, 2024
8771f69
add: recipe and unit test for RSPEC-S6202
Oct 22, 2024
dc85402
update: add recipe to list
Oct 22, 2024
81f30fd
Merge branch 'main' into feature/new_recipes_for_rspec_1170_and_6202
Oct 22, 2024
554ce96
fix: correct the name of the recipe
Oct 22, 2024
6cc2947
update: for more cases in unit test
Oct 22, 2024
4140086
update: correct copyright messages
Oct 24, 2024
7d43903
refactor: format code
Oct 24, 2024
0b6bac5
Merge branch 'main' into feature/new_recipes_for_rspec_1170_and_6202
Oct 24, 2024
40c508e
Update src/test/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
137fc0c
Update src/test/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
8f8008d
Update src/test/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
3826d81
Update src/main/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
5c6fc8b
Update src/main/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
b4a1505
Update src/main/java/org/openrewrite/staticanalysis/ReplaceClassIsIns…
yurii-yu Oct 25, 2024
9160beb
Update src/main/java/org/openrewrite/staticanalysis/AddStaticModifier…
yurii-yu Oct 25, 2024
e8e062c
Update src/main/java/org/openrewrite/staticanalysis/AddStaticModifier…
yurii-yu Oct 25, 2024
21c31cf
Merge branch 'main' into feature/new_recipes_for_rspec_1170_and_6202
timtebeek Oct 25, 2024
f1990fa
Test additional cases pointed out in review
timtebeek Oct 25, 2024
5b0b9b2
Format tests
timtebeek Oct 25, 2024
1bc5dce
Slight polish to ReplaceClassIsInstanceWithInstanceof
timtebeek Oct 25, 2024
9fb0732
Apply suggestions from code review
timtebeek Oct 25, 2024
8bdf819
update: Recipe for RSPEC-S1170 is removed because it needs further co…
Oct 28, 2024
d405b9b
Merge branch 'main' into feature/new_recipes_for_rspec_1170_and_6202
yurii-yu Oct 28, 2024
8d59c77
Minor polish
timtebeek Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2024 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.staticanalysis;

import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.Tree;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.Modifier;
import org.openrewrite.java.tree.Space;
import org.openrewrite.marker.Markers;

import java.time.Duration;
import java.util.Collections;
import java.util.Set;

import static java.util.Collections.emptyList;

public class AddStaticModifierToPublicFinalConstantsAndFields extends Recipe {

@Override
public String getDisplayName() {
return "Add `static` to `public final` variables";
}

@Override
public String getDescription() {
return "Finds fields declared as `public final` and adds `static` modifier, meanwhile sort all the modifiers.";
}

@Override
public Set<String> getTags() {
return Collections.singleton("RSPEC-S1170");
}

@Override
public Duration getEstimatedEffortPerOccurrence() {
return Duration.ofMinutes(3);
}

@Override
public JavaIsoVisitor<ExecutionContext> getVisitor() {
return new JavaIsoVisitor<ExecutionContext>() {

@Override
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable,
ExecutionContext executionContext) {

if (multiVariable.hasModifier(Modifier.Type.Public) &&
multiVariable.hasModifier(Modifier.Type.Final) &&
!multiVariable.hasModifier(Modifier.Type.Static)) {
J.VariableDeclarations v = super.visitVariableDeclarations(multiVariable, executionContext);

multiVariable.getModifiers().add(new J.Modifier(Tree.randomId(),
Space.format(" "), Markers.EMPTY, " ",
Modifier.Type.Static, emptyList()));

return v.withModifiers(ModifierOrder.sortModifiers(multiVariable.getModifiers()));

}
return super.visitVariableDeclarations(multiVariable, executionContext);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2024 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.staticanalysis;

import java.time.Duration;
import java.util.Collections;
import java.util.Set;

import org.openrewrite.ExecutionContext;
import org.openrewrite.NlsRewrite.Description;
import org.openrewrite.Recipe;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.FieldAccess;
import org.openrewrite.java.tree.J.Identifier;
import org.openrewrite.java.tree.J.MethodInvocation;
import org.openrewrite.java.tree.JavaType;

public class ReplaceClassIsInstanceWithInstanceof extends Recipe {

@Override
public String getDisplayName() {
return "Replace `A.class.isInstance(a)` with `a instanceof A`";
}

@Override
public @Description
String getDescription() {
return "There should be no `A.class.isInstance(a)`, it should be replaced by `a instanceof A`.";
}

@Override
public Set<String> getTags() {
return Collections.singleton("RSPEC-S6202");
}

@Override
public Duration getEstimatedEffortPerOccurrence() {
return Duration.ofMinutes(3);
}

@Override
public JavaVisitor<ExecutionContext> getVisitor() {
//use JavaVisitor instead of JavaIsoVisitor because we changed the type of LST
return new JavaVisitor<ExecutionContext>() {

private final MethodMatcher matcher = new MethodMatcher("java.lang.Class isInstance(java.lang.Object)");
private final JavaTemplate template = JavaTemplate.builder(
"#{any(org.openrewrite.java.tree.Expression)} instanceof #{}").build();

@Override
public J visitMethodInvocation(MethodInvocation method, ExecutionContext ctx) {

//make sure we find the right method and the left part is something like "SomeClass.class"
if (matcher.matches(method) && isObjectClass(method.getSelect())) {
//for code like "A.class.isInstance(a)", select is "String.class", name is "isInstance", argument is "a"
Identifier objectExpression = (Identifier) method.getArguments().get(0);

FieldAccess fieldAccessPart = (FieldAccess) method.getSelect();
String className = ((JavaType.Class) ((Identifier) fieldAccessPart.getTarget()).getType()).getClassName();

//upcast to type J, so J.MethodInfocation can be replaced by J.InstanceOf
return maybeAutoFormat((J)method,
(J)template.apply(updateCursor(method), method.getCoordinates().replace(), objectExpression, className),
ctx);

}
return (MethodInvocation) super.visitMethodInvocation(method, ctx);
}

private boolean isObjectClass(Expression expression) {
if (expression instanceof J.FieldAccess) {
J.FieldAccess fieldAccess = (J.FieldAccess) expression;
if (fieldAccess.getTarget() instanceof Identifier) {
Identifier identifier = (Identifier) fieldAccess.getTarget();
return identifier.getType() instanceof JavaType.Class;
}
}
return false;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,5 @@ recipeList:
- org.openrewrite.kotlin.cleanup.EqualsMethodUsage
- org.openrewrite.kotlin.cleanup.ImplicitParameterInLambda
- org.openrewrite.kotlin.cleanup.ReplaceCharToIntWithCode
- org.openrewrite.staticanalysis.AddStaticModifierToPublicFinalConstantsAndFields
- org.openrewrite.staticanalysis.ReplaceClassIsInstanceWithInstanceof
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2022 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.staticanalysis;

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.java;

class AddStaticModifierToPublicFinalConstantsAndFieldsTest implements RewriteTest {

@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new AddStaticModifierToPublicFinalConstantsAndFields());
}

@Test
void doesNotModify() {
rewriteRun(
//language=java
java(
"""
class A {
public final static String s1;
public String s2;
static String s3;
}
"""
)
);
}

@DocumentExample
@Test
void addStaticModifier() {
rewriteRun(
//language=java
java(
"""
class A {
final public String s1;
public final String s2;
}
""",
"""
class A {
public static final String s1;
public static final String s2;
}
"""
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.openrewrite.staticanalysis;

import org.junit.jupiter.api.Test;
import static org.openrewrite.java.Assertions.java;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

class ReplaceClassIsInstanceWithInstanceofTest implements RewriteTest {


@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new ReplaceClassIsInstanceWithInstanceof());
//spec.recipe(new AvoidBoxedBooleanExpressions());
}

@Test
void doesNotMatchMethod() {
rewriteRun(
//language=java
java(
"""
class A {
boolean foo() {
String s = "";
return s instanceof String;
}
}
"""
)
);
}

@Test
void changeInstanceOf() {
rewriteRun(
//language=java
java(
"""
class A {
void foo() {
String s = "";
boolean result = String.class.isInstance(s);
result = Integer.class.isInstance(s);
}
}
""",
"""
class A {
void foo() {
String s = "";
boolean result = s instanceof String;
result = s instanceof Integer;
}
}
"""
)
);
}

}