1717package com .palantir .javaformat .gradle ;
1818
1919import com .google .common .base .Preconditions ;
20- import com .google .common .collect .ImmutableMap ;
21- import com .google .common .io .Files ;
20+ import com .google .common .collect .ImmutableList ;
2221import com .palantir .gradle .ideaconfiguration .IdeaConfigurationExtension ;
2322import com .palantir .gradle .ideaconfiguration .IdeaConfigurationPlugin ;
24- import groovy .util .Node ;
25- import groovy .util .XmlNodePrinter ;
26- import groovy .util .XmlParser ;
27- import java .io .BufferedWriter ;
28- import java .io .File ;
29- import java .io .IOException ;
30- import java .io .PrintWriter ;
31- import java .net .URI ;
32- import java .nio .charset .Charset ;
23+ import java .nio .file .Paths ;
3324import java .util .List ;
3425import java .util .Optional ;
35- import java .util .function .Consumer ;
36- import java .util .stream .Collectors ;
26+ import java .util .stream .Stream ;
3727import javax .inject .Inject ;
38- import javax . xml . parsers . ParserConfigurationException ;
28+ import org . gradle . StartParameter ;
3929import org .gradle .api .Plugin ;
4030import org .gradle .api .Project ;
4131import org .gradle .api .artifacts .Configuration ;
4232import org .gradle .api .artifacts .ConfigurationContainer ;
4333import org .gradle .api .tasks .Nested ;
44- import org .gradle .plugins .ide .idea .model .IdeaModel ;
45- import org .xml .sax .SAXException ;
34+ import org .gradle .api .tasks .TaskProvider ;
4635
4736public abstract class PalantirJavaFormatIdeaPlugin implements Plugin <Project > {
4837
@@ -62,13 +51,46 @@ public void apply(Project rootProject) {
6251
6352 rootProject .getPlugins ().apply (PalantirJavaFormatProviderPlugin .class );
6453 rootProject .getPluginManager ().withPlugin ("idea" , ideaPlugin -> {
65- Configuration implConfiguration =
66- rootProject .getConfigurations ().getByName (PalantirJavaFormatProviderPlugin .CONFIGURATION_NAME );
67-
68- Optional <Configuration > nativeImplConfiguration = maybeGetNativeImplConfiguration ();
69-
70- configureLegacyIdea (rootProject , implConfiguration , nativeImplConfiguration );
71- configureIntelliJImport (rootProject , implConfiguration , nativeImplConfiguration );
54+ TaskProvider <UpdatePalantirJavaFormatIdeaXmlFile > updatePalantirJavaFormatXml = rootProject
55+ .getTasks ()
56+ .register ("updatePalantirJavaFormatXml" , UpdatePalantirJavaFormatIdeaXmlFile .class , task -> {
57+ task .getXmlOutputFile ().set (rootProject .file (".idea/palantir-java-format.xml" ));
58+ task .getImplementationConfig ()
59+ .from (rootProject
60+ .getConfigurations ()
61+ .getByName (PalantirJavaFormatProviderPlugin .CONFIGURATION_NAME ));
62+ maybeGetNativeImplConfiguration ().ifPresent (config -> {
63+ task .getNativeImageConfig ().from (config );
64+ task .getNativeImageOutputFile ().fileProvider (rootProject .provider (() -> rootProject
65+ .getGradle ()
66+ .getGradleUserHomeDir ()
67+ .toPath ()
68+ .resolve ("palantir-java-format-caches/" )
69+ .resolve (Paths .get (task .getNativeImageConfig ()
70+ .getSingleFile ()
71+ .toURI ())
72+ .getFileName ()
73+ .toString ())
74+ .toFile ()));
75+ });
76+ });
77+
78+ TaskProvider <UpdateWorkspaceXmlFile > updateWorkspaceXml = rootProject
79+ .getTasks ()
80+ .register ("updateWorkspaceXml" , UpdateWorkspaceXmlFile .class , task -> {
81+ task .getOutputFile ().set (rootProject .file (".idea/workspace.xml" ));
82+ });
83+
84+ // Add the task to the Gradle start parameters so it executes automatically.
85+ StartParameter startParameter = rootProject .getGradle ().getStartParameter ();
86+ List <String > updateTasks = Stream .of (updatePalantirJavaFormatXml , updateWorkspaceXml )
87+ .map (taskProvider -> String .format (":%s" , taskProvider .getName ()))
88+ .toList ();
89+ List <String > taskNames = ImmutableList .<String >builder ()
90+ .addAll (startParameter .getTaskNames ())
91+ .addAll (updateTasks )
92+ .build ();
93+ startParameter .setTaskNames (taskNames );
7294 });
7395
7496 rootProject .getPluginManager ().apply (IdeaConfigurationPlugin .class );
@@ -83,87 +105,4 @@ private Optional<Configuration> maybeGetNativeImplConfiguration() {
83105 ? Optional .of (getConfigurations ().getByName (NativeImageFormatProviderPlugin .NATIVE_CONFIGURATION_NAME ))
84106 : Optional .empty ();
85107 }
86-
87- private static void configureLegacyIdea (
88- Project project , Configuration implConfiguration , Optional <Configuration > nativeImplConfiguration ) {
89- IdeaModel ideaModel = project .getExtensions ().getByType (IdeaModel .class );
90- ideaModel .getProject ().getIpr ().withXml (xmlProvider -> {
91- // this block is lazy
92- List <URI > uris =
93- implConfiguration .getFiles ().stream ().map (File ::toURI ).collect (Collectors .toList ());
94- Optional <URI > nativeUri =
95- nativeImplConfiguration .map (conf -> conf .getSingleFile ().toURI ());
96- ConfigureJavaFormatterXml .configureJavaFormat (xmlProvider .asNode (), uris , nativeUri );
97- });
98-
99- ideaModel .getWorkspace ().getIws ().withXml (xmlProvider -> {
100- ConfigureJavaFormatterXml .configureWorkspaceXml (xmlProvider .asNode ());
101- });
102- }
103-
104- private static void configureIntelliJImport (
105- Project project , Configuration implConfiguration , Optional <Configuration > nativeImplConfiguration ) {
106- // Note: we tried using 'org.jetbrains.gradle.plugin.idea-ext' and afterSync triggers, but these are currently
107- // very hard to manage as the tasks feel disconnected from the Sync operation, and you can't remove them once
108- // you've added them. For that reason, we accept that we have to resolve this configuration at
109- // configuration-time, but only do it when part of an IDEA import.
110- if (!Boolean .getBoolean ("idea.active" )) {
111- return ;
112- }
113- project .getGradle ().projectsEvaluated (gradle -> {
114- List <URI > uris =
115- implConfiguration .getFiles ().stream ().map (File ::toURI ).collect (Collectors .toList ());
116-
117- Optional <URI > nativeImageUri =
118- nativeImplConfiguration .map (conf -> conf .getSingleFile ().toURI ());
119-
120- createOrUpdateIdeaXmlFile (
121- project .file (".idea/palantir-java-format.xml" ),
122- node -> ConfigureJavaFormatterXml .configureJavaFormat (node , uris , nativeImageUri ));
123- createOrUpdateIdeaXmlFile (
124- project .file (".idea/workspace.xml" ), ConfigureJavaFormatterXml ::configureWorkspaceXml );
125-
126- // Still configure legacy idea if using intellij import
127- updateIdeaXmlFileIfExists (project .file (project .getName () + ".ipr" ), node -> {
128- ConfigureJavaFormatterXml .configureJavaFormat (node , uris , nativeImageUri );
129- });
130- updateIdeaXmlFileIfExists (
131- project .file (project .getName () + ".iws" ), ConfigureJavaFormatterXml ::configureWorkspaceXml );
132- });
133- }
134-
135- private static void createOrUpdateIdeaXmlFile (File configurationFile , Consumer <Node > configure ) {
136- updateIdeaXmlFile (configurationFile , configure , true );
137- }
138-
139- private static void updateIdeaXmlFileIfExists (File configurationFile , Consumer <Node > configure ) {
140- updateIdeaXmlFile (configurationFile , configure , false );
141- }
142-
143- private static void updateIdeaXmlFile (File configurationFile , Consumer <Node > configure , boolean createIfAbsent ) {
144- Node rootNode ;
145- if (configurationFile .isFile ()) {
146- try {
147- rootNode = new XmlParser ().parse (configurationFile );
148- } catch (IOException | SAXException | ParserConfigurationException e ) {
149- throw new RuntimeException ("Couldn't parse existing configuration file: " + configurationFile , e );
150- }
151- } else {
152- if (!createIfAbsent ) {
153- return ;
154- }
155- rootNode = new Node (null , "project" , ImmutableMap .of ("version" , "4" ));
156- }
157-
158- configure .accept (rootNode );
159-
160- try (BufferedWriter writer = Files .newWriter (configurationFile , Charset .defaultCharset ());
161- PrintWriter printWriter = new PrintWriter (writer )) {
162- XmlNodePrinter nodePrinter = new XmlNodePrinter (printWriter );
163- nodePrinter .setPreserveWhitespace (true );
164- nodePrinter .print (rootNode );
165- } catch (IOException e ) {
166- throw new RuntimeException ("Failed to write back to configuration file: " + configurationFile , e );
167- }
168- }
169108}
0 commit comments