Skip to content

Commit

Permalink
Merge pull request #188 from lutovich/maven-plugin
Browse files Browse the repository at this point in the history
Initial version of Spotless Maven plugin
  • Loading branch information
nedtwigg authored Feb 12, 2018
2 parents d2bffd6 + 4162569 commit 7ea2d66
Show file tree
Hide file tree
Showing 66 changed files with 3,386 additions and 183 deletions.
7 changes: 6 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
language: java
jdk:
- oraclejdk8
script: "./.ci/ci.sh"
install: true
script:
- ./.ci/ci.sh
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
- rm -fr plugin-maven/build/localMavenRepository/com/diffplug/spotless/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.m2/
- plugin-maven/build/localMavenRepository/
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ output = [
'| --------------------------------------------- | ------------- | ------------ | --------|',
lib('generic.EndWithNewlineStep') +'{{yes}} | {{no}} | {{no}} |',
lib('generic.IndentStep') +'{{yes}} | {{no}} | {{no}} |',
lib('generic.LicenseHeaderStep') +'{{yes}} | {{no}} | {{no}} |',
lib('generic.LicenseHeaderStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('generic.ReplaceRegexStep') +'{{yes}} | {{no}} | {{no}} |',
lib('generic.ReplaceStep') +'{{yes}} | {{no}} | {{no}} |',
lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{no}} | {{no}} |',
extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{no}} | {{no}} |',
lib('java.ImportOrderStep') +'{{yes}} | {{no}} | {{no}} |',
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{no}} | {{no}} |',
extra('java.EclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('java.ImportOrderStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('java.RemoveUnusedImportsStep') +'{{yes}} | {{yes}} | {{no}} |',
extra('java.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('kotlin.KtLintStep') +'{{yes}} | {{no}} | {{no}} |',
lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} |',
lib('scala.ScalaFmtStep') +'{{yes}} | {{no}} | {{no}} |',
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
'| [(Your FormatterStep here)](https://github.com/nedtwigg/spotless/blob/markdown-preview-temp/CONTRIBUTING.md#how-to-add-a-new-formatterstep) | {{no}} | {{no}} | {{no}} |',
'| Fast up-to-date checking | {{yes}} | {{no}} | {{no}} |',
Expand All @@ -57,18 +57,18 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}
| --------------------------------------------- | ------------- | ------------ | --------|
| [`generic.EndWithNewlineStep`](lib/src/main/java/com/diffplug/spotless/generic/EndWithNewlineStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`generic.IndentStep`](lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :+1: | :white_large_square: |
| [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`java.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :white_large_square: |
| [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :+1: | :white_large_square: |
| [`java.RemoveUnusedImportsStep`](lib/src/main/java/com/diffplug/spotless/java/RemoveUnusedImportsStep.java) | :+1: | :+1: | :white_large_square: |
| [`java.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/java/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: |
| [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: |
| [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [(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: |
| Fast up-to-date checking | :+1: | :white_large_square: | :white_large_square: |
Expand All @@ -77,6 +77,7 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}

## Acknowledgements

* Thanks to [Konstantin Lutovich](https://github.com/lutovich) for [implementing the maven plugin](https://github.com/diffplug/spotless/pull/188).
* Thanks to [Baptiste Mesta](https://github.com/baptistemesta) for
+ 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.
+ making license headers date-aware [#180](https://github.com/diffplug/spotless/pull/180)
Expand Down
9 changes: 8 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ artifactIdTestLib=spotless-testlib

versionMaven=1.0.0-SNAPSHOT
stableMaven=unreleased
artifactIdMaven=spotless-plugin-maven
# naming convention '-maven-plugin' allows mvn 'spotless:check' instead of 'spotless-plugin-maven:check'
artifactIdMaven=spotless-maven-plugin

versionGradle=3.10.0-SNAPSHOT
stableGradle=3.9.0
Expand All @@ -31,3 +32,9 @@ VER_PEGDOWN_DOCLET=1.3
VER_DURIAN=1.2.0
VER_JUNIT=4.12
VER_ASSERTJ=3.5.2
VER_MOCKITO=2.13.0

# Used for Maven Plugin
VER_MAVEN_API=3.0
VER_ECLIPSE_AETHER=1.1.0
VER_MUSTACHE=0.9.5
7 changes: 7 additions & 0 deletions gradle/java-publish.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ model {
}
}
developers {
if (project.ext.artifactId == 'spotless-plugin-maven') {
developer {
id 'lutovich'
name 'Konstantin Lutovich'
email 'konstantin.lutovich@neotechnology.com'
}
}
developer {
id 'nedtwigg'
name 'Ned Twigg'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.gradle.spotless;
package com.diffplug.spotless.extra.integration;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;

import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.EditList;
Expand All @@ -31,48 +31,89 @@
import org.eclipse.jgit.diff.RawTextComparator;

import com.diffplug.common.base.CharMatcher;
import com.diffplug.common.base.Errors;
import com.diffplug.common.base.Preconditions;
import com.diffplug.common.base.Splitter;
import com.diffplug.spotless.Formatter;
import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.PaddedCell;

/** Formats the messages of failed spotlessCheck invocations with a nice diff message. */
final class DiffMessageFormatter {
private static final int MAX_CHECK_MESSAGE_LINES = 50;
static final int MAX_FILES_TO_LIST = 10;

static String messageFor(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException {
DiffMessageFormatter diffFormater = new DiffMessageFormatter(task, formatter, problemFiles);
return "The following files had format violations:\n"
+ diffFormater.buffer
+ "Run 'gradlew "
+ SpotlessPlugin.EXTENSION
+ SpotlessPlugin.APPLY
+ "' to fix these violations.";
public final class DiffMessageFormatter {
public static Builder builder() {
return new Builder();
}

public static class Builder {
private Builder() {}

private String runToFix;
private boolean isPaddedCell;
private Formatter formatter;
private List<File> problemFiles;

/** "Run 'gradlew spotlessApply' to fix these violations." */
public Builder runToFix(String runToFix) {
this.runToFix = Objects.requireNonNull(runToFix);
return this;
}

public Builder isPaddedCell(boolean isPaddedCell) {
this.isPaddedCell = isPaddedCell;
return this;
}

public Builder formatter(Formatter formatter) {
this.formatter = Objects.requireNonNull(formatter);
return this;
}

public Builder problemFiles(List<File> problemFiles) {
this.problemFiles = Objects.requireNonNull(problemFiles);
Preconditions.checkArgument(!problemFiles.isEmpty(), "cannot be empty");
return this;
}

/** Returns the error message. */
public String getMessage() {
try {
Objects.requireNonNull(runToFix, "runToFix");
Objects.requireNonNull(formatter, "formatter");
Objects.requireNonNull(problemFiles, "problemFiles");
DiffMessageFormatter diffFormater = new DiffMessageFormatter(this);
return "The following files had format violations:\n"
+ diffFormater.buffer
+ runToFix;
} catch (IOException e) {
throw Errors.asRuntime(e);
}
}

String relativePath(File file) {
return formatter.getRootDir().relativize(file.toPath()).toString();
}
}

private static final int MAX_CHECK_MESSAGE_LINES = 50;
public static final int MAX_FILES_TO_LIST = 10;

private final StringBuilder buffer = new StringBuilder(MAX_CHECK_MESSAGE_LINES * 64);
private int numLines = 0;

private DiffMessageFormatter(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException {
Preconditions.checkArgument(!problemFiles.isEmpty(), "Problem files must not be empty");

Path rootDir = task.getProject().getRootDir().toPath();
ListIterator<File> problemIter = problemFiles.listIterator();
private DiffMessageFormatter(Builder builder) throws IOException {
ListIterator<File> problemIter = builder.problemFiles.listIterator();
while (problemIter.hasNext() && numLines < MAX_CHECK_MESSAGE_LINES) {
File file = problemIter.next();
addFile(rootDir.relativize(file.toPath()) + "\n" +
DiffMessageFormatter.diff(task, formatter, file));
addFile(builder.relativePath(file) + "\n" + DiffMessageFormatter.diff(builder, file));
}
if (problemIter.hasNext()) {
int remainingFiles = problemFiles.size() - problemIter.nextIndex();
int remainingFiles = builder.problemFiles.size() - problemIter.nextIndex();
if (remainingFiles >= MAX_FILES_TO_LIST) {
buffer.append("Violations also present in ").append(remainingFiles).append(" other files.\n");
} else {
buffer.append("Violations also present in:\n");
while (problemIter.hasNext()) {
addIntendedLine(NORMAL_INDENT, rootDir.relativize(problemIter.next().toPath()).toString());
addIntendedLine(NORMAL_INDENT, builder.relativePath(problemIter.next()));
}
}
}
Expand Down Expand Up @@ -126,19 +167,19 @@ private void addIntendedLine(String indent, String line) {
* look like if formatted using the given formatter. Does not end with any newline
* sequence (\n, \r, \r\n).
*/
private static String diff(SpotlessTask task, Formatter formatter, File file) throws IOException {
String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding());
private static String diff(Builder builder, File file) throws IOException {
String raw = new String(Files.readAllBytes(file.toPath()), builder.formatter.getEncoding());
String rawUnix = LineEnding.toUnix(raw);
String formattedUnix;
if (task.isPaddedCell()) {
formattedUnix = PaddedCell.check(formatter, file, rawUnix).canonical();
if (builder.isPaddedCell) {
formattedUnix = PaddedCell.check(builder.formatter, file, rawUnix).canonical();
} else {
formattedUnix = formatter.compute(rawUnix, file);
formattedUnix = builder.formatter.compute(rawUnix, file);
}

if (rawUnix.equals(formattedUnix)) {
// the formatting is fine, so it's a line-ending issue
String formatted = formatter.computeLineEndings(formattedUnix, file);
String formatted = builder.formatter.computeLineEndings(formattedUnix, file);
return diffWhitespaceLineEndings(raw, formatted, false, true);
} else {
return diffWhitespaceLineEndings(rawUnix, formattedUnix, true, false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Integration code for plugins.
*/
@ParametersAreNonnullByDefault
@ReturnValuesAreNonnullByDefault
package com.diffplug.spotless.extra.integration;

import javax.annotation.ParametersAreNonnullByDefault;

import com.diffplug.spotless.annotations.ReturnValuesAreNonnullByDefault;
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Files;
Expand All @@ -45,6 +44,7 @@
import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.PaddedCell;
import com.diffplug.spotless.PaddedCellBulk;
import com.diffplug.spotless.extra.integration.DiffMessageFormatter;

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

/** Returns an exception which indicates problem files nicely. */
GradleException formatViolationsFor(Formatter formatter, List<File> problemFiles) throws IOException {
return new GradleException(DiffMessageFormatter.messageFor(this, formatter, problemFiles));
GradleException formatViolationsFor(Formatter formatter, List<File> problemFiles) {
return new GradleException(DiffMessageFormatter.builder()
.runToFix("Run 'gradlew spotlessApply' to fix these violations.")
.isPaddedCell(paddedCell)
.formatter(formatter)
.problemFiles(problemFiles)
.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.ResourceHarness;
import com.diffplug.spotless.extra.integration.DiffMessageFormatter;

public class DiffMessageFormatterTest extends ResourceHarness {
private SpotlessTask create(File... files) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
import com.diffplug.spotless.ResourceHarness;

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

0 comments on commit 7ea2d66

Please sign in to comment.