Skip to content

Commit 1c2969b

Browse files
committed
Support multiple formats in Maven plugin
Format is a configuration element that makes it possible to apply generic formatting steps (EndWithNewline, LicenseHeader, etc.) to a set of files defined by custom includes and excludes. Example of format configuration: ``` <configuration> <format> <includes> <include>src/**/txt/**/*.txt</include> </includes> <excludes> <exclude>src/**/txt/**/*Wrong.txt</exclude> </excludes> <endWithNewline/> <trimTrailingWhitespace/> <licenseHeader> <content>// License Text</content> <delimiter>start</delimiter> </licenseHeader> </format> </configuration> ``` It is currently possible to only define a single `<format>` element in plugin configuration. This commit makes it possible to define multiple formats. Format configuration structure remains the same but all formats should be enclosed in `<formats>...</formats>`. Example: ``` <configuration> <formats> <format>...format 1 includes, excludes and steps</format> <format>...format 2 includes, excludes and steps</format> <format>...format 3 includes, excludes and steps</format> </formats> </configuration> ```
1 parent 143864e commit 1c2969b

File tree

4 files changed

+140
-57
lines changed

4 files changed

+140
-57
lines changed

plugin-maven/README.md

+51-44
Original file line numberDiff line numberDiff line change
@@ -168,53 +168,60 @@ By default, all files matching `src/main/kotlin/**/*.kt` and `src/test/kotlin/**
168168

169169
## Applying to custom sources
170170

171-
By default, no Ant-Style include patterns are defined. Each element under `<format>` is a step, and they will be applied in the order specified. Every step is optional, and they will be applied in the order specified.
171+
By default, no Ant-Style include patterns are defined. Each element under `<format>` is a step, and they will be applied in the order specified. Every step is optional, and they will be applied in the order specified. It is possible to define multiple custom formats.
172172

173173
```xml
174174
<configuration>
175-
<format>
176-
<includes>
177-
<!-- include all property files in "resource" folders under "src" -->
178-
<include>src/**/resources/**/*.properties</include>
179-
</includes>
180-
181-
<licenseHeader>
182-
<!-- Specify either content or file, but not both -->
183-
<content>/* Licensed under Apache-2.0 */</content>
184-
<file>${basedir}/license-header</file>
185-
<!-- conent until first occurrence of the delimiter regex will be interpreted as header section -->
186-
<delimiter>#</delimiter>
187-
</licenseHeader>
188-
189-
<!-- Files must end with a newline -->
190-
<endWithNewline />
191-
192-
<!-- Specify whether to use tabs or spaces for indentation -->
193-
<indent>
194-
<!-- Specify either spaces or tabs -->
195-
<spaces>true</spaces>
196-
<tabs>true</tabs>
197-
<!-- Specify how many spaces are used to convert one tab and vice versa. Defaults to 4 -->
198-
<spacesPerTab>4</spacesPerTab>
199-
</indent>
200-
201-
<!-- Trim trailing whitespaces -->
202-
<trimTrailingWhitespace />
203-
204-
<!-- Specify replacements using search and replace -->
205-
<replace>
206-
<name>Say Hello to Mars</name>
207-
<search>World</search>
208-
<replacement>Mars</replacement>
209-
</replace>
210-
211-
<!-- Specify replacements using regex match and replace -->
212-
<replaceRegex>
213-
<name>Say Hello to Mars from Regex</name>
214-
<searchRegex>(Hello) W[a-z]{3}d</searchRegex>
215-
<replacement>$1 Mars</replacement>
216-
</replaceRegex>
217-
</format>
175+
<formats>
176+
177+
<!-- Define first formatter that operates on properties files -->
178+
<format>
179+
<includes>
180+
<!-- Include all property files in "resource" folders under "src" -->
181+
<include>src/**/resources/**/*.properties</include>
182+
</includes>
183+
184+
<licenseHeader>
185+
<!-- Specify either content or file, but not both -->
186+
<content>/* Licensed under Apache-2.0 */</content>
187+
<file>${basedir}/license-header</file>
188+
<!-- conent until first occurrence of the delimiter regex will be interpreted as header section -->
189+
<delimiter>#</delimiter>
190+
</licenseHeader>
191+
192+
<!-- Files must end with a newline -->
193+
<endWithNewline />
194+
195+
<!-- Specify whether to use tabs or spaces for indentation -->
196+
<indent>
197+
<!-- Specify either spaces or tabs -->
198+
<spaces>true</spaces>
199+
<tabs>true</tabs>
200+
<!-- Specify how many spaces are used to convert one tab and vice versa. Defaults to 4 -->
201+
<spacesPerTab>4</spacesPerTab>
202+
</indent>
203+
204+
<!-- Trim trailing whitespaces -->
205+
<trimTrailingWhitespace />
206+
207+
<!-- Specify replacements using search and replace -->
208+
<replace>
209+
<name>Say Hello to Mars</name>
210+
<search>World</search>
211+
<replacement>Mars</replacement>
212+
</replace>
213+
214+
<!-- Specify replacements using regex match and replace -->
215+
<replaceRegex>
216+
<name>Say Hello to Mars from Regex</name>
217+
<searchRegex>(Hello) W[a-z]{3}d</searchRegex>
218+
<replacement>$1 Mars</replacement>
219+
</replaceRegex>
220+
</format>
221+
222+
<!-- Other formats can be defined here, they will be allied in the order specified -->
223+
224+
</formats>
218225
</configuration>
219226
```
220227

plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919

2020
import java.io.File;
2121
import java.io.IOException;
22-
import java.util.HashSet;
23-
import java.util.List;
24-
import java.util.Objects;
25-
import java.util.Set;
22+
import java.util.*;
2623
import java.util.stream.Stream;
2724

2825
import org.apache.maven.plugin.AbstractMojo;
@@ -78,7 +75,7 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
7875
private LicenseHeader licenseHeader;
7976

8077
@Parameter
81-
private Format format;
78+
private List<Format> formats = Collections.emptyList();
8279

8380
@Parameter
8481
private Java java;
@@ -146,7 +143,7 @@ private FileLocator getFileLocator() {
146143
}
147144

148145
private List<FormatterFactory> getFormatterFactories() {
149-
return Stream.of(format, java, scala, kotlin)
146+
return Stream.concat(formats.stream(), Stream.of(java, scala, kotlin))
150147
.filter(Objects::nonNull)
151148
.collect(toList());
152149
}

plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationTest.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private File copy(String path) throws IOException {
8787
}
8888

8989
protected void writePomWithFormatSteps(String... steps) throws IOException {
90-
writePom(groupWithSteps("format", including("<include>src/**/java/**/*.java</include>"), steps));
90+
writePom(formats(groupWithSteps("format", including("<include>src/**/java/**/*.java</include>"), steps)));
9191
}
9292

9393
protected void writePomWithJavaSteps(String... steps) throws IOException {
@@ -177,12 +177,12 @@ private static String[] groupWithSteps(String group, String... steps) {
177177
return groupWithSteps(group, new String[]{}, steps);
178178
}
179179

180-
private static String[] including(String... include) {
181-
String[] result = new String[include.length + 2];
182-
result[0] = "<includes>";
183-
System.arraycopy(include, 0, result, 1, include.length);
184-
result[result.length - 1] = "</includes>";
185-
return result;
180+
private static String[] including(String... includes) {
181+
return groupWithSteps("includes", includes);
182+
}
183+
184+
private static String[] formats(String... formats) {
185+
return groupWithSteps("formats", formats);
186186
}
187187

188188
protected class MultiModuleProjectCreator {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2016 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.maven;
17+
18+
import org.junit.Test;
19+
20+
public class MultipleFormatsTest extends MavenIntegrationTest {
21+
22+
@Test
23+
public void testMultipleFormatsWithDifferentIncludes() throws Exception {
24+
writePom(
25+
"<formats>",
26+
" <format>",
27+
" <includes>",
28+
" <include>src/**/java/**/*.java</include>",
29+
" </includes>",
30+
" <replace>",
31+
" <name>Greetings to Mars</name>",
32+
" <search>World</search>",
33+
" <replacement>Mars</replacement>",
34+
" </replace>",
35+
" <licenseHeader>",
36+
" <content>// License Header #1</content>",
37+
" <delimiter>package</delimiter>",
38+
" </licenseHeader>",
39+
" </format>",
40+
" <format>",
41+
" <includes>",
42+
" <include>src/**/txt/**/*.txt</include>",
43+
" </includes>",
44+
" <replace>",
45+
" <name>Greetings to Titan</name>",
46+
" <search>World</search>",
47+
" <replacement>Titan</replacement>",
48+
" </replace>",
49+
" <licenseHeader>",
50+
" <content>// License Header #2</content>",
51+
" <delimiter>Just</delimiter>",
52+
" </licenseHeader>",
53+
" </format>",
54+
"</formats>");
55+
56+
String path1 = "src/main/java/test1.java";
57+
String path2 = "src/main/java/test2.java";
58+
59+
String path3 = "src/main/txt/test1.txt";
60+
String path4 = "src/main/txt/test2.txt";
61+
String path5 = "src/main/txt/test3.txt";
62+
63+
setFile(path1).toContent("package test;\npublic class JavaWorld1 {}");
64+
setFile(path2).toContent("package test;\npublic class JavaWorld2 {}");
65+
66+
setFile(path3).toContent("Just a text file #1\nHello World!");
67+
setFile(path4).toContent("Just a text file #2\nHello World!");
68+
setFile(path5).toContent("Just a text file #3\nHello World!");
69+
70+
mavenRunner().withArguments("spotless:apply").runNoError();
71+
72+
assertFile(path1).hasContent("// License Header #1\npackage test;\npublic class JavaMars1 {}");
73+
assertFile(path2).hasContent("// License Header #1\npackage test;\npublic class JavaMars2 {}");
74+
75+
assertFile(path3).hasContent("// License Header #2\nJust a text file #1\nHello Titan!");
76+
assertFile(path4).hasContent("// License Header #2\nJust a text file #2\nHello Titan!");
77+
assertFile(path5).hasContent("// License Header #2\nJust a text file #3\nHello Titan!");
78+
}
79+
}

0 commit comments

Comments
 (0)