Skip to content

Commit 7ea2d66

Browse files
authored
Merge pull request #188 from lutovich/maven-plugin
Initial version of Spotless Maven plugin
2 parents d2bffd6 + 4162569 commit 7ea2d66

File tree

66 files changed

+3386
-183
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+3386
-183
lines changed

.travis.yml

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
language: java
22
jdk:
33
- oraclejdk8
4-
script: "./.ci/ci.sh"
4+
install: true
5+
script:
6+
- ./.ci/ci.sh
57
before_cache:
68
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
79
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
10+
- rm -fr plugin-maven/build/localMavenRepository/com/diffplug/spotless/
811
cache:
912
directories:
1013
- $HOME/.gradle/caches/
1114
- $HOME/.gradle/wrapper/
15+
- $HOME/.m2/
16+
- plugin-maven/build/localMavenRepository/

README.md

+13-12
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@ output = [
3434
'| --------------------------------------------- | ------------- | ------------ | --------|',
3535
lib('generic.EndWithNewlineStep') +'{{yes}} | {{no}} | {{no}} |',
3636
lib('generic.IndentStep') +'{{yes}} | {{no}} | {{no}} |',
37-
lib('generic.LicenseHeaderStep') +'{{yes}} | {{no}} | {{no}} |',
37+
lib('generic.LicenseHeaderStep') +'{{yes}} | {{yes}} | {{no}} |',
3838
lib('generic.ReplaceRegexStep') +'{{yes}} | {{no}} | {{no}} |',
3939
lib('generic.ReplaceStep') +'{{yes}} | {{no}} | {{no}} |',
4040
lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{no}} | {{no}} |',
4141
extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
42-
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{no}} | {{no}} |',
43-
lib('java.ImportOrderStep') +'{{yes}} | {{no}} | {{no}} |',
44-
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{no}} | {{no}} |',
45-
extra('java.EclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
42+
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} |',
43+
lib('java.ImportOrderStep') +'{{yes}} | {{yes}} | {{no}} |',
44+
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{yes}} | {{no}} |',
45+
extra('java.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
4646
lib('kotlin.KtLintStep') +'{{yes}} | {{no}} | {{no}} |',
4747
lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} |',
48-
lib('scala.ScalaFmtStep') +'{{yes}} | {{no}} | {{no}} |',
48+
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |',
4949
lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
5050
'| [(Your FormatterStep here)](https://github.com/nedtwigg/spotless/blob/markdown-preview-temp/CONTRIBUTING.md#how-to-add-a-new-formatterstep) | {{no}} | {{no}} | {{no}} |',
5151
'| Fast up-to-date checking | {{yes}} | {{no}} | {{no}} |',
@@ -57,18 +57,18 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}
5757
| --------------------------------------------- | ------------- | ------------ | --------|
5858
| [`generic.EndWithNewlineStep`](lib/src/main/java/com/diffplug/spotless/generic/EndWithNewlineStep.java) | :+1: | :white_large_square: | :white_large_square: |
5959
| [`generic.IndentStep`](lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java) | :+1: | :white_large_square: | :white_large_square: |
60-
| [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :white_large_square: | :white_large_square: |
60+
| [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :+1: | :white_large_square: |
6161
| [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :white_large_square: | :white_large_square: |
6262
| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :white_large_square: | :white_large_square: |
6363
| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :white_large_square: | :white_large_square: |
6464
| [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
65-
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :white_large_square: | :white_large_square: |
66-
| [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :white_large_square: | :white_large_square: |
67-
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :white_large_square: | :white_large_square: |
68-
| [`java.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
65+
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :white_large_square: |
66+
| [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :+1: | :white_large_square: |
67+
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :+1: | :white_large_square: |
68+
| [`java.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: |
6969
| [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :white_large_square: | :white_large_square: |
7070
| [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: |
71-
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :white_large_square: | :white_large_square: |
71+
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: |
7272
| [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
7373
| [(Your FormatterStep here)](https://github.com/nedtwigg/spotless/blob/markdown-preview-temp/CONTRIBUTING.md#how-to-add-a-new-formatterstep) | :white_large_square: | :white_large_square: | :white_large_square: |
7474
| Fast up-to-date checking | :+1: | :white_large_square: | :white_large_square: |
@@ -77,6 +77,7 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}
7777

7878
## Acknowledgements
7979

80+
* Thanks to [Konstantin Lutovich](https://github.com/lutovich) for [implementing the maven plugin](https://github.com/diffplug/spotless/pull/188).
8081
* Thanks to [Baptiste Mesta](https://github.com/baptistemesta) for
8182
+ porting the DBeaver formatter to Spotless, and thanks to [DBeaver](https://dbeaver.jkiss.org/) and [its authors](https://github.com/serge-rider/dbeaver/graphs/contributors) for their excellent SQL formatter.
8283
+ making license headers date-aware [#180](https://github.com/diffplug/spotless/pull/180)

gradle.properties

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ artifactIdTestLib=spotless-testlib
1212

1313
versionMaven=1.0.0-SNAPSHOT
1414
stableMaven=unreleased
15-
artifactIdMaven=spotless-plugin-maven
15+
# naming convention '-maven-plugin' allows mvn 'spotless:check' instead of 'spotless-plugin-maven:check'
16+
artifactIdMaven=spotless-maven-plugin
1617

1718
versionGradle=3.10.0-SNAPSHOT
1819
stableGradle=3.9.0
@@ -31,3 +32,9 @@ VER_PEGDOWN_DOCLET=1.3
3132
VER_DURIAN=1.2.0
3233
VER_JUNIT=4.12
3334
VER_ASSERTJ=3.5.2
35+
VER_MOCKITO=2.13.0
36+
37+
# Used for Maven Plugin
38+
VER_MAVEN_API=3.0
39+
VER_ECLIPSE_AETHER=1.1.0
40+
VER_MUSTACHE=0.9.5

gradle/java-publish.gradle

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ model {
9898
}
9999
}
100100
developers {
101+
if (project.ext.artifactId == 'spotless-plugin-maven') {
102+
developer {
103+
id 'lutovich'
104+
name 'Konstantin Lutovich'
105+
email 'konstantin.lutovich@neotechnology.com'
106+
}
107+
}
101108
developer {
102109
id 'nedtwigg'
103110
name 'Ned Twigg'

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/DiffMessageFormatter.java lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java

+70-29
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.diffplug.gradle.spotless;
16+
package com.diffplug.spotless.extra.integration;
1717

1818
import java.io.ByteArrayOutputStream;
1919
import java.io.File;
2020
import java.io.IOException;
2121
import java.nio.charset.StandardCharsets;
2222
import java.nio.file.Files;
23-
import java.nio.file.Path;
2423
import java.util.List;
2524
import java.util.ListIterator;
25+
import java.util.Objects;
2626

2727
import org.eclipse.jgit.diff.DiffFormatter;
2828
import org.eclipse.jgit.diff.EditList;
@@ -31,48 +31,89 @@
3131
import org.eclipse.jgit.diff.RawTextComparator;
3232

3333
import com.diffplug.common.base.CharMatcher;
34+
import com.diffplug.common.base.Errors;
3435
import com.diffplug.common.base.Preconditions;
3536
import com.diffplug.common.base.Splitter;
3637
import com.diffplug.spotless.Formatter;
3738
import com.diffplug.spotless.LineEnding;
3839
import com.diffplug.spotless.PaddedCell;
3940

4041
/** Formats the messages of failed spotlessCheck invocations with a nice diff message. */
41-
final class DiffMessageFormatter {
42-
private static final int MAX_CHECK_MESSAGE_LINES = 50;
43-
static final int MAX_FILES_TO_LIST = 10;
44-
45-
static String messageFor(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException {
46-
DiffMessageFormatter diffFormater = new DiffMessageFormatter(task, formatter, problemFiles);
47-
return "The following files had format violations:\n"
48-
+ diffFormater.buffer
49-
+ "Run 'gradlew "
50-
+ SpotlessPlugin.EXTENSION
51-
+ SpotlessPlugin.APPLY
52-
+ "' to fix these violations.";
42+
public final class DiffMessageFormatter {
43+
public static Builder builder() {
44+
return new Builder();
45+
}
46+
47+
public static class Builder {
48+
private Builder() {}
49+
50+
private String runToFix;
51+
private boolean isPaddedCell;
52+
private Formatter formatter;
53+
private List<File> problemFiles;
54+
55+
/** "Run 'gradlew spotlessApply' to fix these violations." */
56+
public Builder runToFix(String runToFix) {
57+
this.runToFix = Objects.requireNonNull(runToFix);
58+
return this;
59+
}
60+
61+
public Builder isPaddedCell(boolean isPaddedCell) {
62+
this.isPaddedCell = isPaddedCell;
63+
return this;
64+
}
65+
66+
public Builder formatter(Formatter formatter) {
67+
this.formatter = Objects.requireNonNull(formatter);
68+
return this;
69+
}
70+
71+
public Builder problemFiles(List<File> problemFiles) {
72+
this.problemFiles = Objects.requireNonNull(problemFiles);
73+
Preconditions.checkArgument(!problemFiles.isEmpty(), "cannot be empty");
74+
return this;
75+
}
76+
77+
/** Returns the error message. */
78+
public String getMessage() {
79+
try {
80+
Objects.requireNonNull(runToFix, "runToFix");
81+
Objects.requireNonNull(formatter, "formatter");
82+
Objects.requireNonNull(problemFiles, "problemFiles");
83+
DiffMessageFormatter diffFormater = new DiffMessageFormatter(this);
84+
return "The following files had format violations:\n"
85+
+ diffFormater.buffer
86+
+ runToFix;
87+
} catch (IOException e) {
88+
throw Errors.asRuntime(e);
89+
}
90+
}
91+
92+
String relativePath(File file) {
93+
return formatter.getRootDir().relativize(file.toPath()).toString();
94+
}
5395
}
5496

97+
private static final int MAX_CHECK_MESSAGE_LINES = 50;
98+
public static final int MAX_FILES_TO_LIST = 10;
99+
55100
private final StringBuilder buffer = new StringBuilder(MAX_CHECK_MESSAGE_LINES * 64);
56101
private int numLines = 0;
57102

58-
private DiffMessageFormatter(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException {
59-
Preconditions.checkArgument(!problemFiles.isEmpty(), "Problem files must not be empty");
60-
61-
Path rootDir = task.getProject().getRootDir().toPath();
62-
ListIterator<File> problemIter = problemFiles.listIterator();
103+
private DiffMessageFormatter(Builder builder) throws IOException {
104+
ListIterator<File> problemIter = builder.problemFiles.listIterator();
63105
while (problemIter.hasNext() && numLines < MAX_CHECK_MESSAGE_LINES) {
64106
File file = problemIter.next();
65-
addFile(rootDir.relativize(file.toPath()) + "\n" +
66-
DiffMessageFormatter.diff(task, formatter, file));
107+
addFile(builder.relativePath(file) + "\n" + DiffMessageFormatter.diff(builder, file));
67108
}
68109
if (problemIter.hasNext()) {
69-
int remainingFiles = problemFiles.size() - problemIter.nextIndex();
110+
int remainingFiles = builder.problemFiles.size() - problemIter.nextIndex();
70111
if (remainingFiles >= MAX_FILES_TO_LIST) {
71112
buffer.append("Violations also present in ").append(remainingFiles).append(" other files.\n");
72113
} else {
73114
buffer.append("Violations also present in:\n");
74115
while (problemIter.hasNext()) {
75-
addIntendedLine(NORMAL_INDENT, rootDir.relativize(problemIter.next().toPath()).toString());
116+
addIntendedLine(NORMAL_INDENT, builder.relativePath(problemIter.next()));
76117
}
77118
}
78119
}
@@ -126,19 +167,19 @@ private void addIntendedLine(String indent, String line) {
126167
* look like if formatted using the given formatter. Does not end with any newline
127168
* sequence (\n, \r, \r\n).
128169
*/
129-
private static String diff(SpotlessTask task, Formatter formatter, File file) throws IOException {
130-
String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding());
170+
private static String diff(Builder builder, File file) throws IOException {
171+
String raw = new String(Files.readAllBytes(file.toPath()), builder.formatter.getEncoding());
131172
String rawUnix = LineEnding.toUnix(raw);
132173
String formattedUnix;
133-
if (task.isPaddedCell()) {
134-
formattedUnix = PaddedCell.check(formatter, file, rawUnix).canonical();
174+
if (builder.isPaddedCell) {
175+
formattedUnix = PaddedCell.check(builder.formatter, file, rawUnix).canonical();
135176
} else {
136-
formattedUnix = formatter.compute(rawUnix, file);
177+
formattedUnix = builder.formatter.compute(rawUnix, file);
137178
}
138179

139180
if (rawUnix.equals(formattedUnix)) {
140181
// the formatting is fine, so it's a line-ending issue
141-
String formatted = formatter.computeLineEndings(formattedUnix, file);
182+
String formatted = builder.formatter.computeLineEndings(formattedUnix, file);
142183
return diffWhitespaceLineEndings(raw, formatted, false, true);
143184
} else {
144185
return diffWhitespaceLineEndings(rawUnix, formattedUnix, true, false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Integration code for plugins.
3+
*/
4+
@ParametersAreNonnullByDefault
5+
@ReturnValuesAreNonnullByDefault
6+
package com.diffplug.spotless.extra.integration;
7+
8+
import javax.annotation.ParametersAreNonnullByDefault;
9+
10+
import com.diffplug.spotless.annotations.ReturnValuesAreNonnullByDefault;

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;
1919

2020
import java.io.File;
21-
import java.io.IOException;
2221
import java.io.Serializable;
2322
import java.nio.charset.Charset;
2423
import java.nio.file.Files;
@@ -45,6 +44,7 @@
4544
import com.diffplug.spotless.LineEnding;
4645
import com.diffplug.spotless.PaddedCell;
4746
import com.diffplug.spotless.PaddedCellBulk;
47+
import com.diffplug.spotless.extra.integration.DiffMessageFormatter;
4848

4949
public class SpotlessTask extends DefaultTask {
5050
// set by SpotlessExtension, but possibly overridden by FormatExtension
@@ -164,7 +164,7 @@ public void performAction(IncrementalTaskInputs inputs) throws Exception {
164164
Formatter formatter = Formatter.builder()
165165
.lineEndingsPolicy(lineEndingsPolicy)
166166
.encoding(Charset.forName(encoding))
167-
.rootDir(getProject().getProjectDir().toPath())
167+
.rootDir(getProject().getRootDir().toPath())
168168
.steps(steps)
169169
.exceptionPolicy(exceptionPolicy)
170170
.build();
@@ -279,7 +279,12 @@ private void check(Formatter formatter, List<File> outOfDate) throws Exception {
279279
}
280280

281281
/** Returns an exception which indicates problem files nicely. */
282-
GradleException formatViolationsFor(Formatter formatter, List<File> problemFiles) throws IOException {
283-
return new GradleException(DiffMessageFormatter.messageFor(this, formatter, problemFiles));
282+
GradleException formatViolationsFor(Formatter formatter, List<File> problemFiles) {
283+
return new GradleException(DiffMessageFormatter.builder()
284+
.runToFix("Run 'gradlew spotlessApply' to fix these violations.")
285+
.isPaddedCell(paddedCell)
286+
.formatter(formatter)
287+
.problemFiles(problemFiles)
288+
.getMessage());
284289
}
285290
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.diffplug.spotless.FormatterStep;
3434
import com.diffplug.spotless.LineEnding;
3535
import com.diffplug.spotless.ResourceHarness;
36+
import com.diffplug.spotless.extra.integration.DiffMessageFormatter;
3637

3738
public class DiffMessageFormatterTest extends ResourceHarness {
3839
private SpotlessTask create(File... files) throws IOException {

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java

+14
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@
3737
import com.diffplug.spotless.ResourceHarness;
3838

3939
public class GradleIntegrationTest extends ResourceHarness {
40+
/**
41+
* Each test gets its own temp folder, and we create a gradle
42+
* build there and run it.
43+
*
44+
* Because those test folders don't have a .gitattributes file,
45+
* git (on windows) will default to \r\n. So now if you read a
46+
* test file from the spotless test resources, and compare it
47+
* to a build result, the line endings won't match.
48+
*
49+
* By sticking this .gitattributes file into the test directory,
50+
* we ensure that the default Spotless line endings policy of
51+
* GIT_ATTRIBUTES will use \n, so that tests match the test
52+
* resources on win and linux.
53+
*/
4054
@Before
4155
public void gitAttributes() throws IOException {
4256
write(".gitattributes", "* text eol=lf");

0 commit comments

Comments
 (0)