added finalguard plugin in aplha state
All checks were successful
CI / build (push) Successful in 3m17s
All checks were successful
CI / build (push) Successful in 3m17s
This commit is contained in:
12
finalguard/build.gradle
Normal file
12
finalguard/build.gradle
Normal file
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id 'java-gradle-plugin'
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("FinalGuardPlugin") {
|
||||
id = 'net.woggioni.gradle.finalguard'
|
||||
implementationClass = "net.woggioni.gradle.finalguard.FinalGuardPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
38
finalguard/finalguard-javac-plugin/build.gradle
Normal file
38
finalguard/finalguard-javac-plugin/build.gradle
Normal file
@@ -0,0 +1,38 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
group = "net.woggioni.finalguard"
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility(JavaVersion.VERSION_1_8.toString())
|
||||
targetCompatibility(JavaVersion.VERSION_1_8.toString())
|
||||
modularity.inferModulePath = false
|
||||
}
|
||||
|
||||
tasks.named(org.gradle.api.plugins.JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile.class) {
|
||||
options.compilerArgs << '-parameters'
|
||||
}
|
||||
|
||||
test {
|
||||
def testCompilationClassPath = sourceSets["main"].output.classesDirs.files +
|
||||
sourceSets["main"].runtimeClasspath.files +
|
||||
sourceSets["test"].resources.srcDirs
|
||||
systemProperty("test.compilation.classpath",
|
||||
String.join(File.pathSeparator, testCompilationClassPath.collect {it.toString() }))
|
||||
}
|
||||
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package net.woggioni.finalguard;
|
||||
|
||||
import com.sun.source.tree.AssignmentTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.CompoundAssignmentTree;
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.UnaryTree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.Plugin;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskListener;
|
||||
import com.sun.source.util.TreePath;
|
||||
import com.sun.source.util.TreePathScanner;
|
||||
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.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
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);
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(JavacTask task, String... args) {
|
||||
task.addTaskListener(new TaskListener() {
|
||||
@Override
|
||||
public void started(TaskEvent e) {}
|
||||
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
|
||||
analyzeFinalVariables(e.getCompilationUnit(), task, e.getTypeElement());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
analyzer.scan(path, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FinalVariableAnalyzer extends TreePathScanner<Void, Void> {
|
||||
private final CompilationUnitTree compilationUnit;
|
||||
private final Trees trees;
|
||||
private final Map<String, VariableInfo> variableInfoMap = new HashMap<>();
|
||||
private final Set<String> reassignedVariables = new HashSet<>();
|
||||
private String currentMethod;
|
||||
|
||||
public FinalVariableAnalyzer(CompilationUnitTree compilationUnit, JavacTask task) {
|
||||
this.compilationUnit = compilationUnit;
|
||||
this.trees = Trees.instance(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMethod(MethodTree node, Void p) {
|
||||
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));
|
||||
}
|
||||
|
||||
// Then analyze method body
|
||||
super.visitMethod(node, p);
|
||||
|
||||
// Check for variables that could be final
|
||||
checkForFinalCandidates();
|
||||
|
||||
currentMethod = previousMethod;
|
||||
return null;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
return super.visitVariable(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAssignment(AssignmentTree node, Void p) {
|
||||
if (node.getVariable() instanceof IdentifierTree) {
|
||||
IdentifierTree ident = (IdentifierTree) node.getVariable();
|
||||
reassignedVariables.add(ident.getName().toString());
|
||||
}
|
||||
return super.visitAssignment(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitUnary(UnaryTree node, Void p) {
|
||||
if ((node.getKind() == Tree.Kind.PREFIX_INCREMENT ||
|
||||
node.getKind() == Tree.Kind.PREFIX_DECREMENT ||
|
||||
node.getKind() == Tree.Kind.POSTFIX_INCREMENT ||
|
||||
node.getKind() == Tree.Kind.POSTFIX_DECREMENT) &&
|
||||
node.getExpression() instanceof IdentifierTree) {
|
||||
|
||||
IdentifierTree ident = (IdentifierTree) node.getExpression();
|
||||
reassignedVariables.add(ident.getName().toString());
|
||||
}
|
||||
return super.visitUnary(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) {
|
||||
if (node.getVariable() instanceof IdentifierTree) {
|
||||
IdentifierTree ident = (IdentifierTree) node.getVariable();
|
||||
reassignedVariables.add(ident.getName().toString());
|
||||
}
|
||||
return super.visitCompoundAssignment(node, p);
|
||||
}
|
||||
|
||||
private void checkForFinalCandidates() {
|
||||
for (Map.Entry<String, VariableInfo> entry : variableInfoMap.entrySet()) {
|
||||
String varName = entry.getKey();
|
||||
VariableInfo info = entry.getValue();
|
||||
|
||||
// Skip if already final
|
||||
if (isFinal(info.variableTree)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if reassigned
|
||||
if (reassignedVariables.contains(varName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String message = "Local variable '" + varName + "' is never reassigned, so it should be declared final";
|
||||
trees.printMessage(FinalGuardPlugin.diagnosticLevel,
|
||||
message,
|
||||
info.variableTree,
|
||||
compilationUnit);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isFinal(VariableTree variableTree) {
|
||||
Set<Modifier> modifiers = variableTree.getModifiers().getFlags();
|
||||
return modifiers.contains(Modifier.FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
private static class VariableInfo {
|
||||
final VariableTree variableTree;
|
||||
|
||||
VariableInfo(VariableTree variableTree, boolean isParameter) {
|
||||
this.variableTree = variableTree;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
net.woggioni.finalguard.FinalGuardPlugin
|
||||
@@ -0,0 +1,183 @@
|
||||
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;
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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;
|
||||
|
||||
public class PluginTest {
|
||||
|
||||
private static class ClassFile extends SimpleJavaFileObject {
|
||||
|
||||
private ByteArrayOutputStream out;
|
||||
|
||||
public ClassFile(URI uri) {
|
||||
super(uri, Kind.CLASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() {
|
||||
return out = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
public byte[] getCompiledBinaries() {
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SourceFile extends SimpleJavaFileObject {
|
||||
public SourceFile(URI uri) {
|
||||
super(uri, Kind.SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
Reader r = new InputStreamReader(uri.toURL().openStream());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] buffer = new char[0x1000];
|
||||
while (true) {
|
||||
int read = r.read(buffer);
|
||||
if(read < 0) break;
|
||||
sb.append(buffer, 0, read);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
|
||||
|
||||
private final List<ClassFile> compiled = new ArrayList<>();
|
||||
|
||||
protected FileManager(StandardJavaFileManager fileManager) {
|
||||
super(fileManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForOutput(Location location,
|
||||
String className,
|
||||
JavaFileObject.Kind kind,
|
||||
FileObject sibling) {
|
||||
ClassFile result = new ClassFile(URI.create("string://" + className));
|
||||
compiled.add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<ClassFile> getCompiled() {
|
||||
return compiled;
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Iterable<Diagnostic<? extends JavaFileObject>>> compile(Iterable<URI> sources) {
|
||||
StringWriter output = new StringWriter();
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
FileManager fileManager =
|
||||
new FileManager(compiler.getStandardFileManager(null, null, null));
|
||||
List<JavaFileObject> compilationUnits = StreamSupport.stream(sources.spliterator(), false)
|
||||
.map(SourceFile::new).collect(Collectors.toList());
|
||||
List<String> arguments = Arrays.asList(
|
||||
"-classpath", System.getProperty("test.compilation.classpath"),
|
||||
"-Xplugin:" + FinalGuardPlugin.class.getSimpleName()
|
||||
);
|
||||
final ArrayList<Diagnostic<? extends JavaFileObject>> compilerMessages = new ArrayList<>();
|
||||
System.setProperty(FinalGuardPlugin.DIAGNOSTIC_LEVEL_KEY, "ERROR");
|
||||
JavaCompiler.CompilationTask task = compiler.getTask(
|
||||
output,
|
||||
fileManager,
|
||||
compilerMessages::add,
|
||||
arguments,
|
||||
null,
|
||||
compilationUnits
|
||||
);
|
||||
if(task.call()) return Optional.empty();
|
||||
else return Optional.of(compilerMessages);
|
||||
}
|
||||
|
||||
private enum CompilationResult {
|
||||
SUCCESS, FAILURE
|
||||
}
|
||||
|
||||
private static class TestCaseProvider implements ArgumentsProvider {
|
||||
@Override
|
||||
public Stream<? extends Arguments> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@ParameterizedTest(name="{0}")
|
||||
@ArgumentsSource(TestCaseProvider.class)
|
||||
public void test(String sourceFilePath, CompilationResult expectedCompilationResult) {
|
||||
Optional<Iterable<Diagnostic<? extends JavaFileObject>>> result;
|
||||
try {
|
||||
ClassLoader cl = getClass().getClassLoader();
|
||||
result = compile(Collections.singletonList(cl.getResource(sourceFilePath).toURI()));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
result.ifPresent(diagnostics -> {
|
||||
for(Diagnostic<? extends JavaFileObject> 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<Diagnostic<? extends JavaFileObject>> illegalSuspendableInvocationMessage = StreamSupport.stream(
|
||||
result.get().spliterator(), false)
|
||||
.filter( diagnostic ->
|
||||
errorMessage.matcher(diagnostic.getMessage(Locale.ENGLISH)).matches()
|
||||
).findFirst();
|
||||
Assertions.assertTrue(illegalSuspendableInvocationMessage.isPresent());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TestCase1 {
|
||||
|
||||
public void testMethod(String param1, String param2) { // Warning: param1 could be final
|
||||
String localVar = "hello"; // Warning: localVar could be final
|
||||
String reassignedVar = "initial"; // No warning (reassigned below)
|
||||
reassignedVar = "changed";
|
||||
|
||||
param2 = "modified"; // No warning for param2 (reassigned)
|
||||
|
||||
for (int i = 0; i < 10; i++) { // Warning: i could be final
|
||||
String loopVar = "constant"; // Warning: loopVar could be final
|
||||
}
|
||||
|
||||
// Enhanced for loop - no warning for loop variable
|
||||
for (String item : Arrays.asList("a", "b")) {
|
||||
// item is effectively final in each iteration
|
||||
}
|
||||
}
|
||||
|
||||
public void finalMethod(final String param1, String param2) { // Warning only for param2
|
||||
final String localVar = "hello"; // No warning (already final)
|
||||
String anotherVar = "world"; // Warning: anotherVar could be final
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
public class TestCase2 {
|
||||
|
||||
public void testMethod(int a, int b, int c, int d, int e, int f, int g, int h, int j, int k, int l, int m, int n) {
|
||||
a++;
|
||||
b--;
|
||||
++c;
|
||||
--d;
|
||||
e |= 2;
|
||||
f &= 1;
|
||||
g <<= 1;
|
||||
h >>= 1;
|
||||
j ^= 1;
|
||||
k += 1;
|
||||
l -= 1;
|
||||
m *= 1;
|
||||
n /= 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class TestCase3 {
|
||||
|
||||
public void testMethod() {
|
||||
int n = 5; // Error: n could be final
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class TestCase4 {
|
||||
|
||||
public void testMethod() {
|
||||
for (int i = 0; i < 10;) { // Error: i could be final
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
public class TestCase5 {
|
||||
|
||||
public void testMethod() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String loopVar = "constant"; // Error: loopVar should be final
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TestCase6 {
|
||||
|
||||
public void testMethod() {
|
||||
for (String item : Arrays.asList("a", "b")) { // Error: item should be final
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class TestCase7 {
|
||||
|
||||
public void testMethod() {
|
||||
try {
|
||||
|
||||
} catch (RuntimeException re) { // Error: re should be final
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.woggioni.gradle.finalguard;
|
||||
|
||||
import org.gradle.api.provider.Property;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
|
||||
public interface FinalGuardExtension {
|
||||
Property<Diagnostic.Kind> getDiagnosticKind();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package net.woggioni.gradle.finalguard;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
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.tasks.TaskContainer;
|
||||
import org.gradle.api.tasks.compile.CompileOptions;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public class FinalGuardPlugin implements Plugin<Project> {
|
||||
private static final String FINALGUARD_PLUGIN_CONFIGURATION = "finalguard_plugin";
|
||||
|
||||
@Override
|
||||
public void apply(final Project project) {
|
||||
final ExtensionContainer extensionContainer = project.getExtensions();
|
||||
final TaskContainer tasks = project.getTasks();
|
||||
final ObjectFactory objects = project.getObjects();
|
||||
|
||||
Configuration javacPluginConfiguration = project.getConfigurations().create(FINALGUARD_PLUGIN_CONFIGURATION);
|
||||
javacPluginConfiguration.withDependencies(new Action<DependencySet>() {
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void execute(DependencySet dependencies) {
|
||||
final Class<?> cls = getClass();
|
||||
final String resourceName = cls.getName().replace('.', '/') + ".class";
|
||||
final URL classUrl = cls.getClassLoader().getResource(resourceName);
|
||||
if (classUrl.getProtocol().startsWith("jar")) {
|
||||
final String path = classUrl.toString();
|
||||
String manifestPath = path.substring(0, path.lastIndexOf("!") + 1) +
|
||||
"/META-INF/MANIFEST.MF";
|
||||
final Manifest manifest = new Manifest(new URL(manifestPath).openStream());
|
||||
final Attributes attr = manifest.getMainAttributes();
|
||||
final String version = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
|
||||
dependencies.add(project.getDependencies().create("net.woggioni.finalguard:finalguard-javac-plugin:" + version));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final FinalGuardExtension finalGuardExtension = objects.newInstance(FinalGuardExtension.class);
|
||||
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);
|
||||
options.getCompilerArgs().add("-Xplugin:net.woggioni.finalguard.FinalGuardPlugin");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user