|
13 | 13 | * See the License for the specific language governing permissions and
|
14 | 14 | * limitations under the License.
|
15 | 15 | */
|
16 |
| -package com.diffplug.gradle.spotless; |
| 16 | +package com.diffplug.spotless.extra.integration; |
17 | 17 |
|
18 | 18 | import java.io.ByteArrayOutputStream;
|
19 | 19 | import java.io.File;
|
20 | 20 | import java.io.IOException;
|
21 | 21 | import java.nio.charset.StandardCharsets;
|
22 | 22 | import java.nio.file.Files;
|
23 |
| -import java.nio.file.Path; |
24 | 23 | import java.util.List;
|
25 | 24 | import java.util.ListIterator;
|
| 25 | +import java.util.Objects; |
26 | 26 |
|
27 | 27 | import org.eclipse.jgit.diff.DiffFormatter;
|
28 | 28 | import org.eclipse.jgit.diff.EditList;
|
|
31 | 31 | import org.eclipse.jgit.diff.RawTextComparator;
|
32 | 32 |
|
33 | 33 | import com.diffplug.common.base.CharMatcher;
|
| 34 | +import com.diffplug.common.base.Errors; |
34 | 35 | import com.diffplug.common.base.Preconditions;
|
35 | 36 | import com.diffplug.common.base.Splitter;
|
36 | 37 | import com.diffplug.spotless.Formatter;
|
37 | 38 | import com.diffplug.spotless.LineEnding;
|
38 | 39 | import com.diffplug.spotless.PaddedCell;
|
39 | 40 |
|
40 | 41 | /** Formats the messages of failed spotlessCheck invocations with a nice diff message. */
|
41 |
| -final class DiffMessageFormatter { |
42 |
| - private static final int MAX_CHECK_MESSAGE_LINES = 50; |
43 |
| - static final int MAX_FILES_TO_LIST = 10; |
44 |
| - |
45 |
| - static String messageFor(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException { |
46 |
| - DiffMessageFormatter diffFormater = new DiffMessageFormatter(task, formatter, problemFiles); |
47 |
| - return "The following files had format violations:\n" |
48 |
| - + diffFormater.buffer |
49 |
| - + "Run 'gradlew " |
50 |
| - + SpotlessPlugin.EXTENSION |
51 |
| - + SpotlessPlugin.APPLY |
52 |
| - + "' to fix these violations."; |
| 42 | +public final class DiffMessageFormatter { |
| 43 | + public static Builder builder() { |
| 44 | + return new Builder(); |
| 45 | + } |
| 46 | + |
| 47 | + public static class Builder { |
| 48 | + private Builder() {} |
| 49 | + |
| 50 | + private String runToFix; |
| 51 | + private boolean isPaddedCell; |
| 52 | + private Formatter formatter; |
| 53 | + private List<File> problemFiles; |
| 54 | + |
| 55 | + /** "Run 'gradlew spotlessApply' to fix these violations." */ |
| 56 | + public Builder runToFix(String runToFix) { |
| 57 | + this.runToFix = Objects.requireNonNull(runToFix); |
| 58 | + return this; |
| 59 | + } |
| 60 | + |
| 61 | + public Builder isPaddedCell(boolean isPaddedCell) { |
| 62 | + this.isPaddedCell = isPaddedCell; |
| 63 | + return this; |
| 64 | + } |
| 65 | + |
| 66 | + public Builder formatter(Formatter formatter) { |
| 67 | + this.formatter = Objects.requireNonNull(formatter); |
| 68 | + return this; |
| 69 | + } |
| 70 | + |
| 71 | + public Builder problemFiles(List<File> problemFiles) { |
| 72 | + this.problemFiles = Objects.requireNonNull(problemFiles); |
| 73 | + Preconditions.checkArgument(!problemFiles.isEmpty(), "cannot be empty"); |
| 74 | + return this; |
| 75 | + } |
| 76 | + |
| 77 | + /** Returns the error message. */ |
| 78 | + public String getMessage() { |
| 79 | + try { |
| 80 | + Objects.requireNonNull(runToFix, "runToFix"); |
| 81 | + Objects.requireNonNull(formatter, "formatter"); |
| 82 | + Objects.requireNonNull(problemFiles, "problemFiles"); |
| 83 | + DiffMessageFormatter diffFormater = new DiffMessageFormatter(this); |
| 84 | + return "The following files had format violations:\n" |
| 85 | + + diffFormater.buffer |
| 86 | + + runToFix; |
| 87 | + } catch (IOException e) { |
| 88 | + throw Errors.asRuntime(e); |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + String relativePath(File file) { |
| 93 | + return formatter.getRootDir().relativize(file.toPath()).toString(); |
| 94 | + } |
53 | 95 | }
|
54 | 96 |
|
| 97 | + private static final int MAX_CHECK_MESSAGE_LINES = 50; |
| 98 | + public static final int MAX_FILES_TO_LIST = 10; |
| 99 | + |
55 | 100 | private final StringBuilder buffer = new StringBuilder(MAX_CHECK_MESSAGE_LINES * 64);
|
56 | 101 | private int numLines = 0;
|
57 | 102 |
|
58 |
| - private DiffMessageFormatter(SpotlessTask task, Formatter formatter, List<File> problemFiles) throws IOException { |
59 |
| - Preconditions.checkArgument(!problemFiles.isEmpty(), "Problem files must not be empty"); |
60 |
| - |
61 |
| - Path rootDir = task.getProject().getRootDir().toPath(); |
62 |
| - ListIterator<File> problemIter = problemFiles.listIterator(); |
| 103 | + private DiffMessageFormatter(Builder builder) throws IOException { |
| 104 | + ListIterator<File> problemIter = builder.problemFiles.listIterator(); |
63 | 105 | while (problemIter.hasNext() && numLines < MAX_CHECK_MESSAGE_LINES) {
|
64 | 106 | File file = problemIter.next();
|
65 |
| - addFile(rootDir.relativize(file.toPath()) + "\n" + |
66 |
| - DiffMessageFormatter.diff(task, formatter, file)); |
| 107 | + addFile(builder.relativePath(file) + "\n" + DiffMessageFormatter.diff(builder, file)); |
67 | 108 | }
|
68 | 109 | if (problemIter.hasNext()) {
|
69 |
| - int remainingFiles = problemFiles.size() - problemIter.nextIndex(); |
| 110 | + int remainingFiles = builder.problemFiles.size() - problemIter.nextIndex(); |
70 | 111 | if (remainingFiles >= MAX_FILES_TO_LIST) {
|
71 | 112 | buffer.append("Violations also present in ").append(remainingFiles).append(" other files.\n");
|
72 | 113 | } else {
|
73 | 114 | buffer.append("Violations also present in:\n");
|
74 | 115 | while (problemIter.hasNext()) {
|
75 |
| - addIntendedLine(NORMAL_INDENT, rootDir.relativize(problemIter.next().toPath()).toString()); |
| 116 | + addIntendedLine(NORMAL_INDENT, builder.relativePath(problemIter.next())); |
76 | 117 | }
|
77 | 118 | }
|
78 | 119 | }
|
@@ -126,19 +167,19 @@ private void addIntendedLine(String indent, String line) {
|
126 | 167 | * look like if formatted using the given formatter. Does not end with any newline
|
127 | 168 | * sequence (\n, \r, \r\n).
|
128 | 169 | */
|
129 |
| - private static String diff(SpotlessTask task, Formatter formatter, File file) throws IOException { |
130 |
| - String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding()); |
| 170 | + private static String diff(Builder builder, File file) throws IOException { |
| 171 | + String raw = new String(Files.readAllBytes(file.toPath()), builder.formatter.getEncoding()); |
131 | 172 | String rawUnix = LineEnding.toUnix(raw);
|
132 | 173 | String formattedUnix;
|
133 |
| - if (task.isPaddedCell()) { |
134 |
| - formattedUnix = PaddedCell.check(formatter, file, rawUnix).canonical(); |
| 174 | + if (builder.isPaddedCell) { |
| 175 | + formattedUnix = PaddedCell.check(builder.formatter, file, rawUnix).canonical(); |
135 | 176 | } else {
|
136 |
| - formattedUnix = formatter.compute(rawUnix, file); |
| 177 | + formattedUnix = builder.formatter.compute(rawUnix, file); |
137 | 178 | }
|
138 | 179 |
|
139 | 180 | if (rawUnix.equals(formattedUnix)) {
|
140 | 181 | // the formatting is fine, so it's a line-ending issue
|
141 |
| - String formatted = formatter.computeLineEndings(formattedUnix, file); |
| 182 | + String formatted = builder.formatter.computeLineEndings(formattedUnix, file); |
142 | 183 | return diffWhitespaceLineEndings(raw, formatted, false, true);
|
143 | 184 | } else {
|
144 | 185 | return diffWhitespaceLineEndings(rawUnix, formattedUnix, true, false);
|
|
0 commit comments