Skip to content

Commit e9ffc69

Browse files
Fix for Kotlin 1.7 breaking changes
fixes: #212 The gradle plugin for Kotlin 1.7 included breaking changes, including making `KotlinCompile` no longer derive from `AbstractCompile`, breaking this plugin. (See https://kotlinlang.org/docs/whatsnew17.html#changes-in-compile-tasks). The fix is to factor out the information required from compile tasks into a `CompileTaskWrapper` interface and provide different impls for tasks derived from `AbstractCompile` vs those that are not (like `KotlinCompile`). The latter uses reflection to access the needed methods.
1 parent 4812f0a commit e9ffc69

File tree

3 files changed

+121
-15
lines changed

3 files changed

+121
-15
lines changed

src/main/java/org/javamodularity/moduleplugin/tasks/CompileJavaTaskMutator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
import org.gradle.api.file.FileCollection;
55
import org.gradle.api.logging.Logger;
66
import org.gradle.api.logging.Logging;
7-
import org.gradle.api.tasks.compile.AbstractCompile;
87
import org.gradle.api.tasks.compile.JavaCompile;
98
import org.javamodularity.moduleplugin.JavaProjectHelper;
109
import org.javamodularity.moduleplugin.extensions.CompileModuleOptions;
1110
import org.javamodularity.moduleplugin.extensions.PatchModuleContainer;
1211
import org.javamodularity.moduleplugin.internal.MutatorHelper;
12+
import org.javamodularity.moduleplugin.tasks.MergeClassesHelper.CompileTaskWrapper;
1313

1414
import java.util.ArrayList;
1515
import java.util.List;
@@ -60,7 +60,7 @@ private List<String> buildCompilerArgs(JavaCompile javaCompile) {
6060
helper().modularityExtension().optionContainer().getPatchModuleContainer());
6161
String moduleName = helper().moduleName();
6262
new MergeClassesHelper(project).otherCompileTaskStream()
63-
.map(AbstractCompile::getDestinationDir)
63+
.map(CompileTaskWrapper::getDestinationDir)
6464
.forEach(dir -> patchModuleContainer.addDir(moduleName, dir.getAbsolutePath()));
6565

6666
// Keep only valid module-path entries (https://github.com/java9-modularity/gradle-modules-plugin/issues/190)

src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesHelper.java

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.javamodularity.moduleplugin.tasks;
22

33
import org.gradle.api.Project;
4+
import org.gradle.api.Task;
5+
import org.gradle.api.file.DirectoryProperty;
46
import org.gradle.api.file.DuplicatesStrategy;
57
import org.gradle.api.file.FileCollection;
68
import org.gradle.api.logging.Logger;
@@ -15,10 +17,13 @@
1517
import org.javamodularity.moduleplugin.internal.StreamHelper;
1618

1719
import java.io.File;
20+
import java.lang.reflect.InvocationTargetException;
21+
import java.lang.reflect.Method;
1822
import java.util.HashSet;
1923
import java.util.List;
2024
import java.util.Optional;
2125
import java.util.Set;
26+
import java.util.function.Supplier;
2227
import java.util.stream.Stream;
2328

