Skip to content

Commit ea0283f

Browse files
committed
List the formatter inside the plugin in the IntelliJ settings
updateOpenJavaFormatXml now writes the jars BundledFormatter extracts into implementationClassPath when palantirJavaFormat is empty, and the declared ones otherwise, so the IDE runs the build's formatter as it did when the formatter came from Maven Central. The extracted jars are where the IDE loads them from after a clean, too. The task takes the bundle's hash as an input, and is not up to date while the extracted jars are missing: after their directory is deleted the next build extracts them again and writes the XML, instead of leaving the IDE with paths to jars that are gone. The check is a class, which the configuration cache stores with the task.
1 parent bbe0cbc commit ea0283f

3 files changed

Lines changed: 56 additions & 6 deletions

File tree

‎gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/PalantirJavaFormatIdeaPlugin.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public void apply(Project rootProject) {
4646
.from(rootProject
4747
.getConfigurations()
4848
.getByName(PalantirJavaFormatProviderPlugin.CONFIGURATION_NAME));
49+
task.getBundledFormatter().set(BundledFormatter.hash());
50+
task.getGradleUserHome().set(rootProject.getGradle().getGradleUserHomeDir());
4951
});
5052

5153
TaskProvider<UpdateWorkspaceXmlFile> updateWorkspaceXml = rootProject

‎gradle-open-java-format/src/main/groovy/com/palantir/javaformat/gradle/UpdatePalantirJavaFormatIdeaXmlFile.java‎

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,69 @@
2020
import java.net.URI;
2121
import java.util.List;
2222
import org.gradle.api.DefaultTask;
23+
import org.gradle.api.Task;
2324
import org.gradle.api.file.ConfigurableFileCollection;
25+
import org.gradle.api.file.DirectoryProperty;
2426
import org.gradle.api.file.RegularFileProperty;
27+
import org.gradle.api.provider.Property;
28+
import org.gradle.api.specs.Spec;
2529
import org.gradle.api.tasks.Classpath;
30+
import org.gradle.api.tasks.Input;
2631
import org.gradle.api.tasks.InputFiles;
32+
import org.gradle.api.tasks.Internal;
2733
import org.gradle.api.tasks.OutputFile;
2834
import org.gradle.api.tasks.TaskAction;
2935
import org.gradle.work.DisableCachingByDefault;
3036

3137
@DisableCachingByDefault(because = "Writes the developer's local .idea configuration; nothing to cache")
3238
public abstract class UpdatePalantirJavaFormatIdeaXmlFile extends DefaultTask {
3339

40+
/**
41+
* The jars a build declared for the formatter. Most builds declare none, and the IDE then gets the formatter inside
42+
* the plugin.
43+
*/
3444
@InputFiles
3545
@Classpath
3646
public abstract ConfigurableFileCollection getImplementationConfig();
3747

48+
/** The hash of the formatter inside the plugin, which names the directory its jars are extracted into. */
49+
@Input
50+
public abstract Property<String> getBundledFormatter();
51+
52+
/** Where the formatter inside the plugin is extracted to. */
53+
@Internal
54+
public abstract DirectoryProperty getGradleUserHome();
55+
56+
public UpdatePalantirJavaFormatIdeaXmlFile() {
57+
// The IDE loads the jars from where the XML says: while they are gone, the task is not up to date.
58+
getOutputs().upToDateWhen(new BundledFormatterIsExtracted());
59+
}
60+
3861
@org.gradle.api.tasks.Optional
3962
@OutputFile
4063
public abstract RegularFileProperty getXmlOutputFile();
4164

4265
@TaskAction
4366
public final void updateXml() {
44-
List<URI> uris =
45-
getImplementationConfig().getFiles().stream().map(File::toURI).toList();
67+
List<URI> uris = BundledFormatter.jarsUnlessOverridden(
68+
getImplementationConfig().getFiles(),
69+
getGradleUserHome().get().getAsFile())
70+
.stream()
71+
.map(File::toURI)
72+
.toList();
4673
XmlUtils.updateIdeaXmlFile(
4774
getXmlOutputFile().getAsFile().get(),
4875
node -> ConfigureJavaFormatterXml.configureJavaFormat(node, uris));
4976
}
77+
78+
/** A class, not a lambda: the configuration cache stores it with the task. */
79+
private static final class BundledFormatterIsExtracted implements Spec<Task> {
80+
@Override
81+
public boolean isSatisfiedBy(Task task) {
82+
var xml = (UpdatePalantirJavaFormatIdeaXmlFile) task;
83+
return !xml.getImplementationConfig().isEmpty()
84+
|| BundledFormatter.isExtracted(
85+
xml.getGradleUserHome().get().getAsFile());
86+
}
87+
}
5088
}

‎gradle-open-java-format/src/main/java/com/palantir/javaformat/gradle/BundledFormatter.java‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ public static List<File> jars(File gradleUserHome) {
6464
return jars(gradleUserHome.toPath(), BundledFormatter.class.getClassLoader());
6565
}
6666

67+
/** Whether the jars are all there under this Gradle user home, so that {@link #jars} would not extract them. */
68+
public static boolean isExtracted(File gradleUserHome) {
69+
var plugin = BundledFormatter.class.getClassLoader();
70+
return isComplete(gradleUserHome.toPath().resolve(CACHES).resolve(hash(plugin)), list(plugin));
71+
}
72+
6773
/**
6874
* The jars a build declared in palantirJavaFormat, which override the formatter inside the plugin; or, when it
6975
* declared none, as most builds do, the plugin's own.
@@ -77,10 +83,7 @@ static String hash(ClassLoader plugin) {
7783
}
7884

7985
static List<File> jars(Path gradleUserHome, ClassLoader plugin) {
80-
var list = new String(resource(plugin, LIST), StandardCharsets.UTF_8)
81-
.lines()
82-
.map(Jar::parse)
83-
.toList();
86+
var list = list(plugin);
8487
var caches = gradleUserHome.resolve(CACHES);
8588
var target = caches.resolve(hash(plugin));
8689
if (!isComplete(target, list)) {
@@ -89,6 +92,13 @@ static List<File> jars(Path gradleUserHome, ClassLoader plugin) {
8992
return list.stream().map(jar -> target.resolve(jar.name()).toFile()).toList();
9093
}
9194

95+
private static List<Jar> list(ClassLoader plugin) {
96+
return new String(resource(plugin, LIST), StandardCharsets.UTF_8)
97+
.lines()
98+
.map(Jar::parse)
99+
.toList();
100+
}
101+
92102
private static boolean isComplete(Path dir, List<Jar> list) {
93103
return list.stream().allMatch(jar -> Files.isRegularFile(dir.resolve(jar.name())));
94104
}

0 commit comments

Comments
 (0)