From 5903bb6ce863d8744534d819d5d022e976dd6f13 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Fri, 8 Dec 2023 18:13:18 +0100 Subject: [PATCH 1/6] Emit contextual error message during incremental m2e builds This closes #1960 --- .../spotless/extra/integration/DiffMessageFormatter.java | 8 ++++++-- .../com/diffplug/spotless/maven/SpotlessCheckMojo.java | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java index d43478c0b6..b0fc26203d 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java @@ -55,10 +55,10 @@ interface CleanProvider { String getFormatted(File file, String rawUnix); } - private static class CleanProviderFormatter implements CleanProvider { + public static class CleanProviderFormatter implements CleanProvider { private final Formatter formatter; - CleanProviderFormatter(Formatter formatter) { + public CleanProviderFormatter(Formatter formatter) { this.formatter = Objects.requireNonNull(formatter); } @@ -234,6 +234,10 @@ private void addIntendedLine(String indent, String line) { * sequence (\n, \r, \r\n). */ private String diff(File file) throws IOException { + return diff(formatter, file); + } + + public static String diff(CleanProvider formatter, File file) throws IOException { String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding()); String rawUnix = LineEnding.toUnix(raw); String formatted = formatter.getFormatted(file, rawUnix); 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 index 03e55e224a..58e176f575 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java @@ -23,10 +23,12 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; +import org.sonatype.plexus.build.incremental.BuildContext; import com.diffplug.spotless.Formatter; import com.diffplug.spotless.PaddedCell; import com.diffplug.spotless.extra.integration.DiffMessageFormatter; +import com.diffplug.spotless.extra.integration.DiffMessageFormatter.CleanProviderFormatter; import com.diffplug.spotless.maven.incremental.UpToDateChecker; /** @@ -54,6 +56,9 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke PaddedCell.DirtyState dirtyState = PaddedCell.calculateDirtyState(formatter, file); if (!dirtyState.isClean() && !dirtyState.didNotConverge()) { problemFiles.add(file); + if (buildContext.isIncremental()) { + buildContext.addMessage(file, 0, 0, DiffMessageFormatter.diff(new CleanProviderFormatter(formatter), file), BuildContext.SEVERITY_ERROR, null); + } counter.cleaned(); } else { counter.checkedButAlreadyClean(); From bdecbad91f66464a84c4d1f326cdfc9402b58066 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Fri, 8 Dec 2023 19:53:02 +0100 Subject: [PATCH 2/6] Emit line number of first difference Keep CleanProviderFormatter private --- .../integration/DiffMessageFormatter.java | 30 ++++++++++++++----- .../spotless/maven/SpotlessCheckMojo.java | 7 +++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java index b0fc26203d..1649d5aef4 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java @@ -22,11 +22,14 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.AbstractMap; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.Objects; import org.eclipse.jgit.diff.DiffFormatter; +import org.eclipse.jgit.diff.Edit; import org.eclipse.jgit.diff.EditList; import org.eclipse.jgit.diff.MyersDiff; import org.eclipse.jgit.diff.RawText; @@ -55,10 +58,10 @@ interface CleanProvider { String getFormatted(File file, String rawUnix); } - public static class CleanProviderFormatter implements CleanProvider { + private static class CleanProviderFormatter implements CleanProvider { private final Formatter formatter; - public CleanProviderFormatter(Formatter formatter) { + CleanProviderFormatter(Formatter formatter) { this.formatter = Objects.requireNonNull(formatter); } @@ -234,10 +237,19 @@ private void addIntendedLine(String indent, String line) { * sequence (\n, \r, \r\n). */ private String diff(File file) throws IOException { - return diff(formatter, file); + return diff(formatter, file).getKey(); } - public static String diff(CleanProvider formatter, File file) throws IOException { + /** + * Returns a map entry with key being a git-style diff between the contents of the given file and what those contents would + * look like if formatted using the given formatter. Does not end with any newline + * sequence (\n, \r, \r\n). The value of the map entry is the line where the first difference occurred. + */ + public static Map.Entry diff(Formatter formatter, File file) throws IOException { + return diff(new CleanProviderFormatter(formatter), file); + } + + private static Map.Entry diff(CleanProvider formatter, File file) throws IOException { String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding()); String rawUnix = LineEnding.toUnix(raw); String formatted = formatter.getFormatted(file, rawUnix); @@ -252,13 +264,13 @@ public static String diff(CleanProvider formatter, File file) throws IOException } /** - * Returns a git-style diff between the two unix strings. + * Returns a map entry with key being a git-style diff between the two unix strings and value being the line of the first difference (in the dirty string) *

* Output has no trailing newlines. *

