aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/backend/jvm/GenBCode.scala20
-rw-r--r--src/dotty/tools/dotc/CompilerCallback.scala42
-rw-r--r--src/dotty/tools/dotc/Driver.scala42
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala1
-rw-r--r--src/dotty/tools/dotc/reporting/Diagnostic.scala14
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala14
-rw-r--r--src/dotty/tools/dotc/util/SourceFile.scala8
-rw-r--r--src/dotty/tools/dotc/util/SourcePosition.scala5
8 files changed, 83 insertions, 63 deletions
diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala
index 2d444d3be..8cec93977 100644
--- a/src/dotty/tools/backend/jvm/GenBCode.scala
+++ b/src/dotty/tools/backend/jvm/GenBCode.scala
@@ -13,6 +13,9 @@ import dotty.tools.dotc
import dotty.tools.dotc.backend.jvm.DottyPrimitives
import dotty.tools.dotc.transform.Erasure
+import dotty.tools.dotc.interfaces
+import java.util.Optional
+
import scala.reflect.ClassTag
import dotty.tools.dotc.core._
import Periods._
@@ -51,7 +54,17 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
var tree: Tree = _
- val sourceJFile: JFile = ctx.compilationUnit.source.file.file
+ val sourceFile = ctx.compilationUnit.source
+
+ /** Convert a `scala.reflect.io.AbstractFile` into a
+ * `dotty.tools.dotc.interfaces.AbstractFile`.
+ */
+ private[this] def convertAbstractFile(absfile: scala.reflect.io.AbstractFile): interfaces.AbstractFile =
+ new interfaces.AbstractFile {
+ override def name = absfile.name
+ override def path = absfile.path
+ override def jfile = Optional.ofNullable(absfile.file)
+ }
final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit)
@@ -307,7 +320,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
// Statistics.stopTimer(BackendStats.bcodeTimer, bcodeStart)
if (ctx.compilerCallback != null)
- ctx.compilerCallback.onSourceCompiled(sourceJFile)
+ ctx.compilerCallback.onSourceCompiled(sourceFile)
/* TODO Bytecode can be verified (now that all classfiles have been written to disk)
*
@@ -373,10 +386,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
else getFileForClassfile(outFolder, jclassName, ".class")
bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile)
- val outJFile = outFile.file
val className = jclassName.replace('/', '.')
if (ctx.compilerCallback != null)
- ctx.compilerCallback.onClassGenerated(sourceJFile, outJFile, className)
+ ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), className)
}
catch {
case e: FileConflictException =>
diff --git a/src/dotty/tools/dotc/CompilerCallback.scala b/src/dotty/tools/dotc/CompilerCallback.scala
deleted file mode 100644
index e2f56430b..000000000
--- a/src/dotty/tools/dotc/CompilerCallback.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-package dotty.tools.dotc
-
-import java.io.File
-
-/** This trait contains methods that can be overriden to execute code during the
- * compilation process.
- *
- * NOTE: This trait is experimental and may be subject to arbitrary changes.
- *
- * Example usage:
- * {{{
- * val args: Array[String] = ...
- * val callback = new CompilerCallback {
- * override def onClassGenerated(source: File, generatedClass: File, className: String) =
- * println(s"onClassGenerated($source, $generatedClass, $className)")
- * override def onSourceCompiled(source: File) =
- * println(s"onSourceCompiled($source)")
- * }
- * dotty.tools.dotc.process(args, callback)
- * // Or, if you have a custom root context `rootCtx`:
- * dotty.tools.dotc.process(args, rootCtx.fresh.setCompilerCallback(callback))
- * }}}
- */
-trait CompilerCallback {
- /** Called when a class has been generated.
- *
- * @param source The source file corresponding to this class.
- * Example: ./src/library/scala/collection/Seq.scala
- * @param generatedClass The generated classfile for this class.
- * Example: ./scala/collection/Seq$.class
- * @param className The name of this class.
- * Example: scala.collection.Seq$
- */
- def onClassGenerated(source: File, generatedClass: File, className: String): Unit = {}
-
- /** Called when every class for this file has been generated.
- *
- * @param source The source file.
- * Example: ./src/library/scala/collection/Seq.scala
- */
- def onSourceCompiled(source: File): Unit = {}
-}
diff --git a/src/dotty/tools/dotc/Driver.scala b/src/dotty/tools/dotc/Driver.scala
index 5f613d67d..887274fa8 100644
--- a/src/dotty/tools/dotc/Driver.scala
+++ b/src/dotty/tools/dotc/Driver.scala
@@ -7,6 +7,12 @@ import util.DotClass
import reporting._
import scala.util.control.NonFatal
+/** Run the Dotty compiler.
+ *
+ * Extending this class lets you customize many aspect of the compilation
+ * process, but in most cases you only need to call [[process]] on the
+ * existing object [[Main]].
+ */
abstract class Driver extends DotClass {
val prompt = "\ndotc> "
@@ -41,12 +47,35 @@ abstract class Driver extends DotClass {
(fileNames, ctx)
}
+ /** Entry point to the compiler that can be conveniently used with Java reflection.
+ *
+ * This entry point can easily be used without depending on the `dotty` package,
+ * you only need to depend on `dotty-interfaces` and call this method using
+ * reflection. This allows you to write code that will work against multiple
+ * versions of dotty without recompilation.
+ *
+ * The trade-off is that you can only pass a SimpleReporter to this method
+ * and not a normal Reporter which is more powerful.
+ *
+ * Usage example: [[https://github.com/lampepfl/dotty/tree/master/test/test/InterfaceEntryPointTest.scala]]
+ *
+ * @param args Arguments to pass to the compiler.
+ * @param simple Used to log errors, warnings, and info messages.
+ * The default reporter is used if this is `null`.
+ * @param callback Used to execute custom code during the compilation
+ * process. No callbacks will be executed if this is `null`.
+ * @return
+ */
+ final def process(args: Array[String], simple: interfaces.SimpleReporter,
+ callback: interfaces.CompilerCallback): interfaces.ReporterResult = {
+ val reporter = if (simple == null) null else Reporter.fromSimpleReporter(simple)
+ process(args, reporter, callback)
+ }
/** Principal entry point to the compiler.
- * Creates a new compiler instance and run it with arguments `args`.
*
- * The optional arguments of this method all have `null` as their default
- * value, this makes it easier to call this method by reflection or from Java.
+ * Usage example: [[https://github.com/lampepfl/dotty/tree/master/test/test/OtherEntryPointsTest.scala]]
+ * in method `runCompiler`
*
* @param args Arguments to pass to the compiler.
* @param reporter Used to log errors, warnings, and info messages.
@@ -57,7 +86,7 @@ abstract class Driver extends DotClass {
* if compilation succeeded.
*/
final def process(args: Array[String], reporter: Reporter = null,
- callback: CompilerCallback = null): Reporter = {
+ callback: interfaces.CompilerCallback = null): Reporter = {
val ctx = initCtx.fresh
if (reporter != null)
ctx.setReporter(reporter)
@@ -75,7 +104,7 @@ abstract class Driver extends DotClass {
* with sbt.
*/
final def process(args: Array[String]): Reporter =
- process(args, null, null)
+ process(args, null: Reporter, null: interfaces.CompilerCallback)
/** Entry point to the compiler using a custom `Context`.
*
@@ -84,6 +113,9 @@ abstract class Driver extends DotClass {
* the other overloads cannot be overriden, instead you
* should override this one which they call internally.
*
+ * Usage example: [[https://github.com/lampepfl/dotty/tree/master/test/test/OtherEntryPointsTest.scala]]
+ * in method `runCompilerWithContext`
+ *
* @param args Arguments to pass to the compiler.
* @param rootCtx The root Context to use.
* @return The `Reporter` used. Use `Reporter#hasErrors` to check
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index c1132ce4b..f0537dffa 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -2,6 +2,7 @@ package dotty.tools
package dotc
package core
+import interfaces.CompilerCallback
import Decorators._
import Periods._
import Names._
diff --git a/src/dotty/tools/dotc/reporting/Diagnostic.scala b/src/dotty/tools/dotc/reporting/Diagnostic.scala
index ea3ea4112..bcf55e993 100644
--- a/src/dotty/tools/dotc/reporting/Diagnostic.scala
+++ b/src/dotty/tools/dotc/reporting/Diagnostic.scala
@@ -4,22 +4,22 @@ package reporting
import util.SourcePosition
-object Diagnostic {
-
- // Error levels
- val ERROR = 2
- val WARNING = 1
- val INFO = 0
+import java.util.Optional
+object Diagnostic {
val nonSensicalStartTag = "<nonsensical>"
val nonSensicalEndTag = "</nonsensical>"
}
-class Diagnostic(msgFn: => String, val pos: SourcePosition, val level: Int) extends Exception {
+class Diagnostic(msgFn: => String, val pos: SourcePosition, val level: Int)
+ extends Exception with interfaces.Diagnostic {
import Diagnostic._
private var myMsg: String = null
private var myIsNonSensical: Boolean = false
+ override def position: Optional[interfaces.SourcePosition] =
+ if (pos.exists && pos.source.exists) Optional.of(pos) else Optional.empty()
+
/** The message to report */
def message: String = {
if (myMsg == null) {
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index f4eb551a1..8236f93ef 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -11,7 +11,7 @@ import config.Settings.Setting
import config.Printers
import java.lang.System.currentTimeMillis
import typer.Mode
-import Diagnostic.{ERROR, WARNING, INFO}
+import interfaces.Diagnostic.{ERROR, WARNING, INFO}
object Reporter {
class Error(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, ERROR)
@@ -33,6 +33,16 @@ object Reporter {
class MigrationWarning(msgFn: => String, pos: SourcePosition) extends ConditionalWarning(msgFn, pos) {
def enablingOption(implicit ctx: Context) = ctx.settings.migration
}
+
+ /** Convert a SimpleReporter into a real Reporter */
+ def fromSimpleReporter(simple: interfaces.SimpleReporter): Reporter =
+ new Reporter with UniqueMessagePositions with HideNonSensicalMessages {
+ override def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {
+ case d: ConditionalWarning if !d.enablingOption.value =>
+ case _ =>
+ simple.report(d)
+ }
+ }
}
import Reporter._
@@ -157,7 +167,7 @@ trait Reporting { this: Context =>
* This interface provides methods to issue information, warning and
* error messages.
*/
-abstract class Reporter {
+abstract class Reporter extends interfaces.ReporterResult {
/** Report a diagnostic */
def doReport(d: Diagnostic)(implicit ctx: Context): Unit
diff --git a/src/dotty/tools/dotc/util/SourceFile.scala b/src/dotty/tools/dotc/util/SourceFile.scala
index ac3ee298e..6b547203e 100644
--- a/src/dotty/tools/dotc/util/SourceFile.scala
+++ b/src/dotty/tools/dotc/util/SourceFile.scala
@@ -11,6 +11,8 @@ import Chars._
import ScriptSourceFile._
import Positions._
+import java.util.Optional
+
object ScriptSourceFile {
@sharable private val headerPattern = Pattern.compile("""^(::)?!#.*(\r|\n|\r\n)""", Pattern.MULTILINE)
private val headerStarts = List("#!", "::#!")
@@ -32,7 +34,7 @@ object ScriptSourceFile {
}
}
-case class SourceFile(file: AbstractFile, content: Array[Char]) {
+case class SourceFile(file: AbstractFile, content: Array[Char]) extends interfaces.SourceFile {
def this(_file: AbstractFile) = this(_file, _file.toCharArray)
def this(sourceName: String, cs: Seq[Char]) = this(new VirtualFile(sourceName), cs.toArray)
@@ -41,6 +43,10 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) {
/** Tab increment; can be overridden */
def tabInc = 8
+ override def name = file.name
+ override def path = file.path
+ override def jfile = Optional.ofNullable(file.file)
+
override def equals(that : Any) = that match {
case that : SourceFile => file.path == that.file.path && start == that.start
case _ => false
diff --git a/src/dotty/tools/dotc/util/SourcePosition.scala b/src/dotty/tools/dotc/util/SourcePosition.scala
index fa7a4650d..0b2b2aa0b 100644
--- a/src/dotty/tools/dotc/util/SourcePosition.scala
+++ b/src/dotty/tools/dotc/util/SourcePosition.scala
@@ -1,10 +1,11 @@
package dotty.tools
-package dotc.util
+package dotc
+package util
import Positions.{Position, NoPosition}
/** A source position is comprised of a position in a source file */
-case class SourcePosition(source: SourceFile, pos: Position) {
+case class SourcePosition(source: SourceFile, pos: Position) extends interfaces.SourcePosition {
def exists = pos.exists
def lineContent: String = source.lineContent(point)