aboutsummaryrefslogtreecommitdiffstats
path: root/buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java')
-rw-r--r--buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java72
1 files changed, 72 insertions, 0 deletions
diff --git a/buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java b/buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java
new file mode 100644
index 00000000..1e33a95d
--- /dev/null
+++ b/buildSrc/src/main/java/tools/refinery/gradle/utils/EclipseUtils.java
@@ -0,0 +1,72 @@
1package tools.refinery.gradle.utils;
2
3import groovy.lang.Closure;
4import org.gradle.api.Action;
5import org.gradle.plugins.ide.api.XmlFileContentMerger;
6import org.gradle.plugins.ide.eclipse.model.AbstractClasspathEntry;
7import org.gradle.plugins.ide.eclipse.model.Classpath;
8import org.gradle.plugins.ide.eclipse.model.EclipseModel;
9
10import java.util.LinkedHashSet;
11import java.util.List;
12import java.util.Set;
13import java.util.function.Consumer;
14
15public final class EclipseUtils {
16 private static final String GRADLE_USED_BY_SCOPE_ATTRIBUTE = "gradle_used_by_scope";
17 private static final String GRADLE_USED_BY_SCOPE_SEPARATOR = ",";
18
19 private EclipseUtils() {
20 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
21 }
22
23 public static void patchClasspathEntries(EclipseModel eclipseModel, Consumer<AbstractClasspathEntry> consumer) {
24 whenClasspathFileMerged(eclipseModel.getClasspath().getFile(),
25 classpath -> patchClasspathEntries(classpath, consumer));
26 }
27
28 public static void patchClasspathEntries(Classpath eclipseClasspath, Consumer<AbstractClasspathEntry> consumer) {
29 for (var entry : eclipseClasspath.getEntries()) {
30 if (entry instanceof AbstractClasspathEntry abstractClasspathEntry) {
31 consumer.accept(abstractClasspathEntry);
32 }
33 }
34 }
35
36 /**
37 * Avoids ambiguous call to ({@link XmlFileContentMerger#whenMerged(Closure)} versus
38 * {@link XmlFileContentMerger#whenMerged(Action)}) in Kotlin build scripts.
39 * <p>
40 * The {@code Closure} variant will use the build script itself as {@code this}, and Kotlin will consider any
41 * type ascription as a cast of {@code this} (instead of the argument of the {@code Action<?>}). This results in
42 * a mysterious {@link ClassCastException}, since the class generated from the build script doesn't extend from
43 * {@link Classpath}. Using this helper method selects the correct call and applies the cast properly.
44 *
45 * @param file The Eclipse classpath file.
46 * @param consumer The lambda to run on when the classpath file is merged.
47 */
48 public static void whenClasspathFileMerged(XmlFileContentMerger file, Consumer<Classpath> consumer) {
49 file.whenMerged(untypedClasspath -> {
50 var classpath = (Classpath) untypedClasspath;
51 consumer.accept(classpath);
52 });
53 }
54
55 public static void patchGradleUsedByScope(AbstractClasspathEntry entry, Consumer<Set<String>> consumer) {
56 var entryAttributes = entry.getEntryAttributes();
57 var usedByValue = entryAttributes.get(GRADLE_USED_BY_SCOPE_ATTRIBUTE);
58 Set<String> usedBySet;
59 if (usedByValue instanceof String usedByString) {
60 usedBySet = new LinkedHashSet<>(List.of(usedByString.split(GRADLE_USED_BY_SCOPE_SEPARATOR)));
61 } else {
62 usedBySet = new LinkedHashSet<>();
63 }
64 consumer.accept(usedBySet);
65 if (usedBySet.isEmpty()) {
66 entryAttributes.remove(GRADLE_USED_BY_SCOPE_ATTRIBUTE);
67 } else {
68 var newUsedByString = String.join(GRADLE_USED_BY_SCOPE_SEPARATOR, usedBySet);
69 entryAttributes.put(GRADLE_USED_BY_SCOPE_ATTRIBUTE, newUsedByString);
70 }
71 }
72}