diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-06-10 13:02:50 +0200 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-06-10 13:02:50 +0200 |
commit | cf8902907756cca2c5b8367c898ca0e9698c6521 (patch) | |
tree | 4b880aac09cf5cfc5a682ff3cf97ef805db6a9cd /src | |
parent | ed3df58ab167f660825e675b6b45eb454fc9869b (diff) | |
parent | ddb29a8105bc3b692bc129cbd8ed111baae7076d (diff) | |
download | scala-cf8902907756cca2c5b8367c898ca0e9698c6521.tar.gz scala-cf8902907756cca2c5b8367c898ca0e9698c6521.tar.bz2 scala-cf8902907756cca2c5b8367c898ca0e9698c6521.zip |
Merge remote-tracking branch 'origin/2.11.x' into merge/2.11.x-to-2.12.x
Diffstat (limited to 'src')
23 files changed, 193 insertions, 144 deletions
diff --git a/src/build/maven/scala-dist-pom.xml b/src/build/maven/scala-dist-pom.xml index 22a24dea21..9477e14285 100644 --- a/src/build/maven/scala-dist-pom.xml +++ b/src/build/maven/scala-dist-pom.xml @@ -40,6 +40,11 @@ <version>@VERSION@</version> </dependency> <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scalap</artifactId> + <version>@VERSION@</version> + </dependency> + <dependency> <groupId>org.scala-lang.plugins</groupId> <!-- plugins are fully cross-versioned. But, we don't publish with 2.11.0-SNAPSHOT, instead use full version of the last non-snapshot version --> <artifactId>scala-continuations-plugin_@SCALA_FULL_VERSION@</artifactId> diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index bab0768ca9..a1d0d52dcf 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -20,9 +20,12 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { def ok = processArgumentsResult._1 def files = processArgumentsResult._2 - /** The name of the command */ + /** The name of the command. */ def cmdName = "scalac" + /** A descriptive alias for version and help messages. */ + def cmdDesc = "compiler" + private def explainAdvanced = "\n" + """ |-- Notes on option parsing -- |Boolean settings are always false unless set. @@ -85,7 +88,11 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { def getInfoMessage(global: Global): String = { import settings._ - if (help) usageMsg + global.pluginOptionsHelp + import Properties.{ versionString, copyrightString } //versionFor + def versionFor(command: String) = f"Scala $command $versionString -- $copyrightString" + + if (version) versionFor(cmdDesc) + else if (help) usageMsg + global.pluginOptionsHelp else if (Xhelp) xusageMsg else if (Yhelp) yusageMsg else if (showPlugins) global.pluginDescriptions diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index 3ac27a42e8..6befa76b3f 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -2,26 +2,24 @@ package scala package tools.nsc import scala.tools.nsc.reporters.ConsoleReporter -import Properties.{ versionString, copyrightString, residentPromptString } +import Properties.{ versionMsg, residentPromptString } import scala.reflect.internal.util.FakePos abstract class Driver { val prompt = residentPromptString - val versionMsg = "Scala compiler " + - versionString + " -- " + - copyrightString - var reporter: ConsoleReporter = _ protected var command: CompilerCommand = _ protected var settings: Settings = _ - protected def scalacError(msg: String) { + protected def scalacError(msg: String): Unit = { reporter.error(FakePos("scalac"), msg + "\n scalac -help gives more information") } - protected def processSettingsHook(): Boolean = true + protected def processSettingsHook(): Boolean = { + if (settings.version) { reporter echo versionMsg ; false } else true + } protected def newCompiler(): Global @@ -37,14 +35,12 @@ abstract class Driver { } def process(args: Array[String]) { - val ss = new Settings(scalacError) - reporter = new ConsoleReporter(ss) + val ss = new Settings(scalacError) + reporter = new ConsoleReporter(ss) command = new CompilerCommand(args.toList, ss) settings = command.settings - if (settings.version) { - reporter.echo(versionMsg) - } else if (processSettingsHook()) { + if (processSettingsHook()) { val compiler = newCompiler() try { if (reporter.hasErrors) @@ -68,5 +64,4 @@ abstract class Driver { process(args) sys.exit(if (reporter.hasErrors) 1 else 0) } - } diff --git a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala index e710222285..dbdeec809f 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerCommand.scala @@ -19,9 +19,10 @@ extends CompilerCommand(args, settings) { def this(args: List[String]) = this(args, str => Console.println("Error: " + str)) - /** name of the associated compiler command */ override def cmdName = "scala" - def compCmdName = "scalac" + override def cmdDesc = "code runner" + + def compCmdName = "scalac" // super.cmdName // change CompilerCommand behavior override def shouldProcessArguments: Boolean = false @@ -50,17 +51,16 @@ extends CompilerCommand(args, settings) { case Nil => AsRepl case hd :: _ => waysToRun find (_.name == settings.howtorun.value) getOrElse guessHowToRun(hd) } - private def interpolate(s: String) = s.trim.replaceAll("@cmd@", cmdName).replaceAll("@compileCmd@", compCmdName) + "\n" - - def shortUsageMsg = interpolate(""" -Usage: @cmd@ <options> [<script|class|object|jar> <arguments>] - or @cmd@ -help -All options to @compileCmd@ (see @compileCmd@ -help) are also allowed. -""") + def shortUsageMsg = +s"""|Usage: $cmdName <options> [<script|class|object|jar> <arguments>] + | or $cmdName -help + | + |All options to $compCmdName (see $compCmdName -help) are also allowed. +""".stripMargin - override def usageMsg = shortUsageMsg + interpolate(""" -The first given argument other than options to @cmd@ designates + override def usageMsg = f"""$shortUsageMsg +The first given argument other than options to $cmdName designates what to run. Runnable targets are: - a file containing scala source @@ -68,7 +68,7 @@ what to run. Runnable targets are: - a runnable jar file with a valid Main-Class attribute - or if no argument is given, the repl (interactive shell) is started -Options to @cmd@ which reach the java runtime: +Options to $cmdName which reach the java runtime: -Dname=prop passed directly to java to set system properties -J<arg> -J is stripped and <arg> passed to java as-is @@ -86,8 +86,7 @@ A file argument will be run as a scala script unless it contains only self-contained compilation units (classes and objects) and exactly one runnable main method. In that case the file will be compiled and the main method invoked. This provides a bridge between scripts and standard -scala source. - """) + "\n" +scala source.%n""" } object GenericRunnerCommand { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 1285ca6862..bffa4bc51d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -686,7 +686,12 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case _ => } if ((targetTypeKind != null) && (sym == definitions.Array_clone) && invokeStyle.isDynamic) { - val target: String = targetTypeKind.asClassBType.internalName + // An invokevirtual points to a CONSTANT_Methodref_info which in turn points to a + // CONSTANT_Class_info of the receiver type. + // The JVMS is not explicit about this, but that receiver type may be an array type + // descriptor (instead of a class internal name): + // invokevirtual #2; //Method "[I".clone:()Ljava/lang/Object + val target: String = targetTypeKind.asRefBType.classOrArrayType bc.invokevirtual(target, "clone", "()Ljava/lang/Object;") } else { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index 9aedc7f8b4..5b0fa6f7a8 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -217,7 +217,8 @@ abstract class BTypes[G <: Global](val __global_dont_use: G) { sealed trait RefBType extends BType { /** * The class or array type of this reference type. Used for ANEWARRAY, MULTIANEWARRAY, - * INSTANCEOF and CHECKCAST instructions. + * INSTANCEOF and CHECKCAST instructions. Also used for emitting invokevirtual calls to + * (a: Array[T]).clone() for any T, see genApply. * * In contrast to the descriptor, this string does not contain the surrounding 'L' and ';' for * class types, for example "java/lang/String". diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 20ccc30ff6..d22dcacad6 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -42,7 +42,7 @@ trait ScalaSettings extends AbsScalaSettings def optimiseSettings = List[BooleanSetting](inline, inlineHandlers, Xcloselim, Xdce, YconstOptimization) /** If any of these settings is enabled, the compiler should print a message and exit. */ - def infoSettings = List[Setting](help, Xhelp, Yhelp, showPlugins, showPhases, genPhaseGraph) + def infoSettings = List[Setting](version, help, Xhelp, Yhelp, showPlugins, showPhases, genPhaseGraph) /** Is an info setting set? */ def isInfo = infoSettings exists (_.isSetByUser) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 6ca2205881..149b4fe446 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -780,32 +780,40 @@ abstract class ICodeReader extends ClassfileParser { bb = otherBlock // Console.println("\t> entering bb: " + bb) } - instr match { - case LJUMP(target) => - otherBlock = blocks(target) - bb.emitOnly(JUMP(otherBlock)) - case LCJUMP(success, failure, cond, kind) => - otherBlock = blocks(success) - val failBlock = blocks(failure) - bb.emitOnly(CJUMP(otherBlock, failBlock, cond, kind)) + if (bb.closed) { + // the basic block is closed, i.e. the previous instruction was a jump, return or throw, + // but the next instruction is not a jump target. this means that the next instruction is + // dead code. we can therefore advance until the next jump target. + debuglog(s"ICode reader skipping dead instruction $instr in classfile $instanceCode") + } else { + instr match { + case LJUMP(target) => + otherBlock = blocks(target) + bb.emitOnly(JUMP(otherBlock)) + + case LCJUMP(success, failure, cond, kind) => + otherBlock = blocks(success) + val failBlock = blocks(failure) + bb.emitOnly(CJUMP(otherBlock, failBlock, cond, kind)) - case LCZJUMP(success, failure, cond, kind) => - otherBlock = blocks(success) - val failBlock = blocks(failure) - bb.emitOnly(CZJUMP(otherBlock, failBlock, cond, kind)) + case LCZJUMP(success, failure, cond, kind) => + otherBlock = blocks(success) + val failBlock = blocks(failure) + bb.emitOnly(CZJUMP(otherBlock, failBlock, cond, kind)) - case LSWITCH(tags, targets) => - bb.emitOnly(SWITCH(tags, targets map blocks)) + case LSWITCH(tags, targets) => + bb.emitOnly(SWITCH(tags, targets map blocks)) - case RETURN(_) => - bb emitOnly instr + case RETURN(_) => + bb emitOnly instr - case THROW(clasz) => - bb emitOnly instr + case THROW(clasz) => + bb emitOnly instr - case _ => - bb emit instr + case _ => + bb emit instr + } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index dceb0a47d8..284ab2f6f9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -174,8 +174,8 @@ trait NamesDefaults { self: Analyzer => // assigning the correct method symbol, typedSelect will just assign the type. the reason // to still call 'typed' is to correctly infer singleton types, SI-5259. val selectPos = - if(qual.pos.isRange && baseFun.pos.isRange) qual.pos.union(baseFun.pos).withStart(Math.min(qual.pos.end, baseFun.pos.end)) - else baseFun.pos + if(qual.pos.isRange && baseFun1.pos.isRange) qual.pos.union(baseFun1.pos).withStart(Math.min(qual.pos.end, baseFun1.pos.end)) + else baseFun1.pos val f = blockTyper.typedOperator(Select(newQual, selected).setSymbol(baseFun1.symbol).setPos(selectPos)) if (funTargs.isEmpty) f else TypeApply(f, funTargs).setType(baseFun.tpe) diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 3b12086cc7..923297bafb 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -141,6 +141,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val run = new Run run.symSource(ownerClass) = NoAbstractFile // need to set file to something different from null, so that currentRun.defines works phase = run.typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled + globalPhase = run.typerPhase // amazing... looks like phase and globalPhase are different things, so we need to set them separately currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions reporter.reset() diff --git a/src/interactive/scala/tools/nsc/interactive/Main.scala b/src/interactive/scala/tools/nsc/interactive/Main.scala index c838606f02..7796c65670 100644 --- a/src/interactive/scala/tools/nsc/interactive/Main.scala +++ b/src/interactive/scala/tools/nsc/interactive/Main.scala @@ -12,7 +12,7 @@ package interactive */ object Main extends nsc.MainClass { override def processSettingsHook(): Boolean = { - if (this.settings.Yidedebug) { + def run(): Unit = { this.settings.Xprintpos.value = true this.settings.Yrangepos.value = true val compiler = new interactive.Global(this.settings, this.reporter) @@ -27,8 +27,9 @@ object Main extends nsc.MainClass { case None => reporter.reset() // Causes other compiler errors to be ignored } askShutdown - false } - else true + super.processSettingsHook() && ( + if (this.settings.Yidedebug) { run() ; false } else true + ) } } diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala index ade04e4de8..42cb37aa24 100755 --- a/src/library/scala/collection/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/IndexedSeqOptimized.scala @@ -206,7 +206,7 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { override /*SeqLike*/ def lastIndexWhere(p: A => Boolean, end: Int): Int = { - var i = end + var i = math.min(end, length - 1) while (i >= 0 && !p(this(i))) i -= 1 i } diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index e321a6adba..f6f46e158f 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -922,6 +922,9 @@ trait Iterator[+A] extends TraversableOnce[A] { /** For reasons which remain to be determined, calling * self.take(n).toSeq cause an infinite loop, so we have * a slight variation on take for local usage. + * NB: self.take.toSeq is slice.toStream, lazily built on self, + * so a subsequent self.hasNext would not test self after the + * group was consumed. */ private def takeDestructively(size: Int): Seq[A] = { val buf = new ArrayBuffer[A] @@ -945,12 +948,10 @@ trait Iterator[+A] extends TraversableOnce[A] { // so the rest of the code can be oblivious val xs: Seq[B] = { val res = takeDestructively(count) - // extra checks so we don't calculate length unless there's reason - if (pad.isDefined && !self.hasNext) { - val shortBy = count - res.length - if (shortBy > 0) res ++ padding(shortBy) else res - } - else res + // was: extra checks so we don't calculate length unless there's reason + // but since we took the group eagerly, just use the fast length + val shortBy = count - res.length + if (shortBy > 0 && pad.isDefined) res ++ padding(shortBy) else res } lazy val len = xs.length lazy val incomplete = len < count diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala index de09bb2040..cc2acb74d4 100644 --- a/src/library/scala/collection/mutable/AVLTree.scala +++ b/src/library/scala/collection/mutable/AVLTree.scala @@ -14,8 +14,8 @@ package mutable * An immutable AVL Tree implementation formerly used by mutable.TreeSet * * @author Lucien Pereira - * @deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.0") */ +@deprecated("AVLTree and its related classes are being removed from the standard library since they're not different enough from RedBlackTree to justify keeping them.", "2.11.2") private[mutable] sealed trait AVLTree[+A] extends Serializable { def balance: Int diff --git a/src/library/scala/concurrent/Channel.scala b/src/library/scala/concurrent/Channel.scala index 067244bd1c..89ad7d8c0e 100644 --- a/src/library/scala/concurrent/Channel.scala +++ b/src/library/scala/concurrent/Channel.scala @@ -10,8 +10,10 @@ package scala.concurrent -/** This class ... +/** This class provides a simple FIFO queue of data objects, + * which are read by one or more reader threads. * + * @tparam A type of data exchanged * @author Martin Odersky * @version 1.0, 10/03/2003 */ @@ -20,11 +22,14 @@ class Channel[A] { var elem: A = _ var next: LinkedList[A] = null } - private var written = new LinkedList[A] // FIFO buffer, realized through + private var written = new LinkedList[A] // FIFO queue, realized through private var lastWritten = written // aliasing of a linked list private var nreaders = 0 - /** + /** Append a value to the FIFO queue to be read by `read`. + * This operation is nonblocking and can be executed by any thread. + * + * @param x object to enqueue to this channel */ def write(x: A) = synchronized { lastWritten.elem = x @@ -33,6 +38,11 @@ class Channel[A] { if (nreaders > 0) notify() } + /** Retrieve the next waiting object from the FIFO queue, + * blocking if necessary until an object is available. + * + * @return next object dequeued from this channel + */ def read: A = synchronized { while (written.next == null) { try { @@ -45,5 +55,4 @@ class Channel[A] { written = written.next x } - } diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index a1e94c8876..4674c9174b 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -77,12 +77,12 @@ trait ExecutionContext { } /** - * Union interface since Java does not support union types + * An [[ExecutionContext]] that is also a Java [[Executor]]. */ trait ExecutionContextExecutor extends ExecutionContext with Executor /** - * Union interface since Java does not support union types + * An [[ExecutionContext]] that is also a Java [[ExecutorService]]. */ trait ExecutionContextExecutorService extends ExecutionContextExecutor with ExecutorService diff --git a/src/library/scala/concurrent/Lock.scala b/src/library/scala/concurrent/Lock.scala index 1c00c0e91f..8d18da2d38 100644 --- a/src/library/scala/concurrent/Lock.scala +++ b/src/library/scala/concurrent/Lock.scala @@ -14,8 +14,8 @@ package scala.concurrent * * @author Martin Odersky * @version 1.0, 10/03/2003 - * @deprecated("Use java.util.concurrent.locks.Lock", "2.11.0") */ +@deprecated("Use java.util.concurrent.locks.Lock", "2.11.2") class Lock { var available = true diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala index d5dc3d7e3f..494c955833 100644 --- a/src/library/scala/concurrent/SyncVar.scala +++ b/src/library/scala/concurrent/SyncVar.scala @@ -13,6 +13,7 @@ import java.util.concurrent.TimeUnit /** A class to provide safe concurrent access to a mutable cell. * All methods are synchronized. * + * @tparam A type of the contained value * @author Martin Odersky * @version 1.0, 10/03/2003 */ @@ -20,6 +21,12 @@ class SyncVar[A] { private var isDefined: Boolean = false private var value: Option[A] = None + /** + * Waits for this SyncVar to become defined and returns + * the result, without modifying the stored value. + * + * @return value that is held in this container + */ def get: A = synchronized { while (!isDefined) wait() value.get @@ -57,8 +64,12 @@ class SyncVar[A] { value } - /** Waits for this SyncVar to become defined and returns - * the result */ + /** + * Waits for this SyncVar to become defined and returns + * the result, unsetting the stored value before returning. + * + * @return value that was held in this container + */ def take(): A = synchronized { try get finally unsetVal() @@ -129,4 +140,3 @@ class SyncVar[A] { } } - diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index cc1350f5a9..4d88253de4 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -55,6 +55,11 @@ package object concurrent { } package concurrent { + /** + * This marker trait is used by [[Await]] to ensure that [[Awaitable.ready]] and [[Awaitable.result]] + * are not directly called by user code. An implicit instance of this trait is only available when + * user code is currently calling the methods on [[Await]]. + */ @implicitNotFound("Don't call `Awaitable` methods directly, use the `Await` object.") sealed trait CanAwait diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index d597feb898..2daa4de9a6 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -155,9 +155,12 @@ private[scala] trait PropertiesTrait { // This is looking for javac, tools.jar, etc. // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME, // and finally the system property based javaHome. - def jdkHome = envOrElse("JDK_HOME", envOrElse("JAVA_HOME", javaHome)) + def jdkHome = envOrElse("JDK_HOME", envOrElse("JAVA_HOME", javaHome)) - def versionMsg = "Scala %s %s -- %s".format(propCategory, versionString, copyrightString) + // private[scala] for 2.12 + private[this] def versionFor(command: String) = f"Scala $command $versionString -- $copyrightString" + + def versionMsg = versionFor(propCategory) def scalaCmd = if (isWin) "scala.bat" else "scala" def scalacCmd = if (isWin) "scalac.bat" else "scalac" diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index 4fccad74ac..a2642628a4 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -40,7 +40,7 @@ abstract class SourceFile { def lineToString(index: Int): String = { val start = lineToOffset(index) var end = start - while (!isEndOfLine(end) && end <= length) end += 1 + while (end < length && !isEndOfLine(end)) end += 1 new String(content, start, end - start) } diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index 3c9bbccba3..e240bed0a7 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -30,7 +30,8 @@ package runtime { import c.universe._ val runtimeClass = c.reifyEnclosingRuntimeClass if (runtimeClass.isEmpty) c.abort(c.enclosingPosition, "call site does not have an enclosing class") - val runtimeUniverse = Select(Select(Select(Ident(newTermName("scala")), newTermName("reflect")), newTermName("runtime")), newTermName("universe")) + val scalaPackage = Select(Ident(newTermName("_root_")), newTermName("scala")) + val runtimeUniverse = Select(Select(Select(scalaPackage, newTermName("reflect")), newTermName("runtime")), newTermName("universe")) val currentMirror = Apply(Select(runtimeUniverse, newTermName("runtimeMirror")), List(Select(runtimeClass, newTermName("getClassLoader")))) c.Expr[Nothing](currentMirror)(c.WeakTypeTag.Nothing) } diff --git a/src/repl/scala/tools/nsc/MainGenericRunner.scala b/src/repl/scala/tools/nsc/MainGenericRunner.scala index 43f0ea1256..34057ed341 100644 --- a/src/repl/scala/tools/nsc/MainGenericRunner.scala +++ b/src/repl/scala/tools/nsc/MainGenericRunner.scala @@ -8,7 +8,6 @@ package tools.nsc import io.{ File } import util.{ ClassPath, ScalaClassLoader } -import Properties.{ versionString, copyrightString } import GenericRunnerCommand._ object JarRunner extends CommonRunner { @@ -28,79 +27,78 @@ object JarRunner extends CommonRunner { } /** An object that runs Scala code. It has three possible - * sources for the code to run: pre-compiled code, a script file, - * or interactive entry. - */ + * sources for the code to run: pre-compiled code, a script file, + * or interactive entry. + */ class MainGenericRunner { - def errorFn(ex: Throwable): Boolean = { - ex.printStackTrace() - false - } - def errorFn(str: String): Boolean = { - Console.err println str - false + def errorFn(str: String, e: Option[Throwable] = None, isFailure: Boolean = true): Boolean = { + if (str.nonEmpty) Console.err println str + e foreach (_.printStackTrace()) + !isFailure } def process(args: Array[String]): Boolean = { val command = new GenericRunnerCommand(args.toList, (x: String) => errorFn(x)) - import command.{ settings, howToRun, thingToRun } - def sampleCompiler = new Global(settings) // def so its not created unless needed - - if (!command.ok) return errorFn("\n" + command.shortUsageMsg) - else if (settings.version) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString)) - else if (command.shouldStopWithInfo) return errorFn(command getInfoMessage sampleCompiler) - - def isE = !settings.execute.isDefault - def dashe = settings.execute.value - - def isI = !settings.loadfiles.isDefault - def dashi = settings.loadfiles.value - - // Deadlocks on startup under -i unless we disable async. - if (isI) - settings.Yreplsync.value = true - - def combinedCode = { - val files = if (isI) dashi map (file => File(file).slurp()) else Nil - val str = if (isE) List(dashe) else Nil - - files ++ str mkString "\n\n" - } - - def runTarget(): Either[Throwable, Boolean] = howToRun match { - case AsObject => - ObjectRunner.runAndCatch(settings.classpathURLs, thingToRun, command.arguments) - case AsScript => - ScriptRunner.runScriptAndCatch(settings, thingToRun, command.arguments) - case AsJar => - JarRunner.runJar(settings, thingToRun, command.arguments) - case Error => - Right(false) - case _ => - // We start the repl when no arguments are given. - Right(new interpreter.ILoop process settings) + import command.{ settings, howToRun, thingToRun, shortUsageMsg, shouldStopWithInfo } + def sampleCompiler = new Global(settings) // def so it's not created unless needed + + def run(): Boolean = { + def isE = !settings.execute.isDefault + def dashe = settings.execute.value + + def isI = !settings.loadfiles.isDefault + def dashi = settings.loadfiles.value + + // Deadlocks on startup under -i unless we disable async. + if (isI) + settings.Yreplsync.value = true + + def combinedCode = { + val files = if (isI) dashi map (file => File(file).slurp()) else Nil + val str = if (isE) List(dashe) else Nil + + files ++ str mkString "\n\n" + } + + def runTarget(): Either[Throwable, Boolean] = howToRun match { + case AsObject => + ObjectRunner.runAndCatch(settings.classpathURLs, thingToRun, command.arguments) + case AsScript => + ScriptRunner.runScriptAndCatch(settings, thingToRun, command.arguments) + case AsJar => + JarRunner.runJar(settings, thingToRun, command.arguments) + case Error => + Right(false) + case _ => + // We start the repl when no arguments are given. + Right(new interpreter.ILoop process settings) + } + + /** If -e and -i were both given, we want to execute the -e code after the + * -i files have been included, so they are read into strings and prepended to + * the code given in -e. The -i option is documented to only make sense + * interactively so this is a pretty reasonable assumption. + * + * This all needs a rewrite though. + */ + if (isE) { + ScriptRunner.runCommand(settings, combinedCode, thingToRun +: command.arguments) + } + else runTarget() match { + case Left(ex) => errorFn("", Some(ex)) // there must be a useful message of hope to offer here + case Right(b) => b + } } - /** If -e and -i were both given, we want to execute the -e code after the - * -i files have been included, so they are read into strings and prepended to - * the code given in -e. The -i option is documented to only make sense - * interactively so this is a pretty reasonable assumption. - * - * This all needs a rewrite though. - */ - if (isE) { - ScriptRunner.runCommand(settings, combinedCode, thingToRun +: command.arguments) - } - else runTarget() match { - case Left(ex) => errorFn(ex) - case Right(b) => b - } + if (!command.ok) + errorFn(f"%n$shortUsageMsg") + else if (shouldStopWithInfo) + errorFn(command getInfoMessage sampleCompiler, isFailure = false) + else + run() } } object MainGenericRunner extends MainGenericRunner { - def main(args: Array[String]) { - if (!process(args)) - sys.exit(1) - } + def main(args: Array[String]): Unit = if (!process(args)) sys.exit(1) } |