diff --git a/.travis.yml b/.travis.yml index a2a78181ca..5de9f5b2c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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/ diff --git a/README.md b/README.md index ebd4f5b1db..5b4a911ec1 100644 --- a/README.md +++ b/README.md @@ -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}} |', @@ -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: | @@ -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) diff --git a/gradle.properties b/gradle.properties index 8b1316075e..a75bdca5aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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.9.0-SNAPSHOT stableGradle=3.8.0 @@ -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 diff --git a/gradle/java-publish.gradle b/gradle/java-publish.gradle index bd98439492..6502b6e7fc 100644 --- a/gradle/java-publish.gradle +++ b/gradle/java-publish.gradle @@ -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' diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/DiffMessageFormatter.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java similarity index 69% rename from plugin-gradle/src/main/java/com/diffplug/gradle/spotless/DiffMessageFormatter.java rename to lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java index d70cf3ab4e..398ccca1ad 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/DiffMessageFormatter.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java @@ -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; @@ -31,6 +31,7 @@ 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; @@ -38,41 +39,81 @@ 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 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 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 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 problemFiles) throws IOException { - Preconditions.checkArgument(!problemFiles.isEmpty(), "Problem files must not be empty"); - - Path rootDir = task.getProject().getRootDir().toPath(); - ListIterator problemIter = problemFiles.listIterator(); + private DiffMessageFormatter(Builder builder) throws IOException { + ListIterator 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())); } } } @@ -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); diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/package-info.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/package-info.java new file mode 100644 index 0000000000..7d152c9079 --- /dev/null +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/package-info.java @@ -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; diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java index a8ac8ea725..801e45f17d 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java @@ -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; @@ -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 @@ -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(); @@ -279,7 +279,12 @@ private void check(Formatter formatter, List outOfDate) throws Exception { } /** Returns an exception which indicates problem files nicely. */ - GradleException formatViolationsFor(Formatter formatter, List problemFiles) throws IOException { - return new GradleException(DiffMessageFormatter.messageFor(this, formatter, problemFiles)); + GradleException formatViolationsFor(Formatter formatter, List problemFiles) { + return new GradleException(DiffMessageFormatter.builder() + .runToFix("Run 'gradlew spotlessApply' to fix these violations.") + .isPaddedCell(paddedCell) + .formatter(formatter) + .problemFiles(problemFiles) + .getMessage()); } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java index 27acc3feb1..1c47c0621c 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/DiffMessageFormatterTest.java @@ -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 { diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java index ec504dcd4b..aad54bc045 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/GradleIntegrationTest.java @@ -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"); diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index dbea2e57bf..3255bd7889 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -1,116 +1,5 @@ -# spotless-plugin-gradle releases +# spotless-plugin-maven releases -### Version 3.0.0-SNAPSHOT - TBD ([javadoc](https://diffplug.github.io/spotless/javadoc/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/spotless-plugin-maven/)) +### Version 1.0.0-SNAPSHOT - TBD ([javadoc](https://diffplug.github.io/spotless/javadoc/spotless-plugin-maven/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/spotless-plugin-maven/)) -* BREAKING CHANGE: `customReplace` and `customReplaceRegex` renamed to just `replace` and `replaceRegex`. -* BREAKING CHANGE: Plugin portal ID is still `com.diffplug.gradle.spotless`, but maven coordinate has changed to `com.diffplug.spotless:spotless-plugin-gradle`. -* HUGE SPEEDUP: Now supports incremental build / up-to-date-checking. - + If you are using `custom` or `customLazy`, you might want to take a look at [this javadoc](https://diffplug.github.io/spotless/javadoc/snapshot/spotless-gradle-plugin/snapshot/com/diffplug/gradle/spotless/FormatExtension.html#bumpThisNumberIfACustomStepChanges-int-). - -### Version 2.4.1 - January 2nd 2017 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.4.1/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.4.1/view)) - -* Java files under the `src/main/groovy` folder are now formatted by default. ([Issue #59](https://github.com/diffplug/spotless/issues/59), [PR #60](https://github.com/diffplug/spotless/pull/60), thanks @ajoberstar). - -### Version 2.4.0 - November 1st 2016 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.4.0/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.4.0/view)) - -* If a formatter step throws an `Error` or any of its subclasses, such as the `AssertionError`s thrown by JUnit, AssertJ, etc. that error will kill the build ([#46](https://github.com/diffplug/spotless/issues/46)) - + This allows custom rules like this: - -```gradle -custom 'no swearing', { - if (it.toLowerCase().contains('fubar')) { - throw new AssertionError('No swearing!'); - } -} -``` - -### Version 2.3.0 - October 27th 2016 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.3.0/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.3.0/view)) - -* When `spotlessCheck` fails, the error message now contains a short diff of what is neccessary to fix the issue ([#10](https://github.com/diffplug/spotless/issues/10), thanks to Jonathan Bluett-Duncan). -* Added a [padded-cell mode](https://github.com/diffplug/spotless/blob/master/PADDEDCELL.md) which allows spotless to band-aid over misbehaving rules, and generate error reports for these rules (See [#37](https://github.com/diffplug/spotless/issues/37) for an example). -* Character encoding is now configurable (spotless-global or format-by-format). -* Line endings were previously only spotless-global, they now also support format-by-format. -* Upgraded eclipse formatter from 4.6.0 to 4.6.1 - -### Version 2.2.0 - October 7th 2016 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.2.0/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.2.0/view)) - -* Added support for [google-java-format](https://github.com/google/google-java-format). - -``` -spotless { - java { - googleJavaFormat() // googleJavaFormat('1.1') to specify a specific version - } -} -``` - -### Version 2.1.0 - October 7th 2016 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.1.0/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.1.0/view)) - -* Added the method `FormatExtension::customLazyGroovy` which fixes the Groovy closure problem. - -### Version 2.0.0 - August 16th 2016 ([javadoc](https://diffplug.github.io/spotless/javadoc/2.0.0/), [jcenter](https://bintray.com/diffplug/opensource/spotless/2.0.0/view)) - -* `spotlessApply` now writes out a file only if it needs to be changed (big performance improvement). -* Java import sorting now removes duplicate imports. -* Eclipse formatter now warns if the formatter xml contains multiple profiles. -* Updated eclipse formatter to Eclipse Neon (4.6). -* BREAKING CHANGE: Eclipse formatter now formats javadoc comments. - + You might want to look at the following settings in your `spotless.eclipseformat.xml`: - -``` -org.eclipse.jdt.core.formatter.join_lines_in_comments=true/false -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true/false -org.eclipse.jdt.core.formatter.comment.format_line_comments=true/false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true/false -``` - -The most important breaking change of 2.0 is the new default line ending mode, `GIT_ATTRIBUTES`. This line ending mode copies git's behavior exactly. This change should require no intervention from users, and should be significantly easier to adopt for users who are already using `.gitattributes` or the `core.eol` property. - -If you aren't using git, you can still use `.gitattributes` files for fine-grained control of line endings. If no git information is found, it behaves the same as PLATFORM_NATIVE (the old default). - -Below is the algorithm used by git and spotless to determine the proper line ending for a file. As soon as a step succeeds in finding a line ending, the other steps will not take place. - -1. If the code is a git repository, look in the `$GIT_DIR/info/attributes` file for the `eol` attribute. -2. Look at the `.gitattributes` in the file's directory, going up the directory tree. -3. Look at the global `.gitattributes` file, if any. -4. Look at the `core.eol` property in the git config (looking first at repo-specific, then user-specific, then system-specific). -5. Use the PLATFORM_NATIVE line ending. - -### Version 1.3.3 - March 10th 2016 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.3.3/view)) - -* Upgraded Eclipse formatter to 4.5.2, which fixes [37 bugs](https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced&resolution=FIXED&short_desc=%5Bformatter%5D&short_desc_type=allwordssubstr&target_milestone=4.5.1&target_milestone=4.5.2) compared to the previous 4.5.0. -* If you have been using `custom 'Lambda fix', { it.replace('} )', '})').replace('} ,', '},') }`, you don't need it anymore. - -### Version 1.3.2 - December 17th 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.3.2/view)) - -* Spotless no longer clobbers package-info.java, fixes [#1](https://github.com/diffplug/spotless/issues/1). -* Added some infrastructure which allows `FormatterStep`s to peek at the filename if they really need to. - -### Version 1.3.1 - September 22nd 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.3.1/view)) - -* Bumped the FreshMark dependency to 1.3.0, because it offers improved error reporting. - -### Version 1.3.0 - September 22nd 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.3.0/view)) - -* Added native support for FreshMark. - -### Version 1.2.0 - August 25th 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.2.0/view)) - -* Updated from Eclipse 4.5 M6 to the official Eclipse 4.5 release, which fixes several bugs in the formatter. -* Fixed a bug in the import sorter which made it impossible to deal with "all unmatched type imports". -* Formatting is now relative to the project directory rather than the root directory. -* Improved the logging levels. - -### Version 1.1 - May 14th 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.1/view)) - -* No functional changes, probably not worth the time for an upgrade. -* First version which is available on plugins.gradle.org as well as jcenter. -* Removed some code that was copy-pasted from Durian, and added a Durian dependency. - -### Version 1.0 - April 29th 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/1.0/view)) - -* Initial release. - -### Version 0.1 - April 28th 2015 ([jcenter](https://bintray.com/diffplug/opensource/spotless/0.1/view)) - -* First release, to test out that we can release to jcenter and whatnot. +* Maven plugin written by [Konstantin Lutovich](https://github.com/lutovich). diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 0696c782c3..6da86878cb 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -1,3 +1,192 @@ # Spotless: Keep your code spotless with Gradle -We're looking for a contributor to build the maven plugin. See [CONTRIBUTING.md](../CONTRIBUTING.md) for more info - you'll have lots of help on hand! + +[![Maven central](https://img.shields.io/badge/mavencentral-com.diffplug.spotless%3Aspotless--maven--plugin-blue.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22) +[![Javadoc](https://img.shields.io/badge/javadoc-unreleased-blue.svg)](https://diffplug.github.io/spotless/javadoc/spotless-plugin-maven/unreleased/) + +[![Changelog](https://img.shields.io/badge/changelog-unreleased-brightgreen.svg)](CHANGES.md) +[![Travis CI](https://travis-ci.org/diffplug/spotless.svg?branch=master)](https://travis-ci.org/diffplug/spotless) +[![Live chat](https://img.shields.io/badge/gitter-chat-brightgreen.svg)](https://gitter.im/diffplug/spotless) +[![License Apache](https://img.shields.io/badge/license-apache-brightgreen.svg)](https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)) + + + + +Spotless is a general-purpose formatting plugin. It is completely à la carte, but also includes powerful "batteries-included" if you opt-in. + +To people who use your build, it looks like this: + +``` +cmd> mvn spotless:check +... +[ERROR] ... The following files had format violations: +[ERROR] src\main\java\com\diffplug\gradle\spotless\FormatExtension.java +[ERROR] @@ -109,7 +109,7 @@ +[ERROR] ... +[ERROR] -\t\t····if·(targets.length·==·0)·{ +[ERROR] +\t\tif·(targets.length·==·0)·{ +[ERROR] ... +[ERROR] Run 'mvn spotless:apply' to fix these violations. +... + +cmd> mvn spotless:apply +... +[INFO] BUILD SUCCESS +... + +cmd> mvn spotless:check +... +[INFO] BUILD SUCCESS +... +``` + +To use it in your pom, just [add the Spotless dependency](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22), and configure it like so: + +```xml + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + ${basedir}/eclipse-fmt.xml + 4.7.1 + + + + +``` + +Spotless supports the following powerful formatters: + +* Eclipse's java code formatter (including style and import ordering) +* Google's [google-java-format](https://github.com/google/google-java-format) +* User-defined license enforcement, regex replacement, etc. + +Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info. + +Spotless requires Maven to be running on JRE 8+. + + + +## Applying to Java source + +By default, all files matching `src/main/java/**/*.java` and `src/test/java/**/*.java` Ant style pattern will be formatted. Each element under `` 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 doesn't make sense to use both eclipse and google-java-format. + +```xml + + + + + /* Licensed under Apache-2.0 */ + ${basedir}/license-header + + + ${basedir}/eclipse-fmt.xml + + 4.7.1 + + + + 1.5 + + + + + + + java,javax,org,com,com.diffplug, + ${basedir}/importOrder + + + +``` + + + +## Line endings and encodings (invisible stuff) + +Spotless uses UTF-8 by default, but you can use [any encoding which Java supports](https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html). You can set it globally, and you can also set it per-format. + +```xml + + + Cp1252 + + + US-ASCII + +``` + +Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `PLATFORM_NATIVE`, and `GIT_ATTRIBUTES`. The default value is `GIT_ATTRIBUTES`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time. + +You can easily set the line endings of different files using [a `.gitattributes` file](https://help.github.com/articles/dealing-with-line-endings/). Here's an example `.gitattributes` which sets all files to unix newlines: `* text eol=lf`. + + + + + +## File incudes and excludes + +Spotless uses [Ant style patterns](https://ant.apache.org/manual/dirtasks.html) to define included and excluded files. +By default, most common compile and test source roots for the supported languages are included. They are `scr/main/java/**/*.java`, `scr/test/java/**/*.java` for Java and `scr/main/scala/**/*.scala`, `scr/main/scala/**/*.sc`, `scr/test/scala/**/*.scala`, `scr/test/scala/**/*.sc` for Scala. +Includes can be completely overriden using `...` configuration section. + +Default excludes only contain output directory (usually `target/`) and various temporary and VCS-related files. Additional excludes can also be configured. + +Includes and excludes can be configured the same way for all supported languages. Excample for Java: + +```xml + + + + src/**/java/**/*.java + + + other/java/**/*.java + + + + + src/test/java/**/*Example.java + + +``` + +## Disabling warnings and error messages + +By default, `spotless:check` is bound to the `verify` phase. You might want to disable this behavior. We [recommend against this](https://github.com/diffplug/spotless/issues/79#issuecomment-290844602), but it's easy to do if you'd like: + +- set `-Dspotless.check.skip=true` at the command line +- set `spotless.check.skip` to `true` in the `` section of the `pom.xml` + + + +## How do I preview what `mvn spotless:apply` will do? + +- Save your working tree with `git add -A`, then `git commit -m "Checkpoint before spotless."` +- Run `mvn spotless:apply` +- View the changes with `git diff` +- If you don't like what spotless did, `git reset --hard` +- If you'd like to remove the "checkpoint" commit, `git reset --soft head~1` will make the checkpoint commit "disappear" from history, but keeps the changes in your working directory. + + + +## Example configurations (from real-world projects) + +TODO + + diff --git a/plugin-maven/build.gradle b/plugin-maven/build.gradle index 0c63129141..3607cf005d 100644 --- a/plugin-maven/build.gradle +++ b/plugin-maven/build.gradle @@ -1,16 +1,181 @@ +buildscript { + repositories { mavenCentral() } + dependencies { classpath "com.github.spullara.mustache.java:compiler:${VER_MUSTACHE}" } +} +plugins { id 'cz.malohlava' version '1.0.3' // https://github.com/mmalohlava/gradle-visteg +} + +// to generate taskGraph.pdf +// - set enabled (below) to true +// - run: ./gradlew :plugin-maven:test +// - run: rm plugin-maven/output.pdf +// - run: dot -Tpdf plugin-maven/build/reports/visteg.dot > plugin-maven/taskGraph.pdf +visteg { + enabled = false + nodeShape = 'box' + startNodeShape = 'box' + endNodeShape = 'box' + colorscheme = 'pastel24' // http://www.graphviz.org/doc/info/colors.html +} + +import com.github.mustachejava.DefaultMustacheFactory + +import java.nio.file.Files +import java.nio.file.Paths + +import static java.nio.charset.StandardCharsets.UTF_8 +import static java.nio.file.StandardOpenOption.CREATE_NEW +import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING + ext.artifactId = project.artifactIdMaven ext.version = project.versionMaven -apply from: rootProject.file('gradle/java-setup.gradle') -apply from: rootProject.file('gradle/java-publish.gradle') +apply from: rootProject.file("gradle/java-setup.gradle") +apply from: rootProject.file("gradle/java-publish.gradle") + +final PROJECT_DIR = project.projectDir.toString() +final BUILD_DIR = project.buildDir.toString() +final MAVEN_PROJECT_DIR = "${BUILD_DIR}/mavenProject" +final LOCAL_MAVEN_REPO_DIR = "${BUILD_DIR}/localMavenRepository" + +def mvnw(String args) { + boolean isWin = System.getProperty('os.name').toLowerCase().contains('win') + if (isWin) { + return [ + 'cmd', + '/c', + 'mvnw.cmd -e ' + args + ] + } else { + return [ + '/bin/sh', + '-c', + './mvnw -e ' + args + ] + } +} dependencies { - compile project(':lib') - compile project(':lib-extra') - compile "org.apache.maven:maven-plugin-api:3.0" - compileOnly "org.apache.maven.plugin-tools:maven-plugin-annotations:3.4" + compile project(":lib") + compile project(":lib-extra") + compileOnly "org.apache.maven:maven-plugin-api:${VER_MAVEN_API}" + compileOnly "org.apache.maven.plugin-tools:maven-plugin-annotations:${VER_MAVEN_API}" + compileOnly "org.eclipse.aether:aether-api:${VER_ECLIPSE_AETHER}" + compileOnly "org.eclipse.aether:aether-util:${VER_ECLIPSE_AETHER}" - testCompile project(':testlib') + testCompile project(":testlib") testCompile "junit:junit:${VER_JUNIT}" testCompile "org.assertj:assertj-core:${VER_ASSERTJ}" + testCompile "org.mockito:mockito-core:${VER_MOCKITO}" testCompile "com.diffplug.durian:durian-testlib:${VER_DURIAN}" + testCompile "com.github.spullara.mustache.java:compiler:${VER_MUSTACHE}" + testCompile "org.apache.maven:maven-plugin-api:${VER_MAVEN_API}" + testCompile "org.eclipse.aether:aether-api:${VER_ECLIPSE_AETHER}" +} + +task cleanMavenProjectDir(type: Delete) { delete MAVEN_PROJECT_DIR } + +task copySourceFiles(type: Sync) { + from "src/main/java" + into "${MAVEN_PROJECT_DIR}/src/main/java" +} + +task copyMvnw(type: Copy) { + from 'src/test/resources' + include 'mvnw' + include 'mvnw.cmd' + include '.mvn/**' + into MAVEN_PROJECT_DIR +} + +task installLocalDependencies +def libs = [ + 'lib', + 'lib-extra', + 'testlib' +] +libs.each { + def groupId = 'com.diffplug.spotless' + def artifactId = "spotless-${it}" + def version = project.versionLib + def jarTask = tasks.getByPath(":${it}:jar") + def file = jarTask.archivePath + + def installDependency = task "install_${artifactId}"(type: Exec) { + workingDir MAVEN_PROJECT_DIR + + inputs.file(file) + outputs.dir(project.file("${LOCAL_MAVEN_REPO_DIR}/${groupId.replace('.', '/')}/${artifactId}/${version}")) + commandLine mvnw("org.apache.maven.plugins:maven-install-plugin:2.3.1:install-file " + + "-Dfile=${file} " + + "-DgroupId=${groupId} " + + "-DartifactId=${artifactId} " + + "-Dversion=${version} " + + "-Dpackaging=jar " + + "-DlocalRepositoryPath=${LOCAL_MAVEN_REPO_DIR}") + } + installDependency.dependsOn(jarTask) + + installLocalDependencies.dependsOn installDependency +} + +task createPomXml(dependsOn: installLocalDependencies) { + doLast { + def additionalDependencies = project.configurations.compile.resolvedConfiguration.resolvedArtifacts.findAll { + return !libs.contains(it.moduleVersion.id.name) + }.collect { + return " \n" + + " ${it.moduleVersion.id.group}\n" + + " ${it.moduleVersion.id.name}\n" + + " ${it.moduleVersion.id.version}\n" + + " \n" + }.join() + + def versions = [ + spotlessMavenPluginVersion: project.versionMaven, + mavenApiVersion : VER_MAVEN_API, + eclipseAetherVersion : VER_ECLIPSE_AETHER, + spotlessLibVersion : project.versionLib, + additionalDependencies : additionalDependencies + ] + + def pomXmlTemplate = Paths.get(PROJECT_DIR, "src/test/resources/pom-build.xml.mustache") + def newPomXml = Paths.get(MAVEN_PROJECT_DIR, "pom.xml") + + Files.newBufferedReader(pomXmlTemplate).withCloseable { reader -> + Files.newBufferedWriter(newPomXml, UTF_8, CREATE_NEW, TRUNCATE_EXISTING).withCloseable { writer -> + def mustache = new DefaultMustacheFactory().compile(reader, "pom") + mustache.execute(writer, versions) + } + } + } +} + +task runMavenBuild(type: Exec, dependsOn: [ + cleanMavenProjectDir, + copySourceFiles, + copyMvnw, + createPomXml +]) { + workingDir MAVEN_PROJECT_DIR + // -B batch mode to make dependency download logging less verbose + commandLine mvnw("clean install -B -Dmaven.repo.local=${LOCAL_MAVEN_REPO_DIR}") +} + +jar.deleteAllActions() +jar.dependsOn(runMavenBuild) +jar.doLast { + Files.copy( + file("${MAVEN_PROJECT_DIR}/target/spotless-maven-plugin-${project.versionMaven}.jar").toPath(), + jar.archivePath.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING + ) +} + +// usually test only depends on testClasses, which doesn't run the maven build that we need +test.dependsOn(jar) + +test { + testLogging { exceptionFormat = 'full' } + // pass location of the local maven repository and plugin version to junit tests + systemProperty "localMavenRepositoryDir", "${LOCAL_MAVEN_REPO_DIR}" + systemProperty "spotlessMavenPluginVersion", project.versionMaven } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java new file mode 100644 index 0000000000..04fb5001cf --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -0,0 +1,140 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.stream.Collectors.toList; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.plexus.util.FileUtils; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.RemoteRepository; + +import com.diffplug.spotless.Formatter; +import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.maven.generic.LicenseHeader; +import com.diffplug.spotless.maven.java.Java; +import com.diffplug.spotless.maven.scala.Scala; + +public abstract class AbstractSpotlessMojo extends AbstractMojo { + + private static final String DEFAULT_ENCODING = "UTF-8"; + private static final String DEFAULT_LINE_ENDINGS = "GIT_ATTRIBUTES"; + + @Component + private RepositorySystem repositorySystem; + + @Parameter(defaultValue = "${repositorySystemSession}", required = true, readonly = true) + private RepositorySystemSession repositorySystemSession; + + @Parameter(defaultValue = "${project.remotePluginRepositories}", required = true, readonly = true) + private List repositories; + + @Parameter(defaultValue = "${project.basedir}", required = true, readonly = true) + private File baseDir; + + @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true) + private File targetDir; + + @Parameter(defaultValue = DEFAULT_ENCODING) + private String encoding; + + @Parameter(defaultValue = DEFAULT_LINE_ENDINGS) + private LineEnding lineEndings; + + @Parameter + private LicenseHeader licenseHeader; + + @Parameter + private Java java; + + @Parameter + private Scala scala; + + protected abstract void process(List files, Formatter formatter) throws MojoExecutionException; + + @Override + public final void execute() throws MojoExecutionException, MojoFailureException { + List formatterFactories = getFormatterFactories(); + + for (FormatterFactory formatterFactory : formatterFactories) { + execute(formatterFactory); + } + } + + private void execute(FormatterFactory formatterFactory) throws MojoExecutionException { + List files = collectFiles(formatterFactory); + Formatter formatter = formatterFactory.newFormatter(files, getFormatterConfig()); + process(files, formatter); + } + + @SuppressWarnings("unchecked") + private List collectFiles(FormatterFactory formatterFactory) throws MojoExecutionException { + Set configuredIncludes = formatterFactory.includes(); + Set configuredExcludes = formatterFactory.excludes(); + + Set includes = configuredIncludes.isEmpty() ? formatterFactory.defaultIncludes() : configuredIncludes; + + Set excludes = new HashSet<>(FileUtils.getDefaultExcludesAsList()); + excludes.add(withTrailingSeparator(targetDir.toString())); + excludes.addAll(configuredExcludes); + + String includesString = String.join(",", includes); + String excludesString = String.join(",", excludes); + + try { + return FileUtils.getFiles(baseDir, includesString, excludesString); + } catch (IOException e) { + throw new MojoExecutionException("Unable to scan file tree rooted at " + baseDir, e); + } + } + + private static String withTrailingSeparator(String path) { + return path.endsWith(File.separator) ? path : path + File.separator; + } + + private FormatterConfig getFormatterConfig() { + ArtifactResolver resolver = new ArtifactResolver(repositorySystem, repositorySystemSession, repositories, getLog()); + Provisioner provisioner = MavenProvisioner.create(resolver); + List formatterStepFactories = getFormatterStepFactories(); + return new FormatterConfig(baseDir, encoding, lineEndings, provisioner, formatterStepFactories); + } + + private List getFormatterFactories() { + return Stream.of(java, scala) + .filter(Objects::nonNull) + .collect(toList()); + } + + private List getFormatterStepFactories() { + return Stream.of(licenseHeader) + .filter(Objects::nonNull) + .collect(toList()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/gradle/spotless/MavenProvisioner.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolutionException.java similarity index 69% rename from plugin-maven/src/main/java/com/diffplug/gradle/spotless/MavenProvisioner.java rename to plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolutionException.java index ab70dc8777..c15ee04274 100644 --- a/plugin-maven/src/main/java/com/diffplug/gradle/spotless/MavenProvisioner.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolutionException.java @@ -13,15 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.gradle.spotless; +package com.diffplug.spotless.maven; -import com.diffplug.spotless.Provisioner; +@SuppressWarnings("serial") +public class ArtifactResolutionException extends RuntimeException { -/** Maven integration for Provisioner. */ -public class MavenProvisioner { - private MavenProvisioner() {} - - public static Provisioner create() { - throw new UnsupportedOperationException(); + public ArtifactResolutionException(String message, Throwable cause) { + super(message, cause); } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolver.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolver.java new file mode 100644 index 0000000000..35508905e2 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/ArtifactResolver.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.stream.Collectors.toSet; + +import java.io.File; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import org.apache.maven.plugin.logging.Log; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyFilter; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; + +public class ArtifactResolver { + + private static final DependencyFilter ACCEPT_ALL_FILTER = (node, parents) -> true; + + private final RepositorySystem repositorySystem; + private final RepositorySystemSession session; + private final List repositories; + private final Log log; + + public ArtifactResolver(RepositorySystem repositorySystem, RepositorySystemSession session, + List repositories, Log log) { + this.repositorySystem = Objects.requireNonNull(repositorySystem); + this.session = Objects.requireNonNull(session); + this.repositories = Objects.requireNonNull(repositories); + this.log = Objects.requireNonNull(log); + } + + public Set resolve(String mavenCoordinate) { + Artifact artifact = new DefaultArtifact(mavenCoordinate); + Dependency dependency = new Dependency(artifact, null); + CollectRequest collectRequest = new CollectRequest(dependency, repositories); + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, ACCEPT_ALL_FILTER); + + DependencyResult dependencyResult = resolveDependencies(dependencyRequest); + + return dependencyResult.getArtifactResults() + .stream() + .peek(this::logResolved) + .map(ArtifactResult::getArtifact) + .map(Artifact::getFile) + .collect(toSet()); + } + + private DependencyResult resolveDependencies(DependencyRequest dependencyRequest) { + try { + return repositorySystem.resolveDependencies(session, dependencyRequest); + } catch (DependencyResolutionException e) { + throw new ArtifactResolutionException("Unable to resolve dependencies", e); + } + } + + private void logResolved(ArtifactResult artifactResult) { + if (log.isDebugEnabled()) { + log.debug("Resolved artifact: " + artifactResult); + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java new file mode 100644 index 0000000000..5656ddb8f9 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.Collections.unmodifiableList; + +import java.io.File; +import java.util.List; + +import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.Provisioner; + +public class FormatterConfig { + + private final File baseDir; + private final String encoding; + private final LineEnding lineEndings; + private final Provisioner provisioner; + private final List globalStepFactories; + + public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Provisioner provisioner, + List globalStepFactories) { + this.baseDir = baseDir; + this.encoding = encoding; + this.lineEndings = lineEndings; + this.provisioner = provisioner; + this.globalStepFactories = globalStepFactories; + } + + public File getBaseDir() { + return baseDir; + } + + public String getEncoding() { + return encoding; + } + + public LineEnding getLineEndings() { + return lineEndings; + } + + public Provisioner getProvisioner() { + return provisioner; + } + + public List getGlobalStepFactories() { + return unmodifiableList(globalStepFactories); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java new file mode 100644 index 0000000000..47b692a8c2 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java @@ -0,0 +1,122 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.Collections.emptySet; +import static java.util.stream.Collectors.toList; + +import java.io.File; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.common.collect.Sets; +import com.diffplug.spotless.FormatExceptionPolicyStrict; +import com.diffplug.spotless.Formatter; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.LineEnding; +import com.diffplug.spotless.maven.generic.LicenseHeader; + +public abstract class FormatterFactory { + @Parameter + private String encoding; + + @Parameter + private LineEnding lineEndings; + + @Parameter + private String[] includes; + + @Parameter + private String[] excludes; + + private final List stepFactories = new ArrayList<>(); + + public abstract Set defaultIncludes(); + + public abstract String licenseHeaderDelimiter(); + + public final Set includes() { + return includes == null ? emptySet() : Sets.newHashSet(includes); + } + + public final Set excludes() { + return excludes == null ? emptySet() : Sets.newHashSet(excludes); + } + + public final Formatter newFormatter(List filesToFormat, FormatterConfig config) { + Charset formatterEncoding = encoding(config); + LineEnding formatterLineEndings = lineEndings(config); + LineEnding.Policy formatterLineEndingPolicy = formatterLineEndings.createPolicy(config.getBaseDir(), () -> filesToFormat); + + FormatterStepConfig stepConfig = stepConfig(formatterEncoding, config); + List factories = gatherStepFactories(config.getGlobalStepFactories(), stepFactories); + + List formatterSteps = factories.stream() + .filter(Objects::nonNull) // all unrecognized steps from XML config appear as nulls in the list + .map(factory -> factory.newFormatterStep(stepConfig)) + .collect(toList()); + + return Formatter.builder() + .encoding(formatterEncoding) + .lineEndingsPolicy(formatterLineEndingPolicy) + .exceptionPolicy(new FormatExceptionPolicyStrict()) + .steps(formatterSteps) + .rootDir(config.getBaseDir().toPath()) + .build(); + } + + public final void addLicenseHeader(LicenseHeader licenseHeader) { + addStepFactory(licenseHeader); + } + + protected void addStepFactory(FormatterStepFactory stepFactory) { + Objects.requireNonNull(stepFactory); + stepFactories.add(stepFactory); + } + + private Charset encoding(FormatterConfig config) { + return Charset.forName(encoding == null ? config.getEncoding() : encoding); + } + + private LineEnding lineEndings(FormatterConfig config) { + return lineEndings == null ? config.getLineEndings() : lineEndings; + } + + private FormatterStepConfig stepConfig(Charset encoding, FormatterConfig config) { + return new FormatterStepConfig(encoding, licenseHeaderDelimiter(), config.getProvisioner()); + } + + private static List gatherStepFactories(List allGlobal, List allConfigured) { + List result = new ArrayList<>(); + for (FormatterStepFactory global : allGlobal) { + if (!formatterStepOverriden(global, allConfigured)) { + result.add(global); + } + } + result.addAll(allConfigured); + return result; + } + + private static boolean formatterStepOverriden(FormatterStepFactory global, List allConfigured) { + return allConfigured.stream() + .anyMatch(configured -> configured.getClass() == global.getClass()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java new file mode 100644 index 0000000000..0a2fbde018 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016 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.spotless.maven; + +import java.nio.charset.Charset; + +import com.diffplug.spotless.Provisioner; + +public class FormatterStepConfig { + + private final Charset encoding; + private final String licenseHeaderDelimiter; + private final Provisioner provisioner; + + public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Provisioner provisioner) { + this.encoding = encoding; + this.licenseHeaderDelimiter = licenseHeaderDelimiter; + this.provisioner = provisioner; + } + + public Charset getEncoding() { + return encoding; + } + + public String getLicenseHeaderDelimiter() { + return licenseHeaderDelimiter; + } + + public Provisioner getProvisioner() { + return provisioner; + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/gradle/spotless/MavenProvisionerTest.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepFactory.java similarity index 76% rename from plugin-maven/src/test/java/com/diffplug/gradle/spotless/MavenProvisionerTest.java rename to plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepFactory.java index 4ecda7c061..119aa56961 100644 --- a/plugin-maven/src/test/java/com/diffplug/gradle/spotless/MavenProvisionerTest.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepFactory.java @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.gradle.spotless; +package com.diffplug.spotless.maven; -import org.junit.Test; +import com.diffplug.spotless.FormatterStep; -public class MavenProvisionerTest { - @Test - public void test() { +public interface FormatterStepFactory { - } + FormatterStep newFormatterStep(FormatterStepConfig config); } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/MavenProvisioner.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/MavenProvisioner.java new file mode 100644 index 0000000000..902aa1e1e6 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/MavenProvisioner.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.stream.Collectors.toSet; + +import java.util.Objects; + +import com.diffplug.spotless.Provisioner; + +/** Maven integration for Provisioner. */ +public class MavenProvisioner { + private MavenProvisioner() {} + + public static Provisioner create(ArtifactResolver artifactResolver) { + Objects.requireNonNull(artifactResolver); + + return mavenCoords -> mavenCoords.stream() + .flatMap(coord -> artifactResolver.resolve(coord).stream()) + .collect(toSet()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java new file mode 100644 index 0000000000..e108ea7d90 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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.spotless.maven; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Mojo; + +import com.diffplug.spotless.Formatter; + +/** + * Performs formatting of all source files according to configured formatters. + */ +@Mojo(name = "apply", threadSafe = true) +public class SpotlessApplyMojo extends AbstractSpotlessMojo { + + @Override + protected void process(List files, Formatter formatter) throws MojoExecutionException { + for (File file : files) { + try { + formatter.applyTo(file); + } catch (IOException e) { + throw new MojoExecutionException("Unable to format file " + file, e); + } + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java new file mode 100644 index 0000000000..2511a09114 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016 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.spotless.maven; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.Formatter; +import com.diffplug.spotless.extra.integration.DiffMessageFormatter; + +/** + * Performs code formatting analysis and prints all violations to the console. + * Fails the build if violations are discovered. + */ +@Mojo(name = "check", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true) +public class SpotlessCheckMojo extends AbstractSpotlessMojo { + + @Parameter(property = "spotless.check.skip", defaultValue = "false") + private boolean skip; + + @Override + protected void process(List files, Formatter formatter) throws MojoExecutionException { + if (skip) { + getLog().info("Spotless check skipped"); + return; + } + + List problemFiles = new ArrayList<>(); + for (File file : files) { + try { + if (!formatter.isClean(file)) { + problemFiles.add(file); + } + } catch (IOException e) { + throw new MojoExecutionException("Unable to format file " + file, e); + } + } + + if (!problemFiles.isEmpty()) { + throw new MojoExecutionException(DiffMessageFormatter.builder() + .runToFix("Run 'mvn spotless:apply' to fix these violations.") + .isPaddedCell(false) + .formatter(formatter) + .problemFiles(problemFiles) + .getMessage()); + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java new file mode 100644 index 0000000000..aa9317616e --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 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.spotless.maven.generic; + +import java.io.File; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.generic.LicenseHeaderStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class LicenseHeader implements FormatterStepFactory { + @Parameter + private File file; + + @Parameter + private String content; + + @Parameter + private String delimiter; + + @Override + public final FormatterStep newFormatterStep(FormatterStepConfig config) { + String delimiterString = delimiter != null ? delimiter : config.getLicenseHeaderDelimiter(); + if (delimiterString == null) { + throw new IllegalArgumentException("You need to specify 'delimiter'."); + } + + if (file != null ^ content != null) { + if (file != null) { + return LicenseHeaderStep.createFromFile(file, config.getEncoding(), delimiterString); + } else { + return LicenseHeaderStep.createFromHeader(content, delimiterString); + } + } else { + throw new IllegalArgumentException("Must specify exactly one of 'file' or 'content'."); + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java new file mode 100644 index 0000000000..7a8dbeb331 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static com.diffplug.spotless.extra.java.EclipseFormatterStep.defaultVersion; +import static java.util.Collections.singleton; + +import java.io.File; +import java.util.Set; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.extra.java.EclipseFormatterStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class Eclipse implements FormatterStepFactory { + + @Parameter(required = true) + private File file; + + @Parameter + private String version; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + String formatterVersion = version == null ? defaultVersion() : version; + Set settingsFiles = singleton(file); + return EclipseFormatterStep.create(formatterVersion, settingsFiles, config.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java new file mode 100644 index 0000000000..3247b22b49 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.GoogleJavaFormatStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class GoogleJavaFormat implements FormatterStepFactory { + @Parameter + private String version; + + @Parameter + private String style; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + String version = this.version != null ? this.version : GoogleJavaFormatStep.defaultVersion(); + String style = this.style != null ? this.style : GoogleJavaFormatStep.defaultStyle(); + return GoogleJavaFormatStep.create(version, style, config.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ImportOrder.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ImportOrder.java new file mode 100644 index 0000000000..3be6897679 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ImportOrder.java @@ -0,0 +1,46 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import java.io.File; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.ImportOrderStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class ImportOrder implements FormatterStepFactory { + @Parameter + private File file; + + @Parameter + private String order; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + if (file != null ^ order != null) { + if (file != null) { + return ImportOrderStep.createFromFile(file); + } else { + return ImportOrderStep.createFromOrder(order.split(",")); + } + } else { + throw new IllegalArgumentException("Must specify exactly one of 'file' or 'order'."); + } + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java new file mode 100644 index 0000000000..f15444f75f --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static com.diffplug.common.collect.Sets.newHashSet; +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import com.diffplug.spotless.maven.FormatterFactory; + +public class Java extends FormatterFactory { + private static final Set DEFAULT_INCLUDES = unmodifiableSet(newHashSet("src/main/java/**/*.java", + "src/test/java/**/*.java")); + private static final String LICENSE_HEADER_DELIMITER = "package "; + + @Override + public Set defaultIncludes() { + return DEFAULT_INCLUDES; + } + + @Override + public String licenseHeaderDelimiter() { + return LICENSE_HEADER_DELIMITER; + } + + public void addEclipse(Eclipse eclipse) { + addStepFactory(eclipse); + } + + public void addGoogleJavaFormat(GoogleJavaFormat googleJavaFormat) { + addStepFactory(googleJavaFormat); + } + + public void addImportOrder(ImportOrder importOrder) { + addStepFactory(importOrder); + } + + public void addRemoveUnusedImports(RemoveUnusedImports removeUnusedImports) { + addStepFactory(removeUnusedImports); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/RemoveUnusedImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/RemoveUnusedImports.java new file mode 100644 index 0000000000..54fd30a167 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/RemoveUnusedImports.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.RemoveUnusedImportsStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class RemoveUnusedImports implements FormatterStepFactory { + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + return RemoveUnusedImportsStep.create(config.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scala.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scala.java new file mode 100644 index 0000000000..0f2034e883 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scala.java @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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.spotless.maven.scala; + +import static com.diffplug.common.collect.Sets.newHashSet; +import static java.util.Collections.unmodifiableSet; + +import java.util.Set; + +import com.diffplug.spotless.maven.FormatterFactory; + +public class Scala extends FormatterFactory { + private static final Set DEFAULT_INCLUDES = unmodifiableSet(newHashSet("src/main/scala/**/*.scala", + "src/test/scala/**/*.scala", "src/main/scala/**/*.sc", "src/test/scala/**/*.sc")); + private static final String LICENSE_HEADER_DELIMITER = "package "; + + @Override + public Set defaultIncludes() { + return DEFAULT_INCLUDES; + } + + @Override + public String licenseHeaderDelimiter() { + return LICENSE_HEADER_DELIMITER; + } + + public void addScalafmt(Scalafmt scalafmt) { + addStepFactory(scalafmt); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scalafmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scalafmt.java new file mode 100644 index 0000000000..ce28bd4813 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scalafmt.java @@ -0,0 +1,40 @@ +/* + * Copyright 2016 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.spotless.maven.scala; + +import java.io.File; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.scala.ScalaFmtStep; + +public class Scalafmt implements FormatterStepFactory { + + @Parameter + private File file; + + @Parameter + private String version; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + String scalafmtVersion = version != null ? version : ScalaFmtStep.defaultVersion(); + return ScalaFmtStep.create(scalafmtVersion, config.getProvisioner(), file); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/IncludesExcludesTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/IncludesExcludesTest.java new file mode 100644 index 0000000000..a6dd0807fa --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/IncludesExcludesTest.java @@ -0,0 +1,190 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; + +import org.junit.Test; + +public class IncludesExcludesTest extends MavenIntegrationTest { + + private static final String JAVA_FORMATTED = "java/eclipse/format/JavaCodeFormatted.test"; + private static final String JAVA_UNFORMATTED = "java/eclipse/format/JavaCodeUnformatted.test"; + private static final String SCALA_UNFORMATTED = "scala/scalafmt/basic.dirty"; + private static final String SCALA_FORMATTED = "scala/scalafmt/basic.clean"; + + @Test + public void testDefaultIncludesJava() throws Exception { + String unformattedCorrectLocation1 = "src/main/java/test1.java"; + String unformattedCorrectLocation2 = "src/main/java/test2.java"; + String unformattedCorrectLocation3 = "src/test/java/test3.java"; + String unformattedCorrectLocation4 = "src/test/java/test4.java"; + String formattedCorrectLocation = "src/main/java/test5.java"; + String unformattedIncorrectLocation1 = "src/main/my-java/test6.java"; + String unformattedIncorrectLocation2 = "sources/main/java/test7.java"; + + writePomWithJavaSteps( + "", + " ${basedir}/formatter.xml", + ""); + + write("formatter.xml", getTestResource("java/eclipse/format/formatter.xml")); + + writeUnformattedJava(unformattedCorrectLocation1); + writeUnformattedJava(unformattedCorrectLocation2); + writeUnformattedJava(unformattedCorrectLocation3); + writeUnformattedJava(unformattedCorrectLocation4); + writeFormattedJava(formattedCorrectLocation); + writeUnformattedJava(unformattedIncorrectLocation1); + writeUnformattedJava(unformattedIncorrectLocation2); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFormattedJava(unformattedCorrectLocation1); + assertFormattedJava(unformattedCorrectLocation2); + assertFormattedJava(unformattedCorrectLocation3); + assertFormattedJava(unformattedCorrectLocation4); + assertFormattedJava(formattedCorrectLocation); + assertUnformattedJava(unformattedIncorrectLocation1); + assertUnformattedJava(unformattedIncorrectLocation2); + } + + @Test + public void testDefaultIncludesScala() throws Exception { + String unformattedCorrectLocation1 = "src/main/scala/test1.scala"; + String unformattedCorrectLocation2 = "src/main/scala/test2.sc"; + String unformattedCorrectLocation3 = "src/test/scala/test3.sc"; + String unformattedCorrectLocation4 = "src/test/scala/test4.scala"; + String formattedCorrectLocation = "src/test/scala/test5.scala"; + String unformattedIncorrectLocation1 = "src/main/not-scala/test6.sc"; + String unformattedIncorrectLocation2 = "scala/scala/scala/test7.scala"; + + writePomWithScalaSteps(""); + + writeUnformattedScala(unformattedCorrectLocation1); + writeUnformattedScala(unformattedCorrectLocation2); + writeUnformattedScala(unformattedCorrectLocation3); + writeUnformattedScala(unformattedCorrectLocation4); + writeFormattedScala(formattedCorrectLocation); + writeUnformattedScala(unformattedIncorrectLocation1); + writeUnformattedScala(unformattedIncorrectLocation2); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFormattedScala(unformattedCorrectLocation1); + assertFormattedScala(unformattedCorrectLocation2); + assertFormattedScala(unformattedCorrectLocation3); + assertFormattedScala(unformattedCorrectLocation4); + assertFormattedScala(formattedCorrectLocation); + assertUnformattedScala(unformattedIncorrectLocation1); + assertUnformattedScala(unformattedIncorrectLocation2); + } + + @Test + public void testInclude() throws Exception { + String unformattedDefaultLocation1 = "src/main/scala/test1.scala"; + String unformattedDefaultLocation2 = "src/test/scala/test2.scala"; + String unformattedCustomLocation1 = "src/main/my-scala/test3.scala"; + String unformattedCustomLocation2 = "src/test/sc/test4.sc"; + + writePomWithScalaSteps( + "", + " src/**/my-scala/*.scala", + " src/test/sc/*.sc", + "", + ""); + + writeUnformattedScala(unformattedDefaultLocation1); + writeUnformattedScala(unformattedDefaultLocation2); + writeUnformattedScala(unformattedCustomLocation1); + writeUnformattedScala(unformattedCustomLocation2); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + // includes override default ones, so files in default location should remain unformatted + assertUnformattedScala(unformattedDefaultLocation1); + assertUnformattedScala(unformattedDefaultLocation2); + // files included via "" should be formatted + assertFormattedScala(unformattedCustomLocation1); + assertFormattedScala(unformattedCustomLocation2); + } + + @Test + public void testExclude() throws Exception { + String unformatted1 = "src/main/scala/test1.scala"; + String unformatted2 = "src/main/scala/test2.sc"; + String unformatted3 = "src/test/scala/test3.scala"; + String unformatted4 = "src/test/scala/test4.sc"; + + writePomWithScalaSteps( + "", + " src/main/scala/*.scala", + "", + "", + " src/main/scala/*.sc", + " src/test/scala", + "", + ""); + + writeUnformattedScala(unformatted1); + writeUnformattedScala(unformatted2); + writeUnformattedScala(unformatted3); + writeUnformattedScala(unformatted4); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFormattedScala(unformatted1); + assertUnformattedScala(unformatted2); + assertUnformattedScala(unformatted3); + assertUnformattedScala(unformatted4); + } + + private void writeFormattedJava(String target) throws IOException { + write(target, getTestResource(JAVA_FORMATTED)); + } + + private void writeUnformattedJava(String target) throws IOException { + write(target, getTestResource(JAVA_UNFORMATTED)); + } + + private void assertFormattedJava(String target) throws IOException { + assertThat(read(target)).isEqualTo(getTestResource(JAVA_FORMATTED)); + } + + private void assertUnformattedJava(String target) throws IOException { + // #write() call adds a new line, append '\n' to the original unformatted java + assertThat(read(target)).isEqualTo(getTestResource(JAVA_UNFORMATTED) + '\n'); + } + + private void writeFormattedScala(String target) throws IOException { + write(target, getTestResource(SCALA_FORMATTED)); + } + + private void writeUnformattedScala(String target) throws IOException { + write(target, getTestResource(SCALA_UNFORMATTED)); + } + + private void assertFormattedScala(String target) throws IOException { + assertThat(read(target)).isEqualTo(getTestResource(SCALA_FORMATTED)); + } + + private void assertUnformattedScala(String target) throws IOException { + // #write() call adds a new line, append '\n' to the original unformatted scala + assertThat(read(target)).isEqualTo(getTestResource(SCALA_UNFORMATTED) + '\n'); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationTest.java new file mode 100644 index 0000000000..d9f25a2bd1 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationTest.java @@ -0,0 +1,147 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static com.diffplug.common.base.Strings.isNullOrEmpty; +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; + +import com.github.mustachejava.DefaultMustacheFactory; +import com.github.mustachejava.Mustache; +import com.github.mustachejava.MustacheFactory; + +import com.diffplug.common.io.Resources; +import com.diffplug.spotless.ResourceHarness; + +public class MavenIntegrationTest extends ResourceHarness { + + private static final String LOCAL_MAVEN_REPOSITORY_DIR = "localMavenRepositoryDir"; + private static final String SPOTLESS_MAVEN_PLUGIN_VERSION = "spotlessMavenPluginVersion"; + private static final String CONFIGURATION = "configuration"; + private static final String EXECUTIONS = "executions"; + + private final MustacheFactory mustacheFactory = new DefaultMustacheFactory(); + + /** + * Each test gets its own temp folder, and we create a maven + * 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"); + // copy the mvnw resources + copy("mvnw").setExecutable(true); + copy("mvnw.cmd"); + copy(".mvn/wrapper/maven-wrapper.jar"); + copy(".mvn/wrapper/maven-wrapper.properties"); + } + + private File copy(String path) throws IOException { + byte[] bytes = Resources.toByteArray(ResourceHarness.class.getResource("/" + path)); + Path target = newFile(path).toPath(); + Files.createDirectories(target.getParent()); + Files.write(target, bytes); + return target.toFile(); + } + + protected void writePomWithJavaSteps(String... steps) throws IOException { + writePom(groupWithSteps("java", steps)); + } + + protected void writePomWithScalaSteps(String... steps) throws IOException { + writePom(groupWithSteps("scala", steps)); + } + + protected void writePom(String... configuration) throws IOException { + writePom(null, configuration); + } + + protected void writePom(String[] executions, String[] configuration) throws IOException { + String pomXmlContent = createPomXmlContent(executions, configuration); + write("pom.xml", pomXmlContent); + } + + protected MavenRunner mavenRunner() throws IOException { + return MavenRunner.create() + .withProjectDir(rootFolder()) + .withLocalRepository(new File(getSystemProperty(LOCAL_MAVEN_REPOSITORY_DIR))); + } + + private String createPomXmlContent(String[] executions, String[] configuration) throws IOException { + URL url = MavenIntegrationTest.class.getResource("/pom-test.xml.mustache"); + try (BufferedReader reader = Resources.asCharSource(url, StandardCharsets.UTF_8).openBufferedStream()) { + Mustache mustache = mustacheFactory.compile(reader, "pom"); + StringWriter writer = new StringWriter(); + Map params = buildPomXmlParams(executions, configuration); + mustache.execute(writer, params); + return writer.toString(); + } + } + + private static Map buildPomXmlParams(String[] executions, String[] configuration) { + Map params = new HashMap<>(); + params.put(LOCAL_MAVEN_REPOSITORY_DIR, getSystemProperty(LOCAL_MAVEN_REPOSITORY_DIR)); + params.put(SPOTLESS_MAVEN_PLUGIN_VERSION, getSystemProperty(SPOTLESS_MAVEN_PLUGIN_VERSION)); + + if (configuration != null) { + params.put(CONFIGURATION, String.join("\n", configuration)); + } + + if (executions != null) { + params.put(EXECUTIONS, String.join("\n", executions)); + } + + return params; + } + + private static String getSystemProperty(String name) { + String value = System.getProperty(name); + if (isNullOrEmpty(value)) { + fail("System property '" + name + "' is not defined"); + } + return value; + } + + private static String[] groupWithSteps(String group, String... steps) { + String[] result = new String[steps.length + 2]; + result[0] = '<' + group + '>'; + System.arraycopy(steps, 0, result, 1, steps.length); + result[result.length - 1] = "'; + return result; + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenProvisionerTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenProvisionerTest.java new file mode 100644 index 0000000000..9430402ac8 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenProvisionerTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static com.diffplug.common.collect.Sets.newHashSet; +import static java.util.Collections.emptySet; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Set; + +import org.junit.Test; + +import com.diffplug.spotless.Provisioner; + +public class MavenProvisionerTest { + + @Test + public void testProvisionWithDependenciesWhenNothingResolved() throws Exception { + ArtifactResolver resolver = mock(ArtifactResolver.class); + when(resolver.resolve(anyString())).thenReturn(emptySet()); + Provisioner provisioner = MavenProvisioner.create(resolver); + + Set files = provisioner.provisionWithDependencies("foo", "bar", "baz"); + + assertThat(files).isEmpty(); + } + + @Test + public void testProvisionWithDependencies() throws Exception { + ArtifactResolver resolver = mock(ArtifactResolver.class); + when(resolver.resolve("foo")).thenReturn(newHashSet(new File("foo-1"), new File("foo-2"))); + when(resolver.resolve("bar")).thenReturn(newHashSet(new File("bar-1"))); + when(resolver.resolve("baz")).thenReturn(newHashSet(new File("baz-1"), new File("baz-2"))); + Provisioner provisioner = MavenProvisioner.create(resolver); + + Set files = provisioner.provisionWithDependencies("foo", "bar", "baz"); + + assertThat(files).containsOnly(new File("foo-1"), new File("foo-2"), new File("bar-1"), new File("baz-1"), new File("baz-2")); + } + + @Test + public void testProvisionWithDependenciesWithDuplicates() throws Exception { + ArtifactResolver resolver = mock(ArtifactResolver.class); + when(resolver.resolve("foo")).thenReturn(newHashSet(new File("foo-1"), new File("foo-2"))); + when(resolver.resolve("bar")).thenReturn(newHashSet(new File("foo-2"))); + when(resolver.resolve("baz")).thenReturn(newHashSet(new File("foo-1"), new File("baz-2"))); + Provisioner provisioner = MavenProvisioner.create(resolver); + + Set files = provisioner.provisionWithDependencies("foo", "bar", "baz"); + + assertThat(files).containsOnly(new File("foo-1"), new File("foo-2"), new File("baz-2")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java new file mode 100644 index 0000000000..9df160a935 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java @@ -0,0 +1,168 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static java.util.stream.Collectors.joining; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +import com.diffplug.common.base.Throwables; +import com.diffplug.common.io.ByteStreams; + +/** + * Harness for running a maven build, same idea as the + * [GradleRunner from the gradle testkit](https://docs.gradle.org/current/javadoc/org/gradle/testkit/runner/GradleRunner.html). + */ +public class MavenRunner { + public static MavenRunner create() { + return new MavenRunner(); + } + + private MavenRunner() {} + + private File projectDir; + private String[] args; + private File localRepositoryDir; + + public MavenRunner withProjectDir(File projectDir) { + this.projectDir = Objects.requireNonNull(projectDir); + return this; + } + + public MavenRunner withArguments(String... args) { + this.args = Objects.requireNonNull(args); + return this; + } + + public MavenRunner withLocalRepository(File localRepositoryDir) { + this.localRepositoryDir = localRepositoryDir; + return this; + } + + private Result run() throws IOException, InterruptedException { + Objects.requireNonNull(projectDir, "Need to call withProjectDir() first"); + Objects.requireNonNull(args, "Need to call withArguments() first"); + // run maven with the given args in the given directory + String argsString = Arrays.stream(args).collect(joining(" ")); + List cmds = getPlatformCmds("-e -Dmaven.repo.local=" + localRepositoryDir + ' ' + argsString); + ProcessBuilder builder = new ProcessBuilder(cmds); + builder.directory(projectDir); + Process process = builder.start(); + // slurp and return the stdout, stderr, and exitValue + Slurper output = new Slurper(process.getInputStream()); + Slurper error = new Slurper(process.getErrorStream()); + int exitValue = process.waitFor(); + output.join(); + error.join(); + return new Result(exitValue, output.result(), error.result()); + } + + /** Runs the command and asserts that exit code is 0. */ + public Result runNoError() throws IOException, InterruptedException { + Result result = run(); + assertThat(result.exitValue()).as("Run without error %s", result).isEqualTo(0); + return result; + } + + /** Runs the command and asserts that exit code is not 0. */ + public Result runHasError() throws IOException, InterruptedException { + Result result = run(); + assertThat(result.exitValue()).as("Run with error %s", result).isNotEqualTo(0); + return result; + } + + public static class Result { + private final int exitValue; + private final String output; + private final String error; + + public Result(int exitValue, String output, String error) { + super(); + this.exitValue = exitValue; + this.output = Objects.requireNonNull(output); + this.error = Objects.requireNonNull(error); + } + + public int exitValue() { + return exitValue; + } + + public String output() { + return output; + } + + public String error() { + return error; + } + + @Override + public String toString() { + return "Result{" + + "exitValue=" + exitValue + + ", output='" + output + '\'' + + ", error='" + error + '\'' + + '}'; + } + } + + /** Prepends any arguments necessary to run a console command. */ + private static List getPlatformCmds(String cmd) { + if (isWin()) { + return Arrays.asList("cmd", "/c", "mvnw " + cmd); + } else { + return Arrays.asList("/bin/sh", "-c", "./mvnw " + cmd); + } + } + + private static boolean isWin() { + String os_name = System.getProperty("os.name").toLowerCase(Locale.getDefault()); + return os_name.contains("win"); + } + + private static class Slurper extends Thread { + private final InputStream input; + private volatile String result; + + Slurper(InputStream input) { + this.input = Objects.requireNonNull(input); + start(); + } + + @Override + public void run() { + try { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + ByteStreams.copy(input, output); + result = output.toString(Charset.defaultCharset().name()); + } catch (Exception e) { + result = Throwables.getStackTraceAsString(e); + } + } + + public String result() { + return result; + } + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/SpotlessCheckMojoTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/SpotlessCheckMojoTest.java new file mode 100644 index 0000000000..cda89aba4f --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/SpotlessCheckMojoTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2016 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.spotless.maven; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; + +import org.junit.Test; + +public class SpotlessCheckMojoTest extends MavenIntegrationTest { + + private static final String UNFORMATTED_FILE = "license/MissingLicense.test"; + private static final String FORMATTED_FILE = "license/HasLicense.test"; + + @Test + public void testSpotlessCheckWithFormattingViolations() throws Exception { + writePomWithJavaLicenseHeaderStep(); + testSpotlessCheck(UNFORMATTED_FILE, "spotless:check", true); + } + + @Test + public void testSpotlessCheckWithoutFormattingViolations() throws Exception { + writePomWithJavaLicenseHeaderStep(); + testSpotlessCheck(FORMATTED_FILE, "spotless:check", false); + } + + @Test + public void testSkipSpotlessCheckWithFormattingViolations() throws Exception { + writePomWithJavaLicenseHeaderStep(); + testSpotlessCheck(UNFORMATTED_FILE, "spotless:check -Dspotless.check.skip", false); + } + + @Test + public void testSpotlessCheckBindingToVerifyPhase() throws Exception { + writePom( + new String[]{ + "", + " check", + " ", + " check", + " ", + ""}, + new String[]{ + "", + " ", + " ${basedir}/license.txt", + " ", + ""}); + + testSpotlessCheck(UNFORMATTED_FILE, "verify", true); + } + + private void testSpotlessCheck(String fileName, String command, boolean expectError) throws Exception { + write("license.txt", getTestResource("license/TestLicense")); + write("src/main/java/com.github.youribonnaffe.gradle.format/Java8Test.java", getTestResource(fileName)); + + MavenRunner mavenRunner = mavenRunner().withArguments(command); + + if (expectError) { + MavenRunner.Result result = mavenRunner.runHasError(); + assertThat(result.output()).contains("The following files had format violations"); + } else { + mavenRunner.runNoError(); + } + } + + private void writePomWithJavaLicenseHeaderStep() throws IOException { + writePomWithJavaSteps( + "", + " ${basedir}/license.txt", + ""); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderTest.java new file mode 100644 index 0000000000..cf41bbbbc7 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 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.spotless.maven.generic; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class LicenseHeaderTest extends MavenIntegrationTest { + private static final String KEY_LICENSE = "license/TestLicense"; + + @Test + public void fromFile() throws Exception { + write("license.txt", getTestResource(KEY_LICENSE)); + writePomWithJavaSteps( + "", + " ${basedir}/license.txt", + ""); + runTest(); + } + + @Test + public void fromContent() throws Exception { + writePomWithJavaSteps( + "", + " ", + "// If you can't trust a man's word", + "// Does it help to have it in writing?", + " ", + ""); + runTest(); + } + + @Test + public void fromFileGlobal() throws Exception { + write("license.txt", getTestResource(KEY_LICENSE)); + writePom("", + " ${basedir}/license.txt", + "", + ""); + + runTest(); + } + + private void runTest() throws Exception { + write("src/main/java/test.java", getTestResource("license/MissingLicense.test")); + mavenRunner().withArguments("spotless:apply").runNoError(); + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("license/HasLicense.test")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/EclipseFormatStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/EclipseFormatStepTest.java new file mode 100644 index 0000000000..cc2202b9d5 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/EclipseFormatStepTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class EclipseFormatStepTest extends MavenIntegrationTest { + + @Test + public void testEclipse() throws Exception { + writePomWithJavaSteps( + "", + " ${basedir}/formatter.xml", + " 4.7.1", + ""); + + write("src/main/java/test.java", getTestResource("java/eclipse/format/JavaCodeUnformatted.test")); + write("formatter.xml", getTestResource("java/eclipse/format/formatter.xml")); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("java/eclipse/format/JavaCodeFormatted.test")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java new file mode 100644 index 0000000000..c3b37d5a5c --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/GoogleJavaFormatTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class GoogleJavaFormatTest extends MavenIntegrationTest { + @Test + public void specificVersionDefaultStyle() throws Exception { + writePomWithJavaSteps( + "", + " 1.2", + ""); + + write("src/main/java/test.java", getTestResource("java/googlejavaformat/JavaCodeUnformatted.test")); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("java/googlejavaformat/JavaCodeFormatted.test")); + } + + @Test + public void specificVersionSpecificStyle() throws Exception { + writePomWithJavaSteps( + "", + " 1.2", + " ", + ""); + + write("src/main/java/test.java", getTestResource("java/googlejavaformat/JavaCodeUnformatted.test")); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("java/googlejavaformat/JavaCodeFormattedAOSP.test")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ImportOrderTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ImportOrderTest.java new file mode 100644 index 0000000000..26bc618452 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ImportOrderTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class ImportOrderTest extends MavenIntegrationTest { + @Test + public void file() throws Exception { + write("import.properties", getTestResource("java/importsorter/import.properties")); + writePomWithJavaSteps( + "", + " ${basedir}/import.properties", + ""); + runTest(); + } + + @Test + public void order() throws Exception { + writePomWithJavaSteps( + "", + " java,javax,org,\\#com", + ""); + runTest(); + } + + private void runTest() throws Exception { + write("src/main/java/test.java", getTestResource("java/importsorter/JavaCodeUnsortedImports.test")); + mavenRunner().withArguments("spotless:apply").runNoError(); + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("java/importsorter/JavaCodeSortedImports.test")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/RemoveUnusedImportsStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/RemoveUnusedImportsStepTest.java new file mode 100644 index 0000000000..c57ff55476 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/RemoveUnusedImportsStepTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016 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.spotless.maven.java; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class RemoveUnusedImportsStepTest extends MavenIntegrationTest { + + @Test + public void testRemoveUnusedInports() throws Exception { + writePomWithJavaSteps(""); + write("src/main/java/test.java", getTestResource("java/removeunusedimports/JavaCodeWithPackageUnformatted.test")); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/java/test.java"); + assertThat(actual).isEqualTo(getTestResource("java/removeunusedimports/JavaCodeWithPackageFormatted.test")); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/scala/ScalafmtTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/scala/ScalafmtTest.java new file mode 100644 index 0000000000..b9a4c85e8a --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/scala/ScalafmtTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 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.spotless.maven.scala; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationTest; + +public class ScalafmtTest extends MavenIntegrationTest { + + @Test + public void testScalafmtWithDefaultConfig() throws Exception { + writePomWithScalaSteps(""); + + write("src/main/scala/test.scala", getTestResource("scala/scalafmt/basic.dirty")); + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/scala/test.scala"); + assertThat(actual).isEqualTo(getTestResource("scala/scalafmt/basic.clean")); + } + + @Test + public void testScalafmtWithCustomConfig() throws Exception { + writePomWithScalaSteps( + "", + " ${project.basedir}/scalafmt.conf", + ""); + + write("src/main/scala/test.scala", getTestResource("scala/scalafmt/basic.dirty")); + write("scalafmt.conf", getTestResource("scala/scalafmt/scalafmt.conf")); + mavenRunner().withArguments("spotless:apply").runNoError(); + + String actual = read("src/main/scala/test.scala"); + assertThat(actual).isEqualTo(getTestResource("scala/scalafmt/basic.cleanWithCustomConf")); + } +} diff --git a/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.jar b/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.jar new file mode 100755 index 0000000000..f775b1c04c Binary files /dev/null and b/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.jar differ diff --git a/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.properties b/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.properties new file mode 100755 index 0000000000..a447c9fa81 --- /dev/null +++ b/plugin-maven/src/test/resources/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip \ No newline at end of file diff --git a/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeFormatted.test b/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeFormatted.test new file mode 100644 index 0000000000..b43ebf6edf --- /dev/null +++ b/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeFormatted.test @@ -0,0 +1,5 @@ +public class Java { + public static void main(String[] args) { + System.out.println("hello"); + } +} diff --git a/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeUnformatted.test b/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeUnformatted.test new file mode 100644 index 0000000000..f673abb3be --- /dev/null +++ b/plugin-maven/src/test/resources/java/eclipse/format/JavaCodeUnformatted.test @@ -0,0 +1,5 @@ +public class Java { +public static void main(String[] args) { +System.out.println("hello"); +} +} diff --git a/plugin-maven/src/test/resources/java/eclipse/format/formatter.xml b/plugin-maven/src/test/resources/java/eclipse/format/formatter.xml new file mode 100644 index 0000000000..365c79b2a3 --- /dev/null +++ b/plugin-maven/src/test/resources/java/eclipse/format/formatter.xml @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormatted.test b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormatted.test new file mode 100644 index 0000000000..de7710d80c --- /dev/null +++ b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormatted.test @@ -0,0 +1,11 @@ + +import mylib.UsedA; +import mylib.UsedB; + +public class Java { + public static void main(String[] args) { + System.out.println("hello"); + UsedB.someMethod(); + UsedA.someMethod(); + } +} diff --git a/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormattedAOSP.test b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormattedAOSP.test new file mode 100644 index 0000000000..10ef7c35f9 --- /dev/null +++ b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeFormattedAOSP.test @@ -0,0 +1,11 @@ + +import mylib.UsedA; +import mylib.UsedB; + +public class Java { + public static void main(String[] args) { + System.out.println("hello"); + UsedB.someMethod(); + UsedA.someMethod(); + } +} diff --git a/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeUnformatted.test b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeUnformatted.test new file mode 100644 index 0000000000..a9a957c9c2 --- /dev/null +++ b/plugin-maven/src/test/resources/java/googlejavaformat/JavaCodeUnformatted.test @@ -0,0 +1,12 @@ + +import mylib.Unused; +import mylib.UsedB; +import mylib.UsedA; + +public class Java { +public static void main(String[] args) { +System.out.println("hello"); +UsedB.someMethod(); +UsedA.someMethod(); +} +} \ No newline at end of file diff --git a/plugin-maven/src/test/resources/java/importsorter/JavaCodeSortedImports.test b/plugin-maven/src/test/resources/java/importsorter/JavaCodeSortedImports.test new file mode 100644 index 0000000000..e20a555950 --- /dev/null +++ b/plugin-maven/src/test/resources/java/importsorter/JavaCodeSortedImports.test @@ -0,0 +1,9 @@ +import java.lang.Runnable; +import java.lang.Thread; + +import org.dooda.Didoo; + +import static java.lang.Exception.*; +import static java.lang.Runnable.*; + +import static com.foo.Bar; diff --git a/plugin-maven/src/test/resources/java/importsorter/JavaCodeUnsortedImports.test b/plugin-maven/src/test/resources/java/importsorter/JavaCodeUnsortedImports.test new file mode 100644 index 0000000000..50d052d456 --- /dev/null +++ b/plugin-maven/src/test/resources/java/importsorter/JavaCodeUnsortedImports.test @@ -0,0 +1,7 @@ +import static java.lang.Exception.*; +import org.dooda.Didoo; +import java.lang.Thread; +import java.lang.Runnable; + +import static java.lang.Runnable.*; +import static com.foo.Bar diff --git a/plugin-maven/src/test/resources/java/importsorter/import.properties b/plugin-maven/src/test/resources/java/importsorter/import.properties new file mode 100644 index 0000000000..24e9660a4e --- /dev/null +++ b/plugin-maven/src/test/resources/java/importsorter/import.properties @@ -0,0 +1,6 @@ +#Organize Import Order +#Mon Jan 14 17:18:26 BRST 2013 +3=\#com +2=org +1=javax +0=java \ No newline at end of file diff --git a/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageFormatted.test b/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageFormatted.test new file mode 100644 index 0000000000..f30facd835 --- /dev/null +++ b/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageFormatted.test @@ -0,0 +1,12 @@ +package hello.world; + +import mylib.UsedB; +import mylib.UsedA; + +public class Java { +public static void main(String[] args) { +System.out.println("hello"); +UsedB.someMethod(); +UsedA.someMethod(); +} +} diff --git a/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageUnformatted.test b/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageUnformatted.test new file mode 100644 index 0000000000..f0dbfb0ef9 --- /dev/null +++ b/plugin-maven/src/test/resources/java/removeunusedimports/JavaCodeWithPackageUnformatted.test @@ -0,0 +1,13 @@ +package hello.world; + +import mylib.Unused; +import mylib.UsedB; +import mylib.UsedA; + +public class Java { +public static void main(String[] args) { +System.out.println("hello"); +UsedB.someMethod(); +UsedA.someMethod(); +} +} \ No newline at end of file diff --git a/plugin-maven/src/test/resources/license/HasLicense.test b/plugin-maven/src/test/resources/license/HasLicense.test new file mode 100644 index 0000000000..775a25028d --- /dev/null +++ b/plugin-maven/src/test/resources/license/HasLicense.test @@ -0,0 +1,30 @@ +// If you can't trust a man's word +// Does it help to have it in writing? +package com.github.youribonnaffe.gradle.format; + +import java.util.function.Function; + + +public class Java8Test { + public void doStuff() throws Exception { + Function example = Integer::parseInt; + example.andThen(val -> { + return val + 2; + } ); + SimpleEnum val = SimpleEnum.A; + switch (val) { + case A: + break; + case B: + break; + case C: + break; + default: + throw new Exception(); + } + } + + public enum SimpleEnum { + A, B, C; + } +} diff --git a/plugin-maven/src/test/resources/license/MissingLicense.test b/plugin-maven/src/test/resources/license/MissingLicense.test new file mode 100644 index 0000000000..c81a2412b7 --- /dev/null +++ b/plugin-maven/src/test/resources/license/MissingLicense.test @@ -0,0 +1,28 @@ +package com.github.youribonnaffe.gradle.format; + +import java.util.function.Function; + + +public class Java8Test { + public void doStuff() throws Exception { + Function example = Integer::parseInt; + example.andThen(val -> { + return val + 2; + } ); + SimpleEnum val = SimpleEnum.A; + switch (val) { + case A: + break; + case B: + break; + case C: + break; + default: + throw new Exception(); + } + } + + public enum SimpleEnum { + A, B, C; + } +} \ No newline at end of file diff --git a/plugin-maven/src/test/resources/license/TestLicense b/plugin-maven/src/test/resources/license/TestLicense new file mode 100644 index 0000000000..4c832cf0a9 --- /dev/null +++ b/plugin-maven/src/test/resources/license/TestLicense @@ -0,0 +1,2 @@ +// If you can't trust a man's word +// Does it help to have it in writing? \ No newline at end of file diff --git a/plugin-maven/src/test/resources/mvnw b/plugin-maven/src/test/resources/mvnw new file mode 100755 index 0000000000..e96ccd5fbb --- /dev/null +++ b/plugin-maven/src/test/resources/mvnw @@ -0,0 +1,227 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/plugin-maven/src/test/resources/mvnw.cmd b/plugin-maven/src/test/resources/mvnw.cmd new file mode 100755 index 0000000000..6a6eec39ba --- /dev/null +++ b/plugin-maven/src/test/resources/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/plugin-maven/src/test/resources/pom-build.xml.mustache b/plugin-maven/src/test/resources/pom-build.xml.mustache new file mode 100644 index 0000000000..7fbd6fc08e --- /dev/null +++ b/plugin-maven/src/test/resources/pom-build.xml.mustache @@ -0,0 +1,78 @@ + + 4.0.0 + + com.diffplug.spotless + spotless-maven-plugin + {{spotlessMavenPluginVersion}} + maven-plugin + + Spotless Maven Plugin + + + UTF-8 + 1.8 + 1.8 + + + {{mavenApiVersion}} + {{eclipseAetherVersion}} + {{spotlessLibVersion}} + + + + + org.apache.maven + maven-plugin-api + ${maven.api.version} + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${maven.api.version} + provided + + + org.eclipse.aether + aether-api + ${eclipse.aether.version} + provided + + + org.eclipse.aether + aether-util + ${eclipse.aether.version} + provided + + + + com.diffplug.spotless + spotless-lib + ${spotless.lib.version} + + + com.diffplug.spotless + spotless-lib-extra + ${spotless.lib.version} + + +{{{additionalDependencies}}} + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.5 + + + + + diff --git a/plugin-maven/src/test/resources/pom-test.xml.mustache b/plugin-maven/src/test/resources/pom-test.xml.mustache new file mode 100644 index 0000000000..26350411d5 --- /dev/null +++ b/plugin-maven/src/test/resources/pom-test.xml.mustache @@ -0,0 +1,33 @@ + + 4.0.0 + + com.diffplug.spotless + spotless-maven-plugin-tests + 1.0.0-SNAPSHOT + + Spotless Maven Plugin Tests + + + UTF-8 + 1.8 + 1.8 + + + + + + com.diffplug.spotless + spotless-maven-plugin + {{spotlessMavenPluginVersion}} + + {{{configuration}}} + + + {{{executions}}} + + + + + + diff --git a/plugin-maven/src/test/resources/scala/scalafmt/basic.clean b/plugin-maven/src/test/resources/scala/scalafmt/basic.clean new file mode 100644 index 0000000000..922a2ccbb9 --- /dev/null +++ b/plugin-maven/src/test/resources/scala/scalafmt/basic.clean @@ -0,0 +1,16 @@ +@foobar("annot", { + val x = 2 + val y = 2 // y=2 + x + y +}) +object a extends b with c { + def foo[T: Int#Double#Triple, R <% String](@annot1 + x: Int @annot2 = 2, + y: Int = 3): Int = { + "match" match { + case 1 | 2 => + 3 + case 2 => 2 + } + } +} diff --git a/plugin-maven/src/test/resources/scala/scalafmt/basic.cleanWithCustomConf b/plugin-maven/src/test/resources/scala/scalafmt/basic.cleanWithCustomConf new file mode 100644 index 0000000000..98bf69b7af --- /dev/null +++ b/plugin-maven/src/test/resources/scala/scalafmt/basic.cleanWithCustomConf @@ -0,0 +1,24 @@ +@foobar("annot", { + val x = 2 + val y = 2 // y=2 + x + y +}) +object a + extends b + with c { + def foo[ + T: Int#Double#Triple, + R <% String]( + @annot1 + x: Int @annot2 = + 2, + y: Int = 3) + : Int = { + "match" match { + case 1 | 2 => + 3 + case 2 => + 2 + } + } +} diff --git a/plugin-maven/src/test/resources/scala/scalafmt/basic.dirty b/plugin-maven/src/test/resources/scala/scalafmt/basic.dirty new file mode 100644 index 0000000000..2844c84555 --- /dev/null +++ b/plugin-maven/src/test/resources/scala/scalafmt/basic.dirty @@ -0,0 +1,21 @@ +@ foobar("annot", { + val x = 2 + val y = 2 // y=2 + x + y +}) + object + a extends b with c { + def + foo[T:Int#Double#Triple, + R <% String]( + @annot1 + x + : Int @annot2 = 2 + , y: Int = 3): Int = { + "match" match { + case 1 | 2 => + 3 + case 2 => 2 + } + } +} \ No newline at end of file diff --git a/plugin-maven/src/test/resources/scala/scalafmt/scalafmt.conf b/plugin-maven/src/test/resources/scala/scalafmt/scalafmt.conf new file mode 100644 index 0000000000..5007f5e8ff --- /dev/null +++ b/plugin-maven/src/test/resources/scala/scalafmt/scalafmt.conf @@ -0,0 +1,2 @@ +style = defaultWithAlign # For pretty alignment. +maxColumn = 20 # For my teensy narrow display diff --git a/plugin-maven/taskGraph.pdf b/plugin-maven/taskGraph.pdf new file mode 100644 index 0000000000..3366d95b9e Binary files /dev/null and b/plugin-maven/taskGraph.pdf differ