Skip to content

Commit

Permalink
Merge pull request #42317 from FroMage/38228
Browse files Browse the repository at this point in the history
Support APT processors in Gradle quarkusdev
  • Loading branch information
FroMage authored Aug 22, 2024
2 parents 77654a9 + cd82d5c commit 59d8bf7
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@ private QuarkusDevModeLauncher newLauncher(final AnalyticsService analyticsServi
builder.sourceJavaVersion(javaPluginExtension.getSourceCompatibility().toString());
builder.targetJavaVersion(javaPluginExtension.getTargetCompatibility().toString());

final SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);

builder.annotationProcessorPaths(mainSourceSet.getAnnotationProcessorPath().getFiles());
// builder.annotationProcessors(SOME);

for (CompilerOption compilerOptions : compilerOptions.getCompilerOptions()) {
builder.compilerOptions(compilerOptions.getName(), compilerOptions.getArgs());
}
Expand Down Expand Up @@ -628,6 +634,8 @@ private void addLocalProject(ResolvedDependency project, GradleDevModeLauncher.B
}
Path classesDir = classesDirs.isEmpty() ? null
: QuarkusGradleUtils.mergeClassesDirs(classesDirs, project.getWorkspaceModule().getBuildDir(), root, false);
Path generatedSourcesPath = sources.getSourceDirs().isEmpty() ? null
: sources.getSourceDirs().iterator().next().getAptSourcesDir();