2429
public class MergeClassesHelper {
@@ -38,10 +43,11 @@ public Project project() {
3843
return project;
3944
}
4045

41-
public Stream<AbstractCompile> otherCompileTaskStream() {
46+
public Stream<CompileTaskWrapper> otherCompileTaskStream() {
4247
return otherCompileTaskNameStream()
43-
.map(name -> helper().findTask(name, AbstractCompile.class))
44-
.flatMap(Optional::stream);
48+
.map(name -> helper().findTask(name, Task.class))
49+
.flatMap(Optional::stream)
50+
.map(this::toWrapper);
4551
}
4652

4753
private Stream<String> otherCompileTaskNameStream() {
@@ -52,16 +58,16 @@ private Stream<String> otherCompileTaskNameStream() {
5258
);
5359
}
5460

55-
public JavaCompile javaCompileTask() {
56-
return helper().task(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile.class);
61+
private CompileTaskWrapper javaCompileTask() {
62+
return toWrapper(helper().task(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile.class));
5763
}
5864

59-
public Stream<AbstractCompile> allCompileTaskStream() {
65+
public Stream<CompileTaskWrapper> allCompileTaskStream() {
6066
return Stream.concat(Stream.of(javaCompileTask()), otherCompileTaskStream());
6167
}
6268

6369
public boolean isMergeRequired() {
64-
return otherCompileTaskStream().anyMatch(task -> !task.getSource().isEmpty());
70+
return otherCompileTaskStream().anyMatch(CompileTaskWrapper::hasSource);
6571
}
6672

6773
public Sync createMergeClassesTask() {
@@ -84,12 +90,112 @@ public FileCollection getMergeAdjustedClasspath(FileCollection classpath) {
8490
}
8591

8692
Set<File> files = new HashSet<>(classpath.getFiles());
87-
allCompileTaskStream().map(AbstractCompile::getDestinationDir).forEach(files::remove);
93+
allCompileTaskStream().map(CompileTaskWrapper::getDestinationDir).forEach(files::remove);
8894
files.add(helper().getMergedDir());
8995
return project.files(files.toArray());
9096
}
9197

98+
private CompileTaskWrapper toWrapper(Task task) {
99+
return task instanceof AbstractCompile
100+
? new GradleTaskWrapper((AbstractCompile) task)
101+
: new ReflectionTaskWrapper(task);
102+
}
103+
92104
private JavaProjectHelper helper() {
93105
return new JavaProjectHelper(project);
94106
}
107+
108+
public interface CompileTaskWrapper {
109+
Task getTask();
110+
111+
File getDestinationDir();
112+
113+
boolean hasSource();
114+
}
115+
116+
private static final class GradleTaskWrapper implements CompileTaskWrapper {
117+
118+
private final AbstractCompile task;
119+
120+
GradleTaskWrapper(AbstractCompile task) {
121+
this.task = task;
122+
}
123+
124+
@Override
125+
public Task getTask() {
126+
return task;
127+
}
128+
129+
@Override
130+
public File getDestinationDir() {
131+
return task.getDestinationDir();
132+
}
133+
134+
@Override
135+
public boolean hasSource() {
136+
return !task.getSource().isEmpty();
137+
}
138+
}
139+
140+
private static final class ReflectionTaskWrapper implements CompileTaskWrapper {
141+
142+
private final Task task;
143+
private final Supplier<DirectoryProperty> destinationDir;
144+
private final Supplier<FileCollection> source;
145+
146+
ReflectionTaskWrapper(Task task) {
147+
this.task = task;
148+
this.destinationDir = supplier(
149+
task,
150+
"getDestinationDirectory",
151+
DirectoryProperty.class
152+
);
153+
this.source = supplier(
154+
task,
155+
"getSources",
156+
FileCollection.class
157+
);
158+
}
159+
160+
@Override
161+
public Task getTask() {
162+
return task;
163+
}
164+
165+
@Override
166+
public File getDestinationDir() {
167+
return destinationDir.get().getAsFile().getOrNull();
168+
}
169+
170+
@Override
171+
public boolean hasSource() {
172+
return !source.get().isEmpty();
173+
}
174+
175+
private static <T> Supplier<T> supplier(Task task, String getterName, Class<T> getterReturnType) {
176+
final Method m = getMethod(task, getterName);
177+
178+
return () -> {
179+
try {
180+
final Object result = m.invoke(task);
181+
return getterReturnType.cast(result);
182+
} catch (InvocationTargetException e) {
183+
if (e.getTargetException() instanceof RuntimeException) {
184+
throw (RuntimeException) e.getTargetException();
185+
}
186+
throw new RuntimeException(e.getTargetException());
187+
} catch (IllegalAccessException e) {
188+
throw new RuntimeException("Failed to invoke " + getterName + " on " + task.getClass(), e);
189+
}
190+
};
191+
}
192+
193+
private static Method getMethod(Task task, String name) {
194+
try {
195+
return task.getClass().getMethod(name);
196+
} catch (NoSuchMethodException e) {
197+
throw new IllegalStateException("Method " + name + " missing on " + task.getClass(), e);
198+
}
199+
}
200+
}
95201
}

src/main/java/org/javamodularity/moduleplugin/tasks/MergeClassesTask.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ public void configureMergeClasses() {
2626
public void configureMergeClassesAfterEvaluate() {
2727
var mergeClasses = mergeClassesHelper().createMergeClassesTask();
2828

29-
mergeClassesHelper().allCompileTaskStream().forEach(task -> {
29+
mergeClassesHelper().allCompileTaskStream().forEach(taskWrapper -> {
3030
List<String> modularTasks = List.of(JavaPlugin.COMPILE_JAVA_TASK_NAME, CompileModuleOptions.COMPILE_MODULE_INFO_TASK_NAME);
31-
if(modularTasks.contains(task.getName())) {
32-
mergeClasses.from(task.getDestinationDir());
31+
if(modularTasks.contains(taskWrapper.getTask().getName())) {
32+
mergeClasses.from(taskWrapper.getDestinationDir());
3333
} else {
34-
mergeClasses.from(task.getDestinationDir(), copySpec -> copySpec.exclude("**/module-info.class"));
34+
mergeClasses.from(taskWrapper.getDestinationDir(), copySpec -> copySpec.exclude("**/module-info.class"));
3535
}
36-
mergeClasses.dependsOn(task);
36+
mergeClasses.dependsOn(taskWrapper.getTask());
3737
});
3838
mergeClasses.into(helper().getMergedDir());
3939
mergeClasses.onlyIf(task -> mergeClassesHelper().isMergeRequired());

0 commit comments

Comments
 (0)