forked from diffplug/spotless
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpotlessExtension.java
More file actions
328 lines (270 loc) · 11.3 KB
/
SpotlessExtension.java
File metadata and controls
328 lines (270 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
/*
* Copyright 2016-2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.gradle.spotless;
import static java.util.Objects.requireNonNull;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Nullable;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.provider.Provider;
import org.gradle.language.base.plugins.LifecycleBasePlugin;
import com.diffplug.spotless.LineEnding;
public abstract class SpotlessExtension {
final Project project;
private final Provider<SpotlessTaskService> spotlessTaskService;
protected static final String TASK_GROUP = LifecycleBasePlugin.VERIFICATION_GROUP;
protected static final String BUILD_SETUP_TASK_GROUP = "build setup";
protected static final String CHECK_DESCRIPTION = "Checks that sourcecode satisfies formatting steps.";
protected static final String APPLY_DESCRIPTION = "Applies code formatting steps to sourcecode in-place.";
protected static final String INSTALL_GIT_PRE_PUSH_HOOK_DESCRIPTION = "Installs Spotless Git pre-push hook.";
static final String EXTENSION = "spotless";
static final String EXTENSION_PREDECLARE = "spotlessPredeclare";
static final String CHECK = "Check";
static final String APPLY = "Apply";
static final String DIAGNOSE = "Diagnose";
static final String INSTALL_GIT_PRE_PUSH_HOOK = "InstallGitPrePushHook";
protected SpotlessExtension(Project project) {
this.project = requireNonNull(project);
this.spotlessTaskService = SpotlessTaskService.registerIfAbsent(project, "");
}
Provider<SpotlessTaskService> getSpotlessTaskService() {
return spotlessTaskService;
}
/** Line endings (if any). */
LineEnding lineEndings = LineEnding.GIT_ATTRIBUTES_FAST_ALLSAME;
public LineEnding getLineEndings() {
return lineEndings;
}
public void setLineEndings(LineEnding lineEndings) {
if (lineEndings == LineEnding.GIT_ATTRIBUTES) {
throw new IllegalArgumentException("GIT_ATTRIBUTES not supported in Gradle, use GIT_ATTRIBUTES_FAST_ALLSAME instead. See https://github.com/diffplug/spotless/issues/1274 for more details.");
}
this.lineEndings = requireNonNull(lineEndings);
}
Charset encoding = StandardCharsets.UTF_8;
/** Returns the encoding to use. */
public Charset getEncoding() {
return encoding;
}
/** Sets encoding to use (defaults to UTF_8). */
public void setEncoding(Charset charset) {
encoding = requireNonNull(charset);
}
/** Sets encoding to use (defaults to UTF_8). */
public void setEncoding(String name) {
requireNonNull(name);
setEncoding(Charset.forName(name));
}
/** Sets encoding to use (defaults to UTF_8). */
public void encoding(Charset charset) {
setEncoding(charset);
}
/** Sets encoding to use (defaults to UTF_8). */
public void encoding(String charset) {
setEncoding(charset);
}
private @Nullable String ratchetFrom;
/**
* Limits the target to only the files which have changed since the given git reference,
* which is resolved according to <a href="https://javadoc.io/static/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-">this</a>
*/
public void setRatchetFrom(String ratchetFrom) {
this.ratchetFrom = ratchetFrom;
}
/** @see #setRatchetFrom(String) */
public @Nullable String getRatchetFrom() {
return ratchetFrom;
}
/** @see #setRatchetFrom(String) */
public void ratchetFrom(String ratchetFrom) {
setRatchetFrom(ratchetFrom);
}
final Map<String, FormatExtension> formats = new LinkedHashMap<>();
/** Configures the special java-specific extension. */
public void java(Action<JavaExtension> closure) {
requireNonNull(closure);
format(JavaExtension.NAME, JavaExtension.class, closure);
}
/** Configures the special scala-specific extension. */
public void scala(Action<ScalaExtension> closure) {
requireNonNull(closure);
format(ScalaExtension.NAME, ScalaExtension.class, closure);
}
/** Configures the special kotlin-specific extension. */
public void kotlin(Action<KotlinExtension> closure) {
requireNonNull(closure);
format(KotlinExtension.NAME, KotlinExtension.class, closure);
}
/** Configures the special Gradle Kotlin DSL specific extension. */
public void kotlinGradle(Action<KotlinGradleExtension> closure) {
requireNonNull(closure);
format(KotlinGradleExtension.NAME, KotlinGradleExtension.class, closure);
}
/** Configures the special freshmark-specific extension. */
public void freshmark(Action<FreshMarkExtension> closure) {
requireNonNull(closure);
format(FreshMarkExtension.NAME, FreshMarkExtension.class, closure);
}
/** Configures the special flexmark-specific extension. */
public void flexmark(Action<FlexmarkExtension> closure) {
requireNonNull(closure);
format(FlexmarkExtension.NAME, FlexmarkExtension.class, closure);
}
/** Configures the special groovy-specific extension. */
public void groovy(Action<GroovyExtension> closure) {
format(GroovyExtension.NAME, GroovyExtension.class, closure);
}
/** Configures the special groovy-specific extension for Gradle files. */
public void groovyGradle(Action<GroovyGradleExtension> closure) {
format(GroovyGradleExtension.NAME, GroovyGradleExtension.class, closure);
}
/** Configures the special sql-specific extension for SQL files. */
public void sql(Action<SqlExtension> closure) {
format(SqlExtension.NAME, SqlExtension.class, closure);
}
/** Configures the special C/C++-specific extension. */
public void cpp(Action<CppExtension> closure) {
format(CppExtension.NAME, CppExtension.class, closure);
}
/** Configures the special javascript-specific extension for javascript files. */
public void javascript(Action<JavascriptExtension> closure) {
format(JavascriptExtension.NAME, JavascriptExtension.class, closure);
}
/** Configures the special tableTest-specific extension for .table files. */
public void tableTest(Action<TableTestExtension> closure) {
requireNonNull(closure);
format(TableTestExtension.NAME, TableTestExtension.class, closure);
}
/** Configures the special typescript-specific extension for typescript files. */
public void typescript(Action<TypescriptExtension> closure) {
format(TypescriptExtension.NAME, TypescriptExtension.class, closure);
}
/** Configures the special antlr4-specific extension for antlr4 files. */
public void antlr4(Action<Antlr4Extension> closure) {
format(Antlr4Extension.NAME, Antlr4Extension.class, closure);
}
/** Configures the special python-specific extension for python files. */
public void python(Action<PythonExtension> closure) {
format(PythonExtension.NAME, PythonExtension.class, closure);
}
/** Configures the special JSON-specific extension. */
public void json(Action<JsonExtension> closure) {
requireNonNull(closure);
format(JsonExtension.NAME, JsonExtension.class, closure);
}
/** Configures the special protobuf-specific extension. */
public void protobuf(Action<ProtobufExtension> closure) {
requireNonNull(closure);
format(ProtobufExtension.NAME, ProtobufExtension.class, closure);
}
/** Configures the special shell-specific extension. */
public void shell(Action<ShellExtension> closure) {
requireNonNull(closure);
format(ShellExtension.NAME, ShellExtension.class, closure);
}
/** Configures the special YAML-specific extension. */
public void yaml(Action<YamlExtension> closure) {
requireNonNull(closure);
format(YamlExtension.NAME, YamlExtension.class, closure);
}
/** Configures the special Gherkin-specific extension. */
public void gherkin(Action<GherkinExtension> closure) {
requireNonNull(closure);
format(GherkinExtension.NAME, GherkinExtension.class, closure);
}
public void go(Action<GoExtension> closure) {
requireNonNull(closure);
format(GoExtension.NAME, GoExtension.class, closure);
}
/** Configures the special CSS-specific extension. */
public void css(Action<CssExtension> closure) {
requireNonNull(closure);
format(CssExtension.NAME, CssExtension.class, closure);
}
/** Configures the special POM-specific extension. */
public void pom(Action<PomExtension> closure) {
requireNonNull(closure);
format(PomExtension.NAME, PomExtension.class, closure);
}
/** Configures a custom extension. */
public void format(String name, Action<FormatExtension> closure) {
requireNonNull(name, "name");
requireNonNull(closure, "closure");
format(name, FormatExtension.class, closure);
}
boolean enforceCheck = true;
/** Returns {@code true} if Gradle's {@code check} task should run {@code spotlessCheck}; {@code false} otherwise. */
public boolean isEnforceCheck() {
return enforceCheck;
}
/**
* Configures Gradle's {@code check} task to run {@code spotlessCheck} if {@code true},
* but to not do so if {@code false}.
* <p>
* {@code true} by default.
*/
public void setEnforceCheck(boolean enforceCheck) {
this.enforceCheck = enforceCheck;
}
@SuppressWarnings("unchecked")
public <T extends FormatExtension> void format(String name, Class<T> clazz, Action<T> configure) {
maybeCreate(name, clazz).lazyActions.add((Action<FormatExtension>) configure);
}
@SuppressWarnings("unchecked")
protected final <T extends FormatExtension> T maybeCreate(String name, Class<T> clazz) {
FormatExtension existing = formats.get(name);
if (existing != null) {
if (!clazz.isInstance(existing)) {
throw new GradleException("Tried to add format named '" + name + "'"
+ " of type " + clazz + " but one has already been created of type " + existing.getClass());
} else {
return (T) existing;
}
} else {
T formatExtension = instantiateFormatExtension(clazz);
formats.put(name, formatExtension);
createFormatTasks(name, formatExtension);
return formatExtension;
}
}
<T extends FormatExtension> T instantiateFormatExtension(Class<T> clazz) {
try {
return project.getObjects().newInstance(clazz, this);
} catch (Exception e) {
throw new GradleException("Must have a constructor " + clazz.getSimpleName() + "(SpotlessExtension root), annotated with @javax.inject.Inject", e);
}
}
protected abstract void createFormatTasks(String name, FormatExtension formatExtension);
public void predeclareDepsFromBuildscript() {
if (project.getRootProject() != project) {
throw new GradleException("predeclareDepsFromBuildscript can only be called from the root project");
}
predeclare(GradleProvisioner.Policy.ROOT_BUILDSCRIPT);
}
public void predeclareDeps() {
if (project.getRootProject() != project) {
throw new GradleException("predeclareDeps can only be called from the root project");
}
predeclare(GradleProvisioner.Policy.ROOT_PROJECT);
}
protected void predeclare(GradleProvisioner.Policy policy) {
project.getExtensions().create(SpotlessExtensionPredeclare.class, EXTENSION_PREDECLARE, SpotlessExtensionPredeclare.class, project, policy);
}
}