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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package dotty.tools
package dotc
package reporting
import java.io.{ PrintStream, PrintWriter, File => JFile, FileOutputStream }
import java.text.SimpleDateFormat
import java.util.Date
import scala.collection.mutable
import util.SourcePosition
import core.Contexts._
import Reporter._
import diagnostic.{ Message, MessageContainer, NoExplanation }
import diagnostic.messages._
import interfaces.Diagnostic.{ ERROR, WARNING, INFO }
class TestReporter protected (outWriter: PrintWriter, filePrintln: String => Unit, logLevel: Int)
extends Reporter with UniqueMessagePositions with HideNonSensicalMessages with MessageRendering {
import MessageContainer._
protected final val _errorBuf = mutable.ArrayBuffer.empty[MessageContainer]
final def errors: Iterator[MessageContainer] = _errorBuf.iterator
protected final val _messageBuf = mutable.ArrayBuffer.empty[String]
final def messages: Iterator[String] = _messageBuf.iterator
private[this] var _didCrash = false
final def compilerCrashed: Boolean = _didCrash
final def flushToFile(): Unit =
_messageBuf
.iterator
.map(_.replaceAll("\u001b\\[.*?m", ""))
.foreach(filePrintln)
final def flushToStdErr(): Unit =
_messageBuf
.iterator
.foreach(System.err.println)
final def inlineInfo(pos: SourcePosition): String =
if (pos.exists) {
if (pos.outer.exists)
s"\ninlined at ${pos.outer}:\n" + inlineInfo(pos.outer)
else ""
}
else ""
def log(msg: String) =
_messageBuf.append(msg)
def logStackTrace(thrown: Throwable): Unit = {
_didCrash = true
val sw = new java.io.StringWriter
val pw = new java.io.PrintWriter(sw)
thrown.printStackTrace(pw)
log(sw.toString)
}
/** Prints the message with the given position indication. */
def printMessageAndPos(m: MessageContainer, extra: String)(implicit ctx: Context): Unit = {
val msg = messageAndPos(m.contained, m.pos, diagnosticLevel(m))
val extraInfo = inlineInfo(m.pos)
if (m.level >= logLevel) {
outWriter.println(msg)
if (extraInfo.nonEmpty) outWriter.println(extraInfo)
}
_messageBuf.append(msg)
if (extraInfo.nonEmpty) _messageBuf.append(extraInfo)
}
override def doReport(m: MessageContainer)(implicit ctx: Context): Unit = {
// Here we add extra information that we should know about the error message
val extra = m.contained match {
case pm: PatternMatchExhaustivity => s": ${pm.uncovered}"
case _ => ""
}
m match {
case m: Error => {
_errorBuf.append(m)
printMessageAndPos(m, extra)
}
case m =>
printMessageAndPos(m, extra)
}
}
}
object TestReporter {
lazy val logWriter = {
val df = new SimpleDateFormat("yyyy-MM-dd-HH:mm")
val timestamp = df.format(new Date)
new JFile("../testlogs").mkdirs()
new PrintWriter(new FileOutputStream(new JFile(s"../testlogs/tests-$timestamp.log"), true))
}
def writeToLog(str: String) = {
logWriter.println(str)
logWriter.flush()
}
def reporter(ps: PrintStream, logLevel: Int): TestReporter =
new TestReporter(new PrintWriter(ps, true), writeToLog, logLevel)
def simplifiedReporter(writer: PrintWriter): TestReporter = {
val rep = new TestReporter(writer, writeToLog, WARNING) {
/** Prints the message with the given position indication in a simplified manner */
override def printMessageAndPos(m: MessageContainer, extra: String)(implicit ctx: Context): Unit = {
def report() = {
val msg = s"${m.pos.line + 1}: " + m.contained.kind + extra
val extraInfo = inlineInfo(m.pos)
writer.println(msg)
_messageBuf.append(msg)
if (extraInfo.nonEmpty) {
writer.println(extraInfo)
_messageBuf.append(extraInfo)
}
}
m match {
case m: Error => report()
case m: Warning => report()
case _ => ()
}
}
}
rep
}
}
|