diff --git a/finalguard/finalguard-javac-plugin/build.gradle b/finalguard/finalguard-javac-plugin/build.gradle index a054ccc..8b0c9b4 100644 --- a/finalguard/finalguard-javac-plugin/build.gradle +++ b/finalguard/finalguard-javac-plugin/build.gradle @@ -25,7 +25,7 @@ test { sourceSets["main"].runtimeClasspath.files + sourceSets["test"].resources.srcDirs systemProperty("test.compilation.classpath", - String.join(File.pathSeparator, testCompilationClassPath.collect {it.toString() })) + String.join(File.pathSeparator, testCompilationClassPath.collect { it.toString() })) } diff --git a/finalguard/finalguard-javac-plugin/src/main/java/net/woggioni/finalguard/FinalGuardPlugin.java b/finalguard/finalguard-javac-plugin/src/main/java/net/woggioni/finalguard/FinalGuardPlugin.java index 67aeeb8..3c1570c 100644 --- a/finalguard/finalguard-javac-plugin/src/main/java/net/woggioni/finalguard/FinalGuardPlugin.java +++ b/finalguard/finalguard-javac-plugin/src/main/java/net/woggioni/finalguard/FinalGuardPlugin.java @@ -1,11 +1,17 @@ package net.woggioni.finalguard; import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.CatchTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.CompoundAssignmentTree; +import com.sun.source.tree.EnhancedForLoopTree; +import com.sun.source.tree.ForLoopTree; import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.LambdaExpressionTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; +import com.sun.source.tree.TryTree; import com.sun.source.tree.UnaryTree; import com.sun.source.tree.VariableTree; import com.sun.source.util.JavacTask; @@ -19,20 +25,86 @@ import com.sun.source.util.Trees; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.tools.Diagnostic; -import java.util.HashMap; +import java.util.AbstractMap; +import java.util.Arrays; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; public class FinalGuardPlugin implements Plugin { public static final String DIAGNOSTIC_LEVEL_KEY = "net.woggioni.finalguard.diagnostic.level"; - private static final Diagnostic.Kind diagnosticLevel = - Optional.ofNullable(System.getProperty(DIAGNOSTIC_LEVEL_KEY)) - .map(Diagnostic.Kind::valueOf) - .orElse(Diagnostic.Kind.WARNING); + enum VariableType { + LOCAL_VAR("net.woggioni.finalguard.diagnostic.local.variable.level"), + METHOD_PARAM("net.woggioni.finalguard.diagnostic.method.param.level"), + LOOP_PARAM("net.woggioni.finalguard.diagnostic.for.param.level"), + TRY_WITH_PARAM("net.woggioni.finalguard.diagnostic.try.param.level"), + CATCH_PARAM("net.woggioni.finalguard.diagnostic.catch.param.level"), + LAMBDA_PARAM("net.woggioni.finalguard.diagnostic.lambda.param.level"); + + private final String propertyKey; + + VariableType(final String propertyKey) { + this.propertyKey = propertyKey; + } + + public String getPropertyKey() { + return propertyKey; + } + + public String getMessage(final String variableName) { + switch (this) { + case LOCAL_VAR: + return "Local variable '" + variableName + "' is never reassigned, so it should be declared final"; + case METHOD_PARAM: + return "Method parameter '" + variableName + "' is never reassigned, so it should be declared final"; + case LOOP_PARAM: + return "Loop parameter '" + variableName + "' is never reassigned, so it should be declared final"; + case TRY_WITH_PARAM: + return "Try-with-resources parameter '" + variableName + "' is never reassigned, so it should be declared final"; + case CATCH_PARAM: + return "Catch parameter '" + variableName + "' is never reassigned, so it should be declared final"; + case LAMBDA_PARAM: + return "Lambda parameter '" + variableName + "' is never reassigned, so it should be declared final"; + default: + throw new UnsupportedOperationException(); + } + } + } + + private static class VariableInfo { + final VariableTree variableTree; + final VariableType variableType; + + VariableInfo(VariableTree variableTree, VariableType variableType) { + this.variableTree = variableTree; + this.variableType = variableType; + } + } + + private static final class Configuration { + private final Map levels; + + public Configuration() { + final Diagnostic.Kind defaultLevel = + Optional.ofNullable(System.getProperty(DIAGNOSTIC_LEVEL_KEY)).map(Diagnostic.Kind::valueOf).orElse(null); + this.levels = Arrays.stream(VariableType.values()).map(vt -> { + final Diagnostic.Kind level = Optional.ofNullable(System.getProperty(vt.getPropertyKey())).map(Diagnostic.Kind::valueOf).orElse(defaultLevel); + if (level != null) { + return new AbstractMap.SimpleEntry<>(vt, level); + } else { + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + } + + private static final Configuration configuration = new Configuration(); @Override public String getName() { @@ -43,7 +115,8 @@ public class FinalGuardPlugin implements Plugin { public void init(JavacTask task, String... args) { task.addTaskListener(new TaskListener() { @Override - public void started(TaskEvent e) {} + public void started(TaskEvent e) { + } @Override public void finished(TaskEvent e) { @@ -57,7 +130,7 @@ public class FinalGuardPlugin implements Plugin { private void analyzeFinalVariables(CompilationUnitTree compilationUnit, JavacTask task, Element typeElement) { FinalVariableAnalyzer analyzer = new FinalVariableAnalyzer(compilationUnit, task); TreePath path = Trees.instance(task).getPath(typeElement); - if(path != null) { + if (path != null) { analyzer.scan(path, null); } } @@ -65,7 +138,7 @@ public class FinalGuardPlugin implements Plugin { private static class FinalVariableAnalyzer extends TreePathScanner { private final CompilationUnitTree compilationUnit; private final Trees trees; - private final Map variableInfoMap = new HashMap<>(); + private final Map variableInfoMap = new LinkedHashMap<>(); private final Set reassignedVariables = new HashSet<>(); private String currentMethod; @@ -76,15 +149,15 @@ public class FinalGuardPlugin implements Plugin { @Override public Void visitMethod(MethodTree node, Void p) { - String previousMethod = currentMethod; + final String previousMethod = currentMethod; currentMethod = node.getName().toString(); variableInfoMap.clear(); reassignedVariables.clear(); // Analyze parameters first for (VariableTree param : node.getParameters()) { - String varName = param.getName().toString(); - variableInfoMap.put(varName, new VariableInfo(param, false)); + final String varName = param.getName().toString(); + variableInfoMap.put(varName, new VariableInfo(param, VariableType.METHOD_PARAM)); } // Then analyze method body @@ -100,9 +173,25 @@ public class FinalGuardPlugin implements Plugin { @Override public Void visitVariable(VariableTree node, Void p) { if (currentMethod != null) { - String varName = node.getName().toString(); - boolean isParameter = node.getKind() == Tree.Kind.METHOD; - variableInfoMap.put(varName, new VariableInfo(node, isParameter)); + final String varName = node.getName().toString(); + final Tree parent = getCurrentPath().getParentPath().getLeaf(); + final VariableType type; + if (parent instanceof LambdaExpressionTree) { + type = VariableType.LAMBDA_PARAM; + } else if (parent instanceof ForLoopTree || parent instanceof EnhancedForLoopTree) { + type = VariableType.LOOP_PARAM; + } else if (parent instanceof CatchTree) { + type = VariableType.CATCH_PARAM; + } else if (parent instanceof TryTree) { + type = VariableType.TRY_WITH_PARAM; + } else if (parent instanceof MethodTree) { + type = VariableType.METHOD_PARAM; + } else if (parent instanceof BlockTree) { + type = VariableType.LOCAL_VAR; + } else { + type = VariableType.LOCAL_VAR; + } + variableInfoMap.put(varName, new VariableInfo(node, type)); } return super.visitVariable(node, p); } @@ -110,7 +199,7 @@ public class FinalGuardPlugin implements Plugin { @Override public Void visitAssignment(AssignmentTree node, Void p) { if (node.getVariable() instanceof IdentifierTree) { - IdentifierTree ident = (IdentifierTree) node.getVariable(); + final IdentifierTree ident = (IdentifierTree) node.getVariable(); reassignedVariables.add(ident.getName().toString()); } return super.visitAssignment(node, p); @@ -124,7 +213,7 @@ public class FinalGuardPlugin implements Plugin { node.getKind() == Tree.Kind.POSTFIX_DECREMENT) && node.getExpression() instanceof IdentifierTree) { - IdentifierTree ident = (IdentifierTree) node.getExpression(); + final IdentifierTree ident = (IdentifierTree) node.getExpression(); reassignedVariables.add(ident.getName().toString()); } return super.visitUnary(node, p); @@ -133,16 +222,22 @@ public class FinalGuardPlugin implements Plugin { @Override public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) { if (node.getVariable() instanceof IdentifierTree) { - IdentifierTree ident = (IdentifierTree) node.getVariable(); + final IdentifierTree ident = (IdentifierTree) node.getVariable(); reassignedVariables.add(ident.getName().toString()); } return super.visitCompoundAssignment(node, p); } private void checkForFinalCandidates() { - for (Map.Entry entry : variableInfoMap.entrySet()) { - String varName = entry.getKey(); - VariableInfo info = entry.getValue(); + for (final Map.Entry entry : variableInfoMap.entrySet()) { + final String varName = entry.getKey(); + final VariableInfo info = entry.getValue(); + + Diagnostic.Kind level = configuration.levels.get(info.variableType); + // Skip if level is not configured + if (level == null) { + continue; + } // Skip if already final if (isFinal(info.variableTree)) { @@ -154,25 +249,16 @@ public class FinalGuardPlugin implements Plugin { continue; } - String message = "Local variable '" + varName + "' is never reassigned, so it should be declared final"; - trees.printMessage(FinalGuardPlugin.diagnosticLevel, - message, + trees.printMessage(level, + info.variableType.getMessage(varName), info.variableTree, compilationUnit); } } private static boolean isFinal(VariableTree variableTree) { - Set modifiers = variableTree.getModifiers().getFlags(); + final Set modifiers = variableTree.getModifiers().getFlags(); return modifiers.contains(Modifier.FINAL); } } - - private static class VariableInfo { - final VariableTree variableTree; - - VariableInfo(VariableTree variableTree, boolean isParameter) { - this.variableTree = variableTree; - } - } } \ No newline at end of file diff --git a/finalguard/finalguard-javac-plugin/src/test/java/net/woggioni/finalguard/PluginTest.java b/finalguard/finalguard-javac-plugin/src/test/java/net/woggioni/finalguard/PluginTest.java index bb71217..cf51140 100644 --- a/finalguard/finalguard-javac-plugin/src/test/java/net/woggioni/finalguard/PluginTest.java +++ b/finalguard/finalguard-javac-plugin/src/test/java/net/woggioni/finalguard/PluginTest.java @@ -1,7 +1,6 @@ package net.woggioni.finalguard; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -30,11 +29,17 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Optional; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; +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.LOCAL_VAR; +import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.LOOP_PARAM; +import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.METHOD_PARAM; +import static net.woggioni.finalguard.FinalGuardPlugin.VariableType.TRY_WITH_PARAM; + public class PluginTest { private static class ClassFile extends SimpleJavaFileObject { @@ -67,7 +72,7 @@ public class PluginTest { char[] buffer = new char[0x1000]; while (true) { int read = r.read(buffer); - if(read < 0) break; + if (read < 0) break; sb.append(buffer, 0, read); } return sb.toString(); @@ -106,7 +111,7 @@ public class PluginTest { .map(SourceFile::new).collect(Collectors.toList()); List arguments = Arrays.asList( "-classpath", System.getProperty("test.compilation.classpath"), - "-Xplugin:" + FinalGuardPlugin.class.getSimpleName() + "-Xplugin:" + FinalGuardPlugin.class.getName() ); final ArrayList> compilerMessages = new ArrayList<>(); System.setProperty(FinalGuardPlugin.DIAGNOSTIC_LEVEL_KEY, "ERROR"); @@ -118,7 +123,7 @@ public class PluginTest { null, compilationUnits ); - if(task.call()) return Optional.empty(); + if (task.call()) return Optional.empty(); else return Optional.of(compilerMessages); } @@ -131,22 +136,43 @@ public class PluginTest { public Stream provideArguments(ExtensionContext context) { String prefix = "net/woggioni/finalguard/test/"; return Stream.of( - Arguments.of(prefix + "TestCase1.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase2.java", CompilationResult.SUCCESS), - Arguments.of(prefix + "TestCase3.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase4.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase5.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase6.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase7.java", CompilationResult.FAILURE), - Arguments.of(prefix + "TestCase8.java", CompilationResult.FAILURE) + Arguments.of(prefix + "TestCase1.java", Arrays.asList( + LOOP_PARAM.getMessage("item"), + LAMBDA_PARAM.getMessage("s"), + LOCAL_VAR.getMessage("f"), + LOCAL_VAR.getMessage("localVar"), + LOCAL_VAR.getMessage("loopVar"), + LOOP_PARAM.getMessage("i"), + TRY_WITH_PARAM.getMessage("is"), + METHOD_PARAM.getMessage("param1"), + CATCH_PARAM.getMessage("ioe"), + LOCAL_VAR.getMessage("anotherVar"), + METHOD_PARAM.getMessage("param2") + )), + Arguments.of(prefix + "TestCase2.java", Collections.emptyList()), + Arguments.of(prefix + "TestCase3.java", + Arrays.asList(LOCAL_VAR.getMessage("n"))), + Arguments.of(prefix + "TestCase4.java", + Arrays.asList(LOOP_PARAM.getMessage("i"))), + Arguments.of(prefix + "TestCase5.java", Arrays.asList(LOCAL_VAR.getMessage("loopVar"))), + Arguments.of(prefix + "TestCase6.java", Arrays.asList(LOOP_PARAM.getMessage("item"))), + Arguments.of(prefix + "TestCase7.java", Arrays.asList(CATCH_PARAM.getMessage("re"))), + Arguments.of(prefix + "TestCase8.java", Arrays.asList(TRY_WITH_PARAM.getMessage("is"))), + 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 + "TestCase11.java", Arrays.asList( + METHOD_PARAM.getMessage("n"), + LOCAL_VAR.getMessage("result"), + LOCAL_VAR.getMessage("size"), + METHOD_PARAM.getMessage("t1s") + )) ); } } - @Disabled - @ParameterizedTest(name="{0}") + @ParameterizedTest(name = "{0}") @ArgumentsSource(TestCaseProvider.class) - public void test(String sourceFilePath, CompilationResult expectedCompilationResult) { + public void test(String sourceFilePath, List expectedErrorMessages) { Optional>> result; try { ClassLoader cl = getClass().getClassLoader(); @@ -155,29 +181,27 @@ public class PluginTest { throw new RuntimeException(e); } result.ifPresent(diagnostics -> { - for(Diagnostic diagnostic : diagnostics) { + for (Diagnostic diagnostic : diagnostics) { System.err.printf("%s:%s %s\n", diagnostic.getSource().getName(), diagnostic.getLineNumber(), diagnostic.getMessage(Locale.getDefault())); } }); - final Pattern errorMessage = Pattern.compile( - "Local variable '[a-zA-Z0-9_]+' is never reassigned, so it should be declared final"); - switch (expectedCompilationResult) { - case SUCCESS: - Assertions.assertFalse(result.isPresent(), "Compilation was expected to succeed but it has failed"); - break; - case FAILURE: - Assertions.assertTrue(result.isPresent(), "Compilation was expected to fail but it succeeded"); - - Optional> illegalSuspendableInvocationMessage = StreamSupport.stream( - result.get().spliterator(), false) - .filter( diagnostic -> - errorMessage.matcher(diagnostic.getMessage(Locale.ENGLISH)).matches() - ).findFirst(); - Assertions.assertTrue(illegalSuspendableInvocationMessage.isPresent()); - break; + if (expectedErrorMessages.isEmpty()) { + Assertions.assertFalse(result.isPresent(), "Compilation was expected to succeed but it has failed"); + } else { + final List compilationErrors = result + .map(it -> StreamSupport.stream(it.spliterator(), false)) + .orElse(Stream.empty()) + .map(it -> it.getMessage(Locale.ENGLISH)) + .collect(Collectors.toList()); + for (String expectedErrorMessage : expectedErrorMessages) { + int index = compilationErrors.indexOf(expectedErrorMessage); + Assertions.assertTrue(index >= 0, String.format("Expected compilation error `%s` not found in output", expectedErrorMessage)); + compilationErrors.remove(index); + } + Assertions.assertTrue(compilationErrors.isEmpty(), "Unexpected compilation errors found in the output"); } } } diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase1.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase1.java index 09e90eb..8b70636 100644 --- a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase1.java +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase1.java @@ -1,4 +1,10 @@ +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; +import java.util.function.Function; public class TestCase1 { @@ -9,7 +15,7 @@ public class TestCase1 { param2 = "modified"; // No warning for param2 (reassigned) - for (int i = 0; i < 10; i++) { // Warning: i could be final + for (int i = 0; i < 10; ) { // Warning: i could be final String loopVar = "constant"; // Warning: loopVar could be final } @@ -17,6 +23,14 @@ public class TestCase1 { for (String item : Arrays.asList("a", "b")) { // item is effectively final in each iteration } + + try (InputStream is = Files.newInputStream(Path.of("/tmp/file.txt"))) { + + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + + Function f = s -> s.toLowerCase(); } public void finalMethod(final String param1, String param2) { // Warning only for param2 diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase10.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase10.java new file mode 100644 index 0000000..b4b8f23 --- /dev/null +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase10.java @@ -0,0 +1,5 @@ +public class TestCase10 { + public void testMethod(int n) { + + } +} \ No newline at end of file diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase11.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase11.java new file mode 100644 index 0000000..96b1af5 --- /dev/null +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase11.java @@ -0,0 +1,15 @@ +import java.util.Arrays; + +public abstract class TestCase11 { + + abstract T1 get(int n); + + public T1[] toArray(T1[] t1s) { + int size = 42; + T1[] result = Arrays.copyOf(t1s, size); + for (int i = 0; i < size; i++) { + result[i] = get(i); + } + return result; + } +} \ No newline at end of file diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase4.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase4.java index 72ebc2c..0c2d4e3 100644 --- a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase4.java +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase4.java @@ -1,7 +1,7 @@ public class TestCase4 { public void testMethod() { - for (int i = 0; i < 10;) { // Error: i could be final + for (int i = 0; i < 10; ) { // Error: i could be final } } } \ No newline at end of file diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase8.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase8.java index d6e24ba..59b0d7a 100644 --- a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase8.java +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase8.java @@ -6,7 +6,7 @@ import java.nio.file.Path; public class TestCase8 { public void testMethod() throws IOException { - try(InputStream is = Files.newInputStream(Path.of("some-path"))) { // Error: is could be final + try (InputStream is = Files.newInputStream(Path.of("some-path"))) { // Error: is could be final } } diff --git a/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase9.java b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase9.java new file mode 100644 index 0000000..cb91f31 --- /dev/null +++ b/finalguard/finalguard-javac-plugin/src/test/resources/net/woggioni/finalguard/test/TestCase9.java @@ -0,0 +1,8 @@ +import java.util.function.Function; + +public class TestCase9 { + + public void testMethod() { + final Function d = s -> s.toLowerCase(); + } +} \ No newline at end of file diff --git a/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardExtension.java b/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardExtension.java index 54903a2..3a20879 100644 --- a/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardExtension.java +++ b/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardExtension.java @@ -6,5 +6,17 @@ import javax.tools.Diagnostic; public interface FinalGuardExtension { - Property getDiagnosticKind(); + Property getDefaultLevel(); + + Property getLocalVariableLevel(); + + Property getLambdaParameterLevel(); + + Property getForLoopParameterLevel(); + + Property getTryWithResourceLevel(); + + Property getMethodParameterLevel(); + + Property getCatchParameterLevel(); } diff --git a/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardPlugin.java b/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardPlugin.java index dadab5b..1aeefd2 100644 --- a/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardPlugin.java +++ b/finalguard/src/main/java/net/woggioni/gradle/finalguard/FinalGuardPlugin.java @@ -8,6 +8,7 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.DependencySet; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ExtensionContainer; +import org.gradle.api.provider.Property; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.compile.CompileOptions; import org.gradle.api.tasks.compile.JavaCompile; @@ -50,10 +51,57 @@ public class FinalGuardPlugin implements Plugin { extensionContainer.add("finalGuard", finalGuardExtension); tasks.withType(JavaCompile.class, javaCompileTask -> { javaCompileTask.doFirst(t -> { - final Diagnostic.Kind diagnosticKind = finalGuardExtension.getDiagnosticKind().getOrElse(Diagnostic.Kind.WARNING); final CompileOptions options = javaCompileTask.getOptions(); options.setAnnotationProcessorPath(options.getAnnotationProcessorPath().plus(javacPluginConfiguration)); - options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.level=" + diagnosticKind); + { + final Property defaultLevel = finalGuardExtension.getDefaultLevel(); + if (defaultLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = defaultLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.level=" + diagnosticKind); + } + } + { + final Property localVariableLevel = finalGuardExtension.getLocalVariableLevel(); + if (localVariableLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = localVariableLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.local.variable.level=" + diagnosticKind); + } + } + { + final Property methodParameterLevel = finalGuardExtension.getMethodParameterLevel(); + if (methodParameterLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = methodParameterLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.method.param.level=" + diagnosticKind); + } + } + { + final Property forLoopParameterLevel = finalGuardExtension.getForLoopParameterLevel(); + if (forLoopParameterLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = forLoopParameterLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.for.param.level=" + diagnosticKind); + } + } + { + final Property tryParameterLevel = finalGuardExtension.getTryWithResourceLevel(); + if (tryParameterLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = tryParameterLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.try.param.level=" + diagnosticKind); + } + } + { + final Property catchParameterLevel = finalGuardExtension.getCatchParameterLevel(); + if (catchParameterLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = catchParameterLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.catch.param.level=" + diagnosticKind); + } + } + { + final Property lambdaParameterLevel = finalGuardExtension.getLambdaParameterLevel(); + if (lambdaParameterLevel.isPresent()) { + final Diagnostic.Kind diagnosticKind = lambdaParameterLevel.get(); + options.getForkOptions().getJvmArgs().add("-Dnet.woggioni.finalguard.diagnostic.lambda.param.level=" + diagnosticKind); + } + } options.getCompilerArgs().add("-Xplugin:net.woggioni.finalguard.FinalGuardPlugin"); }); }); diff --git a/gradle.properties b/gradle.properties index d294032..2d2656b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ lys.catalog.version=2025.09.30 -version.myGradlePlugins=2025.11.17 +version.myGradlePlugins=2025.11.18 version.gradle=8.12 gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven diff --git a/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java b/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java index f252eba..d3df45e 100644 --- a/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java +++ b/lombok/src/main/java/net/woggioni/gradle/lombok/LombokPlugin.java @@ -6,7 +6,6 @@ import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ExtraPropertiesExtension; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginExtension;