Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial version of Spotless Maven plugin #188

Merged
merged 93 commits into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
5ff5581
Initial version of Spotless Maven plugin
lutovich Jan 14, 2018
9956473
Switched maven plugin over to Formatter.
nedtwigg Jan 17, 2018
c219ef1
Improved config handling in maven plugin
lutovich Jan 17, 2018
a5a6cc9
Removed dependency on maven-core
lutovich Jan 17, 2018
1d63aa2
Simplified maven plugin build process
lutovich Jan 17, 2018
af677ab
Set maven plugin version from gradle props
lutovich Jan 17, 2018
b059d53
Added "aspiring" docs for the maven plugin.
nedtwigg Jan 19, 2018
c0a2fa6
Merge branch 'master' into maven-plugin
nedtwigg Jan 19, 2018
a431b71
Switch indent from tab to 2-space for better GitHub render.
nedtwigg Jan 19, 2018
3639269
Update feature matrix for current maven ambitions.
nedtwigg Jan 19, 2018
240f87c
Fixed some typos in README.
nedtwigg Jan 19, 2018
8570064
Made maven plugin build use template for pom
lutovich Jan 19, 2018
75f0204
Fixed code formatting and build dir reference
lutovich Jan 19, 2018
40da7f5
Improve maven plugin configuration
lutovich Jan 21, 2018
3696310
Changed maven artifactId to spotless-maven-plugin, but kept project f…
nedtwigg Jan 21, 2018
49c2753
Added an explicit steps container inside each "java" configuration.
nedtwigg Jan 21, 2018
35da59a
Change task names from "spotless-{check|apply}" to just "check|apply".
nedtwigg Jan 21, 2018
fd38755
First cut at an integration test system for the maven plugin.
nedtwigg Jan 21, 2018
3864178
Use ByteStreams.copy to reduce boilerplate.
nedtwigg Jan 22, 2018
d54b183
Made maven plugin ITs runnable
lutovich Jan 22, 2018
ddbf0eb
Better package name for maven plugin
lutovich Jan 22, 2018
4754a8f
Include stdout and stderr in maven plugin test failures
lutovich Jan 22, 2018
88bcd19
Assert on exit code, not stderr
lutovich Jan 22, 2018
c84becf
Refactored DiffMessageFormatter out of gradle and into lib-extra.
nedtwigg Jan 23, 2018
012b118
Added "check" to the maven plugin, but not properly integrated.
nedtwigg Jan 23, 2018
0c01e64
Made maven plugin use all dependencies from local repo
lutovich Jan 23, 2018
c43ed45
Consistent naming of mustache variables
lutovich Jan 23, 2018
66bb67e
Use correct root dir for DiffMessageFormatter
lutovich Jan 24, 2018
31d5357
Fix maven provisioner to resolve transitive dependencies
lutovich Jan 24, 2018
4b032eb
Support RemoveUnusedImports in maven plugin
lutovich Jan 24, 2018
4cf839a
Use correct artifactId for maven plugin in tests
lutovich Jan 24, 2018
622d2df
Extracted check MOJO
lutovich Jan 24, 2018
e759a0b
Removed DiffMessageFormatter::rootDir() because Formatter has it alre…
nedtwigg Jan 27, 2018
0185af6
The local dependencies repo now contains only our local deps, and it …
nedtwigg Jan 27, 2018
0dba10c
Forced buildMavenPlugin to act like the standard jar task, so that pu…
nedtwigg Jan 27, 2018
9bb5bbc
Added a GoogleJavaFormat step.
nedtwigg Jan 27, 2018
3189d7d
Added an ImportOrder step.
nedtwigg Jan 27, 2018
6568440
Reorganized packages.
nedtwigg Jan 27, 2018
21f8d00
Make the parent FormatterFactory available to the FormatterStepFactory.
nedtwigg Jan 27, 2018
8ebdbfc
Refactored non-java stuff out of FormatterFactory.
nedtwigg Jan 27, 2018
24f7096
Added a License step.
nedtwigg Jan 27, 2018
5e9fce6
Refactor formatter and step configuration
lutovich Jan 27, 2018
d95f76d
Allow multiple file extension for formatters
lutovich Jan 27, 2018
4f2952c
Made spotless mojo scan for files starting at basedir
lutovich Jan 28, 2018
1d82ba9
Added scalafmt step
lutovich Jan 28, 2018
4b34991
Fixed license header tests
lutovich Jan 28, 2018
7db3759
Mark check and apply MOJOs as thread safe
lutovich Jan 28, 2018
d8258bd
Removed need for "<steps>" config element
lutovich Jan 30, 2018
a8de57d
Added property to skip 'spotless:check'
lutovich Jan 30, 2018
3ca2bf7
Added javadoc to check and apply MOJOs
lutovich Jan 30, 2018
807291e
Bind 'spotless:check' to verify phase by default
lutovich Jan 30, 2018
48cb4c9
Run maven plugin tests with full stacktrace logging
lutovich Jan 30, 2018
08f90d2
Use mvnw to build maven plugin
lutovich Jan 31, 2018
5ccbd09
Cache the .m2 directory on Travis.
nedtwigg Feb 1, 2018
7df6191
Use mvnw to run tests.
nedtwigg Feb 1, 2018
a676bc4
Moved mvnw out of src/main/resources into the project route.
nedtwigg Feb 1, 2018
d4cddc0
Revert "Moved mvnw out of src/main/resources into the project route."
nedtwigg Feb 1, 2018
b9a4fa4
Added task graph vis, which shows problem in build.
nedtwigg Feb 1, 2018
bafc30c
Fixed the problem in the build.
nedtwigg Feb 1, 2018
9d3ea05
Moved mvnw and the template poms into src/test/resources.
nedtwigg Feb 1, 2018
e438881
Only run the maven tests on CI, for faster debugging. Also format fix.
nedtwigg Feb 1, 2018
f8bf47d
mvnw now works on Windows.
nedtwigg Feb 2, 2018
d2170fe
Disable the apache-snapshots repo.
nedtwigg Feb 2, 2018
da36b36
Another attempt at disabling the apache-snapshots repo.
nedtwigg Feb 2, 2018
07b6d68
Update docs for skipping spotless:check.
nedtwigg Feb 2, 2018
243035e
Try to figure out what travis is using for $HOME/.m2/settings.xml
nedtwigg Feb 2, 2018
ea6ebb5
Attempt #2...
nedtwigg Feb 2, 2018
6d660c6
Instead of snapshot-repo-whackamole, I'm just setting a restrictive s…
nedtwigg Feb 2, 2018
aef8b32
Another shot at a settings.xml - none at all.
nedtwigg Feb 2, 2018
21f163b
Force maven tests to run in "offline" mode.
nedtwigg Feb 2, 2018
e7cea18
Run Maven with debug logging and use "special" version
lutovich Feb 4, 2018
da77c39
Set version back to normal
lutovich Feb 4, 2018
34ff0e9
Local repo as repository, not only pluginRepository
lutovich Feb 4, 2018
7de4e1a
Do not use offline mode for maven plugin tests
lutovich Feb 4, 2018
8e77cf7
Force snapshot updates in maven plugin tests
lutovich Feb 4, 2018
fcebff7
Install maven plugin to local repo during build
lutovich Feb 4, 2018
53d8013
Turn off debug logging and cleanup local repo cmd
lutovich Feb 4, 2018
d52a448
Run all tests on CI
lutovich Feb 4, 2018
079e9a2
Removed repository declaration from POMs
lutovich Feb 4, 2018
3fdc785
Less verbose download logging when building maven plugin
lutovich Feb 4, 2018
95c7fc9
Cache the localMavenRepository on Travis, but delete the com.diffplug…
nedtwigg Feb 5, 2018
bd8a3b9
Merge branch 'master' into maven-plugin
nedtwigg Feb 5, 2018
d215905
Added support for google-java-format's style parameter.
nedtwigg Feb 5, 2018
2345cbd
Added `~/.m2` as a cached directory, because stuff gets downloaded fo…
nedtwigg Feb 5, 2018
0f9ff8e
Added a test for GoogleJavaFormat's style parameter.
nedtwigg Feb 5, 2018
9cee266
Gah! Fumble-fingers, I forgot the build.
nedtwigg Feb 5, 2018
15e65a0
Allow custom file includes and excludes
lutovich Feb 10, 2018
740317c
Added docs about includes & excludes configuration
lutovich Feb 10, 2018
a154f59
Fix serialization warning.
nedtwigg Feb 10, 2018
49987d7
Update README because maven-plugin is integrated with scala.
nedtwigg Feb 10, 2018
81477a6
Add @lutovich as first author of the maven plugin for the mavencentra…
nedtwigg Feb 10, 2018
a934a73
Fixed LicenseHeader when configured globally
lutovich Feb 11, 2018
4162569
Moved license header config handling to FormatterFactory
lutovich Feb 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
import com.diffplug.spotless.ResourceHarness;

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

import java.io.IOException;

import org.assertj.core.api.Assertions;
import org.junit.Ignore;
import org.junit.Test;

/**
* This test is ignored because it doesn't work.
* To make it work, we'll need something like the following:
*
* build.gradle
* task publishTestToLocalRepo()
* test.dependsOn(publishTestToLocalRepo)
*
* Then in MavenIntegratonTest.POM_HEADER, set <pluginRepositories> appropriately
*
* Would also be good if we had mvnw setup, so that
* the test harness used mvnw to control the verison
* of maven that was used.
*/
@Ignore
public class EclipseFormatStepTest extends MavenIntegrationTest {
@Test
public void testEclipse() throws IOException, InterruptedException {
// write the pom
writePomJavaSteps(
"<eclipse>",
" <file>${basedir}/eclipse-fmt.xml</file>",
" <version>4.7.1</version>",
"</eclipse>");
write("src/main/java/test.java", getTestResource("java/eclipse/format/JavaCodeUnformatted.test"));
mavenRunner().withArguments("spotless:apply").runNoError();

String actual = read("src/main/java/test.java");
Assertions.assertThat(actual).isEqualTo(getTestResource("java/eclipse/format/JavaCodeFormatted.test"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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.gradle.spotless;

import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;

import org.junit.Before;

import com.diffplug.spotless.ResourceHarness;

public class MavenIntegrationTest extends ResourceHarness {
/**
* 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");
}

private static final String POM_HEADER = "" +
"<project>\n" +
" <modelVersion>4.0.0</modelVersion>\n" +
" <repositories>\n" +
" <repository>\n" +
" <id>central</id>\n" +
" <name>Central Repository</name>\n" +
" <url>http://repo.maven.apache.org/maven2</url>\n" +
" <layout>default</layout>\n" +
" <snapshots>\n" +
" <enabled>false</enabled>\n" +
" </snapshots>\n" +
" </repository>\n" +
" </repositories>\n" +
" <pluginRepositories>\n" + // TODO: setup test so that the plugin gets compiled first, and put into this repository
" <pluginRepository>\n" +
" <id>central</id>\n" +
" <name>Central Repository</name>\n" +
" <url>http://repo.maven.apache.org/maven2</url>\n" +
" <layout>default</layout>\n" +
" <snapshots>\n" +
" <enabled>false</enabled>\n" +
" </snapshots>\n" +
" <releases>\n" +
" <updatePolicy>never</updatePolicy>\n" +
" </releases>\n" +
" </pluginRepository>\n" +
" </pluginRepositories>\n" +
" <build>\n" +
" <plugins>\n" +
" <plugin>\n" +
" <groupId>com.diffplug.spotless</groupId>\n" +
" <artifactId>spotless-maven-plugin</artifactId>\n" +
" <version>+</version>\n" +
" <configuration>\n";

private static final String POM_FOOTER = "" +
" </configuration>\n" +
" </plugin>\n" +
" </plugins>\n" +
" </build>\n" +
"</project>\n";

protected void writePomJavaSteps(String... steps) throws IOException {
write("pom.xml",
POM_HEADER,
"<java><steps>",
Arrays.stream(steps).collect(Collectors.joining("\n")),
"</steps></java>",
POM_FOOTER);
}

protected MavenRunner mavenRunner() throws IOException {
return MavenRunner.create()
.withProjectDir(rootFolder());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* 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.gradle.spotless;

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 java.util.stream.Collectors;

import org.assertj.core.api.Assertions;

import com.diffplug.common.base.Throwables;

/**
* 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;

public MavenRunner withProjectDir(File projectDir) {
this.projectDir = Objects.requireNonNull(projectDir);
return this;
}

public MavenRunner withArguments(String... args) {
this.args = Objects.requireNonNull(args);
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
List<String> cmds = getPlatformCmds("mvn " + Arrays.stream(args).collect(Collectors.joining(" ")));
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());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nedtwigg If we expect MavenRunner to be instantiated many times, I think we should consider using a shared ExecutorService, like an Executors.newFixedThreadPool(Runtime.getRuntime().getAvailableProcessors() - 1). Otherwise, this whole commit looks pretty reasonable to me. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, I'm proposing we use an ExecutorService instead of using Threads directly through the Slurper class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger. There will only be 10's of integration tests, so I don't think there's much of a performance hit for starting 2x threads per.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, that sounds reasonable to me.

int exitValue = process.waitFor();
output.join();
error.join();
return new Result(exitValue, output.result(), error.result());
}

/** Runs the command and asserts that nothing was printed to stderr. */
public Result runNoError() throws IOException, InterruptedException {
Result result = run();
Assertions.assertThat(result.error()).isEmpty();
return result;
}

/** Runs the command and asserts that something was printed to stderr. */
public Result runHasError() throws IOException, InterruptedException {
Result result = run();
Assertions.assertThat(result.error()).isNotEmpty();
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;
}
}

/** Prepends any arguments necessary to run a console command. */
private static List<String> getPlatformCmds(String cmd) {
if (isWin()) {
return Arrays.asList("cmd", "/c", cmd);
} else {
return Arrays.asList("/bin/sh", "-c", 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();
byte[] buffer = new byte[1024];
int numRead;
while ((numRead = input.read(buffer)) != -1) {
output.write(buffer, 0, numRead);
}
result = output.toString(Charset.defaultCharset().name());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nedtwigg Minor nit: I seem to remember that we have access to Guava in some way through a re-packaged version that Diffplug distributes on Maven Central and JCenter.

If we do have access to Guava in this way, then I think we should consider using ByteStreams.copy to simplify the code inside this try statement. But I'd understand if you don't want to do this for dependency reasons or such. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, implemented in next commit. For the rest of this review, I'd like to focus on bashing out the high-level design. We can fix performance nits and duplicate code after we have something working :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger! :)

} catch (Exception e) {
result = Throwables.getStackTraceAsString(e);
}
}

public String result() {
return result;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class Java {
public static void main(String[] args) {
System.out.println("hello");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class Java {
public static void main(String[] args) {
System.out.println("hello");
}
}
Loading