-
Notifications
You must be signed in to change notification settings - Fork 89
/
Diff.scala
112 lines (102 loc) · 3.21 KB
/
Diff.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package munit.diff
import munit.diff.console.Printers
import munit.diff.console.AnsiColors
import scala.collection.JavaConverters._
class Diff(val obtained: String, val expected: String) extends Serializable {
val obtainedClean: String = AnsiColors.filterAnsi(obtained)
val expectedClean: String = AnsiColors.filterAnsi(expected)
val obtainedLines: Seq[String] = splitIntoLines(obtainedClean)
val expectedLines: Seq[String] = splitIntoLines(expectedClean)
val unifiedDiff: String = createUnifiedDiff(obtainedLines, expectedLines)
def isEmpty: Boolean = unifiedDiff.isEmpty()
def createReport(
title: String,
printObtainedAsStripMargin: Boolean = true
): String = {
val sb = new StringBuilder
if (title.nonEmpty) {
sb.append(title)
.append("\n")
}
if (obtainedClean.length < 1000) {
header("Obtained", sb).append("\n")
if (printObtainedAsStripMargin) {
sb.append(asStripMargin(obtainedClean))
} else {
sb.append(obtainedClean)
}
sb.append("\n")
}
appendDiffOnlyReport(sb)
sb.toString()
}
def createDiffOnlyReport(): String = {
val out = new StringBuilder
appendDiffOnlyReport(out)
out.toString()
}
private def appendDiffOnlyReport(sb: StringBuilder): Unit = {
header("Diff", sb)
val red = AnsiColors.use(AnsiColors.LightRed)
val reset = AnsiColors.use(AnsiColors.Reset)
val green = AnsiColors.use(AnsiColors.LightGreen)
sb.append(s" (${red}- obtained${reset}, ${green}+ expected${reset})")
sb.append("\n")
sb.append(unifiedDiff)
}
private def asStripMargin(obtained: String): String = {
if (!obtained.contains("\n")) Printers.print(obtained)
else {
val out = new StringBuilder
val lines = obtained.trim.linesIterator
val head = if (lines.hasNext) lines.next() else ""
out.append(" \"\"\"|" + head + "\n")
lines.foreach(line => {
out.append(" |").append(line).append("\n")
})
out.append(" |\"\"\".stripMargin")
out.toString()
}
}
private def header(t: String, sb: StringBuilder): StringBuilder = {
sb.append(AnsiColors.c(s"=> $t", AnsiColors.Bold))
}
private def createUnifiedDiff(
original: Seq[String],
revised: Seq[String]
): String = {
val diff = DiffUtils.diff(original.asJava, revised.asJava)
val result =
if (diff.getDeltas.isEmpty) ""
else {
DiffUtils
.generateUnifiedDiff(
"obtained",
"expected",
original.asJava,
diff,
1
)
.asScala
.iterator
.drop(2)
.filterNot(_.startsWith("@@"))
.map { line =>
if (line.isEmpty()) line
else if (line.last == ' ') line + "∙"
else line
}
.map { line =>
if (line.startsWith("-")) AnsiColors.c(line, AnsiColors.LightRed)
else if (line.startsWith("+"))
AnsiColors.c(line, AnsiColors.LightGreen)
else line
}
.mkString("\n")
}
result
}
private def splitIntoLines(string: String): Seq[String] = {
string.trim().replace("\r\n", "\n").split("\n").toIndexedSeq
}
}