added special handling for abstract method parameters in finalguard plugin
All checks were successful
CI / build (push) Successful in 3m31s
All checks were successful
CI / build (push) Successful in 3m31s
This commit is contained in:
@@ -21,9 +21,9 @@ import com.sun.source.util.TaskListener;
|
|||||||
import com.sun.source.util.TreePath;
|
import com.sun.source.util.TreePath;
|
||||||
import com.sun.source.util.TreePathScanner;
|
import com.sun.source.util.TreePathScanner;
|
||||||
import com.sun.source.util.Trees;
|
import com.sun.source.util.Trees;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -36,8 +36,8 @@ import java.util.Set;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class FinalGuardPlugin implements Plugin {
|
public class FinalGuardPlugin implements Plugin {
|
||||||
|
|
||||||
public static final String DIAGNOSTIC_LEVEL_KEY = "net.woggioni.finalguard.diagnostic.level";
|
public static final String DIAGNOSTIC_LEVEL_KEY = "net.woggioni.finalguard.diagnostic.level";
|
||||||
|
public static final String IGNORE_ABSTRACT_METHOD_PARAMS_KEY = "net.woggioni.finalguard.ignore.abstract.method.params";
|
||||||
|
|
||||||
enum VariableType {
|
enum VariableType {
|
||||||
LOCAL_VAR("net.woggioni.finalguard.diagnostic.local.variable.level"),
|
LOCAL_VAR("net.woggioni.finalguard.diagnostic.local.variable.level"),
|
||||||
@@ -45,7 +45,8 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
LOOP_PARAM("net.woggioni.finalguard.diagnostic.for.param.level"),
|
LOOP_PARAM("net.woggioni.finalguard.diagnostic.for.param.level"),
|
||||||
TRY_WITH_PARAM("net.woggioni.finalguard.diagnostic.try.param.level"),
|
TRY_WITH_PARAM("net.woggioni.finalguard.diagnostic.try.param.level"),
|
||||||
CATCH_PARAM("net.woggioni.finalguard.diagnostic.catch.param.level"),
|
CATCH_PARAM("net.woggioni.finalguard.diagnostic.catch.param.level"),
|
||||||
LAMBDA_PARAM("net.woggioni.finalguard.diagnostic.lambda.param.level");
|
LAMBDA_PARAM("net.woggioni.finalguard.diagnostic.lambda.param.level"),
|
||||||
|
ABSTRACT_METHOD_PARAM("net.woggioni.finalguard.diagnostic.abstract.method.param.level");
|
||||||
|
|
||||||
private final String propertyKey;
|
private final String propertyKey;
|
||||||
|
|
||||||
@@ -71,6 +72,8 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
return "Catch parameter '" + variableName + "' is never reassigned, so it should be declared final";
|
return "Catch parameter '" + variableName + "' is never reassigned, so it should be declared final";
|
||||||
case LAMBDA_PARAM:
|
case LAMBDA_PARAM:
|
||||||
return "Lambda parameter '" + variableName + "' is never reassigned, so it should be declared final";
|
return "Lambda parameter '" + variableName + "' is never reassigned, so it should be declared final";
|
||||||
|
case ABSTRACT_METHOD_PARAM:
|
||||||
|
return "Abstract method parameter '" + variableName + "' is never reassigned, so it should be declared final";
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@@ -80,7 +83,6 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
private static class VariableInfo {
|
private static class VariableInfo {
|
||||||
final VariableTree variableTree;
|
final VariableTree variableTree;
|
||||||
final VariableType variableType;
|
final VariableType variableType;
|
||||||
|
|
||||||
VariableInfo(VariableTree variableTree, VariableType variableType) {
|
VariableInfo(VariableTree variableTree, VariableType variableType) {
|
||||||
this.variableTree = variableTree;
|
this.variableTree = variableTree;
|
||||||
this.variableType = variableType;
|
this.variableType = variableType;
|
||||||
@@ -109,7 +111,6 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final Configuration configuration = new Configuration();
|
private static final Configuration configuration = new Configuration();
|
||||||
|
|
||||||
private static final boolean isJava17OrHigher = isJava17OrHigher();
|
private static final boolean isJava17OrHigher = isJava17OrHigher();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -156,9 +157,7 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
public Void visitMethod(MethodTree node, Void p) {
|
public Void visitMethod(MethodTree node, Void p) {
|
||||||
variableInfoMap.clear();
|
variableInfoMap.clear();
|
||||||
reassignedVariables.clear();
|
reassignedVariables.clear();
|
||||||
|
|
||||||
super.visitMethod(node, p);
|
super.visitMethod(node, p);
|
||||||
|
|
||||||
// Check for variables that could be final
|
// Check for variables that could be final
|
||||||
checkForFinalCandidates();
|
checkForFinalCandidates();
|
||||||
return null;
|
return null;
|
||||||
@@ -171,6 +170,7 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
final TreePath parentPath = currentPath.getParentPath();
|
final TreePath parentPath = currentPath.getParentPath();
|
||||||
final Tree parent = parentPath.getLeaf();
|
final Tree parent = parentPath.getLeaf();
|
||||||
final VariableType type;
|
final VariableType type;
|
||||||
|
|
||||||
if (parent instanceof LambdaExpressionTree) {
|
if (parent instanceof LambdaExpressionTree) {
|
||||||
type = VariableType.LAMBDA_PARAM;
|
type = VariableType.LAMBDA_PARAM;
|
||||||
} else if (parent instanceof ForLoopTree || parent instanceof EnhancedForLoopTree) {
|
} else if (parent instanceof ForLoopTree || parent instanceof EnhancedForLoopTree) {
|
||||||
@@ -180,11 +180,15 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
} else if (parent instanceof TryTree) {
|
} else if (parent instanceof TryTree) {
|
||||||
type = VariableType.TRY_WITH_PARAM;
|
type = VariableType.TRY_WITH_PARAM;
|
||||||
} else if (parent instanceof MethodTree) {
|
} else if (parent instanceof MethodTree) {
|
||||||
type = VariableType.METHOD_PARAM;
|
if (isAbstractMethodParameter(node, (MethodTree) parent)) {
|
||||||
if(isJava17OrHigher && ((MethodTree) parent).getName().contentEquals("<init>")) {
|
type = VariableType.ABSTRACT_METHOD_PARAM;
|
||||||
final TreePath grandParentPath = parentPath.getParentPath();
|
} else {
|
||||||
if(grandParentPath.getLeaf().getKind() == Tree.Kind.RECORD) {
|
type = VariableType.METHOD_PARAM;
|
||||||
return super.visitVariable(node, p);
|
if (isJava17OrHigher && ((MethodTree) parent).getName().contentEquals("<init>")) {
|
||||||
|
final TreePath grandParentPath = parentPath.getParentPath();
|
||||||
|
if (grandParentPath.getLeaf().getKind() == Tree.Kind.RECORD) {
|
||||||
|
return super.visitVariable(node, p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (parent instanceof BlockTree) {
|
} else if (parent instanceof BlockTree) {
|
||||||
@@ -192,10 +196,21 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
} else {
|
} else {
|
||||||
type = VariableType.LOCAL_VAR;
|
type = VariableType.LOCAL_VAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
variableInfoMap.put(varName, new VariableInfo(node, type));
|
variableInfoMap.put(varName, new VariableInfo(node, type));
|
||||||
return super.visitVariable(node, p);
|
return super.visitVariable(node, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAbstractMethodParameter(VariableTree variableTree, MethodTree methodTree) {
|
||||||
|
// Get the element for the method
|
||||||
|
Element methodElement = trees.getElement(getCurrentPath().getParentPath());
|
||||||
|
if (methodElement instanceof ExecutableElement) {
|
||||||
|
ExecutableElement executableElement = (ExecutableElement) methodElement;
|
||||||
|
return executableElement.getModifiers().contains(Modifier.ABSTRACT);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitAssignment(AssignmentTree node, Void p) {
|
public Void visitAssignment(AssignmentTree node, Void p) {
|
||||||
if (node.getVariable() instanceof IdentifierTree) {
|
if (node.getVariable() instanceof IdentifierTree) {
|
||||||
@@ -212,8 +227,7 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
node.getKind() == Tree.Kind.POSTFIX_INCREMENT ||
|
node.getKind() == Tree.Kind.POSTFIX_INCREMENT ||
|
||||||
node.getKind() == Tree.Kind.POSTFIX_DECREMENT) &&
|
node.getKind() == Tree.Kind.POSTFIX_DECREMENT) &&
|
||||||
node.getExpression() instanceof IdentifierTree) {
|
node.getExpression() instanceof IdentifierTree) {
|
||||||
|
IdentifierTree ident = (IdentifierTree) node.getExpression();
|
||||||
final IdentifierTree ident = (IdentifierTree) node.getExpression();
|
|
||||||
reassignedVariables.add(ident.getName().toString());
|
reassignedVariables.add(ident.getName().toString());
|
||||||
}
|
}
|
||||||
return super.visitUnary(node, p);
|
return super.visitUnary(node, p);
|
||||||
@@ -232,23 +246,19 @@ public class FinalGuardPlugin implements Plugin {
|
|||||||
for (final Map.Entry<String, VariableInfo> entry : variableInfoMap.entrySet()) {
|
for (final Map.Entry<String, VariableInfo> entry : variableInfoMap.entrySet()) {
|
||||||
final String varName = entry.getKey();
|
final String varName = entry.getKey();
|
||||||
final VariableInfo info = entry.getValue();
|
final VariableInfo info = entry.getValue();
|
||||||
|
|
||||||
Diagnostic.Kind level = configuration.levels.get(info.variableType);
|
Diagnostic.Kind level = configuration.levels.get(info.variableType);
|
||||||
// Skip if level is not configured
|
// Skip if level is not configured
|
||||||
if (level == null) {
|
if (level == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if already final
|
// Skip if already final
|
||||||
if (isFinal(info.variableTree)) {
|
if (isFinal(info.variableTree)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if reassigned
|
// Skip if reassigned
|
||||||
if (reassignedVariables.contains(varName)) {
|
if (reassignedVariables.contains(varName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
trees.printMessage(level,
|
trees.printMessage(level,
|
||||||
info.variableType.getMessage(varName),
|
info.variableType.getMessage(varName),
|
||||||
info.variableTree,
|
info.variableTree,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.ABSTRACT_METHOD_PARAM;
|
||||||
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.CATCH_PARAM;
|
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.CATCH_PARAM;
|
||||||
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.LAMBDA_PARAM;
|
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.LAMBDA_PARAM;
|
||||||
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.LOCAL_VAR;
|
import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.LOCAL_VAR;
|
||||||
@@ -161,12 +162,14 @@ public class PluginTest {
|
|||||||
Arguments.of(prefix + "TestCase9.java", Arrays.asList(LAMBDA_PARAM.getMessage("s"))),
|
Arguments.of(prefix + "TestCase9.java", Arrays.asList(LAMBDA_PARAM.getMessage("s"))),
|
||||||
Arguments.of(prefix + "TestCase10.java", Arrays.asList(METHOD_PARAM.getMessage("n"))),
|
Arguments.of(prefix + "TestCase10.java", Arrays.asList(METHOD_PARAM.getMessage("n"))),
|
||||||
Arguments.of(prefix + "TestCase11.java", Arrays.asList(
|
Arguments.of(prefix + "TestCase11.java", Arrays.asList(
|
||||||
METHOD_PARAM.getMessage("n"),
|
ABSTRACT_METHOD_PARAM.getMessage("n"),
|
||||||
LOCAL_VAR.getMessage("result"),
|
LOCAL_VAR.getMessage("result"),
|
||||||
LOCAL_VAR.getMessage("size"),
|
LOCAL_VAR.getMessage("size"),
|
||||||
METHOD_PARAM.getMessage("t1s")
|
METHOD_PARAM.getMessage("t1s")
|
||||||
)),
|
)),
|
||||||
Arguments.of(prefix + "TestCase12.java", Collections.emptyList())
|
Arguments.of(prefix + "TestCase12.java", Collections.emptyList()),
|
||||||
|
Arguments.of(prefix + "TestCase13.java", Arrays.asList(ABSTRACT_METHOD_PARAM.getMessage("x"), ABSTRACT_METHOD_PARAM.getMessage("y"))),
|
||||||
|
Arguments.of(prefix + "TestCase14.java", Arrays.asList(ABSTRACT_METHOD_PARAM.getMessage("x"), ABSTRACT_METHOD_PARAM.getMessage("y")))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public interface TestCase13 {
|
||||||
|
void foo(double x, double y);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public abstract class TestCase14 {
|
||||||
|
abstract public void foo(double x, double y);
|
||||||
|
}
|
||||||
@@ -18,5 +18,7 @@ public interface FinalGuardExtension {
|
|||||||
|
|
||||||
Property<Diagnostic.Kind> getMethodParameterLevel();
|
Property<Diagnostic.Kind> getMethodParameterLevel();
|
||||||
|
|
||||||
|
Property<Diagnostic.Kind> getAbstractMethodParameterLevel();
|
||||||
|
|
||||||
Property<Diagnostic.Kind> getCatchParameterLevel();
|
Property<Diagnostic.Kind> getCatchParameterLevel();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,13 @@ public class FinalGuardPlugin implements Plugin<Project> {
|
|||||||
setProperty.accept("method.param.level", diagnosticKind);
|
setProperty.accept("method.param.level", diagnosticKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
final Property<Diagnostic.Kind> abstractMethodParameterLevel = finalGuardExtension.getAbstractMethodParameterLevel();
|
||||||
|
if (abstractMethodParameterLevel.isPresent()) {
|
||||||
|
final Diagnostic.Kind diagnosticKind = abstractMethodParameterLevel.get();
|
||||||
|
setProperty.accept("abstract.method.param.level", diagnosticKind);
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
final Property<Diagnostic.Kind> forLoopParameterLevel = finalGuardExtension.getForLoopParameterLevel();
|
final Property<Diagnostic.Kind> forLoopParameterLevel = finalGuardExtension.getForLoopParameterLevel();
|
||||||
if (forLoopParameterLevel.isPresent()) {
|
if (forLoopParameterLevel.isPresent()) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
lys.catalog.version=2025.11.18
|
lys.catalog.version=2025.11.18
|
||||||
version.myGradlePlugins=2025.11.28
|
version.myGradlePlugins=2025.11.29
|
||||||
version.gradle=8.12
|
version.gradle=8.12
|
||||||
|
|
||||||
gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven
|
gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven
|
||||||
|
|||||||
Reference in New Issue
Block a user