Improve diff algorithm
This commit is contained in:
@@ -364,11 +364,7 @@ public class NoBuild {
|
||||
* @throws Exception
|
||||
*/
|
||||
public static int commandThrows(String... command) throws IOException {
|
||||
ProcessBuilder pb =
|
||||
new ProcessBuilder(command)
|
||||
.redirectInput(Redirect.INHERIT)
|
||||
.redirectOutput(Redirect.INHERIT)
|
||||
.redirectError(Redirect.INHERIT);
|
||||
ProcessBuilder pb = new ProcessBuilder(command).inheritIO();
|
||||
Process process;
|
||||
try {
|
||||
process = pb.start();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import static notest.Test.Util.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import notest.Test;
|
||||
|
||||
@@ -15,21 +15,21 @@ class TestJtags {
|
||||
|
||||
@Test
|
||||
static void basicExample() throws IOException {
|
||||
Path file = Files.createTempFile("jtags", null);
|
||||
var tags =
|
||||
var process =
|
||||
runJava(
|
||||
new String[] {"-Dlogger.level=CONFIG"},
|
||||
Jtags,
|
||||
"-o",
|
||||
"-",
|
||||
"src/test/java/examples/BasicExample.java")
|
||||
.inputReader();
|
||||
"src/test/java/examples/BasicExample.java");
|
||||
|
||||
var tags = readAllLines(process.inputReader());
|
||||
|
||||
Diff.diff(
|
||||
tags,
|
||||
new FileReader(
|
||||
readAllLines(new BufferedReader(new FileReader(
|
||||
Path.of("src", "test", "java", "snapshots", "BasicExample.basicExample.1")
|
||||
.toFile()))
|
||||
.assertEquals();
|
||||
.toFile()))))
|
||||
.assertEqual();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ package notest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -42,7 +41,6 @@ import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.IntSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -84,13 +82,13 @@ public @interface Test {
|
||||
System.err.println(ex.toString());
|
||||
System.err.println();
|
||||
return 0;
|
||||
} catch (InvocationTargetException ex) {
|
||||
System.err.println(
|
||||
boxMiddle(ex.getTargetException().getClass().getSimpleName(), 50));
|
||||
System.err.println(
|
||||
boxLeft(
|
||||
Optional.ofNullable(ex.getTargetException().getMessage())
|
||||
.orElse("")));
|
||||
} catch (InvocationTargetException invocationException) {
|
||||
var ex = invocationException.getTargetException();
|
||||
System.err.println(boxMiddle(ex.getClass().getSimpleName(), 50));
|
||||
System.err.println(boxLeft(Optional.ofNullable(ex.getMessage()).orElse("")));
|
||||
if (!(ex instanceof AssertionError)) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
System.err.println(boxBottom(it.getName() + ": FAIL", 50));
|
||||
System.err.println();
|
||||
return 0;
|
||||
@@ -170,51 +168,50 @@ public @interface Test {
|
||||
}
|
||||
}
|
||||
|
||||
/** Representation of changes between two string sequences */
|
||||
public static record Diff(List<String> diff) {
|
||||
|
||||
public static Diff diff(Reader readerA, Reader readerB) throws IOException {
|
||||
List<String> diff = new ArrayList<>();
|
||||
|
||||
BufferedReader
|
||||
bufReaderA = readerA instanceof BufferedReader ra ? ra : new BufferedReader(readerA),
|
||||
bufReaderB = readerB instanceof BufferedReader rb ? rb : new BufferedReader(readerB);
|
||||
|
||||
String a = bufReaderA.readLine(), b = bufReaderB.readLine();
|
||||
boolean different = false;
|
||||
while (a != null || b != null) {
|
||||
if (a == null || b == null || (a != null && !a.equals(b))) {
|
||||
different = true;
|
||||
if (a != null) {
|
||||
diff.add("-" + a);
|
||||
/** Creates a {@code Diff} representing changes from {@code a} to {@code b} */
|
||||
public static Diff diff(List<String> a, List<String> b) {
|
||||
int diffSize = 0;
|
||||
// longest common subsequence algorithm
|
||||
int[][] dp = new int[a.size() + 1][b.size() + 1];
|
||||
for (int i = 1; i <= a.size(); i++) {
|
||||
for (int j = 1; j <= b.size(); j++) {
|
||||
if (a.get(i - 1).equals(b.get(j - 1))) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
|
||||
}
|
||||
if (b != null) {
|
||||
diff.add("+" + b);
|
||||
}
|
||||
} else {
|
||||
diff.add(" " + a);
|
||||
}
|
||||
|
||||
a = bufReaderA.readLine();
|
||||
b = bufReaderB.readLine();
|
||||
}
|
||||
|
||||
if (different) {
|
||||
diff.sort(
|
||||
new Comparator<String>() {
|
||||
public int compare(String s1, String s2) {
|
||||
char a = s1.charAt(0), b = s2.charAt(0);
|
||||
if (a == ' ' || b == ' ') return 0;
|
||||
return b - a;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
diff = List.of();
|
||||
int lcs = dp[a.size()][b.size()];
|
||||
if (lcs == a.size()) return new Diff(List.of());
|
||||
|
||||
List<String> diff = new ArrayList<>(a.size());
|
||||
int i = a.size(), j = b.size();
|
||||
while (true) {
|
||||
if (i > 0 && j > 0 && a.get(i - 1).equals(b.get(j - 1))) {
|
||||
diff.add(" " + a.get(i - 1));
|
||||
i--;
|
||||
j--;
|
||||
} else if (j > 0 && (i == 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
||||
if (j > 0) diff.add("+" + b.get(j - 1));
|
||||
j--;
|
||||
} else if (i > 0 && (j == 0 || dp[i][j - 1] < dp[i - 1][j])) {
|
||||
if (i > 0) diff.add("-" + a.get(i - 1));
|
||||
i--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Diff(diff);
|
||||
return new Diff(diff.reversed());
|
||||
}
|
||||
|
||||
public void assertEquals() {
|
||||
/** Asserts that the two sequences are the same */
|
||||
public void assertEqual() {
|
||||
if (diff.isEmpty()) return;
|
||||
|
||||
throw new AssertionError(
|
||||
@@ -246,6 +243,14 @@ public @interface Test {
|
||||
}
|
||||
}
|
||||
|
||||
/** Reads all lines from {@code reader} */
|
||||
public static List<String> readAllLines(BufferedReader reader) throws IOException {
|
||||
var lines = new ArrayList<String>();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) lines.add(line);
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads string to center.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
ABC
|
||||
!_TAG_FILE_ENCODING utf-8
|
||||
!_TAG_FILE_SORTED 2 /0=unsorted, 1=sorted, 2=foldcase/
|
||||
BasicExample src/test/java/examples/BasicExample.java /^public class BasicExample {$/;" Cls package:examples
|
||||
@@ -5,5 +6,4 @@ InnerClass src/test/java/examples/BasicExample.java /^ class InnerClass {$/;"
|
||||
method1 src/test/java/examples/BasicExample.java /^ private boolean method1() {$/;" mthd class:BasicExample
|
||||
ABC lorem ipsum dolor
|
||||
method2 src/test/java/examples/BasicExample.java /^ public static void method2($/;" mthd file: class:BasicExample
|
||||
method3 src/test/java/examples/BasicExample.java /^ void method3() {}$/;" mthd class:InnerClass
|
||||
method4 src/test/java/examples/BasicExample.java /^ private void method4() {}$/;" mthd class:InnerClass
|
||||
|
||||
Reference in New Issue
Block a user