17
17
package com .palantir .javaformat .gradle ;
18
18
19
19
import 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 ;
22
21
import com .palantir .gradle .ideaconfiguration .IdeaConfigurationExtension ;
23
22
import 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 ;
33
24
import java .util .List ;
34
25
import java .util .Optional ;
35
- import java .util .function .Consumer ;
36
- import java .util .stream .Collectors ;
26
+ import java .util .stream .Stream ;
37
27
import javax .inject .Inject ;
38
- import javax . xml . parsers . ParserConfigurationException ;
28
+ import org . gradle . StartParameter ;
39
29
import org .gradle .api .Plugin ;
40
30
import org .gradle .api .Project ;
41
31
import org .gradle .api .artifacts .Configuration ;
42
32
import org .gradle .api .artifacts .ConfigurationContainer ;
43
33
import 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 ;
46
35
47
36
public abstract class PalantirJavaFormatIdeaPlugin implements Plugin <Project > {
48
37
@@ -62,13 +51,46 @@ public void apply(Project rootProject) {
62
51
63
52
rootProject .getPlugins ().apply (PalantirJavaFormatProviderPlugin .class );
64
53
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 );
72
94
});
73
95
74
96
rootProject .getPluginManager ().apply (IdeaConfigurationPlugin .class );
@@ -83,87 +105,4 @@ private Optional<Configuration> maybeGetNativeImplConfiguration() {
83
105
? Optional .of (getConfigurations ().getByName (NativeImageFormatProviderPlugin .NATIVE_CONFIGURATION_NAME ))
84
106
: Optional .empty ();
85
107
}
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
- }
169
108
}
0 commit comments