* Boolean args determine whether whitespace or line endings will be visible. */ - private static String diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException { + private static Map.Entry diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException { dirty = visibleWhitespaceLineEndings(dirty, whitespace, lineEndings); clean = visibleWhitespaceLineEndings(clean, whitespace, lineEndings); @@ -275,7 +287,11 @@ private static String diffWhitespaceLineEndings(String dirty, String clean, bool // we don't need the diff to show this, since we display newlines ourselves formatted = formatted.replace("\\ No newline at end of file\n", ""); - return NEWLINE_MATCHER.trimTrailingFrom(formatted); + return new AbstractMap.SimpleEntry<>(NEWLINE_MATCHER.trimTrailingFrom(formatted), getLineOfFirstDifference(edits)); + } + + private static int getLineOfFirstDifference(EditList edits) { + return edits.stream().mapToInt(Edit::getBeginA).min().getAsInt(); } private static final CharMatcher NEWLINE_MATCHER = CharMatcher.is('\n'); 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 index 58e176f575..c0e959e362 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; @@ -28,7 +29,6 @@ import com.diffplug.spotless.Formatter; import com.diffplug.spotless.PaddedCell; import com.diffplug.spotless.extra.integration.DiffMessageFormatter; -import com.diffplug.spotless.extra.integration.DiffMessageFormatter.CleanProviderFormatter; import com.diffplug.spotless.maven.incremental.UpToDateChecker; /** @@ -57,7 +57,8 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke if (!dirtyState.isClean() && !dirtyState.didNotConverge()) { problemFiles.add(file); if (buildContext.isIncremental()) { - buildContext.addMessage(file, 0, 0, DiffMessageFormatter.diff(new CleanProviderFormatter(formatter), file), BuildContext.SEVERITY_ERROR, null); + Map.Entry diffEntry = DiffMessageFormatter.diff(formatter, file); + buildContext.addMessage(file, diffEntry.getValue(), 0, diffEntry.getKey(), BuildContext.SEVERITY_ERROR, null); } counter.cleaned(); } else { @@ -65,7 +66,7 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke upToDateChecker.setUpToDate(file.toPath()); } } catch (IOException | RuntimeException e) { - throw new MojoExecutionException("Unable to format file " + file, e); + throw new MojoExecutionException("Unable to check file " + file, e); } } From 0f2e67fa153c9d208c2ea837555937a2fbb7c985 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Fri, 8 Dec 2023 20:00:02 +0100 Subject: [PATCH 3/6] Line numbers must be 1-based --- .../java/com/diffplug/spotless/maven/SpotlessCheckMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index c0e959e362..d04cf46c73 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java @@ -58,7 +58,7 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke problemFiles.add(file); if (buildContext.isIncremental()) { Map.Entry diffEntry = DiffMessageFormatter.diff(formatter, file); - buildContext.addMessage(file, diffEntry.getValue(), 0, diffEntry.getKey(), BuildContext.SEVERITY_ERROR, null); + buildContext.addMessage(file, diffEntry.getValue() + 1, 0, diffEntry.getKey(), BuildContext.SEVERITY_ERROR, null); } counter.cleaned(); } else { From 7b65d9a2ba6fb3d6f60bdb5a0ea36f98bef5d769 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Sat, 9 Dec 2023 12:04:08 +0100 Subject: [PATCH 4/6] Swap key and value in map Use Map.entry() instead of AbstractMap.SimpleEntry() --- .../extra/integration/DiffMessageFormatter.java | 17 ++++++++--------- .../spotless/maven/SpotlessCheckMojo.java | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java index 1649d5aef4..9294055a4f 100644 --- a/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java +++ b/lib-extra/src/main/java/com/diffplug/spotless/extra/integration/DiffMessageFormatter.java @@ -22,7 +22,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.AbstractMap; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -237,19 +236,19 @@ private void addIntendedLine(String indent, String line) { * sequence (\n, \r, \r\n). */ private String diff(File file) throws IOException { - return diff(formatter, file).getKey(); + return diff(formatter, file).getValue(); } /** - * Returns a map entry with key being a git-style diff between the contents of the given file and what those contents would + * Returns a map entry with value being a git-style diff between the contents of the given file and what those contents would * look like if formatted using the given formatter. Does not end with any newline - * sequence (\n, \r, \r\n). The value of the map entry is the line where the first difference occurred. + * sequence (\n, \r, \r\n). The key of the map entry is the 0-based line where the first difference occurred. */ - public static Map.Entry diff(Formatter formatter, File file) throws IOException { + public static Map.Entry diff(Formatter formatter, File file) throws IOException { return diff(new CleanProviderFormatter(formatter), file); } - private static Map.Entry diff(CleanProvider formatter, File file) throws IOException { + private static Map.Entry diff(CleanProvider formatter, File file) throws IOException { String raw = new String(Files.readAllBytes(file.toPath()), formatter.getEncoding()); String rawUnix = LineEnding.toUnix(raw); String formatted = formatter.getFormatted(file, rawUnix); @@ -264,13 +263,13 @@ private static Map.Entry diff(CleanProvider formatter, File fil } /** - * Returns a map entry with key being a git-style diff between the two unix strings and value being the line of the first difference (in the dirty string) + * Returns a map entry with value being a git-style diff between the two unix strings and key being the 0-based line of the first difference (in the dirty string) *

* Output has no trailing newlines. *

* Boolean args determine whether whitespace or line endings will be visible. */ - private static Map.Entry diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException { + private static Map.Entry diffWhitespaceLineEndings(String dirty, String clean, boolean whitespace, boolean lineEndings) throws IOException { dirty = visibleWhitespaceLineEndings(dirty, whitespace, lineEndings); clean = visibleWhitespaceLineEndings(clean, whitespace, lineEndings); @@ -287,7 +286,7 @@ private static Map.Entry diffWhitespaceLineEndings(String dirty // we don't need the diff to show this, since we display newlines ourselves formatted = formatted.replace("\\ No newline at end of file\n", ""); - return new AbstractMap.SimpleEntry<>(NEWLINE_MATCHER.trimTrailingFrom(formatted), getLineOfFirstDifference(edits)); + return Map.entry(getLineOfFirstDifference(edits), NEWLINE_MATCHER.trimTrailingFrom(formatted)); } private static int getLineOfFirstDifference(EditList edits) { 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 index d04cf46c73..cc83b3f3c9 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java @@ -57,8 +57,8 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke if (!dirtyState.isClean() && !dirtyState.didNotConverge()) { problemFiles.add(file); if (buildContext.isIncremental()) { - Map.Entry diffEntry = DiffMessageFormatter.diff(formatter, file); - buildContext.addMessage(file, diffEntry.getValue() + 1, 0, diffEntry.getKey(), BuildContext.SEVERITY_ERROR, null); + Map.Entry diffEntry = DiffMessageFormatter.diff(formatter, file); + buildContext.addMessage(file, diffEntry.getKey() + 1, 0, diffEntry.getValue(), BuildContext.SEVERITY_ERROR, null); } counter.cleaned(); } else { From 478135bab9a0d183527fcaa7e3bbdd625c753a7d Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Thu, 14 Dec 2023 20:28:16 +0100 Subject: [PATCH 5/6] Add changelog entries --- CHANGES.md | 1 + plugin-maven/CHANGES.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 8293abcd22..13b18f6ecf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Changes +* Add new static method to `DiffMessageFormatter` which allows to retrieve diffs with their line numbers ([#1960](https://github.com/diffplug/spotless/issues/1960)) * Use palantir-java-format 2.39.0 on Java 21. ([#1948](https://github.com/diffplug/spotless/pull/1948)) ## [2.43.1] - 2023-12-04 diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 4fab316049..84d21f29b7 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,6 +4,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Changes +* M2E support: Emit file specific errors during incremental build. ([#1960](https://github.com/diffplug/spotless/issues/1960)) * Use palantir-java-format 2.39.0 on Java 21. ([#1948](https://github.com/diffplug/spotless/pull/1948)) ## [2.41.1] - 2023-12-04 From a4641caf52e469a2b5513a5849e0fe22fc92f4a1 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Fri, 15 Dec 2023 15:27:06 -0800 Subject: [PATCH 6/6] Minor update to changelog entries. --- CHANGES.md | 3 ++- plugin-maven/CHANGES.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 13b18f6ecf..dc040c9aa2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,8 +10,9 @@ This document is intended for Spotless developers. We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +* New static method to `DiffMessageFormatter` which allows to retrieve diffs with their line numbers ([#1960](https://github.com/diffplug/spotless/issues/1960)) ### Changes -* Add new static method to `DiffMessageFormatter` which allows to retrieve diffs with their line numbers ([#1960](https://github.com/diffplug/spotless/issues/1960)) * Use palantir-java-format 2.39.0 on Java 21. ([#1948](https://github.com/diffplug/spotless/pull/1948)) ## [2.43.1] - 2023-12-04 diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 84d21f29b7..55f451ad4e 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,8 +3,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] -### Changes +### Added * M2E support: Emit file specific errors during incremental build. ([#1960](https://github.com/diffplug/spotless/issues/1960)) +### Changes * Use palantir-java-format 2.39.0 on Java 21. ([#1948](https://github.com/diffplug/spotless/pull/1948)) ## [2.41.1] - 2023-12-04