summaryrefslogtreecommitdiff
path: root/src/repl/scala/tools/nsc/interpreter/IMain.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/repl/scala/tools/nsc/interpreter/IMain.scala')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala46
1 files changed, 29 insertions, 17 deletions
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)
}
}
+