summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2015-09-22 19:44:09 +0200
committerLukas Rytz <lukas.rytz@typesafe.com>2015-09-22 19:44:09 +0200
commitdf704ef7389ff6265afc1278783489ee97ee4ce7 (patch)
treeca7e4df33c4e5404f18e0b664e28c7c8bc4e3375 /src
parent9995935b6160171527b121263db75b56be6a9ca7 (diff)
parentfe755d5ff2518ff94d6a0dee43f14ba24f9af5eb (diff)
downloadscala-df704ef7389ff6265afc1278783489ee97ee4ce7.tar.gz
scala-df704ef7389ff6265afc1278783489ee97ee4ce7.tar.bz2
scala-df704ef7389ff6265afc1278783489ee97ee4ce7.zip
Merge pull request #4761 from lrytz/merge-2.11-to-2.12-sep-22
Merge 2.11 to 2.12 sep 22
Diffstat (limited to 'src')
-rw-r--r--[-rwxr-xr-x]src/compiler/scala/tools/nsc/ast/DocComments.scala0
-rw-r--r--[-rwxr-xr-x]src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala0
-rw-r--r--[-rwxr-xr-x]src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala0
-rw-r--r--[-rwxr-xr-x]src/compiler/scala/tools/nsc/ast/parser/xml/Utility.scala0
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--[-rwxr-xr-x]src/compiler/scala/tools/nsc/util/DocStrings.scala0
-rw-r--r--src/interactive/scala/tools/nsc/interactive/CompilerControl.scala9
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala125
-rw-r--r--src/library-aux/scala/Any.scala2
-rw-r--r--src/library/scala/AnyVal.scala4
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/IndexedSeqOptimized.scala0
-rw-r--r--src/library/scala/collection/Iterator.scala221
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/JavaConverters.scala0
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/LinearSeqOptimized.scala0
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/generic/FilterMonadic.scala0
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/generic/HasNewBuilder.scala0
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/immutable/DefaultMap.scala0
-rw-r--r--src/library/scala/collection/immutable/IntMap.scala2
-rw-r--r--src/library/scala/collection/immutable/List.scala2
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala86
-rw-r--r--src/library/scala/collection/immutable/PagedSeq.scala4
-rw-r--r--src/library/scala/collection/immutable/Range.scala29
-rw-r--r--src/library/scala/collection/immutable/RedBlackTree.scala3
-rw-r--r--src/library/scala/collection/immutable/Vector.scala11
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/mutable/IndexedSeqOptimized.scala0
-rw-r--r--src/library/scala/collection/mutable/Queue.scala2
-rw-r--r--src/library/scala/collection/package.scala3
-rw-r--r--[-rwxr-xr-x]src/library/scala/collection/readme-if-you-want-to-add-something.txt0
-rw-r--r--src/library/scala/io/Codec.scala2
-rw-r--r--[-rwxr-xr-x]src/library/scala/reflect/NameTransformer.scala0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/TraitSetter.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileBooleanRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileByteRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileCharRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileDoubleRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileFloatRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileIntRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileLongRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileObjectRef.java0
-rw-r--r--[-rwxr-xr-x]src/library/scala/runtime/VolatileShortRef.java0
-rw-r--r--src/library/scala/sys/process/Process.scala4
-rw-r--r--src/library/scala/util/Properties.scala4
-rw-r--r--src/manual/scala/man1/Command.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Chars.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala3
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala2
-rw-r--r--src/reflect/scala/reflect/macros/blackbox/Context.scala2
-rw-r--r--src/reflect/scala/reflect/macros/package.scala4
-rw-r--r--src/reflect/scala/reflect/macros/whitebox/Context.scala2
-rw-r--r--src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala2
-rw-r--r--src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala64
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala115
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala46
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Imports.scala8
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala11
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala56
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Power.scala41
-rw-r--r--src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala110
-rw-r--r--src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala139
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/base/LinkTo.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala0
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js12
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery-ui.js0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/html/resource/lib/ref-index.css0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala0
-rw-r--r--[-rwxr-xr-x]src/scaladoc/scala/tools/nsc/doc/model/TreeFactory.scala0
77 files changed, 888 insertions, 298 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index c70690e697..c70690e697 100755..100644
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 52b8a51a79..52b8a51a79 100755..100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index 67241ef639..67241ef639 100755..100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
diff --git a/src/compiler/scala/tools/nsc/ast/parser/xml/Utility.scala b/src/compiler/scala/tools/nsc/ast/parser/xml/Utility.scala
index 6dcfa173df..6dcfa173df 100755..100644
--- a/src/compiler/scala/tools/nsc/ast/parser/xml/Utility.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/xml/Utility.scala
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 74d152a4cf..70170d9e97 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -172,6 +172,7 @@ trait ScalaSettings extends AbsScalaSettings
val YconstOptimization = BooleanSetting ("-Yconst-opt", "Perform optimization with constant values.")
val Ycompacttrees = BooleanSetting ("-Ycompact-trees", "Use compact tree printer when displaying trees.")
val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL.")
+ val completion = ChoiceSetting ("-Ycompletion", "provider", "Select tab-completion in the REPL.", List("pc","adhoc","none"), "pc")
val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination.")
val debug = BooleanSetting ("-Ydebug", "Increase the quantity of debugging output.")
//val doc = BooleanSetting ("-Ydoc", "Generate documentation")
@@ -364,8 +365,8 @@ trait ScalaSettings extends AbsScalaSettings
*/
val YpresentationVerbose = BooleanSetting("-Ypresentation-verbose", "Print information about presentation compiler tasks.")
val YpresentationDebug = BooleanSetting("-Ypresentation-debug", "Enable debugging output for the presentation compiler.")
- val YpresentationStrict = BooleanSetting("-Ypresentation-strict", "Do not report type errors in sources with syntax errors.")
-
+ val YpresentationAnyThread = BooleanSetting("-Ypresentation-any-thread", "Allow use of the presentation compiler from any thread")
+ val YpresentationStrict = BooleanSetting("-Ypresentation-strict", "Do not report type errors in sources with syntax errors.")
val YpresentationLog = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "")
val YpresentationReplay = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "")
val YpresentationDelay = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, Some((0, 999)), str => Some(str.toInt))
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 49a4990722..62d9c497ba 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -38,7 +38,7 @@ trait Logic extends Debugging {
padded.transpose.map(alignedColumns).transpose map (_.mkString(sep)) mkString(lineSep)
}
- // http://www.cis.upenn.edu/~cis510/tcl/chap3.pdf
+ // ftp://ftp.cis.upenn.edu/pub/cis511/public_html/Spring04/chap3.pdf
// http://users.encs.concordia.ca/~ta_ahmed/ms_thesis.pdf
// propositional logic with constants and equality
trait PropositionalLogic {
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 00de77a8d4..f259283e48 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -150,7 +150,11 @@ trait TreeAndTypeAnalysis extends Debugging {
acc: List[List[Type]]): List[List[Type]] = wl match {
case hd :: tl =>
val children = enumerateChildren(hd)
- groupChildren(tl ++ children, acc :+ filterChildren(children))
+ // put each trait in a new group, since traits could belong to the same
+ // group as a derived class
+ val (traits, nonTraits) = children.partition(_.isTrait)
+ val filtered = (traits.map(List(_)) ++ List(nonTraits)).map(filterChildren)
+ groupChildren(tl ++ children, acc ++ filtered)
case Nil => acc
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index c28cd8d69c..3fe2f24818 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -574,19 +574,23 @@ trait Contexts { self: Analyzer =>
/** Issue/buffer/throw the given implicit ambiguity error according to the current mode for error reporting. */
private[typechecker] def issueAmbiguousError(err: AbsAmbiguousTypeError) = reporter.issueAmbiguousError(err)(this)
/** Issue/throw the given error message according to the current mode for error reporting. */
- def error(pos: Position, msg: String) = reporter.error(pos, msg)
+ def error(pos: Position, msg: String) = reporter.error(fixPosition(pos), msg)
/** Issue/throw the given error message according to the current mode for error reporting. */
- def warning(pos: Position, msg: String) = reporter.warning(pos, msg)
- def echo(pos: Position, msg: String) = reporter.echo(pos, msg)
+ def warning(pos: Position, msg: String) = reporter.warning(fixPosition(pos), msg)
+ def echo(pos: Position, msg: String) = reporter.echo(fixPosition(pos), msg)
+ def fixPosition(pos: Position): Position = pos match {
+ case NoPosition => nextEnclosing(_.tree.pos != NoPosition).tree.pos
+ case _ => pos
+ }
def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit =
- currentRun.reporting.deprecationWarning(pos, sym, msg)
+ currentRun.reporting.deprecationWarning(fixPosition(pos), sym, msg)
def deprecationWarning(pos: Position, sym: Symbol): Unit =
- currentRun.reporting.deprecationWarning(pos, sym) // TODO: allow this to escalate to an error, and implicit search will ignore deprecated implicits
+ currentRun.reporting.deprecationWarning(fixPosition(pos), sym) // TODO: allow this to escalate to an error, and implicit search will ignore deprecated implicits
def featureWarning(pos: Position, featureName: String, featureDesc: String, featureTrait: Symbol, construct: => String = "", required: Boolean): Unit =
- currentRun.reporting.featureWarning(pos, featureName, featureDesc, featureTrait, construct, required)
+ currentRun.reporting.featureWarning(fixPosition(pos), featureName, featureDesc, featureTrait, construct, required)
// nextOuter determines which context is searched next for implicits
@@ -1204,7 +1208,7 @@ trait Contexts { self: Analyzer =>
type Error = AbsTypeError
type Warning = (Position, String)
- def issue(err: AbsTypeError)(implicit context: Context): Unit = handleError(err.errPos, addDiagString(err.errMsg))
+ def issue(err: AbsTypeError)(implicit context: Context): Unit = handleError(context.fixPosition(err.errPos), addDiagString(err.errMsg))
protected def handleError(pos: Position, msg: String): Unit
protected def handleSuppressedAmbiguous(err: AbsAmbiguousTypeError): Unit = ()
@@ -1221,7 +1225,7 @@ trait Contexts { self: Analyzer =>
* - else, let this context reporter decide
*/
final def issueAmbiguousError(err: AbsAmbiguousTypeError)(implicit context: Context): Unit =
- if (context.ambiguousErrors) reporter.error(err.errPos, addDiagString(err.errMsg)) // force reporting... see TODO above
+ if (context.ambiguousErrors) reporter.error(context.fixPosition(err.errPos), addDiagString(err.errMsg)) // force reporting... see TODO above
else handleSuppressedAmbiguous(err)
@inline final def withFreshErrorBuffer[T](expr: => T): T = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 2fb3ae41e2..383baad2ad 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -920,7 +920,7 @@ trait Implicits {
/** Returns all eligible ImplicitInfos and their SearchResults in a map.
*/
- def findAll() = linkedMapFrom(eligible)(typedImplicit(_, ptChecked = false, isLocalToCallsite))
+ def findAll() = linkedMapFrom(eligible)(x => try typedImplicit(x, ptChecked = false, isLocalToCallsite) finally context.reporter.clearAll())
/** Returns the SearchResult of the best match.
*/
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index 501546b8f6..501546b8f6 100755..100644
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
diff --git a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
index 9caebb711d..586f011429 100644
--- a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
@@ -268,10 +268,12 @@ trait CompilerControl { self: Global =>
/** Info given for every member found by completion
*/
abstract class Member {
+ def prefix: Type
val sym: Symbol
val tpe: Type
val accessible: Boolean
def implicitlyAdded = false
+ def symNameDropLocal: Name = sym.name.dropLocal
private def accessible_s = if (accessible) "" else "[inaccessible] "
def forceInfoString = {
@@ -288,6 +290,8 @@ trait CompilerControl { self: Global =>
accessible: Boolean,
inherited: Boolean,
viaView: Symbol) extends Member {
+ // should be a case class parameter, but added as a var instead to preserve compatibility with the IDE
+ var prefix: Type = NoType
override def implicitlyAdded = viaView != NoSymbol
}
@@ -295,7 +299,10 @@ trait CompilerControl { self: Global =>
sym: Symbol,
tpe: Type,
accessible: Boolean,
- viaImport: Tree) extends Member
+ viaImport: Tree) extends Member {
+ // should be a case class parameter, but added as a var instead to preserve compatibility with the IDE
+ var prefix: Type = NoType
+ }
// items that get sent to scheduler
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index e79c1a01ab..5298a6ae57 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -21,6 +21,7 @@ import scala.tools.nsc.typechecker.Typers
import scala.util.control.Breaks._
import java.util.concurrent.ConcurrentHashMap
import scala.collection.JavaConverters.mapAsScalaMapConverter
+import scala.reflect.internal.Chars.isIdentifierStart
/**
* This trait allows the IDE to have an instance of the PC that
@@ -122,6 +123,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
val debugIDE: Boolean = settings.YpresentationDebug.value
val verboseIDE: Boolean = settings.YpresentationVerbose.value
+ private val anyThread: Boolean = settings.YpresentationAnyThread.value
private def replayName = settings.YpresentationReplay.value
private def logName = settings.YpresentationLog.value
@@ -521,7 +523,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
*/
@elidable(elidable.WARNING)
override def assertCorrectThread() {
- assert(initializing || onCompilerThread,
+ assert(initializing || anyThread || onCompilerThread,
"Race condition detected: You are running a presentation compiler method outside the PC thread.[phase: %s]".format(globalPhase) +
" Please file a ticket with the current stack trace at https://www.assembla.com/spaces/scala-ide/support/tickets")
}
@@ -650,7 +652,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
/** Make sure unit is typechecked
*/
- private def typeCheck(unit: RichCompilationUnit) {
+ private[scala] def typeCheck(unit: RichCompilationUnit) {
debugLog("type checking: "+unit)
parseAndEnter(unit)
unit.status = PartiallyChecked
@@ -781,7 +783,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
/** A fully attributed tree located at position `pos` */
- private[interactive] def typedTreeAt(pos: Position): Tree = getUnit(pos.source) match {
+ private[scala] def typedTreeAt(pos: Position): Tree = getUnit(pos.source) match {
case None =>
reloadSources(List(pos.source))
try typedTreeAt(pos)
@@ -987,7 +989,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
def add(sym: Symbol, pre: Type, implicitlyAdded: Boolean)(toMember: (Symbol, Type) => M) {
if ((sym.isGetter || sym.isSetter) && sym.accessed != NoSymbol) {
add(sym.accessed, pre, implicitlyAdded)(toMember)
- } else if (!sym.name.decodedName.containsName("$") && !sym.isSynthetic && sym.hasRawInfo) {
+ } else if (!sym.name.decodedName.containsName("$") && !sym.isError && !sym.isArtifact && sym.hasRawInfo) {
val symtpe = pre.memberType(sym) onTypeError ErrorType
matching(sym, symtpe, this(sym.name)) match {
case Some(m) =>
@@ -1019,10 +1021,12 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) =
locals.add(sym, pre, implicitlyAdded = false) { (s, st) =>
// imported val and var are always marked as inaccessible, but they could be accessed through their getters. SI-7995
- if (s.hasGetter)
+ val member = if (s.hasGetter)
new ScopeMember(s, st, context.isAccessible(s.getter, pre, superAccess = false), viaImport)
else
new ScopeMember(s, st, context.isAccessible(s, pre, superAccess = false), viaImport)
+ member.prefix = pre
+ member
}
def localsToEnclosing() = {
enclosing.addNonShadowed(locals)
@@ -1089,10 +1093,13 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) = {
val implicitlyAdded = viaView != NoSymbol
members.add(sym, pre, implicitlyAdded) { (s, st) =>
- new TypeMember(s, st,
+ val result = new TypeMember(s, st,
context.isAccessible(if (s.hasGetter) s.getterIn(s.owner) else s, pre, superAccess && !implicitlyAdded),
inherited,
viaView)
+ result.prefix = pre
+ result
+
}
}
@@ -1136,6 +1143,112 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
}
+ sealed abstract class CompletionResult {
+ type M <: Member
+ def results: List[M]
+ /** The (possibly partial) name detected that precedes the cursor */
+ def name: Name
+ /** Cursor Offset - positionDelta == position of the start of the name */
+ def positionDelta: Int
+ def matchingResults(nameMatcher: (Name) => Name => Boolean = entered => candidate => candidate.startsWith(entered)): List[M] = {
+ val enteredName = if (name == nme.ERROR) nme.EMPTY else name
+ val matcher = nameMatcher(enteredName)
+ results filter { (member: Member) =>
+ val symbol = member.sym
+ def isStable = member.tpe.isStable || member.sym.isStable || member.sym.getterIn(member.sym.owner).isStable
+ def isJunk = symbol.name.isEmpty || !isIdentifierStart(member.sym.name.charAt(0)) // e.g. <byname>
+ !isJunk && member.accessible && !symbol.isConstructor && (name.isEmpty || matcher(member.sym.name) && (symbol.name.isTermName == name.isTermName || name.isTypeName && isStable))
+ }
+ }
+ }
+ object CompletionResult {
+ final case class ScopeMembers(positionDelta: Int, results: List[ScopeMember], name: Name) extends CompletionResult {
+ type M = ScopeMember
+ }
+ final case class TypeMembers(positionDelta: Int, qualifier: Tree, tree: Tree, results: List[TypeMember], name: Name) extends CompletionResult {
+ type M = TypeMember
+ }
+ case object NoResults extends CompletionResult {
+ override def results = Nil
+ override def name = nme.EMPTY
+ override def positionDelta = 0
+
+ }
+ private val CamelRegex = "([A-Z][^A-Z]*)".r
+ private def camelComponents(s: String): List[String] = {
+ CamelRegex.findAllIn("X" + s).toList match { case head :: tail => head.drop(1) :: tail; case Nil => Nil }
+ }
+ def camelMatch(entered: Name): Name => Boolean = {
+ val enteredS = entered.toString
+ val enteredLowercaseSet = enteredS.toLowerCase().toSet
+
+ (candidate: Name) => {
+ def candidateChunks = camelComponents(candidate.toString)
+ // Loosely based on IntelliJ's autocompletion: the user can just write everything in
+ // lowercase, as we'll let `isl` match `GenIndexedSeqLike` or `isLovely`.
+ def lenientMatch(entered: String, candidate: List[String], matchCount: Int): Boolean = {
+ candidate match {
+ case Nil => entered.isEmpty && matchCount > 0
+ case head :: tail =>
+ val enteredAlternatives = Set(entered, entered.capitalize)
+ head.inits.filter(_.length <= entered.length).exists(init =>
+ enteredAlternatives.exists(entered =>
+ lenientMatch(entered.stripPrefix(init), tail, matchCount + (if (init.isEmpty) 0 else 1))
+ )
+ )
+ }
+ }
+ val containsAllEnteredChars = {
+ // Trying to rule out some candidates quickly before the more expensive `lenientMatch`
+ val candidateLowercaseSet = candidate.toString.toLowerCase().toSet
+ enteredLowercaseSet.diff(candidateLowercaseSet).isEmpty
+ }
+ containsAllEnteredChars && lenientMatch(enteredS, candidateChunks, 0)
+ }
+ }
+ }
+
+ final def completionsAt(pos: Position): CompletionResult = {
+ val focus1: Tree = typedTreeAt(pos)
+ def typeCompletions(tree: Tree, qual: Tree, nameStart: Int, name: Name): CompletionResult = {
+ val qualPos = qual.pos
+ val allTypeMembers = typeMembers(qualPos).toList.flatten
+ val positionDelta: Int = pos.start - nameStart
+ val subName: Name = name.newName(new String(pos.source.content, nameStart, pos.start - nameStart)).encodedName
+ CompletionResult.TypeMembers(positionDelta, qual, tree, allTypeMembers, subName)
+ }
+ focus1 match {
+ case imp@Import(i @ Ident(name), head :: Nil) if head.name == nme.ERROR =>
+ val allMembers = scopeMembers(pos)
+ val nameStart = i.pos.start
+ val positionDelta: Int = pos.start - nameStart
+ val subName = name.subName(0, pos.start - i.pos.start)
+ CompletionResult.ScopeMembers(positionDelta, allMembers, subName)
+ case imp@Import(qual, selectors) =>
+ selectors.reverseIterator.find(_.namePos <= pos.start) match {
+ case None => CompletionResult.NoResults
+ case Some(selector) =>
+ typeCompletions(imp, qual, selector.namePos, selector.name)
+ }
+ case sel@Select(qual, name) =>
+ val qualPos = qual.pos
+ def fallback = qualPos.end + 2
+ val source = pos.source
+ val nameStart: Int = (qualPos.end + 1 until focus1.pos.end).find(p =>
+ source.identifier(source.position(p)).exists(_.length > 0)
+ ).getOrElse(fallback)
+ typeCompletions(sel, qual, nameStart, name)
+ case Ident(name) =>
+ val allMembers = scopeMembers(pos)
+ val positionDelta: Int = pos.start - focus1.pos.start
+ val subName = name.subName(0, positionDelta)
+ CompletionResult.ScopeMembers(positionDelta, allMembers, subName)
+ case _ =>
+ CompletionResult.NoResults
+ }
+ }
+
+
/** Implements CompilerControl.askLoadedTyped */
private[interactive] def waitLoadedTyped(source: SourceFile, response: Response[Tree], keepLoaded: Boolean = false, onSameThread: Boolean = true) {
getUnit(source) match {
diff --git a/src/library-aux/scala/Any.scala b/src/library-aux/scala/Any.scala
index 8caf0c5c0e..e6ed46740e 100644
--- a/src/library-aux/scala/Any.scala
+++ b/src/library-aux/scala/Any.scala
@@ -27,7 +27,7 @@ package scala
* w.print()
* }}}
*
- * See the [[http://docs.scala-lang.org/sips/completed/value-classes.html value classes guide]] for more
+ * See the [[http://docs.scala-lang.org/overviews/core/value-classes.html Value Classes and Universal Traits]] for more
* details on the interplay of universal traits and value classes.
*/
abstract class Any {
diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala
index fb3d213e19..e861860196 100644
--- a/src/library/scala/AnyVal.scala
+++ b/src/library/scala/AnyVal.scala
@@ -48,9 +48,7 @@ package scala
*
* It's important to note that user-defined value classes are limited, and in some circumstances,
* still must allocate a value class instance at runtime. These limitations and circumstances are
- * explained in greater detail in the [[http://docs.scala-lang.org/overviews/core/value-classes.html Value Classes Guide]]
- * as well as in [[http://docs.scala-lang.org/sips/completed/value-classes.html SIP-15: Value Classes]],
- * the Scala Improvement Proposal.
+ * explained in greater detail in the [[http://docs.scala-lang.org/overviews/core/value-classes.html Value Classes and Universal Traits]].
*/
abstract class AnyVal extends Any {
def getClass(): Class[_ <: AnyVal] = null
diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala
index a7e06b4d1a..a7e06b4d1a 100755..100644
--- a/src/library/scala/collection/IndexedSeqOptimized.scala
+++ b/src/library/scala/collection/IndexedSeqOptimized.scala
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index e2c271145d..ff10fb44d7 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -431,8 +431,16 @@ trait Iterator[+A] extends TraversableOnce[A] {
*/
def flatMap[B](f: A => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] {
private var cur: Iterator[B] = empty
- def hasNext: Boolean =
- cur.hasNext || self.hasNext && { cur = f(self.next()).toIterator; hasNext }
+ private def nextCur() { cur = f(self.next()).toIterator }
+ def hasNext: Boolean = {
+ // Equivalent to cur.hasNext || self.hasNext && { nextCur(); hasNext }
+ // but slightly shorter bytecode (better JVM inlining!)
+ while (!cur.hasNext) {
+ if (!self.hasNext) return false
+ nextCur()
+ }
+ true
+ }
def next(): B = (if (hasNext) cur else empty).next()
}
@@ -444,6 +452,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @note Reuse: $consumesAndProducesIterator
*/
def filter(p: A => Boolean): Iterator[A] = new AbstractIterator[A] {
+ // TODO 2.12 - Make a full-fledged FilterImpl that will reverse sense of p
private var hd: A = _
private var hdDefined: Boolean = false
@@ -509,13 +518,27 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @note Reuse: $consumesAndProducesIterator
*/
@migration("`collect` has changed. The previous behavior can be reproduced with `toSeq`.", "2.8.0")
- def collect[B](pf: PartialFunction[A, B]): Iterator[B] = {
- val self = buffered
- new AbstractIterator[B] {
- private def skip() = while (self.hasNext && !pf.isDefinedAt(self.head)) self.next()
- def hasNext = { skip(); self.hasNext }
- def next() = { skip(); pf(self.next()) }
+ def collect[B](pf: PartialFunction[A, B]): Iterator[B] = new AbstractIterator[B] {
+ // Manually buffer to avoid extra layer of wrapping with buffered
+ private[this] var hd: A = _
+
+ // Little state machine to keep track of where we are
+ // Seek = 0; Found = 1; Empty = -1
+ // Not in vals because scalac won't make them static (@inline def only works with -optimize)
+ // BE REALLY CAREFUL TO KEEP COMMENTS AND NUMBERS IN SYNC!
+ private[this] var status = 0/*Seek*/
+
+ def hasNext = {
+ while (status == 0/*Seek*/) {
+ if (self.hasNext) {
+ hd = self.next()
+ if (pf.isDefinedAt(hd)) status = 1/*Found*/
+ }
+ else status = -1/*Empty*/
+ }
+ status == 1/*Found*/
}
+ def next() = if (hasNext) { status = 0/*Seek*/; pf(hd) } else Iterator.empty.next()
}
/** Produces a collection containing cumulative results of applying the
@@ -617,33 +640,105 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @note Reuse: $consumesOneAndProducesTwoIterators
*/
def span(p: A => Boolean): (Iterator[A], Iterator[A]) = {
- val self = buffered
-
- // Must be a named class to avoid structural call to finish from trailing iterator
+ /*
+ * Giving a name to following iterator (as opposed to trailing) because
+ * anonymous class is represented as a structural type that trailing
+ * iterator is referring (the finish() method) and thus triggering
+ * handling of structural calls. It's not what's intended here.
+ */
class Leading extends AbstractIterator[A] {
- private val drained = new mutable.Queue[A]
- private var finished = false
- def finish(): Unit = {
- require(!finished)
- finished = true
- while (selfish) drained += self.next
+ var lookahead: mutable.Queue[A] = null
+ var hd: A = _
+ /* Status is kept with magic numbers
+ * 1 means next element is in hd and we're still reading into this iterator
+ * 0 means we're still reading but haven't found a next element
+ * -1 means we are done reading into the iterator, so we must rely on lookahead
+ * -2 means we are done but have saved hd for the other iterator to use as its first element
+ */
+ var status = 0
+ private def store(a: A) {
+ if (lookahead == null) lookahead = new mutable.Queue[A]
+ lookahead += a
+ }
+ def hasNext = {
+ if (status < 0) (lookahead ne null) && lookahead.nonEmpty
+ else if (status > 0) true
+ else {
+ if (self.hasNext) {
+ hd = self.next()
+ status = if (p(hd)) 1 else -2
+ }
+ else status = -1
+ status > 0
+ }
}
- private def selfish = self.hasNext && p(self.head)
- def hasNext = if (finished) drained.nonEmpty else selfish
def next() = {
- if (finished) drained.dequeue()
- else if (selfish) self.next()
+ if (hasNext) {
+ if (status == 1) { status = 0; hd }
+ else lookahead.dequeue()
+ }
else empty.next()
}
+ def finish(): Boolean = {
+ if (status == -1) false
+ else if (status == -2) {
+ status = -1
+ true
+ }
+ else {
+ if (status == 1) store(hd)
+ while (self.hasNext) {
+ val a = self.next()
+ if (p(a)) store(a)
+ else {
+ hd = a
+ status = -1
+ return true
+ }
+ }
+ false
+ }
+ }
}
+
val leading = new Leading
+
val trailing = new AbstractIterator[A] {
- private lazy val it = {
- leading.finish()
- self
+ private[this] var myLeading = leading
+ /* Status flags meanings:
+ * -1 not yet accesssed
+ * 0 single element waiting in leading
+ * 1 defer to self
+ */
+ private[this] var status = -1
+ def hasNext = {
+ if (status > 0) self.hasNext
+ else {
+ if (status == 0) true
+ else if (myLeading.finish()) {
+ status = 0
+ true
+ }
+ else {
+ status = 1
+ myLeading = null
+ self.hasNext
+ }
+ }
+ }
+ def next() = {
+ if (hasNext) {
+ if (status > 0) self.next()
+ else {
+ status = 1
+ val ans = myLeading.hd
+ myLeading = null
+ ans
+ }
+ }
+ else Iterator.empty.next()
}
- def hasNext = it.hasNext
- def next() = it.next()
+
override def toString = "unknown-if-empty iterator"
}
@@ -657,18 +752,35 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @return an iterator consisting of the remaining elements
* @note Reuse: $consumesAndProducesIterator
*/
- def dropWhile(p: A => Boolean): Iterator[A] = {
- val self = buffered
- new AbstractIterator[A] {
- var dropped = false
- private def skip() =
- if (!dropped) {
- while (self.hasNext && p(self.head)) self.next()
- dropped = true
+ def dropWhile(p: A => Boolean): Iterator[A] = new AbstractIterator[A] {
+ // Magic value: -1 = hasn't dropped, 0 = found first, 1 = defer to parent iterator
+ private[this] var status = -1
+ // Local buffering to avoid double-wrap with .buffered
+ private[this] var fst: A = _
+ def hasNext: Boolean =
+ if (status == 1) self.hasNext
+ else if (status == 0) true
+ else {
+ while (self.hasNext) {
+ val a = self.next()
+ if (!p(a)) {
+ fst = a
+ status = 0
+ return true
+ }
}
- def hasNext = { skip(); self.hasNext }
- def next() = { skip(); self.next() }
- }
+ status = 1
+ false
+ }
+ def next() =
+ if (hasNext) {
+ if (status == 1) self.next()
+ else {
+ status = 1
+ fst
+ }
+ }
+ else Iterator.empty.next()
}
/** Creates an iterator formed from this iterator and another iterator
@@ -816,7 +928,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
* is equal (as determined by `==`) to `elem`, `false` otherwise.
* @note Reuse: $consumesIterator
*/
- def contains(elem: Any): Boolean = exists(_ == elem)
+ def contains(elem: Any): Boolean = exists(_ == elem) // Note--this seems faster than manual inlining!
/** Finds the first value produced by the iterator satisfying a
* predicate, if any.
@@ -828,12 +940,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
* @note Reuse: $consumesIterator
*/
def find(p: A => Boolean): Option[A] = {
- var res: Option[A] = None
- while (res.isEmpty && hasNext) {
- val e = next()
- if (p(e)) res = Some(e)
+ while (hasNext) {
+ val a = next()
+ if (p(a)) return Some(a)
}
- res
+ None
}
/** Returns the index of the first produced value satisfying a predicate, or -1.
@@ -863,15 +974,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
i += 1
}
- var found = false
- while (!found && hasNext) {
- if (p(next())) {
- found = true
- } else {
- i += 1
- }
+ while (hasNext) {
+ if (p(next())) return i
+ i += 1
}
- if (found) i else -1
+ -1
}
/** Returns the index of the first occurrence of the specified
@@ -903,15 +1010,11 @@ trait Iterator[+A] extends TraversableOnce[A] {
i += 1
}
- var found = false
- while (!found && hasNext) {
- if (next() == elem) {
- found = true
- } else {
- i += 1
- }
+ while (hasNext) {
+ if (next() == elem) return i
+ i += 1
}
- if (found) i else -1
+ -1
}
/** Creates a buffered iterator from this iterator.
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
index 875f6e1c02..875f6e1c02 100755..100644
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala
index 571d58a3f3..571d58a3f3 100755..100644
--- a/src/library/scala/collection/LinearSeqOptimized.scala
+++ b/src/library/scala/collection/LinearSeqOptimized.scala
diff --git a/src/library/scala/collection/generic/FilterMonadic.scala b/src/library/scala/collection/generic/FilterMonadic.scala
index 8aefbdb926..8aefbdb926 100755..100644
--- a/src/library/scala/collection/generic/FilterMonadic.scala
+++ b/src/library/scala/collection/generic/FilterMonadic.scala
diff --git a/src/library/scala/collection/generic/HasNewBuilder.scala b/src/library/scala/collection/generic/HasNewBuilder.scala
index aa0ce6698d..aa0ce6698d 100755..100644
--- a/src/library/scala/collection/generic/HasNewBuilder.scala
+++ b/src/library/scala/collection/generic/HasNewBuilder.scala
diff --git a/src/library/scala/collection/immutable/DefaultMap.scala b/src/library/scala/collection/immutable/DefaultMap.scala
index e9b277b9c4..e9b277b9c4 100755..100644
--- a/src/library/scala/collection/immutable/DefaultMap.scala
+++ b/src/library/scala/collection/immutable/DefaultMap.scala
diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala
index 8991d0b75a..cb6196e130 100644
--- a/src/library/scala/collection/immutable/IntMap.scala
+++ b/src/library/scala/collection/immutable/IntMap.scala
@@ -146,7 +146,7 @@ private[immutable] class IntMapKeyIterator[V](it: IntMap[V]) extends IntMapItera
import IntMap._
/** Specialised immutable map structure for integer keys, based on
- * <a href="http://citeseer.ist.psu.edu/okasaki98fast.html">Fast Mergeable Integer Maps</a>
+ * [[http://ittc.ku.edu/~andygill/papers/IntMap98.pdf Fast Mergeable Integer Maps]]
* by Okasaki and Gill. Essentially a trie based on binary digits of the integers.
*
* '''Note:''' This class is as of 2.8 largely superseded by HashMap.
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index eb095dbbc2..66150c1a13 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -16,7 +16,7 @@ import scala.annotation.tailrec
import java.io.{ObjectOutputStream, ObjectInputStream}
/** A class for immutable linked lists representing ordered collections
- * of elements of type.
+ * of elements of type `A`.
*
* This class comes with two implementing case classes `scala.Nil`
* and `scala.::` that implement the abstract members `isEmpty`,
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 28e56a6d87..11603a118b 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -175,34 +175,68 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
catch { case _: ClassCastException => false }
final override def sum[B >: T](implicit num: Numeric[B]): B = {
- // arithmetic series formula can be used for regular addition
- if ((num eq scala.math.Numeric.IntIsIntegral)||
- (num eq scala.math.Numeric.BigIntIsIntegral)||
- (num eq scala.math.Numeric.ShortIsIntegral)||
- (num eq scala.math.Numeric.ByteIsIntegral)||
- (num eq scala.math.Numeric.CharIsIntegral)||
- (num eq scala.math.Numeric.LongIsIntegral)||
- (num eq scala.math.Numeric.FloatAsIfIntegral)||
- (num eq scala.math.Numeric.BigDecimalIsFractional)||
- (num eq scala.math.Numeric.DoubleAsIfIntegral)) {
- val numAsIntegral = num.asInstanceOf[Integral[B]]
- import numAsIntegral._
- if (isEmpty) num fromInt 0
- else if (numRangeElements == 1) head
- else ((num fromInt numRangeElements) * (head + last) / (num fromInt 2))
- } else {
- // user provided custom Numeric, we cannot rely on arithmetic series formula
- if (isEmpty) num.zero
+ if (isEmpty) num.zero
+ else if (numRangeElements == 1) head
+ else {
+ // If there is no overflow, use arithmetic series formula
+ // a + ... (n terms total) ... + b = n*(a+b)/2
+ if ((num eq scala.math.Numeric.IntIsIntegral)||
+ (num eq scala.math.Numeric.ShortIsIntegral)||
+ (num eq scala.math.Numeric.ByteIsIntegral)||
+ (num eq scala.math.Numeric.CharIsIntegral)) {
+ // We can do math with no overflow in a Long--easy
+ val exact = (numRangeElements * ((num toLong head) + (num toInt last))) / 2
+ num fromInt exact.toInt
+ }
+ else if (num eq scala.math.Numeric.LongIsIntegral) {
+ // Uh-oh, might be overflow, so we have to divide before we overflow.
+ // Either numRangeElements or (head + last) must be even, so divide the even one before multiplying
+ val a = head.toLong
+ val b = last.toLong
+ val ans =
+ if ((numRangeElements & 1) == 0) (numRangeElements / 2) * (a + b)
+ else numRangeElements * {
+ // Sum is even, but we might overflow it, so divide in pieces and add back remainder
+ val ha = a/2
+ val hb = b/2
+ ha + hb + ((a - 2*ha) + (b - 2*hb)) / 2
+ }
+ ans.asInstanceOf[B]
+ }
+ else if ((num eq scala.math.Numeric.FloatAsIfIntegral) ||
+ (num eq scala.math.Numeric.DoubleAsIfIntegral)) {
+ // Try to compute sum with reasonable accuracy, avoiding over/underflow
+ val numAsIntegral = num.asInstanceOf[Integral[B]]
+ import numAsIntegral._
+ val a = math.abs(head.toDouble)
+ val b = math.abs(last.toDouble)
+ val two = num fromInt 2
+ val nre = num fromInt numRangeElements
+ if (a > 1e38 || b > 1e38) nre * ((head / two) + (last / two)) // Compute in parts to avoid Infinity if possible
+ else (nre / two) * (head + last) // Don't need to worry about infinity; this will be more accurate and avoid underflow
+ }
+ else if ((num eq scala.math.Numeric.BigIntIsIntegral) ||
+ (num eq scala.math.Numeric.BigDecimalIsFractional)) {
+ // No overflow, so we can use arithmetic series formula directly
+ // (not going to worry about running out of memory)
+ val numAsIntegral = num.asInstanceOf[Integral[B]]
+ import numAsIntegral._
+ ((num fromInt numRangeElements) * (head + last)) / (num fromInt 2)
+ }
else {
- var acc = num.zero
- var i = head
- var idx = 0
- while(idx < length) {
- acc = num.plus(acc, i)
- i = i + step
- idx = idx + 1
+ // User provided custom Numeric, so we cannot rely on arithmetic series formula (e.g. won't work on something like Z_6)
+ if (isEmpty) num.zero
+ else {
+ var acc = num.zero
+ var i = head
+ var idx = 0
+ while(idx < length) {
+ acc = num.plus(acc, i)
+ i = i + step
+ idx = idx + 1
+ }
+ acc
}
- acc
}
}
}
diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala
index 8910ee16b9..c8d0b00327 100644
--- a/src/library/scala/collection/immutable/PagedSeq.scala
+++ b/src/library/scala/collection/immutable/PagedSeq.scala
@@ -190,8 +190,8 @@ extends scala.collection.AbstractSeq[T]
val e = if (_end == UndeterminedEnd) _end else start + _end
var f = first1
while (f.end <= s && !f.isLast) {
- if (f.next eq null) f.addMore(more)
- f = f.next
+ if (f.next eq null) f = f.addMore(more)
+ else f = f.next
}
// Warning -- not refining `more` means that slices can freely request and obtain
// data outside of their slice. This is part of the design of PagedSeq
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 984ea7ba50..fb7dd4cfbf 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -153,19 +153,15 @@ extends scala.collection.AbstractSeq[Int]
}
@inline final override def foreach[@specialized(Unit) U](f: Int => U) {
- validateMaxLength()
- val isCommonCase = (start != Int.MinValue || end != Int.MinValue)
- var i = start
- var count = 0
- val terminal = terminalElement
- val step = this.step
- while(
- if(isCommonCase) { i != terminal }
- else { count < numRangeElements }
- ) {
- f(i)
- count += 1
- i += step
+ // Implementation chosen on the basis of favorable microbenchmarks
+ // Note--initialization catches step == 0 so we don't need to here
+ if (!isEmpty) {
+ var i = start
+ while (true) {
+ f(i)
+ if (i == lastElement) return
+ i += step
+ }
}
}
@@ -364,18 +360,19 @@ extends scala.collection.AbstractSeq[Int]
// this is normal integer range with usual addition. arithmetic series formula can be used
if (isEmpty) 0
else if (numRangeElements == 1) head
- else (numRangeElements.toLong * (head + last) / 2).toInt
+ else ((numRangeElements * (head.toLong + last)) / 2).toInt
} else {
// user provided custom Numeric, we cannot rely on arithmetic series formula
if (isEmpty) num.toInt(num.zero)
else {
var acc = num.zero
var i = head
- while(i != terminalElement) {
+ while (true) {
acc = num.plus(acc, i)
+ if (i == lastElement) return num.toInt(acc)
i = i + step
}
- num.toInt(acc)
+ 0 // Never hit this--just to satisfy compiler since it doesn't know while(true) has type Nothing
}
}
}
diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala
index 0dad106b29..7e8cfcc902 100644
--- a/src/library/scala/collection/immutable/RedBlackTree.scala
+++ b/src/library/scala/collection/immutable/RedBlackTree.scala
@@ -168,7 +168,8 @@ object RedBlackTree {
}
/* Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees
- * http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html */
+ * Constructing Red-Black Trees, Ralf Hinze: http://www.cs.ox.ac.uk/ralf.hinze/publications/WAAAPL99b.ps.gz
+ * Red-Black Trees in a Functional Setting, Chris Okasaki: https://wiki.rice.edu/confluence/download/attachments/2761212/Okasaki-Red-Black.pdf */
private[this] def del[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = if (tree eq null) null else {
def balance(x: A, xv: B, tl: Tree[A, B], tr: Tree[A, B]) = if (isRedTree(tl)) {
if (isRedTree(tr)) {
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 46d5d0c69c..8bb581d44c 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -1156,8 +1156,6 @@ private[immutable] trait VectorPointer[T] {
if (depth == 3) {
display3 = new Array(32)
display3((oldIndex >> 15) & 31) = display2
- display2 = new Array(32)
- display1 = new Array(32)
depth +=1
}
display2 = display3((newIndex >> 15) & 31).asInstanceOf[Array[AnyRef]]
@@ -1170,9 +1168,6 @@ private[immutable] trait VectorPointer[T] {
if (depth == 4) {
display4 = new Array(32)
display4((oldIndex >> 20) & 31) = display3
- display3 = new Array(32)
- display2 = new Array(32)
- display1 = new Array(32)
depth +=1
}
display3 = display4((newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
@@ -1187,13 +1182,9 @@ private[immutable] trait VectorPointer[T] {
if (depth == 5) {
display5 = new Array(32)
display5((oldIndex >> 25) & 31) = display4
- display4 = new Array(32)
- display3 = new Array(32)
- display2 = new Array(32)
- display1 = new Array(32)
depth +=1
}
- display4 = display5((newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
+ display4 = display5((newIndex >> 25) & 31).asInstanceOf[Array[AnyRef]]
if (display4 == null) display4 = new Array(32)
display3 = display4((newIndex >> 20) & 31).asInstanceOf[Array[AnyRef]]
if (display3 == null) display3 = new Array(32)
diff --git a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala
index 09f0712862..09f0712862 100755..100644
--- a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala
diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala
index 03d387a535..ad60173b64 100644
--- a/src/library/scala/collection/mutable/Queue.scala
+++ b/src/library/scala/collection/mutable/Queue.scala
@@ -21,7 +21,7 @@ import generic._
* @author Martin Odersky
* @version 2.8
* @since 1
- * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_queues "Scala's Collection Library overview"]]
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#queues "Scala's Collection Library overview"]]
* section on `Queues` for more information.
*
* @define Coll `mutable.Queue`
diff --git a/src/library/scala/collection/package.scala b/src/library/scala/collection/package.scala
index 6a2b6de75a..13fe7a79c4 100644
--- a/src/library/scala/collection/package.scala
+++ b/src/library/scala/collection/package.scala
@@ -69,6 +69,9 @@ package scala
* characteristics which are described
* in [[http://docs.scala-lang.org/overviews/collections/performance-characteristics.html the guide]].
*
+ * The concrete parallel collections also have specific performance characteristics which are
+ * described in [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#performance-characteristics the parallel collections guide]]
+ *
* === Converting between Java Collections ===
*
* The `JavaConversions` object provides implicit defs that will allow mostly seamless integration
diff --git a/src/library/scala/collection/readme-if-you-want-to-add-something.txt b/src/library/scala/collection/readme-if-you-want-to-add-something.txt
index 6700cb7b68..6700cb7b68 100755..100644
--- a/src/library/scala/collection/readme-if-you-want-to-add-something.txt
+++ b/src/library/scala/collection/readme-if-you-want-to-add-something.txt
diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala
index 2a41e25b01..7cb7858b36 100644
--- a/src/library/scala/io/Codec.scala
+++ b/src/library/scala/io/Codec.scala
@@ -21,7 +21,7 @@ import scala.language.implicitConversions
// XML: optional encoding parameter.
// <?xml version="1.0" encoding="ISO8859-1" ?>
//
-// MacRoman vs. UTF-8: see http://jira.codehaus.org/browse/JRUBY-3576
+// MacRoman vs. UTF-8: see http://osdir.com/ml/lang-jruby-devel/2009-04/msg00071.html
// -Dfile.encoding: see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4375816
/** A class for character encoding/decoding preferences.
diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala
index a8430548f5..a8430548f5 100755..100644
--- a/src/library/scala/reflect/NameTransformer.scala
+++ b/src/library/scala/reflect/NameTransformer.scala
diff --git a/src/library/scala/runtime/TraitSetter.java b/src/library/scala/runtime/TraitSetter.java
index d9907c0ac0..d9907c0ac0 100755..100644
--- a/src/library/scala/runtime/TraitSetter.java
+++ b/src/library/scala/runtime/TraitSetter.java
diff --git a/src/library/scala/runtime/VolatileBooleanRef.java b/src/library/scala/runtime/VolatileBooleanRef.java
index ef5b691118..ef5b691118 100755..100644
--- a/src/library/scala/runtime/VolatileBooleanRef.java
+++ b/src/library/scala/runtime/VolatileBooleanRef.java
diff --git a/src/library/scala/runtime/VolatileByteRef.java b/src/library/scala/runtime/VolatileByteRef.java
index d792b0a386..d792b0a386 100755..100644
--- a/src/library/scala/runtime/VolatileByteRef.java
+++ b/src/library/scala/runtime/VolatileByteRef.java
diff --git a/src/library/scala/runtime/VolatileCharRef.java b/src/library/scala/runtime/VolatileCharRef.java
index 555b171283..555b171283 100755..100644
--- a/src/library/scala/runtime/VolatileCharRef.java
+++ b/src/library/scala/runtime/VolatileCharRef.java
diff --git a/src/library/scala/runtime/VolatileDoubleRef.java b/src/library/scala/runtime/VolatileDoubleRef.java
index 1932055c6a..1932055c6a 100755..100644
--- a/src/library/scala/runtime/VolatileDoubleRef.java
+++ b/src/library/scala/runtime/VolatileDoubleRef.java
diff --git a/src/library/scala/runtime/VolatileFloatRef.java b/src/library/scala/runtime/VolatileFloatRef.java
index 3a81be1146..3a81be1146 100755..100644
--- a/src/library/scala/runtime/VolatileFloatRef.java
+++ b/src/library/scala/runtime/VolatileFloatRef.java
diff --git a/src/library/scala/runtime/VolatileIntRef.java b/src/library/scala/runtime/VolatileIntRef.java
index ae015bc8b1..ae015bc8b1 100755..100644
--- a/src/library/scala/runtime/VolatileIntRef.java
+++ b/src/library/scala/runtime/VolatileIntRef.java
diff --git a/src/library/scala/runtime/VolatileLongRef.java b/src/library/scala/runtime/VolatileLongRef.java
index e596f5aa69..e596f5aa69 100755..100644
--- a/src/library/scala/runtime/VolatileLongRef.java
+++ b/src/library/scala/runtime/VolatileLongRef.java
diff --git a/src/library/scala/runtime/VolatileObjectRef.java b/src/library/scala/runtime/VolatileObjectRef.java
index 6063501ffb..6063501ffb 100755..100644
--- a/src/library/scala/runtime/VolatileObjectRef.java
+++ b/src/library/scala/runtime/VolatileObjectRef.java
diff --git a/src/library/scala/runtime/VolatileShortRef.java b/src/library/scala/runtime/VolatileShortRef.java
index 0a2825941f..0a2825941f 100755..100644
--- a/src/library/scala/runtime/VolatileShortRef.java
+++ b/src/library/scala/runtime/VolatileShortRef.java
diff --git a/src/library/scala/sys/process/Process.scala b/src/library/scala/sys/process/Process.scala
index dcd06c89e9..c40838bb06 100644
--- a/src/library/scala/sys/process/Process.scala
+++ b/src/library/scala/sys/process/Process.scala
@@ -155,8 +155,8 @@ trait ProcessCreation {
* import java.net.URL
* import java.io.File
*
- * val spde = new URL("http://technically.us/spde/About")
- * val dispatch = new URL("http://databinder.net/dispatch/About")
+ * val spde = new URL("http://technically.us/spde.html")
+ * val dispatch = new URL("http://dispatch.databinder.net/Dispatch.html")
* val build = new File("project/build.properties")
* cat(spde, dispatch, build) #| "grep -i scala" !
* }}}
diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala
index 367488f116..d4a5e2f0e8 100644
--- a/src/library/scala/util/Properties.scala
+++ b/src/library/scala/util/Properties.scala
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2006-2015, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -105,7 +105,7 @@ private[scala] trait PropertiesTrait {
* or "version (unknown)" if it cannot be determined.
*/
val versionString = "version " + scalaPropOrElse("version.number", "(unknown)")
- val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2013, LAMP/EPFL")
+ val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2015, LAMP/EPFL")
/** This is the encoding to use reading in source files, overridden with -encoding.
* Note that it uses "prop" i.e. looks in the scala jar, not the system properties.
diff --git a/src/manual/scala/man1/Command.scala b/src/manual/scala/man1/Command.scala
index 8f811f950e..13e21757c0 100644
--- a/src/manual/scala/man1/Command.scala
+++ b/src/manual/scala/man1/Command.scala
@@ -42,7 +42,7 @@ trait Command {
def authors = Section("AUTHOR",
"Written by Martin Odersky and other members of the " &
- Link("Scala team", "http://www.scala-lang.org/node/89") & ".")
+ Link("Scala team", "http://www.scala-lang.org/news/2014/01/22/10-years-of-scala.html") & ".")
def copyright = Section("COPYRIGHT",
diff --git a/src/reflect/scala/reflect/internal/Chars.scala b/src/reflect/scala/reflect/internal/Chars.scala
index 74413fdaba..0f532a4e57 100644
--- a/src/reflect/scala/reflect/internal/Chars.scala
+++ b/src/reflect/scala/reflect/internal/Chars.scala
@@ -66,7 +66,7 @@ trait Chars {
'0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
/** Can character start an alphanumeric Scala identifier? */
- def isIdentifierStart(c: Char): Boolean =
+ def isIdentifierStart(c: Char): Boolean =
(c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c)
/** Can character form part of an alphanumeric Scala identifier? */
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 05fdfb51ed..c3b2a8da08 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -503,6 +503,19 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case _ => new StubTermSymbol(this, name.toTermName, missingMessage)
}
+ /** Given a field, construct a term symbol that represents the source construct that gave rise the the field */
+ def sugaredSymbolOrSelf = {
+ val getter = getterIn(owner)
+ if (getter == NoSymbol) {
+ this
+ } else {
+ val result = owner.newValue(getter.name.toTermName, newFlags = getter.flags & ~Flags.METHOD).setPrivateWithin(getter.privateWithin).setInfo(getter.info.resultType)
+ val setter = setterIn(owner)
+ if (setter != NoSymbol) result.setFlag(Flags.MUTABLE)
+ result
+ }
+ }
+
// ----- locking and unlocking ------------------------------------------------------
// True if the symbol is unlocked.
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 375218248e..2ae95c98e5 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -2524,6 +2524,9 @@ trait Types
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def narrow: Type = resultType.narrow
+ // SI-9475: PolyTypes with dependent method types are still dependent
+ override def isDependentMethodType = resultType.isDependentMethodType
+
/** @M: typeDefSig wraps a TypeBounds in a PolyType
* to represent a higher-kinded type parameter
* wrap lo&hi in polytypes to bind variables
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index 15e0f9cc14..277e89d656 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -243,7 +243,7 @@ abstract class UnPickler {
(module map { case (group, art) =>
s"""\n(NOTE: It looks like the $art module is missing; try adding a dependency on "$group" : "$art".
- | See http://docs.scala-lang.org/overviews/core/scala-2.11.html for more information.)""".stripMargin
+ | See http://docs.scala-lang.org/overviews/ for more information.)""".stripMargin
} getOrElse "")
}
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index d6d216863b..28a7fb37a6 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -343,7 +343,7 @@ private[internal] trait TypeMaps {
object rawToExistentialInJava extends TypeMap {
def apply(tp: Type): Type = tp match {
// any symbol that occurs in a java sig, not just java symbols
- // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ // see https://issues.scala-lang.org/browse/SI-2454?focusedCommentId=46618
case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
val eparams = typeParamsToExistentials(sym, sym.typeParams)
existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
diff --git a/src/reflect/scala/reflect/macros/blackbox/Context.scala b/src/reflect/scala/reflect/macros/blackbox/Context.scala
index 2f9c512efa..ce28b5911e 100644
--- a/src/reflect/scala/reflect/macros/blackbox/Context.scala
+++ b/src/reflect/scala/reflect/macros/blackbox/Context.scala
@@ -29,7 +29,7 @@ package blackbox
* which means that its expansion will be upcast to its return type, enforcing faithfullness of that macro to its
* type signature. Whitebox macros, i.e. the ones defined with `whitebox.Context`, aren't bound by this restriction,
* which enables a number of important use cases, but they are also going to enjoy less support than blackbox macros,
- * so choose wisely. See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information.
+ * so choose wisely. See the [[http://docs.scala-lang.org/overviews/macros/overview.html Macros Guide]] for more information.
*
* @see `scala.reflect.macros.whitebox.Context`
*/
diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala
index cc7111d794..b63d419d61 100644
--- a/src/reflect/scala/reflect/macros/package.scala
+++ b/src/reflect/scala/reflect/macros/package.scala
@@ -10,14 +10,14 @@ package reflect
* Within these functions the programmer has access to compiler APIs.
* For example, it is possible to generate, analyze and typecheck code.
*
- * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] on how to get started with Scala macros.
+ * See the [[http://docs.scala-lang.org/overviews/macros/overview.html Macros Guide]] on how to get started with Scala macros.
*/
package object macros {
/** The Scala macros context.
*
* In Scala 2.11, macros that were once the one are split into blackbox and whitebox macros,
* with the former being better supported and the latter being more powerful. You can read about
- * the details of the split and the associated trade-offs in the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]].
+ * the details of the split and the associated trade-offs in the [[http://docs.scala-lang.org/overviews/macros/overview.html Macros Guide]].
*
* `scala.reflect.macros.Context` follows this tendency and turns into `scala.reflect.macros.blackbox.Context`
* and `scala.reflect.macros.whitebox.Context`. The original `Context` is left in place for compatibility reasons,
diff --git a/src/reflect/scala/reflect/macros/whitebox/Context.scala b/src/reflect/scala/reflect/macros/whitebox/Context.scala
index bd48df46cc..272991cba9 100644
--- a/src/reflect/scala/reflect/macros/whitebox/Context.scala
+++ b/src/reflect/scala/reflect/macros/whitebox/Context.scala
@@ -29,7 +29,7 @@ package whitebox
* gaining the ability to refine the type of its expansion beyond its official return type, which enables a number of important use cases.
* Blackbox macros, i.e. the ones defined with `blackbox.Context`, can't do that, so they are less powerful.
* However blackbox macros are also going to enjoy better support than whitebox macros, so choose wisely.
- * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] for more information.
+ * See the [[http://docs.scala-lang.org/overviews/macros/overview.html Macros Guide]] for more information.
*
* @see `scala.reflect.macros.blackbox.Context`
*/
diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala
index c18a9809a0..89e849429d 100644
--- a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala
+++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala
@@ -11,7 +11,7 @@ import _root_.jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, Arg
// implements a jline interface
class JLineDelimiter extends ArgumentDelimiter {
- def toJLine(args: List[String], cursor: Int) = args match {
+ def toJLine(args: List[String], cursor: Int): ArgumentList = 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)
}
diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
index f0fce13fe8..b5db4c2098 100644
--- a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
+++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
@@ -10,12 +10,13 @@ package scala.tools.nsc.interpreter.jline
import java.util.{Collection => JCollection, List => JList}
import _root_.jline.{console => jconsole}
-import jconsole.completer.{Completer, ArgumentCompleter}
+import jline.console.ConsoleReader
+import jline.console.completer.{CompletionHandler, Completer, ArgumentCompleter}
import jconsole.history.{History => JHistory}
import scala.tools.nsc.interpreter
-import scala.tools.nsc.interpreter.Completion
+import scala.tools.nsc.interpreter.{Completion, JLineCompletion, NoCompletion}
import scala.tools.nsc.interpreter.Completion.Candidates
import scala.tools.nsc.interpreter.session.History
@@ -121,23 +122,48 @@ private class JLineConsoleReader extends jconsole.ConsoleReader with interpreter
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
+ // adapt the JLine completion interface
+ def completer =
+ 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
+ }
+ }
+
+ // a last bit of nastiness: parsing help depending on the flavor of completer (fixme)
+ completion match {
+ case _: JLineCompletion =>
+ val jlineCompleter = new ArgumentCompleter(new JLineDelimiter, completer)
+ jlineCompleter setStrict false
+ this addCompleter jlineCompleter
+ case NoCompletion => ()
+ case _ => this addCompleter completer
}
+
+ // This is a workaround for https://github.com/jline/jline2/issues/208
+ // and should not be necessary once we upgrade to JLine 2.13.1
+ ///
+ // Test by:
+ // scala> {" ".char}<LEFT><TAB>
+ //
+ // And checking we don't get an extra } on the line.
+ ///
+ val handler = getCompletionHandler
+ setCompletionHandler(new CompletionHandler {
+ override def complete(consoleReader: ConsoleReader, list: JList[CharSequence], i: Int): Boolean = {
+ try {
+ handler.complete(consoleReader, list, i)
+ } finally if (getCursorBuffer.cursor != getCursorBuffer.length()) {
+ print(" ")
+ getCursorBuffer.write(' ')
+ backspace()
+ }
+ }
+ })
+ setAutoprintThreshold(400) // max completion candidates without warning
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 612bdd98c9..6721ff6dd6 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -1,8 +1,7 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
+ * Copyright 2005-2015 LAMP/EPFL
* @author Alexander Spoon
*/
-
package scala
package tools.nsc
package interpreter
@@ -24,9 +23,9 @@ import io.AbstractFile
import scala.collection.generic.Clearable
import scala.concurrent.{ ExecutionContext, Await, Future, future }
import ExecutionContext.Implicits._
-import java.io.{ BufferedReader, FileReader }
+import java.io.{ BufferedReader, FileReader, StringReader }
-import scala.util.{Try, Success, Failure}
+import scala.util.{ Try, Success, Failure }
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
@@ -657,12 +656,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
unleashAndSetPhase()
asyncEcho(isDuringInit, power.banner)
}
- private def unleashAndSetPhase() {
- if (isReplPower) {
- power.unleash()
- // Set the phase to "typer"
- intp beSilentDuring phaseCommand("typer")
- }
+ private def unleashAndSetPhase() = if (isReplPower) {
+ power.unleash()
+ intp beSilentDuring phaseCommand("typer") // Set the phase to "typer"
}
def asyncEcho(async: Boolean, msg: => String) {
@@ -750,28 +746,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
result
}
- private object paste extends Pasted {
- import scala.util.matching.Regex.quote
- val ContinuePrompt = replProps.continuePrompt
- val ContinueString = replProps.continueText // " | "
- val PromptString = prompt.lines.toList.last
- val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
-
- def isPrompted(line: String) = matchesPrompt(line)
- def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
-
- def interpret(line: String): Unit = {
- echo(line.trim)
- intp interpret line
- echo("")
- }
-
- def transcript(start: String) = {
- echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
- apply(Iterator(start) ++ readWhile(!isPromptOnly(_)))
- }
-
- def unapply(line: String): Boolean = isPrompted(line)
+ private object paste extends Pasted(prompt) {
+ def interpret(line: String) = intp interpret line
+ def echo(message: String) = ILoop.this echo message
}
private object invocation {
@@ -786,30 +763,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* read, go ahead and interpret it. Return the full string
* to be recorded for replay, if any.
*/
- def interpretStartingWith(code: String): Option[String] = {
+ final def interpretStartingWith(code: String): Option[String] = {
// signal completion non-completion input has been received
in.completion.resetVerbosity()
- def reallyInterpret = intp.interpret(code) match {
- case IR.Error => None
- case IR.Success => Some(code)
- case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
- echo("You typed two blank lines. Starting a new command.")
- None
- case IR.Incomplete =>
- in.readLine(paste.ContinuePrompt) match {
- case null =>
- // we know compilation is going to fail since we're at EOF and the
- // parser thinks the input is still incomplete, but since this is
- // a file being read non-interactively we want to fail. So we send
- // it straight to the compiler for the nice error message.
- intp.compileString(code)
- None
-
- case line => interpretStartingWith(code + "\n" + line)
- }
- }
-
/* Here we place ourselves between the user and the interpreter and examine
* the input they are ostensibly submitting. We intervene in several cases:
*
@@ -822,9 +779,33 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
code match {
case "" => None
case lineComment() => None // line comment, do nothing
- case paste() if !paste.running => paste.transcript(code) ; None
+ case paste() if !paste.running => paste.transcript(Iterator(code) ++ readWhile(!paste.isPromptOnly(_))) match {
+ case Some(s) => interpretStartingWith(s)
+ case _ => None
+ }
case invocation() if intp.mostRecentVar != "" => interpretStartingWith(intp.mostRecentVar + code)
- case _ => reallyInterpret
+ case _ => intp.interpret(code) match {
+ case IR.Error => None
+ case IR.Success => Some(code)
+ case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
+ echo("You typed two blank lines. Starting a new command.")
+ None
+ case IR.Incomplete =>
+ val saved = intp.partialInput
+ intp.partialInput = code + "\n"
+ try {
+ in.readLine(paste.ContinuePrompt) match {
+ case null =>
+ // we know compilation is going to fail since we're at EOF and the
+ // parser thinks the input is still incomplete, but since this is
+ // a file being read non-interactively we want to fail. So we send
+ // it straight to the compiler for the nice error message.
+ intp.compileString(code)
+ None
+ case line => interpretStartingWith(s"$code\n$line")
+ }
+ } finally intp.partialInput = saved
+ }
}
}
@@ -840,9 +821,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
case _ =>
}
- /** Tries to create a JLineReader, falling back to SimpleReader:
- * unless settings or properties are such that it should start
- * with SimpleReader.
+ /** Tries to create a JLineReader, falling back to SimpleReader,
+ * unless settings or properties are such that it should start with SimpleReader.
+ * The constructor of the InteractiveReader must take a Completion strategy,
+ * supplied as a `() => Completion`; the Completion object provides a concrete Completer.
*/
def chooseReader(settings: Settings): InteractiveReader = {
if (settings.Xnojline || Properties.isEmacsShell) SimpleReader()
@@ -850,20 +832,25 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
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")
+ def instantiater(className: String): ReaderMaker = completer => {
+ if (settings.debug) Console.println(s"Trying to instantiate an 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 mkReader(maker: ReaderMaker) = maker { () =>
+ settings.completion.value match {
+ case _ if settings.noCompletion => NoCompletion
+ case "none" => NoCompletion
+ case "adhoc" => new JLineCompletion(intp) // JLineCompletion is a misnomer; it's not tied to jline
+ case "pc" | _ => new PresentationCompilerCompleter(intp)
+ }
+ }
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 readers = readerClasses map (cls => Try { mkReader(instantiater(cls)) })
val reader = (readers collect { case Success(reader) => reader } headOption) getOrElse SimpleReader()
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index 3b54f5274e..ef6ab4063a 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -15,10 +15,13 @@ import scala.concurrent.{ Future, ExecutionContext }
import scala.reflect.runtime.{ universe => ru }
import scala.reflect.{ ClassTag, classTag }
import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
+import scala.tools.nsc.interactive
+import scala.tools.nsc.reporters.StoreReporter
+import scala.tools.nsc.util.ClassPath.DefaultJavaContext
import scala.tools.util.PathResolverFactory
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
-import scala.tools.nsc.util.{ ScalaClassLoader, stringFromReader, stringFromWriter, StackTraceOps, ClassPath, MergedClassPath }
+import scala.tools.nsc.util._
import ScalaClassLoader.URLClassLoader
import scala.tools.nsc.util.Exceptional.unwrap
import scala.tools.nsc.backend.JavaPlatform
@@ -58,7 +61,7 @@ import java.io.File
* @author Moez A. Abdel-Gawad
* @author Lex Spoon
*/
-class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Settings, protected val out: JPrintWriter) extends AbstractScriptEngine with Compilable with Imports {
+class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Settings, protected val out: JPrintWriter) extends AbstractScriptEngine with Compilable with Imports with PresentationCompilation {
imain =>
setBindings(createBindings, ScriptContext.ENGINE_SCOPE)
@@ -77,6 +80,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
private var _isInitialized: Future[Boolean] = null // set up initialization future
private var bindExceptions = true // whether to bind the lastException variable
private var _executionWrapper = "" // code to be wrapped around all lines
+ var partialInput: String = "" // code accumulated in multi-line REPL input
/** We're going to go to some trouble to initialize the compiler asynchronously.
* It's critical that nothing call into it until it's been initialized or we will
@@ -446,7 +450,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
/** Build a request from the user. `trees` is `line` after being parsed.
*/
- private def buildRequest(line: String, trees: List[Tree]): Request = {
+ private[interpreter] def buildRequest(line: String, trees: List[Tree]): Request = {
executingRequest = new Request(line, trees)
executingRequest
}
@@ -465,11 +469,12 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
pos
}
- private def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
- val content = line //indentCode(line)
- val trees = parse(content) match {
- case parse.Incomplete => return Left(IR.Incomplete)
- case parse.Error => return Left(IR.Error)
+ private[interpreter] def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
+ val content = line
+
+ val trees: List[global.Tree] = parse(content) match {
+ case parse.Incomplete(_) => return Left(IR.Incomplete)
+ case parse.Error(_) => return Left(IR.Error)
case parse.Success(trees) => trees
}
repltrace(
@@ -854,7 +859,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
/** One line of code submitted by the user for interpretation */
- class Request(val line: String, val trees: List[Tree]) {
+ class Request(val line: String, val trees: List[Tree], generousImports: Boolean = false) {
def defines = defHandlers flatMap (_.definedSymbols)
def imports = importedSymbols
def value = Some(handlers.last) filter (h => h.definesValue) map (h => definedSymbols(h.definesTerm.get)) getOrElse NoSymbol
@@ -888,7 +893,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
* append to objectName to access anything bound by request.
*/
lazy val ComputedImports(headerPreamble, importsPreamble, importsTrailer, accessPath) =
- exitingTyper(importsCode(referencedNames.toSet, ObjectSourceCode, definesClass))
+ exitingTyper(importsCode(referencedNames.toSet, ObjectSourceCode, definesClass, generousImports))
/** the line of code to compute */
def toCompute = line
@@ -915,6 +920,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
|${envLines mkString (" ", ";\n ", ";\n")}
|$importsPreamble
|${indentCode(toCompute)}""".stripMargin
+ def preambleLength = preamble.length - toCompute.length - 1
val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this
@@ -954,7 +960,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def postwrap = s"}\nval $iw = new $iw\n"
}
- private lazy val ObjectSourceCode: Wrapper =
+ private[interpreter] lazy val ObjectSourceCode: Wrapper =
if (isClassBased) new ClassBasedWrapper else new ObjectBasedWrapper
private object ResultObjectSourceCode extends IMain.CodeAssembler[MemberHandler] {
@@ -1015,6 +1021,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
lazy val resultSymbol = lineRep.resolvePathToSymbol(fullAccessPath)
+
def applyToResultMember[T](name: Name, f: Symbol => T) = exitingTyper(f(resultSymbol.info.nonPrivateDecl(name)))
/* typeOf lookup with encoding */
@@ -1168,20 +1175,22 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
/** Parse a line into and return parsing result (error, incomplete or success with list of trees) */
object parse {
- abstract sealed class Result
- case object Error extends Result
- case object Incomplete extends Result
+ abstract sealed class Result { def trees: List[Tree] }
+ case class Error(trees: List[Tree]) extends Result
+ case class Incomplete(trees: List[Tree]) extends Result
case class Success(trees: List[Tree]) extends Result
def apply(line: String): Result = debugging(s"""parse("$line")""") {
var isIncomplete = false
- currentRun.parsing.withIncompleteHandler((_, _) => isIncomplete = true) {
+ def parse = {
reporter.reset()
val trees = newUnitParser(line).parseStats()
- if (reporter.hasErrors) Error
- else if (isIncomplete) Incomplete
+ if (reporter.hasErrors) Error(trees)
+ else if (isIncomplete) Incomplete(trees)
else Success(trees)
}
+ currentRun.parsing.withIncompleteHandler((_, _) => isIncomplete = true) {parse}
+
}
}
@@ -1264,6 +1273,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
/** Utility methods for the Interpreter. */
object IMain {
import java.util.Arrays.{ asList => asJavaList }
+ /** Dummy identifier fragement inserted at the cursor before presentation compilation. Needed to support completion of `global.def<TAB>` */
+ val DummyCursorFragment = "_CURSOR_"
class Factory extends ScriptEngineFactory {
@BeanProperty
@@ -1361,3 +1372,4 @@ object IMain {
def stripImpl(str: String): String = naming.unmangle(str)
}
}
+
diff --git a/src/repl/scala/tools/nsc/interpreter/Imports.scala b/src/repl/scala/tools/nsc/interpreter/Imports.scala
index 5b231d94b6..5742c1d0d8 100644
--- a/src/repl/scala/tools/nsc/interpreter/Imports.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Imports.scala
@@ -95,7 +95,8 @@ trait Imports {
* last one imported is actually usable.
*/
case class ComputedImports(header: String, prepend: String, append: String, access: String)
- protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper, definesClass: Boolean): ComputedImports = {
+
+ protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper, definesClass: Boolean, generousImports: Boolean): ComputedImports = {
val header, code, trailingBraces, accessPath = new StringBuilder
val currentImps = mutable.HashSet[Name]()
var predefEscapes = false // only emit predef import header if name not resolved in history, loosely
@@ -116,8 +117,9 @@ trait Imports {
def keepHandler(handler: MemberHandler) = handler match {
// While defining classes in class based mode - implicits are not needed.
case h: ImportHandler if isClassBased && definesClass => h.importedNames.exists(x => wanted.contains(x))
- case _: ImportHandler => true
- case x => x.definesImplicit || (x.definedNames exists wanted)
+ case _: ImportHandler => true
+ case x if generousImports => x.definesImplicit || (x.definedNames exists (d => wanted.exists(w => d.startsWith(w))))
+ case x => x.definesImplicit || (x.definedNames exists wanted)
}
reqs match {
diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
index d878988e26..e9b0234a4f 100644
--- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -9,6 +9,7 @@ package interpreter
import Completion._
import scala.collection.mutable.ListBuffer
import scala.reflect.internal.util.StringOps.longestCommonPrefix
+import scala.tools.nsc.interactive.Global
// REPL completor - queries supplied interpreter for valid
// completions based on current contents of buffer.
@@ -296,7 +297,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
override def complete(buf: String, cursor: Int): Candidates = {
verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
repldbg(f"%ncomplete($buf, $cursor%d) last = ($lastBuf, $lastCursor%d), verbosity: $verbosity")
-
// we don't try lower priority completions unless higher ones return no results.
def tryCompletion(p: Parsed, completionFunction: Parsed => List[String]): Option[Candidates] = {
val winners = completionFunction(p)
diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
index bcba7b6dfd..4e45f6d615 100644
--- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -35,7 +35,16 @@ trait MemberHandlers {
// XXX this is obviously inadequate but it's going to require some effort
// to get right.
if (name.toString startsWith "x$") ()
- else importVars += name
+ else {
+ importVars += name
+ // Needed to import `xxx` during line 2 of:
+ // scala> val xxx = ""
+ // scala> def foo: x<TAB>
+ if (name.endsWith(IMain.DummyCursorFragment)) {
+ val stripped = name.stripSuffix(IMain.DummyCursorFragment)
+ importVars += stripped
+ }
+ }
case _ => super.traverse(ast)
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index f8d8c2ddb1..3a7eda1b77 100644
--- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
@@ -15,19 +15,23 @@ package interpreter
* a transcript should itself be pasteable and should achieve
* the same result.
*/
-abstract class Pasted {
- def interpret(line: String): Unit
- def ContinueString: String
- def PromptString: String
- def AltPromptString: String = "scala> "
+abstract class Pasted(prompt: String) {
+ def interpret(line: String): IR.Result
+ def echo(message: String): Unit
- /* `testBoth` cannot be a val, as `Pasted` is inherited by `object paste` in ILoop,
- which would cause `val testBoth` to be initialized before `val PromptString` was.
+ val PromptString = prompt.lines.toList.last
+ val AltPromptString = "scala> "
+ val ContinuePrompt = replProps.continuePrompt
+ val ContinueString = replProps.continueText // " | "
+ val anyPrompt = {
+ import scala.util.matching.Regex.quote
+ s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
+ }
+
+ def isPrompted(line: String) = matchesPrompt(line)
+ def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
- object paste extends Pasted {
- val PromptString = prompt.lines.toList.last
- */
- private def testBoth = PromptString != AltPromptString
+ private val testBoth = PromptString != AltPromptString
private val spacey = " \t".toSet
def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString)
@@ -91,13 +95,26 @@ abstract class Pasted {
case _ => code
}
- def run(): Unit = {
- println("// Replaying %d commands from transcript.\n" format cmds.size)
- cmds foreach { cmd =>
- print(ActualPromptString)
- interpret(cmd)
- }
+ def interpreted(line: String) = {
+ echo(line.trim)
+ val res = interpret(line)
+ if (res != IR.Incomplete) echo("")
+ res
+ }
+ def incompletely(cmd: String) = {
+ print(ActualPromptString)
+ interpreted(cmd) == IR.Incomplete
}
+ def run(): Option[String] = {
+ echo(s"// Replaying ${cmds.size} commands from transcript.\n")
+ cmds find incompletely
+ }
+ }
+
+ // Run transcript and return incomplete line if any.
+ def transcript(lines: TraversableOnce[String]): Option[String] = {
+ echo("\n// Detected repl transcript. Paste more, or ctrl-D to finish.\n")
+ apply(lines)
}
/** Commands start on lines beginning with "scala>" and each successive
@@ -105,9 +122,10 @@ abstract class Pasted {
* Everything else is discarded. When the end of the transcript is spotted,
* all the commands are replayed.
*/
- def apply(lines: TraversableOnce[String]) = {
+ def apply(lines: TraversableOnce[String]): Option[String] = {
isRunning = true
- try new PasteAnalyzer(lines.toList) run()
+ try new PasteAnalyzer(lines.toList).run()
finally isRunning = false
}
+ def unapply(line: String): Boolean = isPrompted(line)
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Power.scala b/src/repl/scala/tools/nsc/interpreter/Power.scala
index 8d8140b638..a14a60d216 100644
--- a/src/repl/scala/tools/nsc/interpreter/Power.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Power.scala
@@ -113,10 +113,13 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
}
}
- private def customBanner = replProps.powerBanner.option flatMap (f => io.File(f).safeSlurp())
+ private def customBanner = replProps.powerBanner.option flatMap {
+ case f if f.getName == "classic" => Some(classic)
+ case f => io.File(f).safeSlurp()
+ }
private def customInit = replProps.powerInitCode.option flatMap (f => io.File(f).safeSlurp())
- def banner = customBanner getOrElse """
+ def classic = """
|** Power User mode enabled - BEEP WHIR GYVE **
|** :phase has been set to 'typer'. **
|** scala.tools.nsc._ has been imported **
@@ -124,28 +127,30 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
|** Try :help, :vals, power.<tab> **
""".stripMargin.trim
- private def initImports = List(
- "scala.tools.nsc._",
- "scala.collection.JavaConverters._",
- "intp.global.{ error => _, _ }",
- "definitions.{ getClass => _, _ }",
- "power.rutil._",
- "replImplicits._",
- "treedsl.CODE._"
- )
-
- def init = customInit match {
- case Some(x) => x
- case _ => initImports.mkString("import ", ", ", "")
- }
+ def banner = customBanner getOrElse """
+ |Power mode enabled. :phase is at typer.
+ |import scala.tools.nsc._, intp.global._, definitions._
+ |Try :help or completions for vals._ and power._
+ """.stripMargin.trim
+
+ private def initImports =
+ """scala.tools.nsc._
+ |scala.collection.JavaConverters._
+ |intp.global.{ error => _, _ }
+ |definitions.{ getClass => _, _ }
+ |power.rutil._
+ |replImplicits._
+ |treedsl.CODE._""".stripMargin.lines
+
+ def init = customInit getOrElse initImports.mkString("import ", ", ", "")
- /** Starts up power mode and runs whatever is in init.
+ /** Quietly starts up power mode and runs whatever is in init.
*/
def unleash(): Unit = beQuietDuring {
// First we create the ReplVals instance and bind it to $r
intp.bind("$r", replVals)
// Then we import everything from $r.
- intp interpret ("import " + intp.originalPath("$r") + "._")
+ intp interpret s"import ${ intp.originalPath("$r") }._"
// And whatever else there is to do.
init.lines foreach (intp interpret _)
}
diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala
new file mode 100644
index 0000000000..3a2177a4cb
--- /dev/null
+++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilation.scala
@@ -0,0 +1,110 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2015 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.tools.nsc.interpreter
+
+import scala.reflect.internal.util.RangePosition
+import scala.tools.nsc.backend.JavaPlatform
+import scala.tools.nsc.{interactive, Settings}
+import scala.tools.nsc.io._
+import scala.tools.nsc.reporters.StoreReporter
+import scala.tools.nsc.util.ClassPath.DefaultJavaContext
+import scala.tools.nsc.util.{DirectoryClassPath, MergedClassPath}
+
+trait PresentationCompilation {
+ self: IMain =>
+
+ /** Typecheck a line of REPL input, suitably wrapped with "interpreter wrapper" objects/classes, with the
+ * presentation compiler. The result of this method gives access to the typechecked tree and to autocompletion
+ * suggestions.
+ *
+ * The caller is responsible for calling [[PresentationCompileResult#cleanup]] to dispose of the compiler instance.
+ */
+ private[scala] def presentationCompile(line: String): Either[IR.Result, PresentationCompileResult] = {
+ if (global == null) Left(IR.Error)
+ else {
+ // special case for:
+ //
+ // scala> 1
+ // scala> .toInt
+ //
+ // and for multi-line input.
+ val line1 = partialInput + (if (Completion.looksLikeInvocation(line)) { self.mostRecentVar + line } else line)
+ val compiler = newPresentationCompiler()
+ val trees = compiler.newUnitParser(line1).parseStats()
+ val importer = global.mkImporter(compiler)
+ val request = new Request(line1, trees map (t => importer.importTree(t)), generousImports = true)
+ val wrappedCode: String = request.ObjectSourceCode(request.handlers)
+ val unit = compiler.newCompilationUnit(wrappedCode)
+ import compiler._
+ val richUnit = new RichCompilationUnit(unit.source)
+ unitOfFile(richUnit.source.file) = richUnit
+ enteringTyper(typeCheck(richUnit))
+ val result = PresentationCompileResult(compiler)(richUnit, request.ObjectSourceCode.preambleLength + line1.length - line.length)
+ Right(result)
+ }
+ }
+
+ /** Create an instance of the presentation compiler with a classpath comprising the REPL's configured classpath
+ * and the classes output by previously compiled REPL lines.
+ *
+ * You may directly interact with this compiler from any thread, although you must not access it concurrently
+ * from multiple threads.
+ *
+ * You may downcast the `reporter` to `StoreReporter` to access type errors.
+ */
+ def newPresentationCompiler(): interactive.Global = {
+ val replOutClasspath: DirectoryClassPath = new DirectoryClassPath(replOutput.dir, DefaultJavaContext)
+ val mergedClasspath = new MergedClassPath[AbstractFile](replOutClasspath :: global.platform.classPath :: Nil, DefaultJavaContext)
+ def copySettings: Settings = {
+ val s = new Settings(_ => () /* ignores "bad option -nc" errors, etc */)
+ s.processArguments(global.settings.recreateArgs, processAll = false)
+ s.YpresentationAnyThread.value = true
+ s
+ }
+ val storeReporter: StoreReporter = new StoreReporter
+ val interactiveGlobal = new interactive.Global(copySettings, storeReporter) { self =>
+ override lazy val platform: ThisPlatform = new JavaPlatform {
+ val global: self.type = self
+
+ override def classPath: PlatformClassPath = mergedClasspath
+ }
+ }
+ new interactiveGlobal.TyperRun()
+ interactiveGlobal
+ }
+
+ abstract class PresentationCompileResult {
+ val compiler: scala.tools.nsc.interactive.Global
+ def unit: compiler.RichCompilationUnit
+ /** The length of synthetic code the precedes the user writtn code */
+ def preambleLength: Int
+ def cleanup(): Unit = {
+ compiler.askShutdown()
+ }
+ import compiler.CompletionResult
+
+ def completionsAt(cursor: Int): CompletionResult = {
+ val pos = unit.source.position(preambleLength + cursor)
+ compiler.completionsAt(pos)
+ }
+ def typedTreeAt(code: String, selectionStart: Int, selectionEnd: Int): compiler.Tree = {
+ val start = selectionStart + preambleLength
+ val end = selectionEnd + preambleLength
+ val pos = new RangePosition(unit.source, start, start, end)
+ compiler.typedTreeAt(pos)
+ }
+ }
+
+ object PresentationCompileResult {
+ def apply(compiler0: interactive.Global)(unit0: compiler0.RichCompilationUnit, preambleLength0: Int) = new PresentationCompileResult {
+
+ override val compiler = compiler0
+
+ override def unit = unit0.asInstanceOf[compiler.RichCompilationUnit]
+
+ override def preambleLength = preambleLength0
+ }
+ }
+}
diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala
new file mode 100644
index 0000000000..0fb3236966
--- /dev/null
+++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala
@@ -0,0 +1,139 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.tools.nsc.interpreter
+
+import scala.reflect.internal.Flags
+import scala.reflect.internal.util.StringOps
+import scala.tools.nsc.interpreter.Completion.{ScalaCompleter, Candidates}
+import scala.util.control.NonFatal
+
+class PresentationCompilerCompleter(intp: IMain) extends Completion with ScalaCompleter {
+ import PresentationCompilerCompleter._
+ import intp.{PresentationCompileResult => Result}
+
+ private type Handler = Result => Candidates
+
+ private var lastRequest = NoRequest
+ private var tabCount = 0
+ private var lastCommonPrefixCompletion: Option[String] = None
+
+ def resetVerbosity(): Unit = { tabCount = 0 ; lastRequest = NoRequest }
+ def completer(): ScalaCompleter = this
+
+ // A convenience for testing
+ def complete(before: String, after: String = ""): Candidates = complete(before + after, before.length)
+ override def complete(buf: String, cursor: Int): Candidates = {
+ val request = Request(buf, cursor)
+ if (request == lastRequest)
+ tabCount += 1
+ else {
+ tabCount = 0
+ lastRequest = request
+ }
+
+ // secret handshakes
+ val slashPrint = """.*// *print *""".r
+ val slashTypeAt = """.*// *typeAt *(\d+) *(\d+) *""".r
+ val Cursor = IMain.DummyCursorFragment
+
+ def print(result: Result) = {
+ val offset = result.preambleLength
+ val pos1 = result.unit.source.position(offset).withEnd(offset + buf.length)
+ import result.compiler._
+ val tree = new Locator(pos1) locateIn result.unit.body match {
+ case Template(_, _, constructor :: (rest :+ last)) => if (rest.isEmpty) last else Block(rest, last)
+ case t => t
+ }
+ val printed = showCode(tree) + " // : " + tree.tpe.safeToString
+ Candidates(cursor, "" :: printed :: Nil)
+ }
+ def typeAt(result: Result, start: Int, end: Int) = {
+ val tpString = result.compiler.exitingTyper(result.typedTreeAt(buf, start, end).tpe.toString)
+ Candidates(cursor, "" :: tpString :: Nil)
+ }
+ def candidates(result: Result): Candidates = {
+ import result.compiler._
+ import CompletionResult._
+ def defStringCandidates(matching: List[Member], name: Name): Candidates = {
+ val defStrings = for {
+ member <- matching
+ if member.symNameDropLocal == name
+ sym <- member.sym.alternatives
+ sugared = sym.sugaredSymbolOrSelf
+ } yield {
+ val tp = member.prefix memberType sym
+ sugared.defStringSeenAs(tp)
+ }
+ Candidates(cursor, "" :: defStrings.distinct)
+ }
+ val found = result.completionsAt(cursor) match {
+ case NoResults => Completion.NoCandidates
+ case r =>
+ def shouldHide(m: Member): Boolean = {
+ val isUniversal = definitions.isUniversalMember(m.sym)
+ def viaUniversalExtensionMethod = m match {
+ case t: TypeMember if t.implicitlyAdded && t.viaView.info.params.head.info.bounds.isEmptyBounds => true
+ case _ => false
+ }
+ (
+ isUniversal && nme.isReplWrapperName(m.prefix.typeSymbol.name)
+ || isUniversal && tabCount == 0 && r.name.isEmpty
+ || viaUniversalExtensionMethod && tabCount == 0 && r.name.isEmpty
+ )
+ }
+
+ val matching = r.matchingResults().filterNot(shouldHide)
+ val tabAfterCommonPrefixCompletion = lastCommonPrefixCompletion.contains(buf.substring(0, cursor)) && matching.exists(_.symNameDropLocal == r.name)
+ val doubleTab = tabCount > 0 && matching.forall(_.symNameDropLocal == r.name)
+ if (tabAfterCommonPrefixCompletion || doubleTab) defStringCandidates(matching, r.name)
+ else if (matching.isEmpty) {
+ // Lenient matching based on camel case and on eliding JavaBean "get" / "is" boilerplate
+ val camelMatches: List[Member] = r.matchingResults(CompletionResult.camelMatch(_)).filterNot(shouldHide)
+ val memberCompletions = camelMatches.map(_.symNameDropLocal.decoded).distinct.sorted
+ def allowCompletion = (
+ (memberCompletions.size == 1)
+ || CompletionResult.camelMatch(r.name)(r.name.newName(StringOps.longestCommonPrefix(memberCompletions)))
+ )
+ if (memberCompletions.isEmpty) Completion.NoCandidates
+ else if (allowCompletion) Candidates(cursor - r.positionDelta, memberCompletions)
+ else Candidates(cursor, "" :: memberCompletions)
+ } else if (matching.nonEmpty && matching.forall(_.symNameDropLocal == r.name))
+ Completion.NoCandidates // don't offer completion if the only option has been fully typed already
+ else {
+ // regular completion
+ val memberCompletions: List[String] = matching.map(_.symNameDropLocal.decoded).distinct.sorted
+ Candidates(cursor - r.positionDelta, memberCompletions)
+ }
+ }
+ lastCommonPrefixCompletion =
+ if (found != Completion.NoCandidates && buf.length >= found.cursor)
+ Some(buf.substring(0, found.cursor) + StringOps.longestCommonPrefix(found.candidates))
+ else
+ None
+ found
+ }
+ val buf1 = buf.patch(cursor, Cursor, 0)
+ try {
+ intp.presentationCompile(buf1) match {
+ case Left(_) => Completion.NoCandidates
+ case Right(result) => try {
+ buf match {
+ case slashPrint() if cursor == buf.length => print(result)
+ case slashTypeAt(start, end) if cursor == buf.length => typeAt(result, start.toInt, end.toInt)
+ case _ => candidates(result)
+ }
+ } finally result.cleanup()
+ }
+ } catch {
+ case NonFatal(e) =>
+ if (isReplDebug) e.printStackTrace()
+ Completion.NoCandidates
+ }
+ }
+}
+object PresentationCompilerCompleter {
+ private case class Request(line: String, cursor: Int)
+ private val NoRequest = Request("", -1)
+}
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
index fb4ed34571..fb4ed34571 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/LinkTo.scala b/src/scaladoc/scala/tools/nsc/doc/base/LinkTo.scala
index 3d80f9da52..3d80f9da52 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/LinkTo.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/LinkTo.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala
index 9de6ec4ab9..9de6ec4ab9 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
index ac5fec80b3..ac5fec80b3 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala
index f257153bd7..f257153bd7 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
index 84ee82f994..84ee82f994 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/ReferenceIndex.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
index 3d9cf8d465..cf81f7fdf5 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -412,7 +412,17 @@ function textFilter() {
var query = $("#textfilter input").attr("value") || '';
var queryRegExp = compilePattern(query);
- if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query)) {
+ // if we are filtering on types, then we have to display types
+ // ("display packages only" is not possible when filtering)
+ if (query !== "") {
+ kindFilter("all");
+ }
+
+ // Three things trigger a reload of the left pane list:
+ // typeof textFilter.lastQuery === "undefined" <-- first load, there is nothing yet in the left pane
+ // textFilter.lastQuery !== query <-- the filter text has changed
+ // focusFilterState != null <-- a package has been "focused"
+ if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query) || (focusFilterState != null)) {
textFilter.lastQuery = query;
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery-ui.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery-ui.js
index faab0cf1a3..faab0cf1a3 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery-ui.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/jquery-ui.js
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/ref-index.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/ref-index.css
index 7d64b9c5c5..7d64b9c5c5 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/ref-index.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/ref-index.css
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
index ad53dc6bfa..ad53dc6bfa 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/TreeFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/TreeFactory.scala
index c1228e8735..c1228e8735 100755..100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/TreeFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/TreeFactory.scala