diff --git a/compile/AnalyzingCompiler.scala b/compile/AnalyzingCompiler.scala index 82f85ae54..e858ee6a1 100644 --- a/compile/AnalyzingCompiler.scala +++ b/compile/AnalyzingCompiler.scala @@ -4,7 +4,7 @@ package sbt package compile - import xsbti.{AnalysisCallback, Logger => xLogger} + import xsbti.{AnalysisCallback, Logger => xLogger, Reporter} import java.io.File import java.net.{URL, URLClassLoader} @@ -12,7 +12,7 @@ package compile * provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and * the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must * be compiled for the version of Scala being used.*/ -class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val cp: ClasspathOptions, log: Logger) extends NotNull +class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: ComponentManager, val cp: ClasspathOptions, log: Logger) { def this(scalaInstance: ScalaInstance, manager: ComponentManager, log: Logger) = this(scalaInstance, manager, ClasspathOptions.auto, log) def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger) @@ -20,16 +20,23 @@ class AnalyzingCompiler(val scalaInstance: ScalaInstance, val manager: Component val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options) compile(arguments, callback, maximumErrors, log) } - def compile(arguments: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger) + + def compile(arguments: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger): Unit = + compile(arguments, callback, log, new LoggerReporter(maximumErrors, log)) + def compile(arguments: Seq[String], callback: AnalysisCallback, log: Logger, reporter: Reporter) { call("xsbt.CompilerInterface", log)( - classOf[Array[String]], classOf[AnalysisCallback], classOf[Int], classOf[xLogger] ) ( - arguments.toArray[String] : Array[String], callback, maximumErrors: java.lang.Integer, log ) + classOf[Array[String]], classOf[AnalysisCallback], classOf[xLogger], classOf[Reporter] ) ( + arguments.toArray[String] : Array[String], callback, log, reporter ) } + def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], maximumErrors: Int, log: Logger): Unit = + doc(sources, classpath, outputDirectory, options, log, new LoggerReporter(maximumErrors, log)) + def doc(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], log: Logger, reporter: Reporter): Unit = { val arguments = (new CompilerArguments(scalaInstance, cp))(sources, classpath, outputDirectory, options) - call("xsbt.ScaladocInterface", log) (classOf[Array[String]], classOf[Int], classOf[xLogger]) (arguments.toArray[String] : Array[String], maximumErrors: java.lang.Integer, log) + call("xsbt.ScaladocInterface", log) (classOf[Array[String]], classOf[xLogger], classOf[Reporter]) ( + arguments.toArray[String] : Array[String], log, reporter) } def console(classpath: Seq[File], options: Seq[String], initialCommands: String, log: Logger)(loader: Option[ClassLoader] = None, bindings: Seq[(String, Any)] = Nil): Unit = { diff --git a/compile/LoggerReporter.scala b/compile/LoggerReporter.scala new file mode 100644 index 000000000..23ad160b9 --- /dev/null +++ b/compile/LoggerReporter.scala @@ -0,0 +1,153 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package sbt + +// The following code is based on scala.tools.nsc.reporters.{AbstractReporter, ConsoleReporter, Reporter} +// Copyright 2002-2009 LAMP/EPFL +// see licenses/LICENSE_Scala +// Original author: Martin Odersky + + import xsbti.{Maybe,Position,Problem,Reporter,Severity} + import java.util.EnumMap + import scala.collection.mutable + import LoggerReporter._ + import Severity.{Error,Info,Warn} + +object LoggerReporter +{ + def m2o[S](m: Maybe[S]): Option[S] = if(m.isDefined) Some(m.get) else None + + final class PositionKey(pos: Position) + { + def offset = pos.offset + def sourceFile = pos.sourceFile + + override def equals(o: Any) = + o match { case pk: PositionKey => equalsKey(pk); case _ => false } + + def equalsKey(o: PositionKey) = + m2o(pos.offset) == m2o(o.offset) && + m2o(pos.sourceFile) == m2o(o.sourceFile) + override def hashCode = + m2o(pos.offset).hashCode * 31 + m2o(pos.sourceFile).hashCode + } + + def countElementsAsString(n: Int, elements: String): String = + n match { + case 0 => "no " + elements + "s" + case 1 => "one " + elements + case 2 => "two " + elements + "s" + case 3 => "three " + elements + "s" + case 4 => "four " + elements + "s" + case _ => "" + n + " " + elements + "s" + } +} + +class LoggerReporter(maximumErrors: Int, log: Logger) extends xsbti.Reporter +{ + val positions = new mutable.HashMap[PositionKey, Severity] + val count = new EnumMap[Severity, Int](classOf[Severity]) + private val allProblems = new mutable.ListBuffer[Problem] + + reset() + + def reset() + { + count.put(Warn, 0) + count.put(Info, 0) + count.put(Error, 0) + positions.clear() + allProblems.clear() + } + def hasWarnings = count.get(Warn) > 0 + def hasErrors = count.get(Error) > 0 + def problems = allProblems.toArray + + def printSummary() + { + val warnings = count.get(Severity.Warn) + if(warnings > 0) + log.warn(countElementsAsString(warnings, "warning") + " found") + val errors = count.get(Severity.Error) + if(errors > 0) + log.error(countElementsAsString(errors, "error") + " found") + } + + def inc(sev: Severity) = count.put(sev, count.get(sev) + 1) + + def display(pos: Position, msg: String, severity: Severity) + { + inc(severity) + if(severity != Warn || maximumErrors <= 0 || count.get(severity) <= maximumErrors) + print(severityLogger(severity), pos, msg) + } + def severityLogger(severity: Severity): (=> String) => Unit = + m => + { + (severity match + { + case Error => log.error(m) + case Warn => log.warn(m) + case Info => log.info(m) + }) + } + + def print(log: (=> String) => Unit, pos: Position, msg: String) + { + if(pos.sourcePath.isEmpty && pos.line.isEmpty) + log(msg) + else + { + val sourcePrefix = m2o(pos.sourcePath).getOrElse("") + val lineNumberString = m2o(pos.line).map(":" + _ + ":").getOrElse(":") + " " + log(sourcePrefix + lineNumberString + msg) + val lineContent = pos.lineContent + if(!lineContent.isEmpty) + { + log(lineContent) + for(space <- m2o(pos.pointerSpace)) + log(space + "^") // pointer to the column position of the error/warning + } + } + } + + def log(pos: Position, msg: String, severity: Severity): Unit = + { + allProblems += problem(pos, msg, severity) + severity match + { + case Warn | Error => + { + if(!testAndLog(pos, severity)) + display(pos, msg, severity) + } + case _ => display(pos, msg, severity) + } + } + def problem(pos: Position, msg: String, sev: Severity): Problem = + new Problem + { + val position = pos + val message = msg + val severity = sev + } + + def testAndLog(pos: Position, severity: Severity): Boolean = + { + if(pos.offset.isEmpty || pos.sourceFile.isEmpty) + false + else + { + val key = new PositionKey(pos) + if(positions.get(key).map(_.ordinal >= severity.ordinal).getOrElse(false)) + true + else + { + positions(key) = severity + false + } + } + } +} \ No newline at end of file diff --git a/compile/RawCompiler.scala b/compile/RawCompiler.scala index c0241da86..02aa4a60a 100644 --- a/compile/RawCompiler.scala +++ b/compile/RawCompiler.scala @@ -36,5 +36,6 @@ class RawCompiler(val scalaInstance: ScalaInstance, cp: ClasspathOptions, log: L } class CompileFailed(val arguments: Array[String], override val toString: String) extends xsbti.CompileFailed { + def problems = Array() override def fillInStackTrace = this } \ No newline at end of file diff --git a/compile/interface/CompilerInterface.scala b/compile/interface/CompilerInterface.scala index adab14236..918b3f855 100644 --- a/compile/interface/CompilerInterface.scala +++ b/compile/interface/CompilerInterface.scala @@ -3,13 +3,13 @@ */ package xsbt -import xsbti.{AnalysisCallback,Logger} +import xsbti.{AnalysisCallback,Logger,Problem,Reporter} import scala.tools.nsc.{Phase, SubComponent} import Log.debug class CompilerInterface { - def run(args: Array[String], callback: AnalysisCallback, maximumErrors: Int, log: Logger) + def run(args: Array[String], callback: AnalysisCallback, log: Logger, delegate: Reporter) { import scala.tools.nsc.{Global, Settings} @@ -17,7 +17,7 @@ class CompilerInterface val settings = new Settings(Log.settingsError(log)) val command = Command(args.toList, settings) - val reporter = LoggerReporter(settings, maximumErrors, log) + val reporter = DelegatingReporter(settings, delegate) def noErrors = !reporter.hasErrors && command.ok val phasesSet = new scala.collection.mutable.HashSet[Any] // 2.7 compatibility @@ -84,8 +84,8 @@ class CompilerInterface if(!noErrors) { debug(log, "Compilation failed (CompilerInterface)") - throw new InterfaceCompileFailed(args, "Compilation failed") + throw new InterfaceCompileFailed(args, reporter.problems, "Compilation failed") } } } -class InterfaceCompileFailed(val arguments: Array[String], override val toString: String) extends xsbti.CompileFailed \ No newline at end of file +class InterfaceCompileFailed(val arguments: Array[String], val problems: Array[Problem], override val toString: String) extends xsbti.CompileFailed \ No newline at end of file diff --git a/compile/interface/ConsoleInterface.scala b/compile/interface/ConsoleInterface.scala index 6acf881e6..ae6a37f41 100644 --- a/compile/interface/ConsoleInterface.scala +++ b/compile/interface/ConsoleInterface.scala @@ -59,6 +59,6 @@ object MakeSettings if(command.ok) command.settings else - throw new InterfaceCompileFailed(Array(), command.usageMsg) + throw new InterfaceCompileFailed(Array(), Array(), command.usageMsg) } } diff --git a/compile/interface/DelegatingReporter.scala b/compile/interface/DelegatingReporter.scala new file mode 100644 index 000000000..d791f95fe --- /dev/null +++ b/compile/interface/DelegatingReporter.scala @@ -0,0 +1,119 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbt + + import xsbti.{F0,Logger,Maybe} + import java.io.File + +private object DelegatingReporter +{ + def apply(settings: scala.tools.nsc.Settings, delegate: xsbti.Reporter): DelegatingReporter = + new DelegatingReporter(Command.getWarnFatal(settings), delegate) +} + +private trait ReporterCompat27 { + // this method is not in 2.7.7, so we need to have a dummy interface or scalac complains nothing is overridden + def hasWarnings: Boolean +} +// The following code is based on scala.tools.nsc.reporters.{AbstractReporter, ConsoleReporter} +// Copyright 2002-2009 LAMP/EPFL +// Original author: Martin Odersky +private final class DelegatingReporter(warnFatal: Boolean, delegate: xsbti.Reporter) extends scala.tools.nsc.reporters.Reporter with ReporterCompat27 +{ + import scala.tools.nsc.util.{FakePos,NoPosition,Position} + + def error(msg: String) { error(FakePos("scalac"), msg) } + + def printSummary() = delegate.printSummary() + + // 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) + + override def hasErrors = delegate.hasErrors + override def hasWarnings = delegate.hasWarnings + def problems = delegate.problems + + override def reset = + { + super.reset + delegate.reset + } + protected def info0(pos: Position, msg: String, rawSeverity: Severity, force: Boolean) + { + val severity = if(warnFatal && rawSeverity == WARNING) ERROR else rawSeverity + delegate.log(convert(pos), msg, convert(rawSeverity)) + } + private[this] def convert(posIn: Position): xsbti.Position = + { + val pos = + posIn match + { + case null | NoPosition => NoPosition + case x: FakePos => x + case x => + posIn.inUltimateSource(o(posIn.source).get) + } + pos match + { + case NoPosition | FakePos(_) => position(None, None, None, "", None, None, None) + case _ => makePosition(pos) + } + } + private[this] def makePosition(pos: Position): xsbti.Position = + { + val srcO = o(pos.source) + val opt(sourcePath, sourceFile) = for(src <- srcO) yield (src.file.path, src.file.file) + val line = o(pos.line) + if(!line.isEmpty) + { + val lineContent = pos.lineContent.stripLineEnd + val offsetO = o(pos.offset) + val opt(pointer, pointerSpace) = + for(offset <- offsetO; src <- srcO) yield + { + val pointer = offset - src.lineToOffset(src.offsetToLine(offset)) + val pointerSpace = ((lineContent: Seq[Char]).take(pointer).map { case '\t' => '\t'; case x => ' ' }).mkString + (pointer, pointerSpace) + } + position(sourcePath, sourceFile, line, lineContent, offsetO, pointer, pointerSpace) + } + else + position(sourcePath, sourceFile, line, "", None, None, None) + } + private[this] object opt + { + def unapply[A,B](o: Option[(A,B)]): Some[(Option[A], Option[B])] = + Some(o match + { + case Some((a,b)) => (Some(a), Some(b)) + case None => (None, None) + }) + } + private[this] def position(sourcePath0: Option[String], sourceFile0: Option[File], line0: Option[Int], lineContent0: String, offset0: Option[Int], pointer0: Option[Int], pointerSpace0: Option[String]) = + new xsbti.Position + { + val line = o2mi(line0) + val lineContent = lineContent0 + val offset = o2mi(offset0) + val sourcePath = o2m(sourcePath0) + val sourceFile = o2m(sourceFile0) + val pointer = o2mi(pointer0) + val pointerSpace = o2m(pointerSpace0) + } + + import xsbti.Severity.{Info, Warn, Error} + private[this] def convert(sev: Severity): xsbti.Severity = + sev match + { + case INFO => Info + case WARNING => Warn + case ERROR => Error + } + + import java.lang.{Integer => I} + private[this] def o2mi(opt: Option[Int]): Maybe[I] = opt match { case None => Maybe.nothing[I]; case Some(s) => Maybe.just[I](s) } + private[this] def o2m[S](opt: Option[S]): Maybe[S] = opt match { case None => Maybe.nothing[S]; case Some(s) => Maybe.just(s) } +} \ No newline at end of file diff --git a/compile/interface/LoggerReporter.scala b/compile/interface/LoggerReporter.scala deleted file mode 100644 index 2455cbb03..000000000 --- a/compile/interface/LoggerReporter.scala +++ /dev/null @@ -1,118 +0,0 @@ -/* 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 - } - } -} \ No newline at end of file diff --git a/compile/interface/ScaladocInterface.scala b/compile/interface/ScaladocInterface.scala index 22d2edecd..a546795f1 100644 --- a/compile/interface/ScaladocInterface.scala +++ b/compile/interface/ScaladocInterface.scala @@ -3,19 +3,20 @@ */ package xsbt -import xsbti.Logger -import Log.debug + import xsbti.Logger + import Log.debug class ScaladocInterface { - def run(args: Array[String], maximumErrors: Int, log: Logger) = (new Runner(args, maximumErrors, log)).run + def run(args: Array[String], log: Logger, delegate: xsbti.Reporter) = (new Runner(args, log, delegate)).run } -private class Runner(args: Array[String], maximumErrors: Int, log: Logger) +private class Runner(args: Array[String], log: Logger, delegate: xsbti.Reporter) { - import scala.tools.nsc.{doc, Global} + import scala.tools.nsc.{doc, Global, reporters} + import reporters.Reporter val docSettings: doc.Settings = new doc.Settings(Log.settingsError(log)) val command = Command(args.toList, docSettings) - val reporter = LoggerReporter(docSettings, maximumErrors, log) + val reporter = DelegatingReporter(docSettings, delegate) def noErrors = !reporter.hasErrors && command.ok import forScope._ @@ -29,12 +30,12 @@ private class Runner(args: Array[String], maximumErrors: Int, log: Logger) processor.document(command.files) } reporter.printSummary() - if(!noErrors) throw new InterfaceCompileFailed(args, "Scaladoc generation failed") + if(!noErrors) throw new InterfaceCompileFailed(args, reporter.problems, "Scaladoc generation failed") } object forScope { - class DocFactory(reporter: LoggerReporter, docSettings: doc.Settings) // 2.7 compatibility + class DocFactory(reporter: Reporter, docSettings: doc.Settings) // 2.7 compatibility { object compiler extends Global(command.settings, reporter) { diff --git a/interface/src/main/java/xsbti/CompileFailed.java b/interface/src/main/java/xsbti/CompileFailed.java index bb5b2a93a..f1cbbc61b 100644 --- a/interface/src/main/java/xsbti/CompileFailed.java +++ b/interface/src/main/java/xsbti/CompileFailed.java @@ -3,4 +3,5 @@ package xsbti; public abstract class CompileFailed extends RuntimeException { public abstract String[] arguments(); + public abstract Problem[] problems(); } \ No newline at end of file diff --git a/interface/src/main/java/xsbti/Maybe.java b/interface/src/main/java/xsbti/Maybe.java new file mode 100644 index 000000000..f730ef918 --- /dev/null +++ b/interface/src/main/java/xsbti/Maybe.java @@ -0,0 +1,30 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbti; + +/** Intended as a lightweight carrier for scala.Option. */ +public abstract class Maybe +{ + // private pending Scala bug #3642 + protected Maybe() {} + + public static Maybe just(final s v) + { + return new Maybe() { + public boolean isDefined() { return true; } + public s get() { return v; } + }; + } + public static Maybe nothing() + { + return new Maybe() { + public boolean isDefined() { return false; } + public s get() { throw new UnsupportedOperationException("nothing.get"); } + }; + } + + public final boolean isEmpty() { return !isDefined(); } + public abstract boolean isDefined(); + public abstract t get(); +} \ No newline at end of file diff --git a/interface/src/main/java/xsbti/Position.java b/interface/src/main/java/xsbti/Position.java new file mode 100644 index 000000000..96c60ebb2 --- /dev/null +++ b/interface/src/main/java/xsbti/Position.java @@ -0,0 +1,18 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbti; + +public interface Position +{ + Maybe line(); + String lineContent(); + Maybe offset(); + + // pointer to the column position of the error/warning + Maybe pointer(); + Maybe pointerSpace(); + + Maybe sourcePath(); + Maybe sourceFile(); +} \ No newline at end of file diff --git a/interface/src/main/java/xsbti/Problem.java b/interface/src/main/java/xsbti/Problem.java new file mode 100644 index 000000000..cf2641900 --- /dev/null +++ b/interface/src/main/java/xsbti/Problem.java @@ -0,0 +1,11 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbti; + +public interface Problem +{ + Severity severity(); + String message(); + Position position(); +} \ No newline at end of file diff --git a/interface/src/main/java/xsbti/Reporter.java b/interface/src/main/java/xsbti/Reporter.java new file mode 100644 index 000000000..8556cbe8a --- /dev/null +++ b/interface/src/main/java/xsbti/Reporter.java @@ -0,0 +1,20 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbti; + +public interface Reporter +{ + /** Resets logging, including any accumulated errors, warnings, messages, and counts.*/ + public void reset(); + /** Returns true if this logger has seen any errors since the last call to reset.*/ + public boolean hasErrors(); + /** Returns true if this logger has seen any warnings since the last call to reset.*/ + public boolean hasWarnings(); + /** Logs a summary of logging since the last reset.*/ + public void printSummary(); + /** Returns a list of warnings and errors since the last reset.*/ + public Problem[] problems(); + /** Logs a message.*/ + public void log(Position pos, String msg, Severity sev); +} \ No newline at end of file diff --git a/interface/src/main/java/xsbti/Severity.java b/interface/src/main/java/xsbti/Severity.java new file mode 100644 index 000000000..09aed574b --- /dev/null +++ b/interface/src/main/java/xsbti/Severity.java @@ -0,0 +1,9 @@ +/* sbt -- Simple Build Tool + * Copyright 2008, 2009, 2010 Mark Harrah + */ +package xsbti; + +public enum Severity +{ + Info, Warn, Error +} \ No newline at end of file diff --git a/main/Compile.scala b/main/Compile.scala index 8bbb7752c..c6fd53eae 100644 --- a/main/Compile.scala +++ b/main/Compile.scala @@ -12,6 +12,16 @@ object Compile { val DefaultMaxErrors = 100 + def allProblems(inc: Incomplete): Seq[Problem] = + allProblems(inc :: Nil) + def allProblems(incs: Seq[Incomplete]): Seq[Problem] = + problems(Incomplete.allExceptions(incs).toSeq) + def problems(es: Seq[Throwable]): Seq[Problem] = + es flatMap { + case cf: xsbti.CompileFailed => cf.problems + case _ => Nil + } + final class Inputs(val compilers: Compilers, val config: Options, val incSetup: IncSetup, val log: Logger) final class Options(val classpath: Seq[File], val sources: Seq[File], val classesDirectory: File, val options: Seq[String], val javacOptions: Seq[String], val maxErrors: Int) final class IncSetup(val javaSrcBases: Seq[File], val analysisMap: Map[File, Analysis], val cacheDirectory: File) diff --git a/sbt/package.scala b/sbt/package.scala index 502329835..1a46c2b4c 100644 --- a/sbt/package.scala +++ b/sbt/package.scala @@ -4,4 +4,6 @@ package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders with sbt.PathExtra { type File = java.io.File + implicit def maybeToOption[S](m: xsbti.Maybe[S]): Option[S] = + if(m.isDefined) Some(m.get) else None } diff --git a/tasks/Incomplete.scala b/tasks/Incomplete.scala index 9d08cdb47..c3fa5fc23 100644 --- a/tasks/Incomplete.scala +++ b/tasks/Incomplete.scala @@ -16,6 +16,9 @@ object Incomplete extends Enumeration { val causeStr = if(i.causes.isEmpty) "" else (i.causes.length + " cause(s)") "Incomplete (" + show(i.tpe) + ") " + i.message.getOrElse("") + causeStr + "\n" + traces } + + def allExceptions(is: Seq[Incomplete]): Iterable[Throwable] = + allExceptions(new Incomplete(causes = is)) def allExceptions(i: Incomplete): Iterable[Throwable] = { val exceptions = IDSet.create[Throwable]