Skip to content

Commit

Permalink
Merge pull request #312 from freefair/feature/lombokConfig
Browse files Browse the repository at this point in the history
Rework lombok.config handling
  • Loading branch information
larsgrefer authored Apr 10, 2021
2 parents fd3551a + ceffc90 commit 6271ac4
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 85 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
lombok.config
secring.gpg

# Created by https://www.gitignore.io/api/IntelliJ,macOS,osx,linux,windows,Gradle,java,gradle,lombok
Expand Down
1 change: 1 addition & 0 deletions examples/lombok/lombok.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lombok.extern.findbugs.addSuppressFBWarnings = true
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class LombokBasePlugin implements Plugin<Project> {

@Override
public void apply(Project project) {

lombokExtension = project.getExtensions().create("lombok", LombokExtension.class);

lombokConfiguration = project.getConfigurations().create("lombok");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.internal.deprecation.DeprecationLogger;

import javax.inject.Inject;

Expand All @@ -26,11 +27,21 @@ public class LombokExtension {
/**
* Additional Entries for the lombok.config file.
*/
@Deprecated
private final MapProperty<String, String> config;

@Inject
public LombokExtension(ObjectFactory objectFactory) {
version = objectFactory.property(String.class).convention(LOMBOK_VERSION);
config = objectFactory.mapProperty(String.class, String.class);
}

@Deprecated
public MapProperty<String, String> getConfig() {
DeprecationLogger.deprecateProperty(LombokExtension.class, "config")
.willBeRemovedInGradle8()
.undocumented()
.nagUser();
return config;
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
package io.freefair.gradle.plugins.lombok;

import io.freefair.gradle.plugins.lombok.tasks.Delombok;
import io.freefair.gradle.plugins.lombok.tasks.GenerateLombokConfig;
import lombok.Getter;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.internal.plugins.DslObject;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.plugins.quality.CodeQualityExtension;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.testing.jacoco.plugins.JacocoPlugin;

import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

@Getter
public class LombokPlugin implements Plugin<Project> {
Expand All @@ -30,20 +31,14 @@ public class LombokPlugin implements Plugin<Project> {

private LombokBasePlugin lombokBasePlugin;
private Project project;
private TaskProvider<GenerateLombokConfig> generateLombokConfig;

private boolean spotbugConfigured;

@Override
public void apply(Project project) {
this.project = project;

lombokBasePlugin = project.getPlugins().apply(LombokBasePlugin.class);
lombokBasePlugin.getLombokExtension().getConfig().put("config.stopBubbling", "true");

generateLombokConfig = project.getTasks().register("generateLombokConfig", GenerateLombokConfig.class, genConfig -> {
genConfig.getProperties().convention(lombokBasePlugin.getLombokExtension().getConfig());
genConfig.setGroup("lombok");
});

project.getTasks().withType(Delombok.class).configureEach(this::configureDelombokDefaults);

Expand All @@ -54,57 +49,45 @@ public void apply(Project project) {
private void configureJavaPluginDefaults() {
JavaPluginConvention javaPluginConvention = project.getConvention().getPlugin(JavaPluginConvention.class);

javaPluginConvention.getSourceSets().all(sourceSet -> {
project.getConfigurations().getByName(sourceSet.getCompileOnlyConfigurationName()).extendsFrom(lombokBasePlugin.getLombokConfiguration());
project.getConfigurations().getByName(sourceSet.getAnnotationProcessorConfigurationName()).extendsFrom(lombokBasePlugin.getLombokConfiguration());
javaPluginConvention.getSourceSets().all(this::configureSourceSetDefaults);

TaskProvider<Delombok> delombokTaskProvider = project.getTasks().register(sourceSet.getTaskName("delombok", ""), Delombok.class, delombok -> {
delombok.setDescription("Runs delombok on the " + sourceSet.getName() + " source-set");
String delombokDir = "generated/sources/delombok/" + sourceSet.getJava().getName() + "/" + sourceSet.getName();
delombok.getTarget().convention(project.getLayout().getBuildDirectory().dir(delombokDir));
});

sourceSet.getExtensions().add("delombokTask", delombokTaskProvider);

TaskProvider<JavaCompile> compileTaskProvider = project.getTasks().named(sourceSet.getCompileJavaTaskName(), JavaCompile.class, compileJava -> {
compileJava.dependsOn(generateLombokConfig);
compileJava.getOptions().getCompilerArgs().add("-Xlint:-processing");
compileJava.getInputs()
.file((Callable<RegularFileProperty>) () -> {
GenerateLombokConfig generateLombokConfig = this.generateLombokConfig.get();
if (generateLombokConfig.isEnabled()) {
return generateLombokConfig.getOutputFile();
}
else {
return null;
}
})
.withPropertyName("lombok.config")
.withPathSensitivity(PathSensitivity.RELATIVE)
.optional();
});
project.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class, javadoc -> {
SourceSet mainSourceSet = javaPluginConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
javadoc.setSource(mainSourceSet.getExtensions().getByName("delombokTask"));
});

project.afterEvaluate(p -> {
handleMapstructSupport(sourceSet);
project.getPlugins().withId("com.github.spotbugs", spotBugsPlugin -> configureForSpotbugs(javaPluginConvention));
project.getPlugins().withId("org.sonarqube", sonarPlugin -> configureForSpotbugs(javaPluginConvention));
}

delombokTaskProvider.configure(delombok -> {
delombok.getEncoding().set(compileTaskProvider.get().getOptions().getEncoding());
delombok.getClasspath().from(sourceSet.getCompileClasspath());
delombok.getInput().from(sourceSet.getJava().getSourceDirectories());
});
});
private void configureSourceSetDefaults(SourceSet sourceSet) {
project.getConfigurations().getByName(sourceSet.getCompileOnlyConfigurationName()).extendsFrom(lombokBasePlugin.getLombokConfiguration());
project.getConfigurations().getByName(sourceSet.getAnnotationProcessorConfigurationName()).extendsFrom(lombokBasePlugin.getLombokConfiguration());

TaskProvider<Delombok> delombokTaskProvider = project.getTasks().register(sourceSet.getTaskName("delombok", ""), Delombok.class, delombok -> {
delombok.setDescription("Runs delombok on the " + sourceSet.getName() + " source-set");
String delombokDir = "generated/sources/delombok/" + sourceSet.getJava().getName() + "/" + sourceSet.getName();
delombok.getTarget().convention(project.getLayout().getBuildDirectory().dir(delombokDir));
});

project.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class, javadoc -> {
SourceSet mainSourceSet = javaPluginConvention.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME);
javadoc.setSource(mainSourceSet.getExtensions().getByName("delombokTask"));
sourceSet.getExtensions().add("delombokTask", delombokTaskProvider);

TaskProvider<JavaCompile> compileTaskProvider = project.getTasks().named(sourceSet.getCompileJavaTaskName(), JavaCompile.class, compileJava -> {
compileJava.getOptions().getCompilerArgs().add("-Xlint:-processing");
});

project.getPlugins().withType(JacocoPlugin.class, jacocoPlugin -> configureForJacoco());
project.afterEvaluate(p -> {
handleMapstructSupport(sourceSet);

handleLombokConfig(sourceSet, compileTaskProvider);

delombokTaskProvider.configure(delombok -> {
delombok.getEncoding().set(compileTaskProvider.get().getOptions().getEncoding());
delombok.getClasspath().from(sourceSet.getCompileClasspath());
delombok.getInput().from(sourceSet.getJava().getSourceDirectories());
});
});

project.getPlugins().withId("com.github.spotbugs", spotBugsPlugin -> configureForSpotbugs(javaPluginConvention));
project.getPlugins().withId("org.sonarqube", sonarPlugin -> configureForSpotbugs(javaPluginConvention));
}

private void configureForSpotbugs(JavaPluginConvention javaPluginConvention) {
Expand All @@ -113,8 +96,6 @@ private void configureForSpotbugs(JavaPluginConvention javaPluginConvention) {
}
spotbugConfigured = true;

lombokBasePlugin.getLombokExtension().getConfig().put("lombok.extern.findbugs.addSuppressFBWarnings", "true");

project.afterEvaluate(p -> {
String toolVersion = resolveSpotBugVersion();

Expand All @@ -140,15 +121,72 @@ private String resolveSpotBugVersion() {
return toolVersionProperty.get();
}

private void configureForJacoco() {
lombokBasePlugin.getLombokExtension().getConfig().put("lombok.addLombokGeneratedAnnotation", "true");
}

private void configureDelombokDefaults(Delombok delombok) {
delombok.setGroup("lombok");
delombok.getFormat().put("pretty", null);
}

private void handleLombokConfig(SourceSet sourceSet, TaskProvider<JavaCompile> compileTaskProvider) {
Map<File, String> lombokConfigs = new HashMap<>();

for (File srcDir : sourceSet.getJava().getSrcDirs()) {
String lombokConfig = getLombokConfig(srcDir);
lombokConfigs.put(srcDir, lombokConfig);
}

compileTaskProvider.configure(javaCompile -> {
StringBuilder combinedConfigs = new StringBuilder();
lombokConfigs.values().forEach(combinedConfigs::append);
javaCompile.getInputs()
.property("lombokConfig", combinedConfigs.toString())
.optional(true);
});

project.getPlugins().withType(JacocoPlugin.class, jacocoPlugin -> {
checkLombokConfig(sourceSet, lombokConfigs, "lombok.addLombokGeneratedAnnotation = true");
});

project.getPlugins().withId("com.github.spotbugs", spotBugsPlugin -> {
checkLombokConfig(sourceSet, lombokConfigs, "lombok.extern.findbugs.addSuppressFBWarnings = true");
});

project.getPlugins().withId("org.sonarqube", spotBugsPlugin -> {
checkLombokConfig(sourceSet, lombokConfigs, "lombok.extern.findbugs.addSuppressFBWarnings = true");
});
}

private void checkLombokConfig(SourceSet sourceSet, Map<File, String> configs, String expected) {
configs.forEach((File dir, @Nullable String config) -> {
if (dir.exists() && (config == null || !config.contains(expected))) {
project.getLogger().warn("'{}' is not configured for '{}' of the {} source-set", expected, dir, sourceSet.getName());
}
});
}

@Nullable
private String getLombokConfig(File dir) {
if (!dir.exists()) {
return null;
}

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

project.javaexec(configTool -> {
configTool.setClasspath(lombokBasePlugin.getLombokConfiguration());
configTool.setStandardOutput(outputStream);

configTool.args("config", dir);
});

String output = outputStream.toString();
project.getLogger().debug(output);

if (output.startsWith("No 'lombok.config' found for")) {
return null;
}
return output;
}

private void handleMapstructSupport(SourceSet sourceSet) {
Configuration annotationProcessor = project.getConfigurations().getByName(sourceSet.getAnnotationProcessorConfigurationName());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

@Getter
@Setter
@Deprecated
public class GenerateLombokConfig extends DefaultTask {

@OutputFile
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.freefair.gradle.plugins.lombok;


import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.testfixtures.ProjectBuilder;
Expand Down Expand Up @@ -44,9 +43,7 @@ public void with_sonar() {
LombokExtension lombokExtension = project.getExtensions().getByType(LombokExtension.class);

assertThat(lombokExtension).isNotNull();
assertThat(lombokExtension.getConfig().get()).doesNotContainKey("lombok.extern.findbugs.addSuppressFBWarnings");

project.getPlugins().apply(SonarQubePlugin.class);
assertThat(lombokExtension.getConfig().get()).containsEntry("lombok.extern.findbugs.addSuppressFBWarnings", "true");
}
}
2 changes: 1 addition & 1 deletion lombok.config
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# This file is generated by the 'io.freefair.lombok' Gradle plugin
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
21 changes: 1 addition & 20 deletions src/docs/asciidoc/_lombok.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ This plugin simplifies the use of https://projectlombok.org/[Lombok] in Gradle b
- For each source set a `delombok` task is created.
- The `javadoc` task will be configured to read the delombok-ed sources instead of the actual sources.
- `lombok-mapstruct-binding` is added to each source-set when 'org.mapstruct:mapstruct-processor' is found.
- A `generateLombokConfig` will be added to the project, which generates the `lombok.config` file
based on the `lombok` extension.
- The compile tasks for each source set will consider the `lombok.config`(s) in their up-to-date checks

[NOTE]
====
Expand All @@ -47,24 +46,6 @@ task myJavadocs(type: Javadoc) {
----
====

==== `lombok.config` handling

.Disable `lombok.config` generation
[source,groovy]
----
generateLombokConfig.enabled = false
----

.Modifying the generated `lombok.config` file
[source,groovy]
----
lombok {
config['lombok.log.fieldName'] = 'LOG'
}
----

NOTE: An already existing `lombok.config` (which was not previously generated by this plugin) will not be overriden.

== Lombok Tasks

The following task are provided:
Expand Down

0 comments on commit 6271ac4

Please sign in to comment.