mirror of https://github.com/sbt/sbt.git
118 lines
3.4 KiB
Scala
118 lines
3.4 KiB
Scala
/* sbt -- Simple Build Tool
|
|
* Copyright 2008, 2009 Mark Harrah
|
|
*/
|
|
package xsbt
|
|
|
|
import xsbti.{F0,Logger}
|
|
|
|
private object LoggerReporter
|
|
{
|
|
def apply(settings: scala.tools.nsc.Settings, maximumErrors: Int, log: Logger): LoggerReporter =
|
|
new LoggerReporter(Command.getWarnFatal(settings), maximumErrors, log)
|
|
}
|
|
|
|
// The following code is based on scala.tools.nsc.reporters.{AbstractReporter, ConsoleReporter}
|
|
// Copyright 2002-2009 LAMP/EPFL
|
|
// Original author: Martin Odersky
|
|
private final class LoggerReporter(warnFatal: Boolean, maximumErrors: Int, log: Logger) extends scala.tools.nsc.reporters.Reporter
|
|
{
|
|
import scala.tools.nsc.util.{FakePos,NoPosition,Position}
|
|
private val positions = new scala.collection.mutable.HashMap[Position, Severity]
|
|
|
|
def error(msg: String) { error(FakePos("scalac"), msg) }
|
|
|
|
def printSummary()
|
|
{
|
|
if(WARNING.count > 0)
|
|
log.warn(Message(countElementsAsString(WARNING.count, "warning") + " found"))
|
|
if(ERROR.count > 0)
|
|
log.error(Message(countElementsAsString(ERROR.count, "error") + " found"))
|
|
}
|
|
|
|
def display(pos: Position, msg: String, severity: Severity)
|
|
{
|
|
severity.count += 1
|
|
if(severity != ERROR || maximumErrors < 0 || severity.count <= maximumErrors)
|
|
print(severityLogger(severity), pos, msg)
|
|
}
|
|
private def severityLogger(severity: Severity) =
|
|
(m: F0[String]) =>
|
|
{
|
|
(severity match
|
|
{
|
|
case ERROR => log.error(m)
|
|
case WARNING => log.warn(m)
|
|
case INFO => log.info(m)
|
|
})
|
|
}
|
|
|
|
// this helps keep source compatibility with the changes in 2.8 : Position.{source,line,column} are no longer Option[X]s, just plain Xs
|
|
// so, we normalize to Option[X]
|
|
private def o[T](t: Option[T]): Option[T] = t
|
|
private def o[T](t: T): Option[T] = Some(t)
|
|
private def print(logger: F0[String] => Unit, posIn: Position, msg: String)
|
|
{
|
|
def log(s: => String) = logger(Message(s))
|
|
val pos =
|
|
posIn match
|
|
{
|
|
case null | NoPosition => NoPosition
|
|
case x: FakePos => x
|
|
case x =>
|
|
posIn.inUltimateSource(o(posIn.source).get)
|
|
}
|
|
pos match
|
|
{
|
|
case NoPosition => log(msg)
|
|
case FakePos(fmsg) => log(fmsg+" "+msg)
|
|
case _ =>
|
|
val sourcePrefix = o(pos.source).map(_.file.path).getOrElse("")
|
|
val lineNumberString = o(pos.line).map(line => ":" + line + ":").getOrElse(":") + " "
|
|
log(sourcePrefix + lineNumberString + msg)
|
|
if (!o(pos.line).isEmpty)
|
|
{
|
|
val lineContent = pos.lineContent.stripLineEnd
|
|
log(lineContent) // source line with error/warning
|
|
for(offset <- o(pos.offset); src <- o(pos.source))
|
|
{
|
|
val pointer = offset - src.lineToOffset(src.offsetToLine(offset))
|
|
val pointerSpace = (lineContent: Seq[Char]).take(pointer).map { case '\t' => '\t'; case x => ' ' }
|
|
log(pointerSpace.mkString + "^") // pointer to the column position of the error/warning
|
|
}
|
|
}
|
|
}
|
|
}
|
|
override def reset =
|
|
{
|
|
super.reset
|
|
positions.clear
|
|
}
|
|
|
|
|
|
protected def info0(pos: Position, msg: String, rawSeverity: Severity, force: Boolean)
|
|
{
|
|
val severity = if(warnFatal && rawSeverity == WARNING) ERROR else rawSeverity
|
|
severity match
|
|
{
|
|
case WARNING | ERROR =>
|
|
{
|
|
if(!testAndLog(pos, severity))
|
|
display(pos, msg, severity)
|
|
}
|
|
case _ => display(pos, msg, severity)
|
|
}
|
|
}
|
|
|
|
private def testAndLog(pos: Position, severity: Severity): Boolean =
|
|
{
|
|
if(pos == null || pos.offset.isEmpty)
|
|
false
|
|
else if(positions.get(pos).map(_ >= severity).getOrElse(false))
|
|
true
|
|
else
|
|
{
|
|
positions(pos) = severity
|
|
false
|
|
}
|
|
}
|
|
} |