final Set<Path> resourcesSrcDirs = new LinkedHashSet<>();
// resourcesSrcDir may exist but if it's empty the resources output dir won't be created
Expand Down Expand Up @@ -660,6 +668,7 @@ private void addLocalProject(ResolvedDependency project, GradleDevModeLauncher.B
.setName(project.getArtifactId())
.setProjectDirectory(project.getWorkspaceModule().getModuleDir().getAbsolutePath())
.setSourcePaths(PathList.from(sourcePaths))
.setGeneratedSourcesPath(generatedSourcesPath != null ? generatedSourcesPath.toString() : null)
.setClassesPath(classesDir.toString())
.setResourcePaths(PathList.from(resourcesSrcDirs))
.setResourcesOutputPath(resourcesOutputPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,14 @@ private static void initProjectModule(Project project, WorkspaceModule.Mutable m

final List<SourceDir> sourceDirs = new ArrayList<>(1);
project.getTasks().withType(AbstractCompile.class,
t -> configureCompileTask(t.getSource(), t.getDestinationDirectory(), allClassesDirs, sourceDirs, t));
t -> configureCompileTask(t.getSource(), t.getDestinationDirectory(), allClassesDirs, sourceDirs, t,
sourceSet));

maybeConfigureKotlinJvmCompile(project, allClassesDirs, sourceDirs);
maybeConfigureKotlinJvmCompile(project, allClassesDirs, sourceDirs, sourceSet);

final LinkedHashMap<File, Path> resourceDirs = new LinkedHashMap<>(1);
final File resourcesOutputDir = sourceSet.getOutput().getResourcesDir();

project.getTasks().withType(ProcessResources.class, t -> {
if (!t.getEnabled()) {
return;
Expand Down Expand Up @@ -567,32 +569,33 @@ private static void initProjectModule(Project project, WorkspaceModule.Mutable m
}

private static void maybeConfigureKotlinJvmCompile(Project project, FileCollection allClassesDirs,
List<SourceDir> sourceDirs) {
List<SourceDir> sourceDirs, SourceSet sourceSet) {
// This "try/catch" is needed because of the way the "quarkus-cli" Gradle tests work. Without it, the tests fail.
try {
Class.forName("org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile");
doConfigureKotlinJvmCompile(project, allClassesDirs, sourceDirs);
doConfigureKotlinJvmCompile(project, allClassesDirs, sourceDirs, sourceSet);
} catch (ClassNotFoundException e) {
// ignore
}
}

private static void doConfigureKotlinJvmCompile(Project project, FileCollection allClassesDirs,
List<SourceDir> sourceDirs) {
List<SourceDir> sourceDirs, SourceSet sourceSet) {
// Use KotlinJvmCompile.class in a separate method to prevent that maybeConfigureKotlinJvmCompile() runs into
// a ClassNotFoundException due to actually using KotlinJvmCompile.class.
project.getTasks().withType(KotlinJvmCompile.class, t -> configureCompileTask(t.getSources().getAsFileTree(),
t.getDestinationDirectory(), allClassesDirs, sourceDirs, t));
t.getDestinationDirectory(), allClassesDirs, sourceDirs, t, sourceSet));
}

private static void configureCompileTask(FileTree sources, DirectoryProperty destinationDirectory,
FileCollection allClassesDirs, List<SourceDir> sourceDirs, Task task) {
FileCollection allClassesDirs, List<SourceDir> sourceDirs, Task task, SourceSet sourceSet) {
if (!task.getEnabled()) {
return;
}
if (sources.isEmpty()) {
return;
}

final File destDir = destinationDirectory.getAsFile().get();
if (!allClassesDirs.contains(destDir)) {
return;
Expand All @@ -601,12 +604,38 @@ private static void configureCompileTask(FileTree sources, DirectoryProperty des
// we are looking for the root dirs containing sources
if (a.getRelativePath().getSegments().length == 1) {
final File srcDir = a.getFile().getParentFile();

sourceDirs
.add(new DefaultSourceDir(srcDir.toPath(), destDir.toPath(), null, Map.of("compiler", task.getName())));
.add(new DefaultSourceDir(srcDir.toPath(), destDir.toPath(),
findGeneratedSourceDir(destDir, sourceSet),
Map.of("compiler", task.getName())));
}
});
}

private static Path findGeneratedSourceDir(File destDir, SourceSet sourceSet) {
// destDir appears to be build/classes/java/main
if (destDir.getParentFile() == null) {
return null;
}
String language = destDir.getParentFile().getName(); // java
String sourceSetName = destDir.getName(); // main
if (language == null) {
return null;
}
// find the corresponding generated sources, same pattern, but under build/generated/sources/annotationProcessor/java/main
for (File generatedDir : sourceSet.getOutput().getGeneratedSourcesDirs().getFiles()) {
if (generatedDir.getParentFile() == null) {
continue;
}
if (generatedDir.getName().equals(sourceSetName)
&& generatedDir.getParentFile().getName().equals(language)) {
return generatedDir.toPath();
}
}
return null;
}

private void addSubstitutedProject(PathList.Builder paths, File projectFile) {
File mainResourceDirectory = new File(projectFile, MAIN_RESOURCES_OUTPUT);
if (mainResourceDirectory.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ dependencies {
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"

compileOnly "org.hibernate.orm:hibernate-jpamodelgen"
compileOnly enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
annotationProcessor "org.hibernate.orm:hibernate-jpamodelgen"
annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")

testImplementation 'io.quarkus:quarkus-junit5'
testImplementation 'io.rest-assured:rest-assured'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
quarkusPlatformArtifactId=quarkus-bom
quarkusPlatformGroupId=io.quarkus
org.gradle.logging.level=INFO
lombokVersion=1.18.12
lombokVersion=1.18.34
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ public class HelloResource {
public String hello() {
return "hello " + myData.getMessage();
}

@Path("jpa")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String jpa() {
return MyEntity_.FIELD;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.playground;

import jakarta.persistence.Id;
import jakarta.persistence.Entity;

@Entity
public class MyEntity {
public String field;
@Id
public String id;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Disabled;

import com.google.common.collect.ImmutableMap;

@Disabled
public class CompileOnlyDependencyDevModeTest extends QuarkusDevGradleTestBase {

@Override
Expand All @@ -24,6 +22,15 @@ protected String[] buildArguments() {
protected void testDevMode() throws Exception {

assertThat(getHttpResponse("/hello", 2, TimeUnit.MINUTES)).contains("hello lombok");
assertThat(getHttpResponse("/hello/jpa", 2, TimeUnit.MINUTES)).isEqualTo("field");

// make sure annotations go to the right place
File testDir = getProjectDir();
File entityMetamodelSourceFile = new File(testDir,
"build/generated/sources/annotationProcessor/java/main/io/playground/MyEntity_.java");
assertThat(entityMetamodelSourceFile).exists().content().contains("FIELD");
File entityMetamodelClassFile = new File(testDir, "build/classes/java/main/io/playground/MyEntity_.class");
assertThat(entityMetamodelClassFile).exists();

replace("src/main/java/io/playground/MyData.java",
ImmutableMap.of("private String other;", "private final String other;"));
Expand All @@ -34,6 +41,18 @@ protected void testDevMode() throws Exception {
ImmutableMap.of("return \"hello \" + myData.getMessage();",
"return \"hello \" + myData.getMessage() + myData.getOther();"));

// Edit the entity to change the field name
replace("src/main/java/io/playground/MyEntity.java", ImmutableMap.of("String field;", "String field2;"));

// Edit the "Hello" message for the new field.
replace("src/main/java/io/playground/HelloResource.java", ImmutableMap.of("return MyEntity_.FIELD;",
"return MyEntity_.FIELD2;"));

assertUpdatedResponseContains("/hello", "hello lombok!", 5, TimeUnit.MINUTES);
assertUpdatedResponseContains("/hello/jpa", "field2", 5, TimeUnit.MINUTES);

// make sure annotations go to the right place
assertThat(entityMetamodelSourceFile).exists().content().contains("FIELD2");
assertThat(entityMetamodelClassFile).exists();
}
}

0 comments on commit 59d8bf7

Please sign in to comment.