diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ee7614..89838f6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ Changelog of Violations lib. +## Unreleased +### GitHub [#95](https://github.com/tomasbjerre/violations-lib/issues/95) Add support for "suggested change" *enhancement* + +**DiffParser** + + +[e282c85c4e58980](https://github.com/tomasbjerre/violations-lib/commit/e282c85c4e58980) Tomas Bjerre *2020-09-06 07:03:03* + + ## 1.127 ### GitHub [#95](https://github.com/tomasbjerre/violations-lib/issues/95) Add support for "suggested change" *enhancement* diff --git a/README.md b/README.md index ad489274..f66a94ac 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ A number of **parsers** have been implemented. Some **parsers** can parse output | [_PHPCS_](https://github.com/squizlabs/PHP_CodeSniffer) | `CHECKSTYLE` | With `phpcs api.php --report=checkstyle`. | [_PHPPMD_](https://phpmd.org/) | `PMD` | With `phpmd api.php xml ruleset.xml`. | [_PMD_](https://pmd.github.io/) | `PMD` | +| [_Patch_](https://en.wikipedia.org/wiki/Diff) | `DIFF` | Unidiff, often used by the `patch` program. | [_Pep8_](https://github.com/PyCQA/pycodestyle) | `FLAKE8` | | [_PerlCritic_](https://github.com/Perl-Critic) | `PERLCRITIC` | | [_PiTest_](http://pitest.org/) | `PITEST` | diff --git a/build.gradle b/build.gradle index 74ac4014..2d08813c 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ apply from: project.buildscript.classLoader.getResource('release.gradle').toURI( dependencies { compile 'com.google.code.gson:gson:2.8.2' + compile 'io.github.java-diff-utils:java-diff-utils:4.7' compileOnly 'com.github.spotbugs:spotbugs-annotations:3.1.12' testCompile 'junit:junit:4.12' testCompile 'org.assertj:assertj-core:2.3.0' @@ -28,6 +29,7 @@ dependencies { } shadowJar { + relocate 'io.github', safeJavaIdentidier(project.group + '.' + project.name + '.io.github') relocate 'com.google', safeJavaIdentidier(project.group + '.' + project.name + '.com.google') relocate 'com.jakewharton', safeJavaIdentidier(project.group + '.' + project.name + '.com.jakewharton') } diff --git a/src/main/java/se/bjurr/violations/lib/parsers/DiffParser.java b/src/main/java/se/bjurr/violations/lib/parsers/DiffParser.java new file mode 100644 index 00000000..9659d2d2 --- /dev/null +++ b/src/main/java/se/bjurr/violations/lib/parsers/DiffParser.java @@ -0,0 +1,103 @@ +package se.bjurr.violations.lib.parsers; + +import static com.github.difflib.patch.DeltaType.CHANGE; +import static com.github.difflib.patch.DeltaType.DELETE; +import static com.github.difflib.patch.DeltaType.EQUAL; +import static com.github.difflib.patch.DeltaType.INSERT; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.stream.Collectors.joining; +import static se.bjurr.violations.lib.model.SEVERITY.ERROR; +import static se.bjurr.violations.lib.model.Violation.violationBuilder; +import static se.bjurr.violations.lib.reports.Parser.DIFF; + +import com.github.difflib.patch.AbstractDelta; +import com.github.difflib.patch.Patch; +import com.github.difflib.unifieddiff.UnifiedDiff; +import com.github.difflib.unifieddiff.UnifiedDiffFile; +import com.github.difflib.unifieddiff.UnifiedDiffReader; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import se.bjurr.violations.lib.ViolationsLogger; +import se.bjurr.violations.lib.model.Violation; + +public class DiffParser implements ViolationsParser { + + @Override + public Set parseReportOutput(String reportContent, ViolationsLogger violationsLogger) + throws Exception { + Set violations = new TreeSet<>(); + InputStream reportContentStream = new ByteArrayInputStream(reportContent.getBytes(UTF_8)); + UnifiedDiff parsedDiff = UnifiedDiffReader.parseUnifiedDiff(reportContentStream); + for (UnifiedDiffFile diffFile : parsedDiff.getFiles()) { + String file = diffFile.getFromFile(); + Patch patch = diffFile.getPatch(); + for (AbstractDelta delta : patch.getDeltas()) { + String fromString = toString(delta.getSource().getLines()); + int fromLine = delta.getSource().getPosition(); + String toString = toString(delta.getTarget().getLines()); + int toLine = delta.getTarget().getPosition(); + + String message = ""; + + if (delta.getType() == CHANGE) { + message = + "Change line " + + fromLine + + ":\n\n" + + fromString + + "\n\nTo line " + + toLine + + ":\n\n" + + toString; + } else if (delta.getType() == DELETE) { + message = + "Delete line " + + fromLine + + ":\n\n" + + fromString + + "\n\nTo line " + + toLine + + ":\n\n" + + toString; + } else if (delta.getType() == EQUAL) { + message = + "Equal line " + + fromLine + + ":\n\n" + + fromString + + "\n\nTo line " + + toLine + + ":\n\n" + + toString; + } else if (delta.getType() == INSERT) { + message = + "Insert line " + + fromLine + + ":\n\n" + + fromString + + "\n\nTo line " + + toLine + + ":\n\n" + + toString; + } + + violations.add( + violationBuilder() + .setParser(DIFF) + .setFile(file) + .setStartLine(fromLine) + .setMessage(message) + .setSeverity(ERROR) + .build()); + } + } + return violations; + } + + private String toString(List lines) { + return lines.stream().collect(joining("\n")).trim(); + } +} diff --git a/src/main/java/se/bjurr/violations/lib/reports/Parser.java b/src/main/java/se/bjurr/violations/lib/reports/Parser.java index 86f2ff22..c3131717 100644 --- a/src/main/java/se/bjurr/violations/lib/reports/Parser.java +++ b/src/main/java/se/bjurr/violations/lib/reports/Parser.java @@ -20,6 +20,7 @@ import se.bjurr.violations.lib.parsers.CodeClimateParser; import se.bjurr.violations.lib.parsers.CodeNarcParser; import se.bjurr.violations.lib.parsers.CppLintParser; +import se.bjurr.violations.lib.parsers.DiffParser; import se.bjurr.violations.lib.parsers.DocFXParser; import se.bjurr.violations.lib.parsers.FindbugsParser; import se.bjurr.violations.lib.parsers.Flake8Parser; @@ -79,6 +80,7 @@ public enum Parser { KOTLINGRADLE(new KotlinGradleParser()), // MSCPP(new MSCPPParser()), // MYPY(new MyPyParser()), // + DIFF(new DiffParser()), // GOLINT(new GoLintParser()), // GOOGLEERRORPRONE(new GoogleErrorProneParser()), // PERLCRITIC(new PerlCriticParser()), // diff --git a/src/main/java/se/bjurr/violations/lib/reports/Reporter.java b/src/main/java/se/bjurr/violations/lib/reports/Reporter.java index 9ebab6dc..9072b664 100644 --- a/src/main/java/se/bjurr/violations/lib/reports/Reporter.java +++ b/src/main/java/se/bjurr/violations/lib/reports/Reporter.java @@ -97,6 +97,11 @@ public enum Reporter { Parser.GOOGLEERRORPRONE, "https://github.com/uber/NullAway", "Same format as Google Error Prone."), + DIFF( + "Patch", + Parser.DIFF, + "https://en.wikipedia.org/wiki/Diff", + "Unidiff, often used by the `patch` program."), PCLINT( "PCLint", Parser.PCLINT, diff --git a/src/test/java/se/bjurr/violations/lib/DiffTest.java b/src/test/java/se/bjurr/violations/lib/DiffTest.java new file mode 100644 index 00000000..ce932a4c --- /dev/null +++ b/src/test/java/se/bjurr/violations/lib/DiffTest.java @@ -0,0 +1,50 @@ +package se.bjurr.violations.lib; + +import static org.assertj.core.api.Assertions.assertThat; +import static se.bjurr.violations.lib.TestUtils.getRootFolder; +import static se.bjurr.violations.lib.ViolationsApi.violationsApi; +import static se.bjurr.violations.lib.model.SEVERITY.ERROR; +import static se.bjurr.violations.lib.reports.Parser.DIFF; + +import java.util.ArrayList; +import java.util.Set; +import org.junit.Test; +import se.bjurr.violations.lib.model.Violation; + +public class DiffTest { + + @Test + public void testChange() { + final String rootFolder = getRootFolder(); + + final Set actual = + violationsApi() // + .withPattern(".*/diff/0001-.*") // + .inFolder(rootFolder) // + .findAll(DIFF) // + .violations(); + + assertThat(actual) // + .hasSize(2); + + Violation v0 = new ArrayList<>(actual).get(0); + assertThat(v0.getMessage()) // + .contains("Changelog of Violations lib"); + assertThat(v0.getFile()) // + .isEqualTo("CHANGELOG.md"); + assertThat(v0.getSeverity()) // + .isEqualTo(ERROR); + assertThat(v0.getStartLine()) // + .isEqualTo(2); + + Violation v1 = new ArrayList<>(actual).get(1); + assertThat(v1.getMessage()) // + .contains("version = 1.127"); + assertThat(v1.getFile()) // + .isEqualTo("gradle.properties"); + assertThat(v1.getSeverity()) // + .isEqualTo(ERROR); + assertThat(v1.getStartLine()) // + .isEqualTo(0); + } +} diff --git a/src/test/resources/diff/0001-Gradle-Release-Plugin-new-version-commit-1.128-SNAPS.patch b/src/test/resources/diff/0001-Gradle-Release-Plugin-new-version-commit-1.128-SNAPS.patch new file mode 100644 index 00000000..d1e5c30f --- /dev/null +++ b/src/test/resources/diff/0001-Gradle-Release-Plugin-new-version-commit-1.128-SNAPS.patch @@ -0,0 +1,41 @@ +From 513d19e33d0a78b778bc2cd33551a300e7605975 Mon Sep 17 00:00:00 2001 +From: Tomas Bjerre +Date: Sun, 6 Sep 2020 07:26:13 +0200 +Subject: [PATCH] [Gradle Release Plugin] - new version commit: + '1.128-SNAPSHOT'. + +--- + CHANGELOG.md | 9 +++++++++ + gradle.properties | 2 +- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index 7b2cb23..a1ee761 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -3,6 +3,15 @@ + + Changelog of Violations lib. + ++## 1.127 ++### GitHub [#95](https://github.com/tomasbjerre/violations-lib/issues/95) Add support for "suggested change" *enhancement* ++ ++**Moving PatchParser from violation-comments-lib** ++ ++ ++[5c52a3933792d14](https://github.com/tomasbjerre/violations-lib/commit/5c52a3933792d14) Tomas Bjerre *2020-09-06 05:24:56* ++ ++ + ## 1.126 + ### GitHub [#95](https://github.com/tomasbjerre/violations-lib/issues/95) Add support for "suggested change" *enhancement* + +diff --git a/gradle.properties b/gradle.properties +index aca4c1a..eda4430 100644 +--- a/gradle.properties ++++ b/gradle.properties +@@ -1 +1 @@ +-version = 1.127 ++version = 1.128-SNAPSHOT +-- +2.25.1 +