diff options
53 files changed, 423 insertions, 318 deletions
@@ -4,4 +4,4 @@ source "https://rubygems.org" gem "jekyll", "2.5.3" gem "rouge" # gem 's3_website' -# gem 'redcarpet' +gem "redcarpet", "3.2.3" @@ -191,6 +191,7 @@ lazy val interactive = configureAsSubproject(project) .settings(disableDocsAndPublishingTasks: _*) .dependsOn(compiler) +// TODO: SI-9339 embed shaded copy of jline & its interface (see #4563) lazy val repl = configureAsSubproject(project) .settings( libraryDependencies += jlineDep, @@ -275,6 +275,10 @@ TODO: <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> </artifact:dependencies> + <artifact:dependencies pathId="jarjar.classpath"> + <dependency groupId="com.googlecode.jarjar" artifactId="jarjar" version="1.3"/> + </artifact:dependencies> + <!-- JUnit --> <property name="junit.version" value="4.11"/> <artifact:dependencies pathId="junit.classpath" filesetId="junit.fileset"> @@ -696,7 +700,7 @@ TODO: <property name="partest-javaagent.description" value="Scala Compiler Testing Tool (compiler-specific java agent)"/> <!-- projects without project-specific options: forkjoin, manual, bin, repl --> - <for list="actors,compiler,interactive,scaladoc,library,parser-combinators,partest,partest-extras,partest-javaagent,reflect,scalap,swing,xml,continuations-plugin,continuations-library" param="project"> + <for list="actors,compiler,interactive,scaladoc,library,parser-combinators,partest,partest-extras,partest-javaagent,reflect,scalap,swing,xml,continuations-plugin,continuations-library,repl-jline" param="project"> <sequential> <!-- description is mandatory --> <init-project-prop project="@{project}" name="package" default=""/> <!-- used by mvn-package, copy-bundle, make-bundle --> @@ -799,6 +803,11 @@ TODO: <path id="quick.repl.build.path"> <path refid="quick.compiler.build.path"/> <pathelement location="${build-quick.dir}/classes/repl"/> + </path> + + <path id="quick.repl-jline.build.path"> + <path refid="quick.repl.build.path"/> + <pathelement location="${build-quick.dir}/classes/repl-jline"/> <path refid="repl.deps.classpath"/> </path> @@ -873,6 +882,8 @@ TODO: <fileset dir="${build-quick.dir}/classes/actors"/> </path> + <path id="pack.repl-jline.files"> <fileset dir="${build-quick.dir}/classes/repl-jline"/> </path> + <path id="pack.compiler.files"> <fileset dir="${build-quick.dir}/classes/compiler"/> @@ -1076,6 +1087,7 @@ TODO: </patternset> <taskdef resource="scala/tools/ant/sabbus/antlib.xml" classpathref="starr.compiler.path"/> + <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="jarjar.classpath" /> </target> <!-- =========================================================================== @@ -1157,7 +1169,31 @@ TODO: <staged-build with="locker" stage="quick" project="compiler"/> </target> <target name="quick.repl" depends="quick.comp"> - <staged-build with="locker" stage="quick" project="repl"/> </target> + <staged-build with="locker" stage="quick" project="repl"/> + <staged-build with="locker" stage="quick" project="repl-jline"/> + + <staged-pack project="repl-jline"/> + + <!-- make jline_embedded jar with classes of repl-jline and jline, then shade--> + <jarjar jarfile="${build-pack.dir}/${repl-jline.targetdir}/scala-repl-jline-embedded.jar" whenmanifestonly="fail"> + <zipfileset src="${jline:jline:jar}"/> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/${repl-jline.targetjar}"/> + + <rule pattern="org.fusesource.**" result="scala.tools.fusesource_embedded.@1"/> + <rule pattern="jline.**" result="scala.tools.jline_embedded.@1"/> + <rule pattern="scala.tools.nsc.interpreter.jline.**" result="scala.tools.nsc.interpreter.jline_embedded.@1"/> + <keep pattern="scala.tools.**"/> + </jarjar> + + <!-- unzip jar to repl's class dir to obtain + - standard repl-jline + - a shaded repl-jline (scala/tools/nsc/interpreter/jline_embedded) & jline (scala.tools.jline_embedded) + --> + <copy todir="${build-quick.dir}/classes/repl"> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/${repl-jline.targetjar}"/> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/scala-repl-jline-embedded.jar"/> + </copy> + </target> <target name="quick.scaladoc" depends="quick.comp"> <staged-build with="locker" stage="quick" project="scaladoc" version="scaladoc"/> </target> diff --git a/src/compiler/scala/reflect/quasiquotes/Holes.scala b/src/compiler/scala/reflect/quasiquotes/Holes.scala index 6fa6b9b37a..47084fc317 100644 --- a/src/compiler/scala/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/reflect/quasiquotes/Holes.scala @@ -151,7 +151,7 @@ trait Holes { self: Quasiquotes => else None } - /** Map high-rank unquotee onto an expression that eveluates as a list of given rank. + /** Map high-rank unquotee onto an expression that evaluates as a list of given rank. * * All possible combinations of representations are given in the table below: * diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala index 4b32aab5ee..ef9818c62d 100644 --- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala +++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala @@ -226,7 +226,7 @@ trait PhaseAssembly { } /** Given the phases set, will build a dependency graph from the phases set - * Using the aux. method of the DependencyGraph to create nodes and egdes. + * Using the aux. method of the DependencyGraph to create nodes and edges. */ private def phasesSetToDepGraph(phsSet: mutable.HashSet[SubComponent]): DependencyGraph = { val graph = new DependencyGraph() diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 137954b52d..3e23291e92 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1022,7 +1022,7 @@ abstract class GenICode extends SubComponent { tree match { case Literal(Constant(null)) if generatedType == NullReference && expectedType != UNIT => // literal null on the stack (as opposed to a boxed null, see SI-8233), - // we can bypass `adapt` which would otherwise emitt a redundant [DROP, CONSTANT(null)] + // we can bypass `adapt` which would otherwise emit a redundant [DROP, CONSTANT(null)] // except one case: when expected type is UNIT (unboxed) where we need to emit just a DROP case _ => adapt(generatedType, expectedType, resCtx, tree.pos) @@ -2108,7 +2108,7 @@ abstract class GenICode extends SubComponent { /** * Represent a label in the current method code. In order * to support forward jumps, labels can be created without - * having a deisgnated target block. They can later be attached + * having a designated target block. They can later be attached * by calling `anchor`. */ class Label(val symbol: Symbol) { diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index 058b6a161d..64c9901a3e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -387,7 +387,7 @@ abstract class TypeFlowAnalysis { Moreover, it's often the case that the last CALL_METHOD of interest ("of interest" equates to "being tracked in `isOnWatchlist`) isn't the last instruction on the block. There are cases where the typeflows computed past this `lastInstruction` are needed, and cases when they aren't. - The reasoning behind this decsision is described in `populatePerimeter()`. All `blockTransfer()` needs to do (in order to know at which instruction it can stop) + The reasoning behind this decision is described in `populatePerimeter()`. All `blockTransfer()` needs to do (in order to know at which instruction it can stop) is querying `isOnPerimeter`. Upon visiting a CALL_METHOD that's an inlining candidate, the relevant pieces of information about the pre-instruction typestack are collected for future use. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index a2fd22d24c..0f67852804 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -90,7 +90,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { override def getCurrentCUnit(): CompilationUnit = { cunit } - /* ---------------- helper utils for generating classes and fiels ---------------- */ + /* ---------------- helper utils for generating classes and fields ---------------- */ def genPlainClass(cd: ClassDef) { assert(cnode == null, "GenBCode detected nested methods.") diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 93734d3935..d68c916f09 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -293,7 +293,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { val javaCompatMembers = { if (linkedClass != NoSymbol && isTopLevelModuleClass(linkedClass)) // phase travel to exitingPickler: this makes sure that memberClassesForInnerClassTable only sees member - // classes, not local classes of the companion module (E in the exmaple) that were lifted by lambdalift. + // classes, not local classes of the companion module (E in the example) that were lifted by lambdalift. exitingPickler(memberClassesForInnerClassTable(linkedClass)) else Nil diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala index 607b7145d6..dbf19744fa 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala @@ -127,7 +127,7 @@ class ByteCodeRepository(val classPath: ClassFileLookup[AbstractFile], val isJav case Nil => Left(failedClasses) } - // In a MethodInsnNode, the `owner` field may be an array descriptor, for exmple when invoking `clone`. We don't have a method node to return in this case. + // In a MethodInsnNode, the `owner` field may be an array descriptor, for example when invoking `clone`. We don't have a method node to return in this case. if (ownerInternalNameOrArrayDescriptor.charAt(0) == '[') Left(MethodNotFound(name, descriptor, ownerInternalNameOrArrayDescriptor, Nil)) else diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala index 5f51a94673..bd5bab28b5 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala @@ -262,7 +262,7 @@ object LocalOptImpls { * the same index, but distinct start / end ranges are different variables, they may have not the * same type or name. */ - def removeUnusedLocalVariableNodes(method: MethodNode)(fistLocalIndex: Int = parametersSize(method), renumber: Int => Int = identity): Boolean = { + def removeUnusedLocalVariableNodes(method: MethodNode)(firstLocalIndex: Int = parametersSize(method), renumber: Int => Int = identity): Boolean = { def variableIsUsed(start: AbstractInsnNode, end: LabelNode, varIndex: Int): Boolean = { start != end && (start match { case v: VarInsnNode if v.`var` == varIndex => true @@ -276,7 +276,7 @@ object LocalOptImpls { val local = localsIter.next() val index = local.index // parameters and `this` (the lowest indices, starting at 0) are never removed or renumbered - if (index >= fistLocalIndex) { + if (index >= firstLocalIndex) { if (!variableIsUsed(local.start, local.end, index)) localsIter.remove() else if (renumber(index) != index) local.index = renumber(index) } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 953e43eaca..d3cdf69d30 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -76,7 +76,7 @@ trait ScalaSettings extends AbsScalaSettings val implicitConversions = Choice("implicitConversions", "Allow definition of implicit functions called views") val higherKinds = Choice("higherKinds", "Allow higher-kinded types") val existentials = Choice("existentials", "Existential types (besides wildcard types) can be written and inferred") - val macros = Choice("experimental.macros", "Allow macro defintion (besides implementation and application)") + val macros = Choice("experimental.macros", "Allow macro definition (besides implementation and application)") } val language = { val description = "Enable or disable language features" diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 55ab73028e..5a7f6c52da 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -444,7 +444,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre def adaptAndPostErase(tree: Tree, pt: Type): (Boolean, Tree) = { val (needsAdapt, adaptedTree) = adapt(tree, pt) val trans = postErasure.newTransformer(unit) - val postErasedTree = trans.atOwner(currentOwner)(trans.transform(adaptedTree)) // SI-8017 elimnates ErasedValueTypes + val postErasedTree = trans.atOwner(currentOwner)(trans.transform(adaptedTree)) // SI-8017 eliminates ErasedValueTypes (needsAdapt, postErasedTree) } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 227c45b3a7..49a4990722 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -510,7 +510,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { def propForEqualsTo(c: Const): Prop = {observed(); symForEqualsTo.getOrElse(c, False)} // [implementation NOTE: don't access until all potential equalities have been registered using registerEquality]p - /** the information needed to construct the boolean proposition that encods the equality proposition (V = C) + /** the information needed to construct the boolean proposition that encodes the equality proposition (V = C) * * that models a type test pattern `_: C` or constant pattern `C`, where the type test gives rise to a TypeConst C, * and the constant pattern yields a ValueConst C diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index e1fe220556..e0fcc05de2 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -642,7 +642,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { } // override def apply - // debug.patmat("before fixerupper: "+ xTree) + // debug.patmat("before fixerUpper: "+ xTree) // currentRun.trackerFactory.snapshot() // debug.patmat("after fixerupper") // currentRun.trackerFactory.snapshot() diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 7edd36dc22..17cf02cce6 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -153,7 +153,7 @@ import scala.language.implicitConversions * * - The fact that `tail` works at all is of interest. In the definition of * `fibs` we have an initial `(0, 1, Stream(...))` so `tail` is deterministic. - * If we deinfed `fibs` such that only `0` were concretely known then the act + * If we defined `fibs` such that only `0` were concretely known then the act * of determining `tail` would require the evaluation of `tail` which would * cause an infinite recursion and stack overflow. If we define a definition * where the tail is not initially computable then we're going to have an diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 47a623a616..46d5d0c69c 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -132,19 +132,25 @@ override def companion: GenericCompanion[Vector] = Vector throw new IndexOutOfBoundsException(index.toString) } - + // If we have a default builder, there are faster ways to perform some operations + @inline private[this] def isDefaultCBF[A, B, That](bf: CanBuildFrom[Vector[A], B, That]): Boolean = + (bf eq IndexedSeq.ReusableCBF) || (bf eq collection.immutable.Seq.ReusableCBF) || (bf eq collection.Seq.ReusableCBF) + // SeqLike api override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = - if (bf eq IndexedSeq.ReusableCBF) updateAt(index, elem).asInstanceOf[That] // just ignore bf + if (isDefaultCBF[A, B, That](bf)) + updateAt(index, elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly else super.updated(index, elem)(bf) override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = - if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf + if (isDefaultCBF[A, B, That](bf)) + appendFront(elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly else super.+:(elem)(bf) override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = - if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf + if (isDefaultCBF(bf)) + appendBack(elem).asInstanceOf[That] // ignore bf--it will just give a Vector, and slowly else super.:+(elem)(bf) override def take(n: Int): Vector[A] = { @@ -211,7 +217,8 @@ override def companion: GenericCompanion[Vector] = Vector // concat (suboptimal but avoids worst performance gotchas) override def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Vector[A], B, That]): That = { - if (bf eq IndexedSeq.ReusableCBF) { + if (isDefaultCBF(bf)) { + // We are sure we will create a Vector, so let's do it efficiently import Vector.{Log2ConcatFaster, TinyAppendFaster} if (that.isEmpty) this.asInstanceOf[That] else { diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index eddfec82e7..d393a841b7 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -802,7 +802,7 @@ trait ReificationSupport { self: SymbolTable => require(enums.nonEmpty, "enumerators can't be empty") enums.head match { case SyntacticValFrom(_, _) => - case t => throw new IllegalArgumentException(s"$t is not a valid fist enumerator of for loop") + case t => throw new IllegalArgumentException(s"$t is not a valid first enumerator of for loop") } enums.tail.foreach { case SyntacticValEq(_, _) | SyntacticValFrom(_, _) | SyntacticFilter(_) => diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index c705ca7069..15a87200f1 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -561,7 +561,7 @@ private[internal] trait TypeMaps { | tparams ${rhsSym.typeParams map own_s mkString ", "} |""" - if (argIndex < 0) + if (!rhsArgs.isDefinedAt(argIndex)) abort(s"Something is wrong: cannot find $lhs in applied type $rhs\n" + explain) else { val targ = rhsArgs(argIndex) diff --git a/src/repl/scala/tools/nsc/interpreter/session/FileBackedHistory.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala index dddfb1b8f6..b6c9792ec0 100644 --- a/src/repl/scala/tools/nsc/interpreter/session/FileBackedHistory.scala +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala @@ -1,20 +1,22 @@ /* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL + * Copyright 2005-2015 LAMP/EPFL * @author Paul Phillips */ -package scala.tools.nsc -package interpreter -package session +package scala.tools.nsc.interpreter.jline -import scala.tools.nsc.io._ -import FileBackedHistory._ +import _root_.jline.console.history.PersistentHistory + + +import scala.tools.nsc.interpreter +import scala.tools.nsc.io.{File, Path} /** TODO: file locking. - */ -trait FileBackedHistory extends JLineHistory with JPersistentHistory { + */ +trait FileBackedHistory extends JLineHistory with PersistentHistory { def maxSize: Int - protected lazy val historyFile: File = defaultFile + + protected lazy val historyFile: File = FileBackedHistory.defaultFile private var isPersistent = true locally { @@ -27,6 +29,7 @@ trait FileBackedHistory extends JLineHistory with JPersistentHistory { try op finally isPersistent = saved } + def addLineToFile(item: CharSequence): Unit = { if (isPersistent) append(item + "\n") @@ -37,6 +40,7 @@ trait FileBackedHistory extends JLineHistory with JPersistentHistory { val lines = asStrings map (_ + "\n") historyFile.writeAll(lines: _*) } + /** Append one or more lines to the history file. */ protected def append(lines: String*): Unit = { historyFile.appendAll(lines: _*) @@ -54,31 +58,36 @@ trait FileBackedHistory extends JLineHistory with JPersistentHistory { // than abandon hope we'll try to read it as ISO-8859-1 case _: Exception => try historyFile.lines("ISO-8859-1").toIndexedSeq - catch { case _: Exception => Vector() } + catch { + case _: Exception => Vector() + } } } - repldbg("Loading " + lines.size + " into history.") + interpreter.repldbg("Loading " + lines.size + " into history.") // avoid writing to the history file withoutSaving(lines takeRight maxSize foreach add) // truncate the history file if it's too big. if (lines.size > maxSize) { - repldbg("File exceeds maximum size: truncating to " + maxSize + " entries.") + interpreter.repldbg("File exceeds maximum size: truncating to " + maxSize + " entries.") sync() } moveToEnd() } def flush(): Unit = () + def purge(): Unit = historyFile.truncate() } object FileBackedHistory { // val ContinuationChar = '\003' // val ContinuationNL: String = Array('\003', '\n').mkString - import Properties.userHome + + import scala.tools.nsc.Properties.userHome def defaultFileName = ".scala_history" + def defaultFile: File = File(Path(userHome) / defaultFileName) } diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala new file mode 100644 index 0000000000..c18a9809a0 --- /dev/null +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala @@ -0,0 +1,25 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc.interpreter.jline + +import scala.tools.nsc.interpreter + +import _root_.jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList } + +// implements a jline interface +class JLineDelimiter extends ArgumentDelimiter { + def toJLine(args: List[String], cursor: Int) = args match { + case Nil => new ArgumentList(new Array[String](0), 0, 0, cursor) + case xs => new ArgumentList(xs.toArray, xs.size - 1, xs.last.length, cursor) + } + + def delimit(buffer: CharSequence, cursor: Int) = { + val p = interpreter.Parsed(buffer.toString, cursor) + toJLine(p.args, cursor) + } + + def isDelimiter(buffer: CharSequence, cursor: Int) = interpreter.Parsed(buffer.toString, cursor).isDelimiter +} diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala new file mode 100644 index 0000000000..1f6a1f7022 --- /dev/null +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala @@ -0,0 +1,77 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc.interpreter.jline + +import java.util.{Iterator => JIterator, ListIterator => JListIterator} + +import _root_.jline.{console => jconsole} +import jconsole.history.History.{Entry => JEntry} +import jconsole.history.{History => JHistory} + +import scala.tools.nsc.interpreter +import scala.tools.nsc.interpreter.session.{History, SimpleHistory} + + +/** A straight scalification of the jline interface which mixes + * in the sparse jline-independent one too. + */ +trait JLineHistory extends JHistory with History { + def size: Int + def isEmpty: Boolean + def index: Int + def clear(): Unit + def get(index: Int): CharSequence + def add(line: CharSequence): Unit + def replace(item: CharSequence): Unit + + def entries(index: Int): JListIterator[JEntry] + def entries(): JListIterator[JEntry] + def iterator: JIterator[JEntry] + + def current(): CharSequence + def previous(): Boolean + def next(): Boolean + def moveToFirst(): Boolean + def moveToLast(): Boolean + def moveTo(index: Int): Boolean + def moveToEnd(): Unit + + override def historicize(text: String): Boolean = { + text.lines foreach add + moveToEnd() + true + } +} + +object JLineHistory { + class JLineFileHistory extends SimpleHistory with FileBackedHistory { + override def add(item: CharSequence): Unit = { + if (!isEmpty && last == item) + interpreter.repldbg("Ignoring duplicate entry '" + item + "'") + else { + super.add(item) + addLineToFile(item) + } + } + override def toString = "History(size = " + size + ", index = " + index + ")" + + import scala.collection.JavaConverters._ + + override def asStrings(from: Int, to: Int): List[String] = + entries(from).asScala.take(to - from).map(_.value.toString).toList + + case class Entry(index: Int, value: CharSequence) extends JEntry { + override def toString = value.toString + } + + private def toEntries(): Seq[JEntry] = buf.zipWithIndex map { case (x, i) => Entry(i, x)} + def entries(idx: Int): JListIterator[JEntry] = toEntries().asJava.listIterator(idx) + def entries(): JListIterator[JEntry] = toEntries().asJava.listIterator() + def iterator: JIterator[JEntry] = toEntries().iterator.asJava + } + + def apply(): History = try new JLineFileHistory catch { case x: Exception => new SimpleHistory() } +} diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala new file mode 100644 index 0000000000..f0fce13fe8 --- /dev/null +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala @@ -0,0 +1,143 @@ +/** NSC -- new Scala compiler + * + * Copyright 2005-2015 LAMP/EPFL + * @author Stepan Koltsov + * @author Adriaan Moors + */ + +package scala.tools.nsc.interpreter.jline + +import java.util.{Collection => JCollection, List => JList} + +import _root_.jline.{console => jconsole} +import jconsole.completer.{Completer, ArgumentCompleter} +import jconsole.history.{History => JHistory} + + +import scala.tools.nsc.interpreter +import scala.tools.nsc.interpreter.Completion +import scala.tools.nsc.interpreter.Completion.Candidates +import scala.tools.nsc.interpreter.session.History + +/** + * Reads from the console using JLine. + * + * Eagerly instantiates all relevant JLine classes, so that we can detect linkage errors on `new JLineReader` and retry. + */ +class InteractiveReader(completer: () => Completion) extends interpreter.InteractiveReader { + val interactive = true + + val history: History = new JLineHistory.JLineFileHistory() + + private val consoleReader = { + val reader = new JLineConsoleReader() + + reader setPaginationEnabled interpreter.`package`.isPaged + + // ASAP + reader setExpandEvents false + + reader setHistory history.asInstanceOf[JHistory] + + reader + } + + private[this] var _completion: Completion = interpreter.NoCompletion + def completion: Completion = _completion + + override def postInit() = { + _completion = completer() + + consoleReader.initCompletion(completion) + } + + def reset() = consoleReader.getTerminal().reset() + def redrawLine() = consoleReader.redrawLineAndFlush() + def readOneLine(prompt: String) = consoleReader.readLine(prompt) + def readOneKey(prompt: String) = consoleReader.readOneKey(prompt) +} + +// implements a jline interface +private class JLineConsoleReader extends jconsole.ConsoleReader with interpreter.VariColumnTabulator { + val isAcross = interpreter.`package`.isAcross + val marginSize = 3 + + def width = getTerminal.getWidth() + def height = getTerminal.getHeight() + + private def morePrompt = "--More--" + + private def emulateMore(): Int = { + val key = readOneKey(morePrompt) + try key match { + case '\r' | '\n' => 1 + case 'q' => -1 + case _ => height - 1 + } + finally { + eraseLine() + // TODO: still not quite managing to erase --More-- and get + // back to a scala prompt without another keypress. + if (key == 'q') { + putString(getPrompt()) + redrawLine() + flush() + } + } + } + + override def printColumns(items: JCollection[_ <: CharSequence]): Unit = { + import scala.tools.nsc.interpreter.javaCharSeqCollectionToScala + printColumns_(items: List[String]) + } + + private def printColumns_(items: List[String]): Unit = if (items exists (_ != "")) { + val grouped = tabulate(items) + var linesLeft = if (isPaginationEnabled()) height - 1 else Int.MaxValue + grouped foreach { xs => + println(xs.mkString) + linesLeft -= 1 + if (linesLeft <= 0) { + linesLeft = emulateMore() + if (linesLeft < 0) + return + } + } + } + + def readOneKey(prompt: String) = { + this.print(prompt) + this.flush() + this.readCharacter() + } + + def eraseLine() = resetPromptLine("", "", 0) + + def redrawLineAndFlush(): Unit = { + flush(); drawLine(); flush() + } + + // A hook for running code after the repl is done initializing. + def initCompletion(completion: Completion): Unit = { + this setBellEnabled false + + if (completion ne interpreter.NoCompletion) { + val jlineCompleter = new ArgumentCompleter(new JLineDelimiter, + new Completer { + val tc = completion.completer() + def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = { + val buf = if (_buf == null) "" else _buf + val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor) + newCandidates foreach (candidates add _) + newCursor + } + } + ) + + jlineCompleter setStrict false + + this addCompleter jlineCompleter + this setAutoprintThreshold 400 // max completion candidates without warning + } + } +} diff --git a/src/repl/scala/tools/nsc/interpreter/Delimited.scala b/src/repl/scala/tools/nsc/interpreter/Delimited.scala deleted file mode 100644 index b7f06f1d0a..0000000000 --- a/src/repl/scala/tools/nsc/interpreter/Delimited.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package interpreter - -import jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList } - -class JLineDelimiter extends ArgumentDelimiter { - def toJLine(args: List[String], cursor: Int) = args match { - case Nil => new ArgumentList(new Array[String](0), 0, 0, cursor) - case xs => new ArgumentList(xs.toArray, xs.size - 1, xs.last.length, cursor) - } - - def delimit(buffer: CharSequence, cursor: Int) = { - val p = Parsed(buffer.toString, cursor) - toJLine(p.args, cursor) - } - def isDelimiter(buffer: CharSequence, cursor: Int) = Parsed(buffer.toString, cursor).isDelimiter -} - -trait Delimited { - self: Parsed => - - def delimited: Char => Boolean - def escapeChars: List[Char] = List('\\') - - /** Break String into args based on delimiting function. - */ - protected def toArgs(s: String): List[String] = - if (s == "") Nil - else (s indexWhere isDelimiterChar) match { - case -1 => List(s) - case idx => (s take idx) :: toArgs(s drop (idx + 1)) - } - - def isDelimiterChar(ch: Char) = delimited(ch) - def isEscapeChar(ch: Char): Boolean = escapeChars contains ch -} diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 4221126caa..a3047ccc8e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -26,6 +26,8 @@ import scala.concurrent.{ ExecutionContext, Await, Future, future } import ExecutionContext.Implicits._ import java.io.{ BufferedReader, FileReader } +import scala.util.{Try, Success, Failure} + /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. * After instantiation, clients should call the main() method. @@ -503,10 +505,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) val errless = intp compileSources new BatchSourceFile("<pastie>", s"object pastel {\n$code\n}") if (errless) echo("The compiler reports no errors.") } - def historicize(text: String) = history match { - case jlh: JLineHistory => text.lines foreach jlh.add ; jlh.moveToEnd() ; true - case _ => false - } + def edit(text: String): Result = editor match { case Some(ed) => val tmp = File.makeTemp() @@ -522,7 +521,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) val res = intp interpret edited if (res == IR.Incomplete) diagnose(edited) else { - historicize(edited) + history.historicize(edited) Result(lineToRecord = Some(edited), keepRunning = true) } case None => echo("Can't read edited text. Did you delete it?") @@ -533,7 +532,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) tmp.delete() } case None => - if (historicize(text)) echo("Placing text in recent history.") + if (history.historicize(text)) echo("Placing text in recent history.") else echo(f"No EDITOR defined and you can't change history, echoing your text:%n$text") } @@ -565,10 +564,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } import scala.collection.JavaConverters._ val index = (start - 1) max 0 - val text = history match { - case jlh: JLineHistory => jlh.entries(index).asScala.take(len) map (_.value) mkString "\n" - case _ => history.asStrings.slice(index, index + len) mkString "\n" - } + val text = history.asStrings(index, index + len) mkString "\n" edit(text) } catch { case _: NumberFormatException => echo(s"Bad range '$what'") @@ -866,16 +862,36 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) * with SimpleReader. */ def chooseReader(settings: Settings): InteractiveReader = { - if (settings.Xnojline || Properties.isEmacsShell) - SimpleReader() - else try new JLineReader( - if (settings.noCompletion) NoCompletion - else new JLineCompletion(intp) - ) - catch { - case ex @ (_: Exception | _: NoClassDefFoundError) => - echo(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.") - SimpleReader() + if (settings.Xnojline || Properties.isEmacsShell) SimpleReader() + else { + type Completer = () => Completion + type ReaderMaker = Completer => InteractiveReader + + def instantiate(className: String): ReaderMaker = completer => { + if (settings.debug) Console.println(s"Trying to instantiate a InteractiveReader from $className") + Class.forName(className).getConstructor(classOf[Completer]). + newInstance(completer). + asInstanceOf[InteractiveReader] + } + + def mkReader(maker: ReaderMaker) = + if (settings.noCompletion) maker(() => NoCompletion) + else maker(() => new JLineCompletion(intp)) // JLineCompletion is a misnomer -- it's not tied to jline + + def internalClass(kind: String) = s"scala.tools.nsc.interpreter.$kind.InteractiveReader" + val readerClasses = sys.props.get("scala.repl.reader").toStream ++ Stream(internalClass("jline"), internalClass("jline_embedded")) + val readers = readerClasses map (cls => Try { mkReader(instantiate(cls)) }) + + val reader = (readers collect { case Success(reader) => reader } headOption) getOrElse SimpleReader() + + if (settings.debug) { + val readerDiags = (readerClasses, readers).zipped map { + case (cls, Failure(e)) => s" - $cls --> " + e.getStackTrace.mkString(e.toString+"\n\t", "\n\t","\n") + case (cls, Success(_)) => s" - $cls OK" + } + Console.println(s"All InteractiveReaders tried: ${readerDiags.mkString("\n","\n","\n")}") + } + reader } } @@ -896,10 +912,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) asyncMessage(power.banner) } // SI-7418 Now, and only now, can we enable TAB completion. - in match { - case x: JLineReader => x.consoleReader.postInit - case _ => - } + in.postInit() } // start an interpreter with the given settings diff --git a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala index ed69d449cb..71753a3e39 100644 --- a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala +++ b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala @@ -13,6 +13,8 @@ import Properties.isMac /** Reads lines from an input stream */ trait InteractiveReader { + def postInit(): Unit = {} + val interactive: Boolean def reset(): Unit diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala index c1122d4223..d878988e26 100644 --- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -12,6 +12,7 @@ import scala.reflect.internal.util.StringOps.longestCommonPrefix // REPL completor - queries supplied interpreter for valid // completions based on current contents of buffer. +// TODO: change class name to reflect it's not specific to jline (nor does it depend on it) class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput { val global: intp.global.type = intp.global import global._ diff --git a/src/repl/scala/tools/nsc/interpreter/JLineReader.scala b/src/repl/scala/tools/nsc/interpreter/JLineReader.scala deleted file mode 100644 index b6e834a1ed..0000000000 --- a/src/repl/scala/tools/nsc/interpreter/JLineReader.scala +++ /dev/null @@ -1,75 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Stepan Koltsov - */ - -package scala.tools.nsc -package interpreter - -import jline.console.ConsoleReader -import jline.console.completer._ -import session._ -import Completion._ - -/** - * Reads from the console using JLine. - */ -class JLineReader(_completion: => Completion) extends InteractiveReader { - val interactive = true - val consoleReader = new JLineConsoleReader() - - lazy val completion = _completion - lazy val history: JLineHistory = JLineHistory() - - private def term = consoleReader.getTerminal() - def reset() = term.reset() - - def scalaToJline(tc: ScalaCompleter): Completer = new Completer { - def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = { - val buf = if (_buf == null) "" else _buf - val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor) - newCandidates foreach (candidates add _) - newCursor - } - } - - class JLineConsoleReader extends ConsoleReader with ConsoleReaderHelper with VariColumnTabulator { - val isAcross = interpreter.`package`.isAcross - - this setPaginationEnabled interpreter.`package`.isPaged - - // ASAP - this setExpandEvents false - - // working around protected/trait/java insufficiencies. - def goBack(num: Int): Unit = back(num) - if ((history: History) ne NoHistory) - this setHistory history - - def readOneKey(prompt: String) = { - this.print(prompt) - this.flush() - this.readCharacter() - } - def eraseLine() = consoleReader.resetPromptLine("", "", 0) - def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() } - - // A hook for running code after the repl is done initializing. - lazy val postInit: Unit = { - this setBellEnabled false - - if (completion ne NoCompletion) { - val argCompletor: ArgumentCompleter = - new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer())) - argCompletor setStrict false - - this addCompleter argCompletor - this setAutoprintThreshold 400 // max completion candidates without warning - } - } - } - - def redrawLine() = consoleReader.redrawLineAndFlush() - def readOneLine(prompt: String) = consoleReader readLine prompt - def readOneKey(prompt: String) = consoleReader readOneKey prompt -} diff --git a/src/repl/scala/tools/nsc/interpreter/Parsed.scala b/src/repl/scala/tools/nsc/interpreter/Parsed.scala index 672a6fd28f..5e58d3a2c4 100644 --- a/src/repl/scala/tools/nsc/interpreter/Parsed.scala +++ b/src/repl/scala/tools/nsc/interpreter/Parsed.scala @@ -8,6 +8,25 @@ package interpreter import util.returning +trait Delimited { + self: Parsed => + + def delimited: Char => Boolean + def escapeChars: List[Char] = List('\\') + + /** Break String into args based on delimiting function. + */ + protected def toArgs(s: String): List[String] = + if (s == "") Nil + else (s indexWhere isDelimiterChar) match { + case -1 => List(s) + case idx => (s take idx) :: toArgs(s drop (idx + 1)) + } + + def isDelimiterChar(ch: Char) = delimited(ch) + def isEscapeChar(ch: Char): Boolean = escapeChars contains ch +} + /** One instance of a command buffer. */ class Parsed private ( diff --git a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/repl/scala/tools/nsc/interpreter/Tabulators.scala index a8d537e314..75bec168eb 100644 --- a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala +++ b/src/repl/scala/tools/nsc/interpreter/Tabulators.scala @@ -3,60 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc -package interpreter - -import jline.console.{ ConsoleReader, CursorBuffer } - -trait ConsoleReaderHelper { _: ConsoleReader with Tabulator => - def isAcross: Boolean - - def terminal = getTerminal() - def width = terminal.getWidth() - def height = terminal.getHeight() - - def readOneKey(prompt: String): Int - def eraseLine(): Unit - - val marginSize = 3 - - private def morePrompt = "--More--" - private def emulateMore(): Int = { - val key = readOneKey(morePrompt) - try key match { - case '\r' | '\n' => 1 - case 'q' => -1 - case _ => height - 1 - } - finally { - eraseLine() - // TODO: still not quite managing to erase --More-- and get - // back to a scala prompt without another keypress. - if (key == 'q') { - putString(getPrompt()) - redrawLine() - flush() - } - } - } - - override def printColumns(items: JCollection[_ <: CharSequence]): Unit = - printColumns_(items: List[String]) - - private def printColumns_(items: List[String]): Unit = if (items exists (_ != "")) { - val grouped = tabulate(items) - var linesLeft = if (isPaginationEnabled()) height - 1 else Int.MaxValue - grouped foreach { xs => - println(xs.mkString) - linesLeft -= 1 - if (linesLeft <= 0) { - linesLeft = emulateMore() - if (linesLeft < 0) - return - } - } - } -} +package scala.tools.nsc.interpreter trait Tabulator { def isAcross: Boolean @@ -72,7 +19,7 @@ trait Tabulator { ) protected def columnize(ss: Seq[String]): Seq[Seq[String]] = ss map (s => Seq(s)) protected def printMultiLineColumns(items: Seq[String]): Seq[Seq[String]] = { - import SimpleMath._ + import scala.tools.nsc.interpreter.SimpleMath._ val longest = (items map (_.length)).max val columnWidth = longest + marginSize val maxcols = ( @@ -101,7 +48,7 @@ trait Tabulator { /** Adjust the column width and number of columns to minimize the row count. */ trait VariColumnTabulator extends Tabulator { override protected def printMultiLineColumns(items: Seq[String]): Seq[Seq[String]] = { - import SimpleMath._ + import scala.tools.nsc.interpreter.SimpleMath._ val longest = (items map (_.length)).max val shortest = (items map (_.length)).min val fattest = longest + marginSize diff --git a/src/repl/scala/tools/nsc/interpreter/session/History.scala b/src/repl/scala/tools/nsc/interpreter/session/History.scala index 794d41adc7..2028a13dfd 100644 --- a/src/repl/scala/tools/nsc/interpreter/session/History.scala +++ b/src/repl/scala/tools/nsc/interpreter/session/History.scala @@ -11,7 +11,10 @@ package session * reference to the jline classes. Very sparse right now. */ trait History { + def historicize(text: String): Boolean = false + def asStrings: List[String] + def asStrings(from: Int, to: Int): List[String] = asStrings.slice(from, to) def index: Int def size: Int } diff --git a/src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala b/src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala deleted file mode 100644 index 18e0ee7c85..0000000000 --- a/src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package interpreter -package session - -/** A straight scalification of the jline interface which mixes - * in the sparse jline-independent one too. - */ -trait JLineHistory extends JHistory with History { - def size: Int - def isEmpty: Boolean - def index: Int - def clear(): Unit - def get(index: Int): CharSequence - def add(line: CharSequence): Unit - def replace(item: CharSequence): Unit - - def entries(index: Int): JListIterator[JEntry] - def entries(): JListIterator[JEntry] - def iterator: JIterator[JEntry] - - def current(): CharSequence - def previous(): Boolean - def next(): Boolean - def moveToFirst(): Boolean - def moveToLast(): Boolean - def moveTo(index: Int): Boolean - def moveToEnd(): Unit -} - -object JLineHistory { - class JLineFileHistory extends SimpleHistory with FileBackedHistory { - override def add(item: CharSequence): Unit = { - if (!isEmpty && last == item) - repldbg("Ignoring duplicate entry '" + item + "'") - else { - super.add(item) - addLineToFile(item) - } - } - override def toString = "History(size = " + size + ", index = " + index + ")" - } - - def apply(): JLineHistory = try new JLineFileHistory catch { case x: Exception => new SimpleHistory() } -} diff --git a/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala b/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala index 7c49b91296..504d0d30ee 100644 --- a/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala +++ b/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala @@ -10,10 +10,9 @@ package session import scala.collection.mutable.{ Buffer, ListBuffer } import scala.collection.JavaConverters._ -class SimpleHistory extends JLineHistory { +class SimpleHistory extends History { private var _index: Int = 0 - private val buf: Buffer[String] = new ListBuffer[String] - private def toEntries(): Seq[JEntry] = buf.zipWithIndex map { case (x, i) => Entry(i, x) } + protected val buf: Buffer[String] = new ListBuffer[String] private def setTo(num: Int) = { _index = num ; true } private def minusOne = { _index -= 1 ; true } private def plusOne = { _index += 1 ; true } @@ -25,10 +24,6 @@ class SimpleHistory extends JLineHistory { "" } - case class Entry(index: Int, value: CharSequence) extends JEntry { - override def toString = value - } - def maxSize: Int = 2500 def last = if (isEmpty) fail("last") else buf.last @@ -42,9 +37,6 @@ class SimpleHistory extends JLineHistory { buf trimEnd 1 add(item) } - def entries(idx: Int): JListIterator[JEntry] = toEntries().asJava.listIterator(idx) - def entries(): JListIterator[JEntry] = toEntries().asJava.listIterator() - def iterator: JIterator[JEntry] = toEntries().iterator.asJava def remove(idx: Int): CharSequence = buf remove idx def removeFirst(): CharSequence = buf remove 0 diff --git a/src/repl/scala/tools/nsc/interpreter/session/package.scala b/src/repl/scala/tools/nsc/interpreter/session/package.scala index a3d7312c98..06e7f6207b 100644 --- a/src/repl/scala/tools/nsc/interpreter/session/package.scala +++ b/src/repl/scala/tools/nsc/interpreter/session/package.scala @@ -14,10 +14,5 @@ package object session { type JIterator[T] = java.util.Iterator[T] type JListIterator[T] = java.util.ListIterator[T] - type JEntry = jline.console.history.History.Entry - type JHistory = jline.console.history.History - type JMemoryHistory = jline.console.history.MemoryHistory - type JPersistentHistory = jline.console.history.PersistentHistory - private[interpreter] implicit def charSequenceFix(x: CharSequence): String = x.toString } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala index b541cf721b..320a8e23b2 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala @@ -383,7 +383,7 @@ class DotDiagramGenerator(settings: doc.Settings, dotRunner: DotRunner) extends if (dotId.count(_ == '|') == 1) { val Array(klass, id) = dotId.toString.split("\\|") /* Sometimes dot "forgets" to add the image -- that's very annoying, but it seems pretty random, and simple - * tests like excute 20K times and diff the output don't trigger the bug -- so it's up to us to place the image + * tests like execute 20K times and diff the output don't trigger the bug -- so it's up to us to place the image * back in the node */ val kind = getKind(klass) if (kind != "") diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala index 03d71f15a3..3cbcbc433e 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala @@ -478,7 +478,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { override lazy val comment = { def nonRootTemplate(sym: Symbol): Option[DocTemplateImpl] = if (sym eq RootPackage) None else findTemplateMaybe(sym) - /* Variable precendence order for implicitly added members: Take the variable defifinitions from ... + /* Variable precendence order for implicitly added members: Take the variable definitions from ... * 1. the target of the implicit conversion * 2. the definition template (owner) * 3. the current template diff --git a/test/files/jvm/unreachable/Test.scala b/test/files/jvm/unreachable/Test.scala index 3f520eb106..4c0fcb2ae8 100644 --- a/test/files/jvm/unreachable/Test.scala +++ b/test/files/jvm/unreachable/Test.scala @@ -6,7 +6,7 @@ import scala.collection.JavaConverters._ object Test extends BytecodeTest { def show: Unit = { val classNode = loadClassNode("Foo_1") - // Foo_1 is full of unreachable code which if not elimintated + // Foo_1 is full of unreachable code which if not eliminated // will result in NOPs as can be confirmed by adding -Ydisable-unreachable-prevention // to Foo_1.flags for (methodNode <- classNode.methods.asScala) { diff --git a/test/files/neg/t3995.scala b/test/files/neg/t3995.scala index b03617ac86..c79f2a5865 100644 --- a/test/files/neg/t3995.scala +++ b/test/files/neg/t3995.scala @@ -27,6 +27,6 @@ object Test { // can be accessed with unambiguous stable prefixes, the implicits infos // which are members of these companion objects." // - // The skolem is stable, but it doen't seem much good to us + // The skolem is stable, but it does not seem much good to us (new Lift).apply("") } diff --git a/test/files/neg/t8237-default.scala b/test/files/neg/t8237-default.scala index f695aa523f..a4370046bd 100644 --- a/test/files/neg/t8237-default.scala +++ b/test/files/neg/t8237-default.scala @@ -1,4 +1,4 @@ -// This test case was extracte from `names-defaults-neg.scala` +// This test case was extracted from `names-defaults-neg.scala` // It pinpoints an improvement an error message that results from // a type inference failure object Test extends App { diff --git a/test/files/neg/t8463.scala b/test/files/neg/t8463.scala index 7c954fd834..1337f8bece 100644 --- a/test/files/neg/t8463.scala +++ b/test/files/neg/t8463.scala @@ -7,7 +7,7 @@ object Test { /* If SI-8230 is fixed, and `viewExists` is changed to no longer leak ambiguity errors, you might expect the check file for this test to - change as folloes: + change as follows: @@ -1,18 +1,10 @@ -t8463.scala:5: error: no type parameters for method apply: (activity: diff --git a/test/files/pos/SI-4012-b.scala b/test/files/pos/SI-4012-b.scala index 6bc8592766..f6d84963e4 100644 --- a/test/files/pos/SI-4012-b.scala +++ b/test/files/pos/SI-4012-b.scala @@ -6,7 +6,7 @@ object Sub extends Super[Int] { // it is expected that super[Super].superb crashes, since // specialization does parent class rewiring, and the super // of Sub becomes Super$mcII$sp and not Super. But I consider - // this normal behavior -- if you want, I can modify duplicatiors + // this normal behavior -- if you want, I can modify duplicators // to make this work, but I consider it's best to keep this // let the user know Super is not the superclass anymore. // super[Super].superb - Vlad diff --git a/test/files/pos/delambdafy-patterns.scala b/test/files/pos/delambdafy-patterns.scala index 95d498629b..ca9eaa67e3 100644 --- a/test/files/pos/delambdafy-patterns.scala +++ b/test/files/pos/delambdafy-patterns.scala @@ -2,7 +2,7 @@ class DelambdafyPatterns { def bar: Unit = () def wildcardPatternInTryCatch: Unit => Unit = (x: Unit) => // patterns in try..catch are preserved so we need to be - // careful when it comes to free variable detction + // careful when it comes to free variable detection // in particular a is _not_ free variable, also the // `_` identifier has no symbol attached to it try bar catch { diff --git a/test/files/pos/t7200b.scala b/test/files/pos/t7200b.scala index 9d579c6ef9..59be898fd0 100644 --- a/test/files/pos/t7200b.scala +++ b/test/files/pos/t7200b.scala @@ -10,7 +10,7 @@ trait Foo { object O extends Foo { def coflatMap[A <: T](f: A) = { val f2 = coflatMap(f) // inferred in 2.9.2 / 2.10.0 as [Nothing] - f2.t // so this does't type check. + f2.t // so this fails to type check. f2 } } diff --git a/test/files/run/deeps.scala b/test/files/run/deeps.scala index 6049cc6024..1546112ed5 100644 --- a/test/files/run/deeps.scala +++ b/test/files/run/deeps.scala @@ -3,7 +3,7 @@ //############################################################################ //############################################################################ -// need to revisit array equqality +// need to revisit array equality object Test { def testEquals1 { diff --git a/test/files/run/finally.scala b/test/files/run/finally.scala index 2c01edaaef..b66354ca03 100644 --- a/test/files/run/finally.scala +++ b/test/files/run/finally.scala @@ -93,7 +93,7 @@ object Test extends App { } } - // nested finallies with return value + // nested finally blocks with return value def nestedFinalies: Int = try { try { diff --git a/test/files/run/iq.scala b/test/files/run/iq.scala index 1eb1d40e37..0ccf67a2e9 100644 --- a/test/files/run/iq.scala +++ b/test/files/run/iq.scala @@ -69,7 +69,7 @@ object iq { val (_, q7) = q6.dequeue //val q8 = q7 + 10 + 11 //deprecated val q8 = q7.enqueue(10).enqueue(11) - /* Test dequeu + /* Test dequeue * Expected: q8: Queue(2,3,4,5,6,7,8,9,10,11) */ Console.println("q8: " + q8) diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala index b7ed490cbc..c364425ec9 100644 --- a/test/files/run/names-defaults.scala +++ b/test/files/run/names-defaults.scala @@ -86,7 +86,7 @@ object Test extends App { def f(a: Object) = "first" val f: String => String = a => "second" } - println(t5.f(new Sub1())) // firsst + println(t5.f(new Sub1())) // first println(t5.f("dfklj")) // second object t6 { diff --git a/test/files/run/nullable-lazyvals.scala b/test/files/run/nullable-lazyvals.scala index c201e74e75..be5d82f3a7 100644 --- a/test/files/run/nullable-lazyvals.scala +++ b/test/files/run/nullable-lazyvals.scala @@ -24,7 +24,7 @@ object Test extends App { // test that try-finally does not generated a liftedTry // helper. This would already fail the first part of the test, - // but this check will help diganose it (if the single access to a + // but this check will help diagnose it (if the single access to a // private field does not happen directly in the lazy val, it won't // be nulled). for (f <- foo.getClass.getDeclaredMethods) { diff --git a/test/files/run/t6240-universe-code-gen.scala b/test/files/run/t6240-universe-code-gen.scala index 9f7061ee1b..60e1f76b54 100644 --- a/test/files/run/t6240-universe-code-gen.scala +++ b/test/files/run/t6240-universe-code-gen.scala @@ -13,8 +13,8 @@ object Test extends App { (sym.isMethod && sym.asMethod.isLazy) || sym.isModule ) - val forcables = tp.members.sorted.filter(isLazyAccessorOrObject) - forcables.map { + val forceables = tp.members.sorted.filter(isLazyAccessorOrObject) + forceables.map { sym => val path = s"$prefix.${sym.name}" " " + ( diff --git a/test/files/run/t8601-closure-elim.scala b/test/files/run/t8601-closure-elim.scala index 2c5b03af77..ebeb16e0c7 100644 --- a/test/files/run/t8601-closure-elim.scala +++ b/test/files/run/t8601-closure-elim.scala @@ -11,7 +11,7 @@ object Test extends BytecodeTest { val classNode = loadClassNode("Foo") val methodNode = getMethod(classNode, "b") val ops = methodNode.instructions.iterator.asScala.map(_.getOpcode).toList - assert(!ops.contains(asm.Opcodes.NEW), ops)// should be allocation free if the closure is eliminiated + assert(!ops.contains(asm.Opcodes.NEW), ops)// should be allocation free if the closure is eliminated } test("b") } diff --git a/test/files/run/t8708_b/Test_2.scala b/test/files/run/t8708_b/Test_2.scala index c978490609..fae3c677ec 100644 --- a/test/files/run/t8708_b/Test_2.scala +++ b/test/files/run/t8708_b/Test_2.scala @@ -13,7 +13,7 @@ object Test extends DirectTest { val c = g.rootMirror.getRequiredClass("p.C") println(c.info.decls) val t = c.info.member(g.newTypeName("T")) - // this test ensrues that the <local child> dummy class symbol is not entered in the + // this test ensures that the <local child> dummy class symbol is not entered in the // scope of trait T during unpickling. println(t.info.decls) }) diff --git a/test/files/specialized/constant_lambda.scala b/test/files/specialized/constant_lambda.scala index bb9a97403e..7c5358ce10 100644 --- a/test/files/specialized/constant_lambda.scala +++ b/test/files/specialized/constant_lambda.scala @@ -1,4 +1,4 @@ -// during development of late delmabdafying there was a problem where +// during development of late delambdafying there was a problem where // specialization would undo some of the work done in uncurry if the body of the // lambda had a constant type. That would result in a compiler crash as // when the delambdafy phase got a tree shape it didn't understand diff --git a/test/scaladoc/run/groups.scala b/test/scaladoc/run/groups.scala index c9e4a8679b..ad5cca89b8 100644 --- a/test/scaladoc/run/groups.scala +++ b/test/scaladoc/run/groups.scala @@ -38,7 +38,7 @@ object Test extends ScaladocModelTest { * @groupdesc C Group C is introduced by B */ trait B { - /** baz descriptopn + /** baz description * @group C */ def baz = 3 } |