diff options
-rw-r--r-- | build.sbt | 1 | ||||
-rwxr-xr-x | build.xml | 40 | ||||
-rw-r--r-- | src/repl-jline/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala (renamed from src/repl/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala) | 0 | ||||
-rw-r--r-- | src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala (renamed from src/repl/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala) | 0 | ||||
-rw-r--r-- | src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala (renamed from src/repl/scala/tools/nsc/interpreter/jline/JLineHistory.scala) | 0 | ||||
-rw-r--r-- | src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala (renamed from src/repl/scala/tools/nsc/interpreter/jline/JLineReader.scala) | 2 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 40 |
7 files changed, 70 insertions, 13 deletions
@@ -191,6 +191,7 @@ lazy val interactive = configureAsSubproject(project) .settings(disableDocsAndPublishingTasks: _*) .dependsOn(compiler) +// TODO: SI-9339 embed shaded copy of jline & its interface (see #4563) lazy val repl = configureAsSubproject(project) .settings(libraryDependencies += jlineDep) .settings(disableDocsAndPublishingTasks: _*) @@ -275,6 +275,10 @@ TODO: <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> </artifact:dependencies> + <artifact:dependencies pathId="jarjar.classpath"> + <dependency groupId="com.googlecode.jarjar" artifactId="jarjar" version="1.3"/> + </artifact:dependencies> + <!-- JUnit --> <property name="junit.version" value="4.11"/> <artifact:dependencies pathId="junit.classpath" filesetId="junit.fileset"> @@ -696,7 +700,7 @@ TODO: <property name="partest-javaagent.description" value="Scala Compiler Testing Tool (compiler-specific java agent)"/> <!-- projects without project-specific options: forkjoin, manual, bin, repl --> - <for list="actors,compiler,interactive,scaladoc,library,parser-combinators,partest,partest-extras,partest-javaagent,reflect,scalap,swing,xml,continuations-plugin,continuations-library" param="project"> + <for list="actors,compiler,interactive,scaladoc,library,parser-combinators,partest,partest-extras,partest-javaagent,reflect,scalap,swing,xml,continuations-plugin,continuations-library,repl-jline" param="project"> <sequential> <!-- description is mandatory --> <init-project-prop project="@{project}" name="package" default=""/> <!-- used by mvn-package, copy-bundle, make-bundle --> @@ -799,6 +803,11 @@ TODO: <path id="quick.repl.build.path"> <path refid="quick.compiler.build.path"/> <pathelement location="${build-quick.dir}/classes/repl"/> + </path> + + <path id="quick.repl-jline.build.path"> + <path refid="quick.repl.build.path"/> + <pathelement location="${build-quick.dir}/classes/repl-jline"/> <path refid="repl.deps.classpath"/> </path> @@ -873,6 +882,8 @@ TODO: <fileset dir="${build-quick.dir}/classes/actors"/> </path> + <path id="pack.repl-jline.files"> <fileset dir="${build-quick.dir}/classes/repl-jline"/> </path> + <path id="pack.compiler.files"> <fileset dir="${build-quick.dir}/classes/compiler"/> @@ -1076,6 +1087,7 @@ TODO: </patternset> <taskdef resource="scala/tools/ant/sabbus/antlib.xml" classpathref="starr.compiler.path"/> + <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpathref="jarjar.classpath" /> </target> <!-- =========================================================================== @@ -1157,7 +1169,31 @@ TODO: <staged-build with="locker" stage="quick" project="compiler"/> </target> <target name="quick.repl" depends="quick.comp"> - <staged-build with="locker" stage="quick" project="repl"/> </target> + <staged-build with="locker" stage="quick" project="repl"/> + <staged-build with="locker" stage="quick" project="repl-jline"/> + + <staged-pack project="repl-jline"/> + + <!-- make jline_embedded jar with classes of repl-jline and jline, then shade--> + <jarjar jarfile="${build-pack.dir}/${repl-jline.targetdir}/scala-repl-jline-embedded.jar" whenmanifestonly="fail"> + <zipfileset src="${jline:jline:jar}"/> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/${repl-jline.targetjar}"/> + + <rule pattern="org.fusesource.**" result="scala.tools.fusesource_embedded.@1"/> + <rule pattern="jline.**" result="scala.tools.jline_embedded.@1"/> + <rule pattern="scala.tools.nsc.interpreter.jline.**" result="scala.tools.nsc.interpreter.jline_embedded.@1"/> + <keep pattern="scala.tools.**"/> + </jarjar> + + <!-- unzip jar to repl's class dir to obtain + - standard repl-jline + - a shaded repl-jline (scala/tools/nsc/interpreter/jline_embedded) & jline (scala.tools.jline_embedded) + --> + <copy todir="${build-quick.dir}/classes/repl"> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/${repl-jline.targetjar}"/> + <zipfileset src="${build-pack.dir}/${repl-jline.targetdir}/scala-repl-jline-embedded.jar"/> + </copy> + </target> <target name="quick.scaladoc" depends="quick.comp"> <staged-build with="locker" stage="quick" project="scaladoc" version="scaladoc"/> </target> diff --git a/src/repl/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala index b6c9792ec0..b6c9792ec0 100644 --- a/src/repl/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/FileBackedHistory.scala diff --git a/src/repl/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala index c18a9809a0..c18a9809a0 100644 --- a/src/repl/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineDelimiter.scala diff --git a/src/repl/scala/tools/nsc/interpreter/jline/JLineHistory.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala index 1f6a1f7022..1f6a1f7022 100644 --- a/src/repl/scala/tools/nsc/interpreter/jline/JLineHistory.scala +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala diff --git a/src/repl/scala/tools/nsc/interpreter/jline/JLineReader.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala index 414868a7e5..f0fce13fe8 100644 --- a/src/repl/scala/tools/nsc/interpreter/jline/JLineReader.scala +++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala @@ -24,7 +24,7 @@ import scala.tools.nsc.interpreter.session.History * * Eagerly instantiates all relevant JLine classes, so that we can detect linkage errors on `new JLineReader` and retry. */ -class JLineReader(completer: () => Completion) extends interpreter.InteractiveReader { +class InteractiveReader(completer: () => Completion) extends interpreter.InteractiveReader { val interactive = true val history: History = new JLineHistory.JLineFileHistory() diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 3ce9668b97..a3047ccc8e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -26,6 +26,8 @@ import scala.concurrent.{ ExecutionContext, Await, Future, future } import ExecutionContext.Implicits._ import java.io.{ BufferedReader, FileReader } +import scala.util.{Try, Success, Failure} + /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. * After instantiation, clients should call the main() method. @@ -860,18 +862,36 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) * with SimpleReader. */ def chooseReader(settings: Settings): InteractiveReader = { - def mkJLineReader(completer: () => Completion): InteractiveReader = - try new jline.JLineReader(completer) - catch { - case ex@(_: Exception | _: NoClassDefFoundError) => - Console.println(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.") - SimpleReader() - } - if (settings.Xnojline || Properties.isEmacsShell) SimpleReader() else { - if (settings.noCompletion) mkJLineReader(() => NoCompletion) - else mkJLineReader(() => new JLineCompletion(intp)) + type Completer = () => Completion + type ReaderMaker = Completer => InteractiveReader + + def instantiate(className: String): ReaderMaker = completer => { + if (settings.debug) Console.println(s"Trying to instantiate a InteractiveReader from $className") + Class.forName(className).getConstructor(classOf[Completer]). + newInstance(completer). + asInstanceOf[InteractiveReader] + } + + def mkReader(maker: ReaderMaker) = + if (settings.noCompletion) maker(() => NoCompletion) + else maker(() => new JLineCompletion(intp)) // JLineCompletion is a misnomer -- it's not tied to jline + + def internalClass(kind: String) = s"scala.tools.nsc.interpreter.$kind.InteractiveReader" + val readerClasses = sys.props.get("scala.repl.reader").toStream ++ Stream(internalClass("jline"), internalClass("jline_embedded")) + val readers = readerClasses map (cls => Try { mkReader(instantiate(cls)) }) + + val reader = (readers collect { case Success(reader) => reader } headOption) getOrElse SimpleReader() + + if (settings.debug) { + val readerDiags = (readerClasses, readers).zipped map { + case (cls, Failure(e)) => s" - $cls --> " + e.getStackTrace.mkString(e.toString+"\n\t", "\n\t","\n") + case (cls, Success(_)) => s" - $cls OK" + } + Console.println(s"All InteractiveReaders tried: ${readerDiags.mkString("\n","\n","\n")}") + } + reader } } |