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/Compiler.scala2
-rw-r--r--src/dotty/tools/dotc/CompilerCallback.scala42
-rw-r--r--src/dotty/tools/dotc/Driver.scala46
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala2
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala1
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala30
-rw-r--r--src/dotty/tools/dotc/reporting/Diagnostic.scala47
-rw-r--r--src/dotty/tools/dotc/reporting/HideNonSensicalMessages.scala20
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala60
-rw-r--r--src/dotty/tools/dotc/reporting/StoreReporter.scala7
-rw-r--r--src/dotty/tools/dotc/reporting/ThrowingReporter.scala2
-rw-r--r--src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala1
-rw-r--r--src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled (renamed from src/dotty/tools/dotc/transform/DropEmptyCompanions.scala)0
-rw-r--r--src/dotty/tools/dotc/transform/ExtensionMethods.scala8
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala16
-rw-r--r--src/dotty/tools/dotc/transform/Getters.scala5
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala8
-rw-r--r--src/dotty/tools/dotc/transform/Literalize.scala.disabled (renamed from src/dotty/tools/dotc/transform/Literalize.scala)0
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala2
-rw-r--r--src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled (renamed from src/dotty/tools/dotc/transform/PrivateToStatic.scala)0
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala1
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala2
-rw-r--r--src/dotty/tools/dotc/util/SourceFile.scala12
-rw-r--r--src/dotty/tools/dotc/util/SourcePosition.scala20
28 files changed, 220 insertions, 152 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/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 7c7648657..f12ab66c5 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -77,7 +77,7 @@ class Compiler {
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new ElimStaticThis,
new Flatten,
- new DropEmptyCompanions,
+ // new DropEmptyCompanions,
new RestoreScopes),
List(new ExpandPrivate,
new CollectEntryPoints,
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 3437b86fc..887274fa8 100644
--- a/src/dotty/tools/dotc/Driver.scala
+++ b/src/dotty/tools/dotc/Driver.scala
@@ -1,11 +1,18 @@
package dotty.tools.dotc
+import dotty.tools.FatalError
import config.CompilerCommand
import core.Contexts.{Context, ContextBase}
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> "
@@ -40,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.
@@ -56,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)
@@ -74,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`.
*
@@ -83,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
@@ -101,6 +134,3 @@ abstract class Driver extends DotClass {
sys.exit(if (process(args).hasErrors) 1 else 0)
}
}
-
-class FatalError(msg: String) extends Exception
-
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index fcc055fc7..8ba155097 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -175,7 +175,7 @@ object desugar {
vparamss = takeUpTo(normalizedVparamss, n),
tpt = TypeTree(),
rhs = vparam.rhs
- ).withMods(vparam.mods & AccessFlags)
+ ).withMods(Modifiers(mods.flags & AccessFlags, mods.privateWithin))
val rest = defaultGetters(vparams :: vparamss1, n + 1)
if (vparam.rhs.isEmpty) rest else defaultGetter :: rest
case Nil :: vparamss1 =>
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/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index 83ac64d53..b60f437d5 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -4,6 +4,7 @@ package core
import Periods._
import Contexts._
import dotty.tools.backend.jvm.{LabelDefs, GenBCode}
+import dotty.tools.dotc.core.Symbols.ClassSymbol
import util.DotClass
import DenotTransformers._
import Denotations._
@@ -347,6 +348,10 @@ object Phases {
override def toString = phaseName
}
+ trait NeedsCompanions {
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean
+ }
+
/** Replace all instances of `oldPhaseClass` in `current` phases
* by the result of `newPhases` applied to the old phase.
*/
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index da3b76c57..91913b935 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -612,7 +612,7 @@ object Types {
/** The set of members of this type having at least one of `requiredFlags` but none of `excludedFlags` set */
final def membersBasedOnFlags(requiredFlags: FlagSet, excludedFlags: FlagSet)(implicit ctx: Context): Seq[SingleDenotation] = track("implicitMembers") {
memberDenots(takeAllFilter,
- (name, buf) => buf ++= member(name).altsWith(x => x.is(requiredFlags, butNot = excludedFlags)))
+ (name, buf) => buf ++= memberExcluding(name, excludedFlags).altsWith(x => x.is(requiredFlags)))
}
/** The info of `sym`, seen as a member of this type. */
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
index 8f1fbf797..f35293d8d 100644
--- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -16,13 +16,13 @@ import scala.reflect.internal.util._
class ConsoleReporter(
reader: BufferedReader = Console.in,
writer: PrintWriter = new PrintWriter(Console.err, true))
- extends Reporter with UniqueMessagePositions {
+ extends Reporter with UniqueMessagePositions with HideNonSensicalMessages {
/** maximal number of error messages to be printed */
protected def ErrorLimit = 100
def printSourceLine(pos: SourcePosition) =
- printMessage(pos.lineContents.stripLineEnd)
+ printMessage(pos.lineContent.stripLineEnd)
def printColumnMarker(pos: SourcePosition) =
if (pos.exists) { printMessage(" " * pos.column + "^") }
@@ -40,21 +40,17 @@ class ConsoleReporter(
}
}
- override def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = {
- val issue = !(d.isSuppressed && hasErrors)
- if (issue) d match {
- case d: Error =>
- printMessageAndPos(s"error: ${d.msg}", d.pos)
- if (ctx.settings.prompt.value) displayPrompt()
- case d: ConditionalWarning if !d.enablingOption.value =>
- case d: MigrationWarning =>
- printMessageAndPos(s"migration warning: ${d.msg}", d.pos)
- case d: Warning =>
- printMessageAndPos(s"warning: ${d.msg}", d.pos)
- case _ =>
- printMessageAndPos(d.msg, d.pos)
- }
- issue
+ override def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {
+ case d: Error =>
+ printMessageAndPos(s"error: ${d.message}", d.pos)
+ if (ctx.settings.prompt.value) displayPrompt()
+ case d: ConditionalWarning if !d.enablingOption.value =>
+ case d: MigrationWarning =>
+ printMessageAndPos(s"migration warning: ${d.message}", d.pos)
+ case d: Warning =>
+ printMessageAndPos(s"warning: ${d.message}", d.pos)
+ case _ =>
+ printMessageAndPos(d.message, d.pos)
}
def displayPrompt(): Unit = {
diff --git a/src/dotty/tools/dotc/reporting/Diagnostic.scala b/src/dotty/tools/dotc/reporting/Diagnostic.scala
new file mode 100644
index 000000000..bcf55e993
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/Diagnostic.scala
@@ -0,0 +1,47 @@
+package dotty.tools
+package dotc
+package reporting
+
+import util.SourcePosition
+
+import java.util.Optional
+
+object Diagnostic {
+ val nonSensicalStartTag = "<nonsensical>"
+ val nonSensicalEndTag = "</nonsensical>"
+}
+
+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) {
+ myMsg = msgFn
+ if (myMsg.contains(nonSensicalStartTag)) {
+ myIsNonSensical = true
+ // myMsg might be composed of several d"..." invocations -> nested nonsensical tags possible
+ myMsg = myMsg.replaceAllLiterally(nonSensicalStartTag, "").replaceAllLiterally(nonSensicalEndTag, "")
+ }
+ }
+ myMsg
+ }
+
+ /** A message is non-sensical if it contains references to <nonsensical> tags.
+ * Such tags are inserted by the error diagnostic framework if a message
+ * contains references to internally generated error types. Normally we
+ * want to suppress error messages referring to types like this because
+ * they look weird and are normally follow-up errors to something that
+ * was diagnosed before.
+ */
+ def isNonSensical = { message; myIsNonSensical }
+
+ override def toString = s"$getClass at $pos: $message"
+ override def getMessage() = message
+}
diff --git a/src/dotty/tools/dotc/reporting/HideNonSensicalMessages.scala b/src/dotty/tools/dotc/reporting/HideNonSensicalMessages.scala
new file mode 100644
index 000000000..a325fe9f7
--- /dev/null
+++ b/src/dotty/tools/dotc/reporting/HideNonSensicalMessages.scala
@@ -0,0 +1,20 @@
+package dotty.tools
+package dotc
+package reporting
+
+import core.Contexts.Context
+
+/**
+ * This trait implements `isHidden` so that we avoid reporting non-sensical messages.
+ */
+trait HideNonSensicalMessages extends Reporter {
+ /** Hides non-sensical messages, unless we haven't reported any error yet or
+ * `-Yshow-suppressed-errors` is set.
+ */
+ override def isHidden(d: Diagnostic)(implicit ctx: Context): Boolean =
+ super.isHidden(d) || {
+ d.isNonSensical &&
+ hasErrors && // if there are no errors yet, report even if diagnostic is non-sensical
+ !ctx.settings.YshowSuppressedErrors.value
+ }
+}
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index 272b1880f..8236f93ef 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -10,46 +10,10 @@ import collection.mutable
import config.Settings.Setting
import config.Printers
import java.lang.System.currentTimeMillis
-import typer.ErrorReporting.DiagnosticString
import typer.Mode
+import interfaces.Diagnostic.{ERROR, WARNING, INFO}
object Reporter {
-
- private val ERROR = 2
- private val WARNING = 1
- private val INFO = 0
-
- class Diagnostic(msgFn: => String, val pos: SourcePosition, val level: Int) extends Exception {
- import DiagnosticString._
-
- private var myMsg: String = null
- private var myIsNonSensical: Boolean = false
-
- /** The message to report */
- def msg: String = {
- if (myMsg == null) {
- myMsg = msgFn
- if (myMsg.contains(nonSensicalStartTag)) {
- myIsNonSensical = true
- // myMsg might be composed of several d"..." invocations -> nested nonsensical tags possible
- myMsg = myMsg.replaceAllLiterally(nonSensicalStartTag, "").replaceAllLiterally(nonSensicalEndTag, "")
- }
- }
- myMsg
- }
-
- /** Report in current reporter */
- def report(implicit ctx: Context) = ctx.reporter.report(this)
-
- def isNonSensical = { msg; myIsNonSensical }
- def isSuppressed(implicit ctx: Context): Boolean = !ctx.settings.YshowSuppressedErrors.value && isNonSensical
-
- override def toString = s"$getClass at $pos: $msg"
- override def getMessage() = msg
-
- def checkingStr: String = msgFn
- }
-
class Error(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, ERROR)
class Warning(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, WARNING)
class Info(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, INFO)
@@ -69,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._
@@ -193,12 +167,10 @@ 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, unless it is suppressed because it is nonsensical
- * @return a diagnostic was reported.
- */
- def doReport(d: Diagnostic)(implicit ctx: Context): Boolean
+ /** Report a diagnostic */
+ def doReport(d: Diagnostic)(implicit ctx: Context): Unit
/** Whether very long lines can be truncated. This exists so important
* debugging information (like printing the classpath) is not rendered
@@ -239,7 +211,8 @@ abstract class Reporter {
}
def report(d: Diagnostic)(implicit ctx: Context): Unit =
- if (!isHidden(d) && doReport(d)(ctx.addMode(Mode.Printing)))
+ if (!isHidden(d)) {
+ doReport(d)(ctx.addMode(Mode.Printing))
d match {
case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1
case d: Warning => warningCount += 1
@@ -249,6 +222,7 @@ abstract class Reporter {
case d: Info => // nothing to do here
// match error if d is something else
}
+ }
def incomplete(d: Diagnostic)(implicit ctx: Context): Unit =
incompleteHandler(d)(ctx)
diff --git a/src/dotty/tools/dotc/reporting/StoreReporter.scala b/src/dotty/tools/dotc/reporting/StoreReporter.scala
index 8209839eb..954bff88e 100644
--- a/src/dotty/tools/dotc/reporting/StoreReporter.scala
+++ b/src/dotty/tools/dotc/reporting/StoreReporter.scala
@@ -4,7 +4,7 @@ package reporting
import core.Contexts.Context
import collection.mutable
-import Reporter.{Diagnostic, Error, Warning}
+import Reporter.{Error, Warning}
import config.Printers._
/**
@@ -14,11 +14,10 @@ class StoreReporter(outer: Reporter) extends Reporter {
private var infos: mutable.ListBuffer[Diagnostic] = null
- def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = {
- typr.println(s">>>> StoredError: ${d.msg}") // !!! DEBUG
+ def doReport(d: Diagnostic)(implicit ctx: Context): Unit = {
+ typr.println(s">>>> StoredError: ${d.message}") // !!! DEBUG
if (infos == null) infos = new mutable.ListBuffer
infos += d
- true
}
override def hasPending: Boolean = infos != null && {
diff --git a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
index 7c63383e9..026453036 100644
--- a/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ThrowingReporter.scala
@@ -11,7 +11,7 @@ import Reporter._
* info to the underlying reporter.
*/
class ThrowingReporter(reportInfo: Reporter) extends Reporter {
- def doReport(d: Diagnostic)(implicit ctx: Context): Boolean = d match {
+ def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {
case _: Error => throw d
case _ => reportInfo.doReport(d)
}
diff --git a/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
index c1f240a23..32554e6b6 100644
--- a/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
+++ b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
@@ -4,7 +4,6 @@ package reporting
import scala.collection.mutable
import util.{SourcePosition, SourceFile}
-import Reporter.Diagnostic
import core.Contexts.Context
/**
diff --git a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled
index 65362f199..65362f199 100644
--- a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala
+++ b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled
diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 90e105ee7..c5ab49c9c 100644
--- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -11,7 +11,7 @@ import dotty.tools.dotc.ast.{Trees, tpd}
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import core._
-import Phases.Phase
+import dotty.tools.dotc.core.Phases.{NeedsCompanions, Phase}
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import TypeErasure.{ valueErasure, ErasedValueType }
@@ -33,7 +33,7 @@ import SymUtils._
* This is different from the implementation of value classes in Scala 2
* (see SIP-15) which uses `asInstanceOf` which does not typecheck.
*/
-class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
+class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization with NeedsCompanions { thisTransformer =>
import tpd._
import ExtensionMethods._
@@ -45,6 +45,10 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
override def runsAfterGroupsOf = Set(classOf[FirstTransform]) // need companion objects to exist
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean = {
+ isDerivedValueClass(cls)
+ }
+
override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case moduleClassSym: ClassDenotation if moduleClassSym is ModuleClass =>
moduleClassSym.linkedClass match {
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index 3b629f9b6..c24c5bbd9 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -3,7 +3,9 @@ package transform
import core._
import Names._
-import dotty.tools.dotc.transform.TreeTransforms.{AnnotationTransformer, TransformerInfo, MiniPhaseTransform, TreeTransformer}
+import dotty.tools.dotc.ast.tpd
+import dotty.tools.dotc.core.Phases.NeedsCompanions
+import dotty.tools.dotc.transform.TreeTransforms._
import ast.Trees._
import Flags._
import Types._
@@ -32,6 +34,16 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
override def phaseName = "firstTransform"
+ private var addCompanionPhases: List[NeedsCompanions] = _
+
+ def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) =
+ addCompanionPhases.exists(_.isCompanionNeeded(cls))
+
+ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
+ addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p })
+ this
+ }
+
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
@@ -80,7 +92,7 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
}
def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
- case stat: TypeDef if singleClassDefs contains stat.name =>
+ case stat: TypeDef if (singleClassDefs contains stat.name) && needsCompanion(stat.symbol.asClass) =>
val objName = stat.name.toTermName
val nameClash = stats.exists {
case other: MemberDef =>
diff --git a/src/dotty/tools/dotc/transform/Getters.scala b/src/dotty/tools/dotc/transform/Getters.scala
index 765791822..882e42d2f 100644
--- a/src/dotty/tools/dotc/transform/Getters.scala
+++ b/src/dotty/tools/dotc/transform/Getters.scala
@@ -12,6 +12,7 @@ import Constants._
import TreeTransforms._
import Flags._
import Decorators._
+import ValueClasses._
/** Performs the following rewritings for fields of a class:
*
@@ -34,7 +35,7 @@ import Decorators._
*
* Omitted from the rewritings are
*
- * - private[this] fields in non-trait classes
+ * - private[this] fields in classes (excluding traits, value classes)
* - fields generated for static modules (TODO: needed?)
* - parameters, static fields, and fields coming from Java
*
@@ -53,7 +54,7 @@ class Getters extends MiniPhaseTransform with SymTransformer { thisTransform =>
override def transformSym(d: SymDenotation)(implicit ctx: Context): SymDenotation = {
def noGetterNeeded =
d.is(NoGetterNeeded) ||
- d.initial.asInstanceOf[SymDenotation].is(PrivateLocal) && !d.owner.is(Trait) && !d.is(Flags.Lazy) ||
+ d.initial.asInstanceOf[SymDenotation].is(PrivateLocal) && !d.owner.is(Trait) && !isDerivedValueClass(d.owner) && !d.is(Flags.Lazy) ||
d.is(Module) && d.isStatic ||
d.isSelfSym
if (d.isTerm && (d.is(Lazy) || d.owner.isClass) && d.info.isValueType && !noGetterNeeded) {
diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala
index 4a8ff83ca..2aece0663 100644
--- a/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -1,6 +1,7 @@
package dotty.tools.dotc
package transform
+import dotty.tools.dotc.core.Phases.NeedsCompanions
import dotty.tools.dotc.typer.Mode
import scala.collection.mutable
@@ -23,7 +24,7 @@ import dotty.tools.dotc.core.SymDenotations.SymDenotation
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer, DenotTransformer}
import Erasure.Boxing.adaptToType
-class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
+class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with NeedsCompanions {
import LazyVals._
import tpd._
@@ -46,6 +47,11 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
* before this phase starts processing same tree */
override def runsAfter = Set(classOf[Mixin])
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean = {
+ def hasLazyVal(x: ClassSymbol) = x.classInfo.membersBasedOnFlags(Flags.Lazy, excludedFlags = Flags.EmptyFlags).nonEmpty
+ hasLazyVal(cls) || cls.mixins.exists(hasLazyVal)
+ }
+
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
transformLazyVal(tree)
diff --git a/src/dotty/tools/dotc/transform/Literalize.scala b/src/dotty/tools/dotc/transform/Literalize.scala.disabled
index f33baa52b..f33baa52b 100644
--- a/src/dotty/tools/dotc/transform/Literalize.scala
+++ b/src/dotty/tools/dotc/transform/Literalize.scala.disabled
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 4d626c67b..b4e32fa66 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -1543,7 +1543,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
val spb = subPatBinders
ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)(
spb,
- subPatRefs(binder, spb, binderTypeTested),
+ subPatRefs(binder, spb, resultType),
aligner.isBool,
checkedLength,
patBinderOrCasted,
diff --git a/src/dotty/tools/dotc/transform/PrivateToStatic.scala b/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled
index 218839d01..218839d01 100644
--- a/src/dotty/tools/dotc/transform/PrivateToStatic.scala
+++ b/src/dotty/tools/dotc/transform/PrivateToStatic.scala.disabled
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index b3089c99c..d6a87acf6 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -8,6 +8,7 @@ import Trees._
import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._
import Applications._, Implicits._, Flags._
import util.Positions._
+import reporting.Diagnostic
import printing.Showable
import printing.Disambiguation.disambiguated
@@ -127,7 +128,6 @@ object ErrorReporting {
* message composition methods, this is crucial.
*/
implicit class DiagnosticString(val sc: StringContext) extends AnyVal {
- import DiagnosticString._
def d(args: Any*)(implicit ctx: Context): String = {
def isSensical(arg: Any): Boolean = arg match {
case l: Seq[_] => l.forall(isSensical(_))
@@ -139,13 +139,8 @@ object ErrorReporting {
}
val s = new StringInterpolators(sc).i(args : _*)
- if (args.forall(isSensical(_))) s else nonSensicalStartTag + s + nonSensicalEndTag
+ if (args.forall(isSensical(_))) s
+ else Diagnostic.nonSensicalStartTag + s + Diagnostic.nonSensicalEndTag
}
}
-
- object DiagnosticString {
- final val nonSensicalStartTag = "<nonsensical>"
- final val nonSensicalEndTag = "</nonsensical>"
- }
-
}
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 9717b5625..99e8cd150 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -15,7 +15,6 @@ import util.{Stats, SimpleMap}
import util.common._
import Decorators._
import Uniques._
-import ErrorReporting.{errorType, DiagnosticString}
import config.Printers._
import annotation.tailrec
import collection.mutable
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index bb411c6b5..afbb43faf 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -715,8 +715,6 @@ object RefChecks {
case List(param) =>
if (param.is(Mutable))
ctx.error("value class parameter must not be a var", param.pos)
- if (param.is(PrivateLocal))
- ctx.error("value class parameter must not be private[this]", param.pos)
case _ =>
ctx.error("value class needs to have exactly one val parameter", clazz.pos)
}
diff --git a/src/dotty/tools/dotc/util/SourceFile.scala b/src/dotty/tools/dotc/util/SourceFile.scala
index da2e54132..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
@@ -113,8 +119,8 @@ case class SourceFile(file: AbstractFile, content: Array[Char]) {
def nextLine(offset: Int): Int =
lineToOffset(offsetToLine(offset) + 1 min lineIndices.length - 1)
- /** The contents of the line containing position `offset` */
- def lineContents(offset: Int): String =
+ /** The content of the line containing position `offset` */
+ def lineContent(offset: Int): String =
content.slice(startOfLine(offset), nextLine(offset)).mkString
/** The column corresponding to `offset`, starting at 0 */
diff --git a/src/dotty/tools/dotc/util/SourcePosition.scala b/src/dotty/tools/dotc/util/SourcePosition.scala
index 9e02841f2..0b2b2aa0b 100644
--- a/src/dotty/tools/dotc/util/SourcePosition.scala
+++ b/src/dotty/tools/dotc/util/SourcePosition.scala
@@ -1,23 +1,29 @@
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) {
- def point: Int = pos.point
- def start: Int = pos.start
- def end: Int = pos.end
+case class SourcePosition(source: SourceFile, pos: Position) extends interfaces.SourcePosition {
def exists = pos.exists
- def lineContents: String = source.lineContents(point)
+ def lineContent: String = source.lineContent(point)
+ def point: Int = pos.point
/** The line of the position, starting at 0 */
def line: Int = source.offsetToLine(point)
-
/** The column of the position, starting at 0 */
def column: Int = source.column(point)
+ def start: Int = pos.start
+ def startLine: Int = source.offsetToLine(start)
+ def startColumn: Int = source.column(start)
+
+ def end: Int = pos.end
+ def endLine: Int = source.offsetToLine(end)
+ def endColumn: Int = source.column(end)
+
override def toString =
if (source.exists) s"${source.file}:${line + 1}"
else s"(no source file, offset = ${pos.point})"