forked from sbt/zinc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This API is inspired by the sbt backend that implements the whole machinery for `ManagedLogger` and instantiates `LoggerReporter`. The provided functionality is to get a default reporter configuration that customises the default instantiation of the reporter. The instantiation is provided in the same API. We use contraband for the default reporter configuration to get the builder pattern so that users can modify it more easily.
- Loading branch information
Showing
5 changed files
with
118 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
internal/zinc-compile-core/src/main/contraband/reporter.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"types": [ | ||
{ | ||
"name": "ReporterConfig", | ||
"namespace": "xsbti", | ||
"target": "Java", | ||
"type": "record", | ||
"fields": [ | ||
{ "name": "loggerName", "type": "String" }, | ||
{ "name": "maximumErrors", "type": "int" }, | ||
{ "name": "useColor", "type": "boolean" }, | ||
{ "name": "logLevel", "type": "java.util.logging.Level" }, | ||
{ "name": "positionMapper", "type": "java.util.function.Function<Position, Position>" } | ||
] | ||
} | ||
] | ||
} |
18 changes: 18 additions & 0 deletions
18
internal/zinc-compile-core/src/main/java/xsbti/ReporterUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package xsbti; | ||
|
||
import sbt.internal.inc.LoggerReporter; | ||
import sbt.internal.inc.ReporterManager; | ||
import sbt.internal.util.ManagedLogger; | ||
import sbt.util.Level$; | ||
|
||
import java.util.function.Function; | ||
|
||
public interface ReporterUtil { | ||
public static ReporterConfig getDefaultReporterConfig() { | ||
return ReporterManager.getDefaultReporterConfig(); | ||
} | ||
|
||
public static Reporter getDefault(ReporterConfig config) { | ||
return ReporterManager.getReporter(System.out, config); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
internal/zinc-compile-core/src/main/scala/sbt/internal/inc/ReporterManager.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package sbt.internal.inc | ||
|
||
import java.io.{ OutputStreamWriter, PrintStream, PrintWriter } | ||
import java.nio.charset.StandardCharsets | ||
import java.util.logging.Level | ||
|
||
import sbt.internal.util.{ ConsoleAppender, MainAppender } | ||
import sbt.util.{ LogExchange } | ||
import sbt.util.{ Level => SbtLevel } | ||
import xsbti.{ Position, Reporter, ReporterConfig } | ||
|
||
object ReporterManager { | ||
import java.util.concurrent.atomic.AtomicInteger | ||
private val idGenerator: AtomicInteger = new AtomicInteger | ||
private val DefaultReporterName = "zinc-out" | ||
private def generateZincReporterId(name: String): String = | ||
s"$name-${idGenerator.incrementAndGet}" | ||
|
||
/** | ||
* Returns the id that is used to know what's the minimum level from which the | ||
* reporter should log messages from the compilers. | ||
* | ||
* It uses `java.util.logging.Level` because `sbt.util.Level` is a Scala enumeration | ||
* and there are lots of deficiencies in its design (as well as in some bugs in | ||
* scalac) that prevent its leak in the public Java API, even though it's supposed | ||
* to be public. For instance, I have tried to refer to it in the following ways: | ||
* | ||
* - `sbt.util.Level.Info` -> Scalac passes, Javac fails. | ||
* - `sbt.util.Level$.Info` -> Scalac error: type mismatch. | ||
* - `sbt.util.Level$.MODULE$.Info` -> Scalac fails with stable identifier required. | ||
* | ||
* Using `CompileOrder.Mixed` does not solve the issue. Therefore, we fallback | ||
* on `java.util.logging.Level` and we transform to `sbt.util.Level` at runtime. This | ||
* provides more type safety than asking users to provide the id of `sbt.util.Level`. | ||
* | ||
* TODO(someone): Don't define `sbt.util.Level` as a Scala enumeration. | ||
*/ | ||
private def fromJavaLogLevel(level: Level): SbtLevel.Value = { | ||
level match { | ||
case Level.INFO => SbtLevel.Info | ||
case Level.WARNING => SbtLevel.Warn | ||
case Level.SEVERE => SbtLevel.Error | ||
case Level.OFF => sys.error("Level.OFF is not supported. Change the logging level.") | ||
case _ => SbtLevel.Debug | ||
} | ||
} | ||
|
||
private val FallbackUseColor = ConsoleAppender.formatEnabled | ||
private val NoPositionMapper = java.util.function.Function.identity[Position]() | ||
|
||
import java.util.function.{ Function => JavaFunction } | ||
private implicit class EnrichedJava[T, R](f: JavaFunction[T, R]) { | ||
def toScala: Function[T, R] = | ||
new Function[T, R] { override def apply(v1: T): R = f.apply(v1) } | ||
} | ||
|
||
/** Returns sane defaults with a long tradition in sbt. */ | ||
def getDefaultReporterConfig: ReporterConfig = | ||
new ReporterConfig(DefaultReporterName, 100, FallbackUseColor, Level.INFO, NoPositionMapper) | ||
|
||
def getReporter(toOutput: PrintWriter, config: ReporterConfig): Reporter = { | ||
val printWriterToAppender = MainAppender.defaultBacked(config.useColor()) | ||
val appender = printWriterToAppender(toOutput) | ||
val freshName = generateZincReporterId(config.loggerName()) | ||
val logger = LogExchange.logger(freshName) | ||
val loggerName = logger.name | ||
|
||
LogExchange.unbindLoggerAppenders(loggerName) | ||
val sbtLogLevel = fromJavaLogLevel(config.logLevel()) | ||
val toAppend = List(appender -> sbtLogLevel) | ||
LogExchange.bindLoggerAppenders(loggerName, toAppend) | ||
new LoggerReporter(config.maximumErrors(), logger, config.positionMapper().toScala) | ||
} | ||
|
||
def getReporter(toOutput: PrintStream, config: ReporterConfig): Reporter = { | ||
val utf8Writer = new OutputStreamWriter(toOutput, StandardCharsets.UTF_8) | ||
val printWriter = new PrintWriter(utf8Writer) | ||
getReporter(printWriter, config) | ||
} | ||
} |