aboutsummaryrefslogtreecommitdiffstats
path: root/buildSrc/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'buildSrc/src/main/java')
-rw-r--r--buildSrc/src/main/java/tools/refinery/buildsrc/EclipseUtils.java72
-rw-r--r--buildSrc/src/main/java/tools/refinery/buildsrc/SonarPropertiesUtils.java44
2 files changed, 116 insertions, 0 deletions
diff --git a/buildSrc/src/main/java/tools/refinery/buildsrc/EclipseUtils.java b/buildSrc/src/main/java/tools/refinery/buildsrc/EclipseUtils.java
new file mode 100644
index 00000000..0014a35d
--- /dev/null
+++ b/buildSrc/src/main/java/tools/refinery/buildsrc/EclipseUtils.java
@@ -0,0 +1,72 @@
1package tools.refinery.buildsrc;
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}
diff --git a/buildSrc/src/main/java/tools/refinery/buildsrc/SonarPropertiesUtils.java b/buildSrc/src/main/java/tools/refinery/buildsrc/SonarPropertiesUtils.java
new file mode 100644
index 00000000..1d89841e
--- /dev/null
+++ b/buildSrc/src/main/java/tools/refinery/buildsrc/SonarPropertiesUtils.java
@@ -0,0 +1,44 @@
1package tools.refinery.buildsrc;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Map;
6
7public final class SonarPropertiesUtils {
8 private SonarPropertiesUtils() {
9 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
10 }
11
12 /**
13 * Adds the entries to a Sonar property of list type.
14 * <p>
15 * According to the Sonar Gradle documentation for {@link org.sonarqube.gradle.SonarProperties}, property values
16 * are converted to Strings as follows:
17 * <ul>
18 * <li>{@code Iterable}s are recursively converted and joined into a comma-separated String.</li>
19 * <li>All other values are converted to Strings by calling their {@code toString()} method.</li>
20 * </ul>
21 * Therefore, we use {@link ArrayList} to retain lists entries, which will be recursively converted later.
22 *
23 * @param properties The sonar properties map returned by
24 * {@link org.sonarqube.gradle.SonarProperties#getProperties()}.
25 * @param propertyName The name of the property to append to.
26 * @param entries The entries to append.
27 */
28 public static void addToList(Map<String, Object> properties, String propertyName, String... entries) {
29 ArrayList<Object> newValue;
30 var currentValue = properties.get(propertyName);
31 if (currentValue instanceof ArrayList<?> currentList) {
32 @SuppressWarnings("unchecked")
33 var objectList = (ArrayList<Object>) currentList;
34 newValue = objectList;
35 } else if (currentValue == null) {
36 newValue = new ArrayList<>(entries.length);
37 } else {
38 newValue = new ArrayList<>(entries.length + 1);
39 newValue.add(currentValue);
40 }
41 Collections.addAll(newValue, entries);
42 properties.put(propertyName, newValue);
43 }
44}