diff --git a/src/main/java/se/bjurr/violations/lib/util/PatchParser.java b/src/main/java/se/bjurr/violations/lib/util/PatchParser.java new file mode 100644 index 00000000..243c0297 --- /dev/null +++ b/src/main/java/se/bjurr/violations/lib/util/PatchParser.java @@ -0,0 +1,75 @@ +package se.bjurr.violations.lib.util; + +import static java.util.Optional.empty; +import static java.util.Optional.of; + +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PatchParser { + + private static final Pattern RANGE_PATTERN = + Pattern.compile( + "@@\\p{IsWhite_Space}-[0-9]+(?:,[0-9]+)?\\p{IsWhite_Space}\\+([0-9]+)(?:,[0-9]+)?\\p{IsWhite_Space}@@.*"); + + private final Map> newLineToOldLineTable; + private final Map> newLineToLineInDiffTable; + + public PatchParser(String patchString) { + newLineToOldLineTable = new TreeMap<>(); + newLineToLineInDiffTable = new TreeMap<>(); + if (patchString == null) { + return; + } + int currentLine = -1; + int patchLocation = 1; + int diffLocation = 0; + for (String line : patchString.split("\n")) { + if (line.startsWith("@")) { + Matcher matcher = RANGE_PATTERN.matcher(line); + if (!matcher.matches()) { + throw new IllegalStateException( + "Unable to parse patch line " + line + "\nFull patch: \n" + patchString); + } + currentLine = Integer.parseInt(matcher.group(1)); + patchLocation = currentLine; + } else if (line.startsWith("+") && !line.startsWith("++")) { + newLineToOldLineTable.put(currentLine, empty()); + currentLine++; + } else if (line.startsWith(" ")) { + newLineToOldLineTable.put(currentLine, of(patchLocation)); + currentLine++; + patchLocation++; + } else { + patchLocation++; + } + diffLocation++; + newLineToLineInDiffTable.put(currentLine, of(diffLocation)); + } + } + + public boolean isLineInDiff(Integer newLine) { + return newLineToLineInDiffTable.containsKey(newLine); + } + + public Optional findOldLine(Integer newLine) { + if (newLineToOldLineTable.containsKey(newLine)) { + return newLineToOldLineTable.get(newLine); + } + return empty(); + } + + public Optional findLineInDiff(final int newLine) { + if (newLineToLineInDiffTable.containsKey(newLine)) { + return newLineToLineInDiffTable.get(newLine); + } + return empty(); + } + + Map> getNewLineToOldLineTable() { + return newLineToOldLineTable; + } +} diff --git a/src/test/java/se/bjurr/violations/lib/util/PatchParserTest.java b/src/test/java/se/bjurr/violations/lib/util/PatchParserTest.java new file mode 100644 index 00000000..3bc57b22 --- /dev/null +++ b/src/test/java/se/bjurr/violations/lib/util/PatchParserTest.java @@ -0,0 +1,147 @@ +package se.bjurr.violations.lib.util; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; +import java.util.Optional; +import java.util.logging.Logger; +import org.junit.Test; + +public class PatchParserTest { + private static Logger LOG = Logger.getLogger(PatchParser.class.getSimpleName()); + + private static final String NEW_DIFF = + "@@ -1,6 +1,6 @@\n \n \n \n-\n+ \n \n "; + private static final String CHANGED_DIFF = + " @@ -1,4 +1,5 @@\n .klass {\n font-size: 14px;\n+ \n font-size: 14px;\n }"; + private static final String CHANGED_DIFF_2 = + "@@ -6,6 +6,16 @@\n void npe(String a, String b) {\n if (a == null) {\n System.out.println();\n+ System.out.println();\n+ } else {\n+\n+ }\n+ a.length();\n+ }\n+\n+ void npe2(String a, String b) {\n+ if (a == null) {\n+ System.out.println();\n } else {\n \n }\n@@ -14,6 +24,6 @@ void npe(String a, String b) {\n \n @Override\n public boolean equals(Object obj) {\n- return true;\n+ return false;\n }\n }"; + + @Test + public void testThatChangedContentCanBeCommented() { + assertThat(findLineToComment("patch", 1)) // + .isNull(); + } + + @Test + public void testThatChangedContentCanBeCommentedNewFile() { + assertThat(findLineToComment(NEW_DIFF, 1)) // + .isEqualTo(1); + + assertThat(findLineToComment(NEW_DIFF, 5)) // + .isEqualTo(6); + } + + @Test + public void testThatChangedContentCanBeCommentedChangedFile() { + assertThat(findLineToComment(CHANGED_DIFF, 1)) // + .isEqualTo(2); + + assertThat(findLineToComment(CHANGED_DIFF, 4)) // + .isEqualTo(5); + } + + @Test + public void testThatChangedContentCanBeCommentedChangedPartsOfFile() { + assertThat(findLineToComment(CHANGED_DIFF_2, 6)) // + .isEqualTo(1); + + assertThat(findLineToComment(CHANGED_DIFF_2, 8)) // + .isEqualTo(3); + + assertThat(findLineToComment(CHANGED_DIFF_2, 14)) // + .isEqualTo(9); + + assertThat(findLineToComment(CHANGED_DIFF_2, 21)) // + .isEqualTo(16); + } + + @Test + public void testThatOldLineIsEmptyIfOutsideOfDiff() { + String patch = + "--- a/src/main/java/se/bjurr/violations/lib/example/OtherClass.java\n+++ b/src/main/java/se/bjurr/violations/lib/example/OtherClass.java\n@@ -4,12 +4,15 @@ package se.bjurr.violations.lib.example;\n * No ending dot\n */\n public class OtherClass {\n- public static String CoNstANT = \"yes\";\n+ public static String CoNstANT = \"yes\"; \n \n public void myMethod() {\n if (CoNstANT.equals(\"abc\")) {\n \n }\n+ if (CoNstANT.equals(\"abc\")) {\n+\n+ }\n }\n \n @Override\n"; + + getIntegerOptionalMap(patch); + + final PatchParser pp = new PatchParser(patch); + + assertThat(pp.isLineInDiff(999)) // + .isFalse(); + assertThat(pp.findOldLine(999).orElse(null)) // + .isNull(); + assertThat(pp.findLineInDiff(999).orElse(null)) // + .isNull(); + + assertThat(pp.isLineInDiff(6)) // + .isTrue(); + assertThat(pp.findOldLine(6).orElse(null)) // + .isEqualTo(6); + assertThat(pp.findLineInDiff(6).orElse(null)) // + .isEqualTo(5); + } + + @Test + public void testThatLineTableCanBeRetrieved() { + String patch = + "--- a/src/main/java/se/bjurr/violations/lib/example/OtherClass.java\n+++ b/src/main/java/se/bjurr/violations/lib/example/OtherClass.java\n@@ -4,12 +4,15 @@ package se.bjurr.violations.lib.example;\n * No ending dot\n */\n public class OtherClass {\n- public static String CoNstANT = \"yes\";\n+ public static String CoNstANT = \"yes\"; \n \n public void myMethod() {\n if (CoNstANT.equals(\"abc\")) {\n \n }\n+ if (CoNstANT.equals(\"abc\")) {\n+\n+ }\n }\n \n @Override\n"; + final Map> map = getIntegerOptionalMap(patch); + + assertThat(map.get(6).orElse(null)) // + .isEqualTo(6); + assertThat(map.get(7).orElse(null)) // + .isNull(); + assertThat(map.get(8).orElse(null)) // + .isEqualTo(8); + + assertThat(map.get(12).orElse(null)) // + .isEqualTo(12); + assertThat(map.get(13).orElse(null)) // + .isNull(); + assertThat(map.get(14).orElse(null)) // + .isNull(); + assertThat(map.get(15).orElse(null)) // + .isNull(); + assertThat(map.get(16).orElse(null)) // + .isEqualTo(13); + } + + @Test + public void testThatLineTableCanBeRetrieved2() { + String patch = + "--- a/src/main/java/se/bjurr/violations/lib/example/MyClass.java\n+++ b/src/main/java/se/bjurr/violations/lib/example/MyClass.java\n@@ -9,6 +9,8 @@ public class MyClass {\n } else {\n \n }\n+ if (a == null)\n+ a.charAt(123);\n a.length();\n }\n \n"; + final Map> map = getIntegerOptionalMap(patch); + + assertThat(map.get(11).orElse(null)) // + .isEqualTo(11); + assertThat(map.get(12).orElse(null)) // + .isNull(); + assertThat(map.get(13).orElse(null)) // + .isNull(); + assertThat(map.get(14).orElse(null)) // + .isEqualTo(12); + } + + private Integer findLineToComment(String patch, int commentLint) { + getIntegerOptionalMap(patch); + + return new PatchParser(patch) // + .findLineInDiff(commentLint) // + .orElse(null); + } + + private Map> getIntegerOptionalMap(final String patch) { + String[] diffLines = patch.split("\n"); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < diffLines.length; i++) { + sb.append(i + 1 + " | " + diffLines[i] + "\n"); + } + final Map> map = + new PatchParser(patch) // + .getNewLineToOldLineTable(); + for (Map.Entry> e : map.entrySet()) { + sb.append(e.getKey() + " : " + e.getValue().orElse(null) + "\n"); + } + LOG.info("\n" + sb.toString()); + return map; + } +}