summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml39
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala30
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala59
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala (renamed from src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala)18
-rw-r--r--src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala (renamed from src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala)5
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala4
-rw-r--r--src/compiler/scala/tools/reflect/StdTags.scala4
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala2
-rw-r--r--src/compiler/scala/tools/util/Javap.scala694
-rw-r--r--src/repl/scala/tools/nsc/Interpreter.scala (renamed from src/compiler/scala/tools/nsc/Interpreter.scala)0
-rw-r--r--src/repl/scala/tools/nsc/InterpreterLoop.scala (renamed from src/compiler/scala/tools/nsc/InterpreterLoop.scala)0
-rw-r--r--src/repl/scala/tools/nsc/MainGenericRunner.scala (renamed from src/compiler/scala/tools/nsc/MainGenericRunner.scala)3
-rw-r--r--src/repl/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala7
-rw-r--r--src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala (renamed from src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ByteCode.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ByteCode.scala)10
-rw-r--r--src/repl/scala/tools/nsc/interpreter/CommandLine.scala (renamed from src/compiler/scala/tools/nsc/interpreter/CommandLine.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Completion.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Completion.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/CompletionAware.scala (renamed from src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/CompletionOutput.scala (renamed from src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Delimited.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Delimited.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ExprTyper.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Formatting.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Formatting.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ILoop.scala)3
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala (renamed from src/compiler/scala/tools/nsc/interpreter/IMain.scala)13
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ISettings.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ISettings.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Imports.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Imports.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala (renamed from src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala (renamed from src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JLineReader.scala (renamed from src/compiler/scala/tools/nsc/interpreter/JLineReader.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JavapClass.scala693
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Logger.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Logger.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/LoopCommands.scala (renamed from src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala (renamed from src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/NamedParam.scala (renamed from src/compiler/scala/tools/nsc/interpreter/NamedParam.scala)1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Naming.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Naming.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Parsed.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Parsed.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Pasted.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Phased.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Phased.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Power.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Power.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplConfig.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplDir.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplDir.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala)8
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplProps.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplProps.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplReporter.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplStrings.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplVals.scala (renamed from src/compiler/scala/tools/nsc/interpreter/ReplVals.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Results.scala (renamed from src/compiler/scala/tools/nsc/interpreter/Results.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/RichClass.scala (renamed from src/compiler/scala/tools/nsc/interpreter/RichClass.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/SimpleReader.scala (renamed from src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/StdReplTags.scala15
-rw-r--r--src/repl/scala/tools/nsc/interpreter/package.scala (renamed from src/compiler/scala/tools/nsc/interpreter/package.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/session/FileBackedHistory.scala (renamed from src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/session/History.scala (renamed from src/compiler/scala/tools/nsc/interpreter/session/History.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala (renamed from src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala (renamed from src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala)0
-rw-r--r--src/repl/scala/tools/nsc/interpreter/session/package.scala (renamed from src/compiler/scala/tools/nsc/interpreter/session/package.scala)0
60 files changed, 823 insertions, 811 deletions
diff --git a/build.xml b/build.xml
index c1deb7ce6f..7e4948c938 100644
--- a/build.xml
+++ b/build.xml
@@ -1095,6 +1095,32 @@ QUICK BUILD (QUICK)
<stopwatch name="quick.comp.timer" action="total"/>
</target>
+ <target name="quick.pre-repl" depends="quick.comp">
+ <uptodate property="quick.repl.available" targetfile="${build-quick.dir}/repl.complete">
+ <srcfiles dir="${src.dir}/repl" />
+ </uptodate>
+ </target>
+
+ <target name="quick.repl" depends="quick.pre-repl" unless="quick.repl.available">
+ <mkdir dir="${build-quick.dir}/classes/repl"/>
+ <scalacfork
+ destdir="${build-quick.dir}/classes/repl"
+ compilerpathref="quick.classpath"
+ params="${scalac.args.quick}"
+ srcdir="${src.dir}/repl"
+ jvmargs="${scalacfork.jvmargs}">
+ <include name="**/*.scala"/>
+ <compilationpath>
+ <pathelement location="${build-quick.dir}/classes/library"/>
+ <pathelement location="${build-quick.dir}/classes/reflect"/>
+ <pathelement location="${build-quick.dir}/classes/compiler"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
+ <pathelement location="${jline.jar}"/>
+ </compilationpath>
+ </scalacfork>
+ <touch file="${build-quick.dir}/repl.complete" verbose="no"/>
+ </target>
+
<target name="quick.swing" depends="quick.comp" if="has.java6" unless="quick.comp.available">
<scalacfork
destdir="${build-quick.dir}/classes/library"
@@ -1107,7 +1133,7 @@ QUICK BUILD (QUICK)
</scalacfork>
</target>
- <target name="quick.pre-plugins" depends="quick.comp">
+ <target name="quick.pre-plugins" depends="quick.repl" unless="quick.repl.available">
<uptodate property="quick.plugins.available" targetfile="${build-quick.dir}/plugins.complete">
<srcfiles dir="${src.dir}/continuations"/>
</uptodate>
@@ -1229,6 +1255,7 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/reflect"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
<pathelement location="${build-quick.dir}/classes/partest"/>
<path refid="asm.classpath"/>
@@ -1247,6 +1274,7 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/reflect"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
<pathelement location="${build-quick.dir}/classes/partest"/>
<pathelement location="${ant.jar}"/>
@@ -1358,11 +1386,12 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/reflect"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
+ <pathelement location="${jline.jar}"/>
+ <path refid="asm.classpath"/>
<path refid="forkjoin.classpath"/>
<path refid="aux.libs"/>
- <path refid="asm.classpath"/>
- <pathelement location="${jline.jar}"/>
</path>
<taskdef name="quick-bin" classname="scala.tools.ant.ScalaTool" classpathref="quick.bin.classpath"/>
<mkdir dir="${build-quick.dir}/bin"/>
@@ -1488,6 +1517,7 @@ PACKED QUICK BUILD (PACK)
<fileset dir="${build-quick.dir}/classes/compiler"/>
<fileset dir="${build-quick.dir}/classes/scaladoc"/>
<fileset dir="${build-quick.dir}/classes/interactive"/>
+ <fileset dir="${build-quick.dir}/classes/repl"/>
<fileset dir="${build-asm.dir}/classes"/>
</jar>
<copy file="${jline.jar}" toDir="${build-pack.dir}/lib"/>
@@ -1998,10 +2028,11 @@ SBT Compiler Interface
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
<compilationpath>
- <pathelement location="${build-quick.dir}/classes/scaladoc"/>
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/reflect"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
+ <pathelement location="${build-quick.dir}/classes/scaladoc"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${sbt.interface.jar}"/>
<path refid="forkjoin.classpath"/>
</compilationpath>
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c0f611daa7..7ee3ee551f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -999,7 +999,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
object typeDeconstruct extends {
val global: Global.this.type = Global.this
- } with interpreter.StructuredTypeStrings
+ } with typechecker.StructuredTypeStrings
/** There are common error conditions where when the exception hits
* here, currentRun.currentUnit is null. This robs us of the knowledge
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index 941ccd9a2d..c1cd3204e0 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -9,7 +9,6 @@ package backend.jvm
import java.io.{ DataOutputStream, FileOutputStream, OutputStream, File => JFile }
import scala.tools.nsc.io._
import scala.tools.nsc.util.ScalaClassLoader
-import scala.tools.util.{ Javap, JavapClass }
import java.util.jar.Attributes.Name
import scala.language.postfixOps
@@ -59,35 +58,6 @@ trait BytecodeWriters {
override def close() = writer.close()
}
- /** To be mixed-in with the BytecodeWriter that generates
- * the class file to be disassembled.
- */
- trait JavapBytecodeWriter extends BytecodeWriter {
- val baseDir = Directory(settings.Ygenjavap.value).createDirectory()
- val cl = ScalaClassLoader.appLoader
-
- def emitJavap(classFile: AbstractFile, javapFile: File) {
- val pw = javapFile.printWriter()
- try {
- val javap = new JavapClass(cl, pw) {
- override def findBytes(path: String): Array[Byte] = classFile.toByteArray
- }
- javap(Seq("-verbose", "-protected", classFile.name)) foreach (_.show())
- } finally pw.close()
- }
- abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
- super.writeClass(label, jclassName, jclassBytes, sym)
-
- val classFile = getFile(sym, jclassName, ".class")
- val segments = jclassName.split("[./]")
- val javapFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "javap" toFile;
- javapFile.parent.createDirectory()
-
- if (Javap.isAvailable(cl)) emitJavap(classFile, javapFile)
- else warning("No javap on classpath, skipping javap output.")
- }
- }
-
trait ClassBytecodeWriter extends BytecodeWriter {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
val outfile = getFile(sym, jclassName, ".class")
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 388efb4625..4a3d1805d9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -72,19 +72,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
new DirectToJarfileWriter(f.file)
case _ =>
- import scala.tools.util.Javap
- if (settings.Ygenjavap.isDefault) {
- if(settings.Ydumpclasses.isDefault)
- new ClassBytecodeWriter { }
- else
- new ClassBytecodeWriter with DumpBytecodeWriter { }
- }
- else if (Javap.isAvailable()) new ClassBytecodeWriter with JavapBytecodeWriter { }
- else {
- warning("No javap on classpath, skipping javap output.")
+ if (settings.Ydumpclasses.isDefault)
new ClassBytecodeWriter { }
- }
-
+ else
+ new ClassBytecodeWriter with DumpBytecodeWriter { }
// TODO A ScalapBytecodeWriter could take asm.util.Textifier as starting point.
// Three areas where javap ouput is less than ideal (e.g. when comparing versions of the same classfile) are:
// (a) unreadable pickle;
@@ -2519,7 +2510,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
if (nextBlock != whereto)
jcode goTo labels(whereto)
// SI-6102: Determine whether eliding this JUMP results in an empty range being covered by some EH.
- // If so, emit a NOP in place of the elided JUMP, to avoid "java.lang.ClassFormatError: Illegal exception table range"
+ // If so, emit a NOP in place of the elided JUMP, to avoid "java.lang.ClassFormatError: Illegal exception table range"
else if (newNormal.isJumpOnly(b) && m.exh.exists(eh => eh.covers(b))) {
debugwarn("Had a jump only block that wasn't collapsed")
emit(asm.Opcodes.NOP)
@@ -3084,7 +3075,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
assert(nonICode.hasNext, "empty block")
nonICode.next.isInstanceOf[JUMP]
}
-
+
/**
* Returns the list of instructions in a block that follow all ICode only instructions,
* where an ICode only instruction is one that won't make it to the JVM
@@ -3101,7 +3092,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
* Returns the target of a block that is "jump only" which is defined
* as being a block that consists only of 0 or more instructions that
* won't make it to the JVM followed by a JUMP.
- *
+ *
* @param b The basic block to examine
* @return Some(target) if b is a "jump only" block or None if it's not
*/
@@ -3150,12 +3141,12 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
def rephraseGotos(detour: mutable.Map[BasicBlock, BasicBlock]) {
def lookup(b: BasicBlock) = detour.getOrElse(b, b)
-
+
m.code.startBlock = lookup(m.code.startBlock)
-
+
for(eh <- m.exh)
eh.setStartBlock(lookup(eh.startBlock))
-
+
for (b <- m.blocks) {
def replaceLastInstruction(i: Instruction) = {
if (b.lastInstruction != i) {
@@ -3164,18 +3155,18 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
b.replaceInstruction(idxLast, i)
}
}
-
+
b.lastInstruction match {
case JUMP(whereto) =>
replaceLastInstruction(JUMP(lookup(whereto)))
case CJUMP(succ, fail, cond, kind) =>
replaceLastInstruction(CJUMP(lookup(succ), lookup(fail), cond, kind))
- case CZJUMP(succ, fail, cond, kind) =>
+ case CZJUMP(succ, fail, cond, kind) =>
replaceLastInstruction(CZJUMP(lookup(succ), lookup(fail), cond, kind))
case SWITCH(tags, labels) =>
val newLabels = (labels map lookup)
replaceLastInstruction(SWITCH(tags, newLabels))
- case _ => ()
+ case _ => ()
}
}
}
@@ -3203,7 +3194,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// blocks
for (key <- detour.keySet) {
// we use the Robert Floyd's classic Tortoise and Hare algorithm
- @tailrec
+ @tailrec
def findDestination(tortoise: BasicBlock, hare: BasicBlock): BasicBlock = {
if (tortoise == hare)
// cycle detected, map key to key
@@ -3227,7 +3218,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
detour
}
-
+
val detour = computeDetour
rephraseGotos(detour)
@@ -3235,33 +3226,33 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
val (remappings, cycles) = detour partition {case (source, target) => source != target}
for ((source, target) <- remappings) {
debuglog(s"Will elide jump only block $source because it can be jumped around to get to $target.")
- if (m.startBlock == source) debugwarn("startBlock should have been re-wired by now")
+ if (m.startBlock == source) debugwarn("startBlock should have been re-wired by now")
}
val sources = remappings.keySet
val targets = remappings.values.toSet
val intersection = sources intersect targets
-
+
if (intersection.nonEmpty) debugwarn(s"contradiction: we seem to have some source and target overlap in blocks ${intersection.mkString}. Map was ${detour.mkString}")
-
+
for ((source, _) <- cycles) {
debuglog(s"Block $source is in a do-nothing infinite loop. Did the user write 'while(true){}'?")
}
}
}
-
+
/**
* Removes all blocks that are unreachable in a method using a standard reachability analysis.
*/
def elimUnreachableBlocks(m: IMethod) {
- assert(m.hasCode, "code-less method")
-
+ assert(m.hasCode, "code-less method")
+
// assume nothing is reachable until we prove it can be reached
val reachable = mutable.Set[BasicBlock]()
-
+
// the set of blocks that we know are reachable but have
// yet to be marked reachable, initially only the start block
val worklist = mutable.Set(m.startBlock)
-
+
while (worklist.nonEmpty) {
val block = worklist.head
worklist remove block
@@ -3271,7 +3262,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// think are unreachable
worklist ++= (block.successors filterNot reachable)
}
-
+
// exception handlers need to be told not to cover unreachable blocks
// and exception handlers that no longer cover any blocks need to be
// removed entirely
@@ -3282,9 +3273,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
unusedExceptionHandlers += exh
}
}
-
+
// remove the unusued exception handler references
- if (settings.debug.value)
+ if (settings.debug.value)
for (exh <- unusedExceptionHandlers) debuglog(s"eliding exception handler $exh because it does not cover any reachable blocks")
m.exh = m.exh filterNot unusedExceptionHandlers
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 2aee9bd4bc..9469113238 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -188,7 +188,6 @@ trait ScalaSettings extends AbsScalaSettings
val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.")
val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.")
val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.")
- val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") andThen (interpreter.replProps.debug setValue _)
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 1693bdbc8c..91ebd798e1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -43,8 +43,15 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
import definitions._
import treeInfo.{isRepeatedParamType => _, _}
import MacrosStats._
+
def globalSettings = global.settings
+ protected def findMacroClassLoader(): ClassLoader = {
+ val classpath = global.classPath.asURLs
+ macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath))
+ ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+ }
+
/** `MacroImplBinding` and its companion module are responsible for
* serialization/deserialization of macro def -> impl bindings.
*
@@ -474,21 +481,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* Loads classes from from -cp (aka the library classpath).
* Is also capable of detecting REPL and reusing its classloader.
*/
- lazy val macroClassloader: ClassLoader = {
- val classpath = global.classPath.asURLs
- macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath))
- val loader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
-
- // a heuristic to detect the REPL
- if (global.settings.exposeEmptyPackage.value) {
- macroLogVerbose("macro classloader: initializing from a REPL classloader: %s".format(global.classPath.asURLs))
- import scala.tools.nsc.interpreter._
- val virtualDirectory = global.settings.outputDirs.getSingleOutput.get
- new AbstractFileClassLoader(virtualDirectory, loader) {}
- } else {
- loader
- }
- }
+ lazy val macroClassloader: ClassLoader = findMacroClassLoader()
/** Produces a function that can be used to invoke macro implementation for a given macro definition:
* 1) Looks up macro implementation symbol in this universe.
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
index 3ecd3b9ae4..65a3fedbd2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
@@ -4,7 +4,7 @@
*/
package scala.tools.nsc
-package interpreter
+package typechecker
import java.lang.{ reflect => r }
import r.TypeVariable
@@ -12,7 +12,6 @@ import scala.reflect.NameTransformer
import NameTransformer._
import scala.reflect.runtime.{universe => ru}
import scala.reflect.{ClassTag, classTag}
-import typechecker.DestructureTypes
/** A more principled system for turning types into strings.
*/
@@ -53,8 +52,7 @@ trait StructuredTypeStrings extends DestructureTypes {
private def shortClass(x: Any) = {
if (settings.debug.value) {
val name = (x.getClass.getName split '.').last
- val isAnon = name.reverse takeWhile (_ != '$') forall (_.isDigit)
- val str = if (isAnon) name else (name split '$').last
+ val str = if (TypeStrings.isAnonClass(x.getClass)) name else (name split '$').last
" // " + str
}
@@ -152,11 +150,11 @@ trait StructuredTypeStrings extends DestructureTypes {
* "definition" is when you want strings like
*/
trait TypeStrings {
+ private type JClass = java.lang.Class[_]
private val ObjectClass = classOf[java.lang.Object]
private val primitives = Set[String]("byte", "char", "short", "int", "long", "float", "double", "boolean", "void")
private val primitiveMap = primitives.toList map { x =>
val key = x match {
- case "void" => "Void"
case "int" => "Integer"
case "char" => "Character"
case s => s.capitalize
@@ -169,6 +167,11 @@ trait TypeStrings {
("java.lang." + key) -> ("scala." + value)
} toMap
+ def isAnonClass(cl: Class[_]) = {
+ val xs = cl.getName.reverse takeWhile (_ != '$')
+ xs.nonEmpty && xs.forall(_.isDigit)
+ }
+
def scalaName(s: String): String = {
if (s endsWith MODULE_SUFFIX_STRING) s.init + ".type"
else if (s == "void") "scala.Unit"
@@ -178,17 +181,16 @@ trait TypeStrings {
// Trying to put humpty dumpty back together again.
def scalaName(clazz: JClass): String = {
val name = clazz.getName
- val isAnon = clazz.isScalaAnonymous
val enclClass = clazz.getEnclosingClass
def enclPre = enclClass.getName + MODULE_SUFFIX_STRING
def enclMatch = name startsWith enclPre
scalaName(
- if (enclClass == null || isAnon || !enclMatch) name
+ if (enclClass == null || isAnonClass(clazz) || !enclMatch) name
else enclClass.getName + "." + (name stripPrefix enclPre)
)
}
- def anyClass(x: Any): JClass = if (x == null) null else x.getClass
+ def anyClass(x: Any): JClass = if (x == null) null else x.getClass
private def brackets(tps: String*): String =
if (tps.isEmpty) ""
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
index e909cd945d..7aef87f387 100644
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
@@ -3,10 +3,9 @@
*/
package scala.tools.nsc
-package interpreter
+package util
import scala.tools.nsc.io.AbstractFile
-import util.ScalaClassLoader
import java.net.{ URL, URLConnection, URLStreamHandler }
import scala.collection.{ mutable, immutable }
@@ -78,7 +77,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
case null => super.classBytes(name)
case file => file.toByteArray
}
- override def findClass(name: String): JClass = {
+ override def findClass(name: String): Class[_] = {
val bytes = classBytes(name)
if (bytes.length == 0)
throw new ClassNotFoundException(name)
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index 4bc393bd0b..f91e94471a 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -13,7 +13,6 @@ import java.lang.Float.intBitsToFloat
import java.lang.Double.longBitsToDouble
import scala.reflect.internal.{Flags, Names}
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
-import interpreter.ByteCode.scalaSigBytesForPath
object ShowPickled extends Names {
import PickleFormat._
@@ -272,7 +271,6 @@ object ShowPickled extends Names {
}
def fromFile(path: String) = fromBytes(io.File(path).toByteArray())
- def fromName(name: String) = fromBytes(scalaSigBytesForPath(name) getOrElse Array())
def fromBytes(data: => Array[Byte]): Option[PickleBuffer] =
try Some(new PickleBuffer(data, 0, data.length))
catch { case _: Exception => None }
@@ -287,7 +285,7 @@ object ShowPickled extends Names {
def main(args: Array[String]) {
args foreach { arg =>
- (fromFile(arg) orElse fromName(arg)) match {
+ fromFile(arg) match {
case Some(pb) => show(arg + ":", pb)
case _ => Console.println("Cannot read " + arg)
}
diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala
index 5c62819f04..6c1821f8aa 100644
--- a/src/compiler/scala/tools/reflect/StdTags.scala
+++ b/src/compiler/scala/tools/reflect/StdTags.scala
@@ -23,7 +23,7 @@ trait StdTags {
}
})
- private def tagOfStaticClass[T: ClassTag]: u.TypeTag[T] =
+ protected def tagOfStaticClass[T: ClassTag]: u.TypeTag[T] =
u.TypeTag[T](
m,
new TypeCreator {
@@ -34,8 +34,6 @@ trait StdTags {
lazy val tagOfString = tagOfStaticClass[String]
lazy val tagOfFile = tagOfStaticClass[scala.tools.nsc.io.File]
lazy val tagOfDirectory = tagOfStaticClass[scala.tools.nsc.io.Directory]
- lazy val tagOfStdReplVals = tagOfStaticClass[scala.tools.nsc.interpreter.StdReplVals]
- lazy val tagOfIMain = tagOfStaticClass[scala.tools.nsc.interpreter.IMain]
lazy val tagOfThrowable = tagOfStaticClass[java.lang.Throwable]
lazy val tagOfClassLoader = tagOfStaticClass[java.lang.ClassLoader]
lazy val tagOfBigInt = tagOfStaticClass[BigInt]
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 3bde280681..e6bbe1dbed 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -5,7 +5,7 @@ import scala.tools.nsc.EXPRmode
import scala.tools.nsc.reporters._
import scala.tools.nsc.CompilerCommand
import scala.tools.nsc.io.VirtualDirectory
-import scala.tools.nsc.interpreter.AbstractFileClassLoader
+import scala.tools.nsc.util.AbstractFileClassLoader
import scala.reflect.internal.Flags._
import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, NoFile}
import java.lang.{Class => jClass}
diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala
index 7e984fd1f7..3cfc1eb2a1 100644
--- a/src/compiler/scala/tools/util/Javap.scala
+++ b/src/compiler/scala/tools/util/Javap.scala
@@ -6,27 +6,14 @@
package scala.tools
package util
-import java.lang.{ ClassLoader => JavaClassLoader, Iterable => JIterable }
import scala.tools.nsc.util.ScalaClassLoader
-import scala.tools.nsc.interpreter.IMain
-import java.io.{ ByteArrayInputStream, CharArrayWriter, FileNotFoundException, InputStream,
- PrintWriter, Writer }
-import java.util.{ Locale }
-import java.util.regex.Pattern
-import javax.tools.{ Diagnostic, DiagnosticCollector, DiagnosticListener,
- ForwardingJavaFileManager, JavaFileManager, JavaFileObject,
- SimpleJavaFileObject, StandardLocation }
-import scala.reflect.io.{ AbstractFile, Directory, File, Path }
-import java.io.{File => JFile}
-import scala.io.Source
-import scala.util.{ Try, Success, Failure }
-import scala.util.Properties.lineSeparator
-import scala.collection.JavaConverters
-import scala.collection.generic.Clearable
-import java.net.URL
-import scala.language.reflectiveCalls
+import java.io.PrintWriter
-import Javap._
+trait JpResult {
+ def isError: Boolean
+ def value: Any
+ def show(): Unit
+}
trait Javap {
def loader: ScalaClassLoader
@@ -43,672 +30,3 @@ object NoJavap extends Javap {
def tryFile(path: String): Option[Array[Byte]] = None
def tryClass(path: String): Array[Byte] = Array()
}
-
-class JavapClass(
- val loader: ScalaClassLoader,
- val printWriter: PrintWriter,
- intp: Option[IMain] = None
-) extends Javap {
- import JavapTool.ToolArgs
- import JavapClass._
-
- lazy val tool = JavapTool()
-
- /** Run the tool. Option args start with "-".
- * The default options are "-protected -verbose".
- * Byte data for filename args is retrieved with findBytes.
- */
- def apply(args: Seq[String]): List[JpResult] = {
- val (options, claases) = args partition (s => (s startsWith "-") && s.length > 1)
- val (flags, upgraded) = upgrade(options)
- import flags.{ app, fun, help, raw }
- val targets = if (fun && !help) FunFinder(loader, intp).funs(claases) else claases
- if (help || claases.isEmpty) List(JpResult(JavapTool.helper(printWriter)))
- else if (targets.isEmpty) List(JpResult("No anonfuns found."))
- else tool(raw, upgraded)(targets map (claas => claas -> bytesFor(claas, app)))
- }
-
- /** Cull our tool options. */
- private def upgrade(options: Seq[String]): (ToolArgs, Seq[String]) = ToolArgs fromArgs options match {
- case (t,s) if s.nonEmpty => (t,s)
- case (t,s) => (t, JavapTool.DefaultOptions)
- }
-
- /** Find bytes. Handle "-", "-app", "Foo#bar" (by ignoring member), "#bar" (by taking "bar"). */
- private def bytesFor(path: String, app: Boolean) = Try {
- def last = intp.get.mostRecentVar // fail if no intp
- def req = if (path == "-") last else {
- val s = path.splitHashMember
- if (s._1.nonEmpty) s._1
- else s._2 getOrElse "#"
- }
- def asAppBody(s: String) = {
- val (cls, fix) = s.splitSuffix
- s"${cls}$$delayedInit$$body${fix}"
- }
- def todo = if (app) asAppBody(req) else req
- val bytes = findBytes(todo)
- if (bytes.isEmpty) throw new FileNotFoundException(s"Could not find class bytes for '${path}'")
- else bytes
- }
-
- def findBytes(path: String): Array[Byte] = tryFile(path) getOrElse tryClass(path)
-
- /** Assume the string is a path and try to find the classfile
- * it represents.
- */
- def tryFile(path: String): Option[Array[Byte]] =
- (Try (File(path.asClassResource)) filter (_.exists) map (_.toByteArray())).toOption
-
- /** Assume the string is a fully qualified class name and try to
- * find the class object it represents.
- * There are other symbols of interest, too:
- * - a definition that is wrapped in an enclosing class
- * - a synthetic that is not in scope but its associated class is
- */
- def tryClass(path: String): Array[Byte] = {
- def load(name: String) = loader classBytes name
- def loadable(name: String) = loader resourceable name
- // if path has an interior dollar, take it as a synthetic
- // if the prefix up to the dollar is a symbol in scope,
- // result is the translated prefix + suffix
- def desynthesize(s: String) = {
- val i = s indexOf '$'
- if (0 until s.length - 1 contains i) {
- val name = s substring (0, i)
- val sufx = s substring i
- val tran = intp flatMap (_ translatePath name)
- def loadableOrNone(strip: Boolean) = {
- def suffix(strip: Boolean)(x: String) =
- (if (strip && (x endsWith "$")) x.init else x) + sufx
- val res = tran map (suffix(strip) _)
- if (res.isDefined && loadable(res.get)) res else None
- }
- // try loading translated+suffix
- val res = loadableOrNone(strip = false)
- // some synthetics lack a dollar, (e.g., suffix = delayedInit$body)
- // so as a hack, if prefix$$suffix fails, also try prefix$suffix
- if (res.isDefined) res else loadableOrNone(strip = true)
- } else None
- }
- val p = path.asClassName // scrub any suffix
- // if repl, translate the name to something replish
- // (for translate, would be nicer to get the sym and ask .isClass,
- // instead of translatePath and then asking did I get a class back)
- val q = if (intp.isEmpty) p else (
- // only simple names get the scope treatment
- Some(p) filter (_ contains '.')
- // take path as a Name in scope
- orElse (intp flatMap (_ translatePath p) filter loadable)
- // take path as a Name in scope and find its enclosing class
- orElse (intp flatMap (_ translateEnclosingClass p) filter loadable)
- // take path as a synthetic derived from some Name in scope
- orElse desynthesize(p)
- // just try it plain
- getOrElse p
- )
- load(q)
- }
-
- /** Base class for javap tool adapters for java 6 and 7. */
- abstract class JavapTool {
- type ByteAry = Array[Byte]
- type Input = Pair[String, Try[ByteAry]]
-
- /** Run the tool. */
- def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult]
-
- // Since the tool is loaded by reflection, check for catastrophic failure.
- protected def failed: Boolean
- implicit protected class Failer[A](a: =>A) {
- def orFailed[B >: A](b: =>B) = if (failed) b else a
- }
- protected def noToolError = new JpError(s"No javap tool available: ${getClass.getName} failed to initialize.")
-
- // output filtering support
- val writer = new CharArrayWriter
- def written = {
- writer.flush()
- val w = writer.toString
- writer.reset()
- w
- }
-
- /** Create a Showable with output massage.
- * @param raw show ugly repl names
- * @param target attempt to filter output to show region of interest
- * @param preamble other messages to output
- */
- def showWithPreamble(raw: Boolean, target: String, preamble: String = ""): Showable = new Showable {
- // ReplStrippingWriter clips and scrubs on write(String)
- // circumvent it by write(mw, 0, mw.length) or wrap it in withoutUnwrapping
- def show() =
- if (raw && intp.isDefined) intp.get withoutUnwrapping { writeLines() }
- else writeLines()
- private def writeLines() {
- // take Foo# as Foo#apply for purposes of filtering. Useful for -fun Foo#;
- // if apply is added here, it's for other than -fun: javap Foo#, perhaps m#?
- val filterOn = target.splitHashMember._2 map { s => if (s.isEmpty) "apply" else s }
- var filtering = false // true if in region matching filter
- // true to output
- def checkFilter(line: String) = if (filterOn.isEmpty) true else {
- // cheap heuristic, todo maybe parse for the java sig.
- // method sigs end in paren semi
- def isAnyMethod = line.endsWith(");")
- def isOurMethod = {
- val lparen = line.lastIndexOf('(')
- val blank = line.lastIndexOf(' ', lparen)
- (blank >= 0 && line.substring(blank+1, lparen) == filterOn.get)
- }
- filtering = if (filtering) {
- // next blank line terminates section
- // for -public, next line is next method, more or less
- line.trim.nonEmpty && !isAnyMethod
- } else {
- isAnyMethod && isOurMethod
- }
- filtering
- }
- for (line <- Source.fromString(preamble + written).getLines(); if checkFilter(line))
- printWriter write line+lineSeparator
- printWriter.flush()
- }
- }
- }
-
- class JavapTool6 extends JavapTool {
- import JavapTool._
- val EnvClass = loader.tryToInitializeClass[FakeEnvironment](Env).orNull
- val PrinterClass = loader.tryToInitializeClass[FakePrinter](Printer).orNull
- override protected def failed = (EnvClass eq null) || (PrinterClass eq null)
-
- val PrinterCtr = PrinterClass.getConstructor(classOf[InputStream], classOf[PrintWriter], EnvClass) orFailed null
- val printWrapper = new PrintWriter(writer)
- def newPrinter(in: InputStream, env: FakeEnvironment): FakePrinter =
- PrinterCtr.newInstance(in, printWrapper, env) orFailed null
- def showable(raw: Boolean, target: String, fp: FakePrinter): Showable = {
- fp.asInstanceOf[{ def print(): Unit }].print() // run tool and flush to buffer
- printWrapper.flush() // just in case
- showWithPreamble(raw, target)
- }
-
- lazy val parser = new JpOptions
- def newEnv(opts: Seq[String]): FakeEnvironment = {
- def result = {
- val env: FakeEnvironment = EnvClass.newInstance()
- parser(opts) foreach { case (name, value) =>
- val field = EnvClass getDeclaredField name
- field setAccessible true
- field.set(env, value.asInstanceOf[AnyRef])
- }
- env
- }
- result orFailed null
- }
-
- override def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult] =
- (inputs map {
- case (claas, Success(ba)) => JpResult(showable(raw, claas, newPrinter(new ByteArrayInputStream(ba), newEnv(options))))
- case (_, Failure(e)) => JpResult(e.toString)
- }).toList orFailed List(noToolError)
- }
-
- class JavapTool7 extends JavapTool {
-
- import JavapTool._
- type Task = {
- def call(): Boolean // true = ok
- //def run(args: Array[String]): Int // all args
- //def handleOptions(args: Array[String]): Unit // options, then run() or call()
- }
- // result of Task.run
- //object TaskResult extends Enumeration {
- // val Ok, Error, CmdErr, SysErr, Abnormal = Value
- //}
- val TaskClaas = loader.tryToInitializeClass[Task](JavapTool.Tool).orNull
- override protected def failed = TaskClaas eq null
-
- val TaskCtor = TaskClaas.getConstructor(
- classOf[Writer],
- classOf[JavaFileManager],
- classOf[DiagnosticListener[_]],
- classOf[JIterable[String]],
- classOf[JIterable[String]]
- ) orFailed null
-
- class JavaReporter extends DiagnosticListener[JavaFileObject] with Clearable {
- import scala.collection.mutable.{ ArrayBuffer, SynchronizedBuffer }
- type D = Diagnostic[_ <: JavaFileObject]
- val diagnostics = new ArrayBuffer[D] with SynchronizedBuffer[D]
- override def report(d: Diagnostic[_ <: JavaFileObject]) {
- diagnostics += d
- }
- override def clear() = diagnostics.clear()
- /** All diagnostic messages.
- * @param locale Locale for diagnostic messages, null by default.
- */
- def messages(implicit locale: Locale = null) = (diagnostics map (_ getMessage locale)).toList
-
- def reportable(raw: Boolean): String = {
- // don't filter this message if raw, since the names are likely to differ
- val container = "Binary file .* contains .*".r
- val m = if (raw) messages
- else messages filter (_ match { case container() => false case _ => true })
- clear()
- if (m.nonEmpty) m mkString ("", lineSeparator, lineSeparator)
- else ""
- }
- }
- val reporter = new JavaReporter
-
- // DisassemblerTool.getStandardFileManager(reporter,locale,charset)
- val defaultFileManager: JavaFileManager =
- (loader.tryToLoadClass[JavaFileManager]("com.sun.tools.javap.JavapFileManager").get getMethod (
- "create",
- classOf[DiagnosticListener[_]],
- classOf[PrintWriter]
- ) invoke (null, reporter, new PrintWriter(System.err, true))).asInstanceOf[JavaFileManager] orFailed null
-
- // manages named arrays of bytes, which might have failed to load
- class JavapFileManager(val managed: Seq[Input])(delegate: JavaFileManager = defaultFileManager)
- extends ForwardingJavaFileManager[JavaFileManager](delegate) {
- import JavaFileObject.Kind
- import Kind._
- import StandardLocation._
- import JavaFileManager.Location
- import java.net.URI
- def uri(name: String): URI = new URI(name) // new URI("jfo:" + name)
-
- def inputNamed(name: String): Try[ByteAry] = (managed find (_._1 == name)).get._2
- def managedFile(name: String, kind: Kind) = kind match {
- case CLASS => fileObjectForInput(name, inputNamed(name), kind)
- case _ => null
- }
- // todo: just wrap it as scala abstractfile and adapt it uniformly
- def fileObjectForInput(name: String, bytes: Try[ByteAry], kind: Kind): JavaFileObject =
- new SimpleJavaFileObject(uri(name), kind) {
- override def openInputStream(): InputStream = new ByteArrayInputStream(bytes.get)
- // if non-null, ClassWriter wrongly requires scheme non-null
- override def toUri: URI = null
- override def getName: String = name
- // suppress
- override def getLastModified: Long = -1L
- }
- override def getJavaFileForInput(location: Location, className: String, kind: Kind): JavaFileObject =
- location match {
- case CLASS_PATH => managedFile(className, kind)
- case _ => null
- }
- override def hasLocation(location: Location): Boolean =
- location match {
- case CLASS_PATH => true
- case _ => false
- }
- }
- def fileManager(inputs: Seq[Input]) = new JavapFileManager(inputs)()
-
- // show tool messages and tool output, with output massage
- def showable(raw: Boolean, target: String): Showable = showWithPreamble(raw, target, reporter.reportable(raw))
-
- // eventually, use the tool interface
- def task(options: Seq[String], claases: Seq[String], inputs: Seq[Input]): Task = {
- //ServiceLoader.load(classOf[javax.tools.DisassemblerTool]).
- //getTask(writer, fileManager, reporter, options.asJava, claases.asJava)
- import JavaConverters.asJavaIterableConverter
- TaskCtor.newInstance(writer, fileManager(inputs), reporter, options.asJava, claases.asJava)
- .orFailed (throw new IllegalStateException)
- }
- // a result per input
- private def applyOne(raw: Boolean, options: Seq[String], claas: String, inputs: Seq[Input]): Try[JpResult] =
- Try {
- task(options, Seq(claas), inputs).call()
- } map {
- case true => JpResult(showable(raw, claas))
- case _ => JpResult(reporter.reportable(raw))
- } recoverWith {
- case e: java.lang.reflect.InvocationTargetException => e.getCause match {
- case t: IllegalArgumentException => Success(JpResult(t.getMessage)) // bad option
- case x => Failure(x)
- }
- } lastly {
- reporter.clear()
- }
- override def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult] = (inputs map {
- case (claas, Success(_)) => applyOne(raw, options, claas, inputs).get
- case (_, Failure(e)) => JpResult(e.toString)
- }).toList orFailed List(noToolError)
- }
-
- object JavapTool {
- // >= 1.7
- val Tool = "com.sun.tools.javap.JavapTask"
-
- // < 1.7
- val Env = "sun.tools.javap.JavapEnvironment"
- val Printer = "sun.tools.javap.JavapPrinter"
- // "documentation"
- type FakeEnvironment = AnyRef
- type FakePrinter = AnyRef
-
- // support JavapEnvironment
- class JpOptions {
- private object Access {
- final val PRIVATE = 0
- final val PROTECTED = 1
- final val PACKAGE = 2
- final val PUBLIC = 3
- }
- private val envActionMap: Map[String, (String, Any)] = {
- val map = Map(
- "-l" -> (("showLineAndLocal", true)),
- "-c" -> (("showDisassembled", true)),
- "-s" -> (("showInternalSigs", true)),
- "-verbose" -> (("showVerbose", true)),
- "-private" -> (("showAccess", Access.PRIVATE)),
- "-package" -> (("showAccess", Access.PACKAGE)),
- "-protected" -> (("showAccess", Access.PROTECTED)),
- "-public" -> (("showAccess", Access.PUBLIC)),
- "-all" -> (("showallAttr", true))
- )
- map ++ List(
- "-v" -> map("-verbose"),
- "-p" -> map("-private")
- )
- }
- def apply(opts: Seq[String]): Seq[(String, Any)] = {
- opts flatMap { opt =>
- envActionMap get opt match {
- case Some(pair) => List(pair)
- case _ =>
- val charOpts = opt.tail.toSeq map ("-" + _)
- if (charOpts forall (envActionMap contains _))
- charOpts map envActionMap
- else Nil
- }
- }
- }
- }
-
- case class ToolArgs(raw: Boolean = false, help: Boolean = false, app: Boolean = false, fun: Boolean = false)
-
- object ToolArgs {
- def fromArgs(args: Seq[String]): (ToolArgs, Seq[String]) = ((ToolArgs(), Seq[String]()) /: (args flatMap massage)) {
- case ((t,others), s) => s match {
- case "-fun" => (t copy (fun=true), others)
- case "-app" => (t copy (app=true), others)
- case "-help" => (t copy (help=true), others)
- case "-raw" => (t copy (raw=true), others)
- case _ => (t, others :+ s)
- }
- }
- }
-
- val helps = List(
- "usage" -> ":javap [opts] [path or class or -]...",
- "-help" -> "Prints this help message",
- "-raw" -> "Don't unmangle REPL names",
- "-app" -> "Show the DelayedInit body of Apps",
- "-fun" -> "Show anonfuns for class or Class#method",
- "-verbose/-v" -> "Stack size, number of locals, method args",
- "-private/-p" -> "Private classes and members",
- "-package" -> "Package-private classes and members",
- "-protected" -> "Protected classes and members",
- "-public" -> "Public classes and members",
- "-l" -> "Line and local variable tables",
- "-c" -> "Disassembled code",
- "-s" -> "Internal type signatures",
- "-sysinfo" -> "System info of class",
- "-constants" -> "Static final constants"
- )
-
- // match prefixes and unpack opts, or -help on failure
- def massage(arg: String): Seq[String] = {
- require(arg startsWith "-")
- // arg matches opt "-foo/-f" if prefix of -foo or exactly -f
- val r = """(-[^/]*)(/(-.))?""".r
- def maybe(opt: String, s: String): Option[String] = opt match {
- // disambiguate by preferring short form
- case r(lf,_,sf) if s == sf => Some(sf)
- case r(lf,_,sf) if lf startsWith s => Some(lf)
- case _ => None
- }
- def candidates(s: String) = (helps map (h => maybe(h._1, s))).flatten
- // one candidate or one single-char candidate
- def uniqueOf(maybes: Seq[String]) = {
- def single(s: String) = s.length == 2
- if (maybes.length == 1) maybes
- else if ((maybes count single) == 1) maybes filter single
- else Nil
- }
- // each optchar must decode to exactly one option
- def unpacked(s: String): Try[Seq[String]] = {
- val ones = (s drop 1) map { c =>
- val maybes = uniqueOf(candidates(s"-$c"))
- if (maybes.length == 1) Some(maybes.head) else None
- }
- Try(ones) filter (_ forall (_.isDefined)) map (_.flatten)
- }
- val res = uniqueOf(candidates(arg))
- if (res.nonEmpty) res
- else (unpacked(arg)
- getOrElse (Seq("-help"))) // or else someone needs help
- }
-
- def helper(pw: PrintWriter) = new Showable {
- def show() = helps foreach (p => pw write "%-12.12s%s%n".format(p._1,p._2))
- }
-
- val DefaultOptions = List("-protected", "-verbose")
-
- def isAvailable = Seq(Env, Tool) exists (cn => hasClass(loader, cn))
-
- private def hasClass(cl: ScalaClassLoader, cn: String) = cl.tryToInitializeClass[AnyRef](cn).isDefined
-
- private def isTaskable(cl: ScalaClassLoader) = hasClass(cl, Tool)
-
- def apply() = if (isTaskable(loader)) new JavapTool7 else new JavapTool6
- }
-}
-
-object JavapClass {
- def apply(
- loader: ScalaClassLoader = ScalaClassLoader.appLoader,
- printWriter: PrintWriter = new PrintWriter(System.out, true),
- intp: Option[IMain] = None
- ) = new JavapClass(loader, printWriter, intp)
-
- // We enjoy flexibility in specifying either a fully-qualified class name com.acme.Widget
- // or a resource path com/acme/Widget.class; but not widget.out
- implicit class MaybeClassLike(val s: String) extends AnyVal {
- /* private[this] final val suffix = ".class" */
- private def suffix = ".class"
- def asClassName = (s stripSuffix suffix).replace('/', '.')
- def asClassResource = if (s endsWith suffix) s else s.replace('.', '/') + suffix
- def splitSuffix: (String, String) = if (s endsWith suffix) (s dropRight suffix.length, suffix) else (s, "")
- def strippingSuffix(f: String => String): String =
- if (s endsWith suffix) f(s dropRight suffix.length) else s
- // e.g. Foo#bar. Foo# yields zero-length member part.
- def splitHashMember: (String, Option[String]) = {
- val i = s lastIndexOf '#'
- if (i < 0) (s, None)
- //else if (i >= s.length - 1) (s.init, None)
- else (s take i, Some(s drop i+1))
- }
- }
- implicit class ClassLoaderOps(val cl: ClassLoader) extends AnyVal {
- private def parentsOf(x: ClassLoader): List[ClassLoader] = if (x == null) Nil else x :: parentsOf(x.getParent)
- def parents: List[ClassLoader] = parentsOf(cl)
- /* all file locations */
- def locations = {
- def alldirs = parents flatMap (_ match {
- case ucl: ScalaClassLoader.URLClassLoader => ucl.classPathURLs
- case jcl: java.net.URLClassLoader => jcl.getURLs
- case _ => Nil
- })
- val dirs = for (d <- alldirs; if d.getProtocol == "file") yield Path(new JFile(d.toURI))
- dirs
- }
- /* only the file location from which the given class is loaded */
- def locate(k: String): Option[Path] = {
- Try {
- val claas = try cl loadClass k catch {
- case _: NoClassDefFoundError => null // let it snow
- }
- // cf ScalaClassLoader.originOfClass
- claas.getProtectionDomain.getCodeSource.getLocation
- } match {
- case Success(null) => None
- case Success(loc) if loc.isFile => Some(Path(new JFile(loc.toURI)))
- case _ => None
- }
- }
- /* would classBytes succeed with a nonempty array */
- def resourceable(className: String): Boolean = cl.getResource(className.asClassResource) != null
- }
- implicit class PathOps(val p: Path) extends AnyVal {
- import scala.tools.nsc.io.Jar
- def isJar = Jar isJarOrZip p
- }
- implicit class URLOps(val url: URL) extends AnyVal {
- def isFile: Boolean = url.getProtocol == "file"
- }
- object FunFinder {
- def apply(loader: ScalaClassLoader, intp: Option[IMain]) = new FunFinder(loader, intp)
- }
- class FunFinder(loader: ScalaClassLoader, intp: Option[IMain]) {
-
- // class k, candidate f without prefix
- def isFunOfClass(k: String, f: String) = {
- val p = (s"${Pattern quote k}\\$$+anonfun").r
- (p findPrefixOf f).nonEmpty
- }
- // class k, candidate f without prefix, method m
- def isFunOfMethod(k: String, m: String, f: String) = {
- val p = (s"${Pattern quote k}\\$$+anonfun\\$$${Pattern quote m}\\$$").r
- (p findPrefixOf f).nonEmpty
- }
- def isFunOfTarget(k: String, m: Option[String], f: String) =
- if (m.isEmpty) isFunOfClass(k, f)
- else isFunOfMethod(k, m.get, f)
- def listFunsInAbsFile(k: String, m: Option[String], d: AbstractFile) = {
- for (f <- d; if !f.isDirectory && isFunOfTarget(k, m, f.name)) yield f.name
- }
- // path prefix p, class k, dir d
- def listFunsInDir(p: String, k: String, m: Option[String])(d: Directory) = {
- val subdir = Path(p)
- for (f <- (d / subdir).toDirectory.list; if f.isFile && isFunOfTarget(k, m, f.name))
- yield f.name
- }
- // path prefix p, class k, jar file f
- def listFunsInJar(p: String, k: String, m: Option[String])(f: File) = {
- import java.util.jar.JarEntry
- import scala.tools.nsc.io.Jar
- def maybe(e: JarEntry) = {
- val (path, name) = {
- val parts = e.getName split "/"
- if (parts.length < 2) ("", e.getName)
- else (parts.init mkString "/", parts.last)
- }
- if (path == p && isFunOfTarget(k, m, name)) Some(name) else None
- }
- (new Jar(f) map maybe).flatten
- }
- def loadable(name: String) = loader resourceable name
- // translated class, optional member, opt member to filter on, whether it is repl output
- def translate(s: String): (String, Option[String], Option[String], Boolean) = {
- val (k0, m0) = s.splitHashMember
- val k = k0.asClassName
- val member = m0 filter (_.nonEmpty) // take Foo# as no member, not ""
- val filter = m0 flatMap { case "" => Some("apply") case _ => None } // take Foo# as filter on apply
- // class is either something replish or available to loader
- // $line.$read$$etc$Foo#member
- ((intp flatMap (_ translatePath k) filter (loadable) map ((_, member, filter, true)))
- // s = "f" and $line.$read$$etc$#f is what we're after,
- // ignoring any #member (except take # as filter on #apply)
- orElse (intp flatMap (_ translateEnclosingClass k) map ((_, Some(k), filter, true)))
- getOrElse (k, member, filter, false))
- }
- /** Find the classnames of anonfuns associated with k,
- * where k may be an available class or a symbol in scope.
- */
- def funsOf(k0: String): Seq[String] = {
- // class is either something replish or available to loader
- val (k, member, filter, isReplish) = translate(k0)
- val splat = k split "\\."
- val name = splat.last
- val prefix = if (splat.length > 1) splat.init mkString "/" else ""
- val pkg = if (splat.length > 1) splat.init mkString "." else ""
- // reconstitute an anonfun with a package
- // if filtered, add the hash back, e.g. pkg.Foo#bar, pkg.Foo$anon$1#apply
- def packaged(s: String) = {
- val p = if (pkg.isEmpty) s else s"$pkg.$s"
- val pm = filter map (p + "#" + _)
- pm getOrElse p
- }
- // is this translated path in (usually virtual) repl outdir? or loadable from filesystem?
- val fs = if (isReplish) {
- def outed(d: AbstractFile, p: Seq[String]): Option[AbstractFile] = {
- if (p.isEmpty) Option(d)
- else Option(d.lookupName(p.head, directory = true)) flatMap (f => outed(f, p.tail))
- }
- outed(intp.get.replOutput.dir, splat.init) map { d =>
- listFunsInAbsFile(name, member, d) map packaged
- }
- } else {
- loader locate k map { w =>
- if (w.isDirectory) listFunsInDir(prefix, name, member)(w.toDirectory) map packaged
- else if (w.isJar) listFunsInJar(prefix, name, member)(w.toFile) map packaged
- else Nil
- }
- }
- fs match {
- case Some(xs) => xs.to[Seq] // maybe empty
- case None => Seq() // nothing found, e.g., junk input
- }
- }
- def funs(ks: Seq[String]) = ks flatMap funsOf _
- }
-}
-
-object Javap {
-
- def isAvailable(cl: ScalaClassLoader = ScalaClassLoader.appLoader) = JavapClass(cl).JavapTool.isAvailable
-
- def apply(path: String): Unit = apply(Seq(path))
- def apply(args: Seq[String]): Unit = JavapClass() apply args foreach (_.show())
-
- trait Showable {
- def show(): Unit
- }
-
- sealed trait JpResult {
- type ResultType
- def isError: Boolean
- def value: ResultType
- def show(): Unit
- // todo
- // def header(): String
- // def fields(): List[String]
- // def methods(): List[String]
- // def signatures(): List[String]
- }
- object JpResult {
- def apply(msg: String) = new JpError(msg)
- def apply(res: Showable) = new JpSuccess(res)
- }
- class JpError(msg: String) extends JpResult {
- type ResultType = String
- def isError = true
- def value = msg
- def show() = println(msg) // makes sense for :javap, less for -Ygen-javap
- }
- class JpSuccess(val value: Showable) extends JpResult {
- type ResultType = AnyRef
- def isError = false
- def show() = value.show() // output to tool's PrintWriter
- }
- implicit class Lastly[A](val t: Try[A]) extends AnyVal {
- private def effect[X](last: =>Unit)(a: X): Try[A] = { last; t }
- def lastly(last: =>Unit): Try[A] = t transform (effect(last) _, effect(last) _)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/repl/scala/tools/nsc/Interpreter.scala
index 434f19f21b..434f19f21b 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/repl/scala/tools/nsc/Interpreter.scala
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/repl/scala/tools/nsc/InterpreterLoop.scala
index a0be3f4fdb..a0be3f4fdb 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/repl/scala/tools/nsc/InterpreterLoop.scala
diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/repl/scala/tools/nsc/MainGenericRunner.scala
index adb03ca374..7195424cf9 100644
--- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala
+++ b/src/repl/scala/tools/nsc/MainGenericRunner.scala
@@ -8,7 +8,6 @@ package scala.tools.nsc
import io.{ File }
import util.{ ClassPath, ScalaClassLoader }
import Properties.{ versionString, copyrightString }
-import interpreter.{ ILoop }
import GenericRunnerCommand._
object JarRunner extends CommonRunner {
@@ -78,7 +77,7 @@ class MainGenericRunner {
Right(false)
case _ =>
// We start the repl when no arguments are given.
- Right(new ILoop process settings)
+ Right(new interpreter.ILoop process settings)
}
/** If -e and -i were both given, we want to execute the -e code after the
diff --git a/src/repl/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/repl/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
new file mode 100644
index 0000000000..712219533d
--- /dev/null
+++ b/src/repl/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
@@ -0,0 +1,7 @@
+package scala.tools.nsc
+package interpreter
+
+import scala.reflect.io.AbstractFile
+
+@deprecated("Use `scala.tools.nsc.util.AbstractFileClassLoader`", "2.11.0")
+class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) extends util.AbstractFileClassLoader(root, parent)
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
index e66e4eff29..e66e4eff29 100644
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
+++ b/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala b/src/repl/scala/tools/nsc/interpreter/ByteCode.scala
index 48890a21c6..e1e3678837 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ByteCode.scala
@@ -28,15 +28,5 @@ object ByteCode {
method.invoke(module, _: String).asInstanceOf[Option[Map[String, String]]]
}
- /** Scala sig bytes.
- */
- def scalaSigBytesForPath(path: String) =
- for {
- module <- DECODER
- method <- decoderMethod("scalaSigAnnotationBytes", classOf[String])
- names <- method.invoke(module, path).asInstanceOf[Option[Array[Byte]]]
- }
- yield names
-
def aliasesForPackage(pkg: String) = aliasMap flatMap (_(pkg))
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala b/src/repl/scala/tools/nsc/interpreter/CommandLine.scala
index 0ab92ab769..0ab92ab769 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala
+++ b/src/repl/scala/tools/nsc/interpreter/CommandLine.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/repl/scala/tools/nsc/interpreter/Completion.scala
index 84a5cb49ae..84a5cb49ae 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Completion.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala b/src/repl/scala/tools/nsc/interpreter/CompletionAware.scala
index 3dd5d93390..3dd5d93390 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala
+++ b/src/repl/scala/tools/nsc/interpreter/CompletionAware.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/repl/scala/tools/nsc/interpreter/CompletionOutput.scala
index d24ad60974..d24ad60974 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/repl/scala/tools/nsc/interpreter/CompletionOutput.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
index 48af261937..48af261937 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala b/src/repl/scala/tools/nsc/interpreter/Delimited.scala
index e88a044931..e88a044931 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Delimited.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
index 9edd54b939..9edd54b939 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Formatting.scala b/src/repl/scala/tools/nsc/interpreter/Formatting.scala
index 43e653edfd..43e653edfd 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Formatting.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Formatting.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 2ea255319d..599a061984 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -11,7 +11,6 @@ import java.io.{ BufferedReader, FileReader }
import session._
import scala.annotation.tailrec
import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName }
-import scala.tools.util.{ Javap }
import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream }
import io.{ File, Directory }
import util.ScalaClassLoader
@@ -19,7 +18,7 @@ import ScalaClassLoader._
import scala.tools.util._
import scala.language.{implicitConversions, existentials}
import scala.reflect.classTag
-import scala.tools.reflect.StdRuntimeTags._
+import StdReplTags._
import scala.concurrent.{ ExecutionContext, Await, Future, future }
import ExecutionContext.Implicits._
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index c54b01dbb0..cb2e3c32b8 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -15,6 +15,7 @@ import scala.tools.nsc.io.AbstractFile
import reporters._
import scala.tools.util.PathResolver
import scala.tools.nsc.util.ScalaClassLoader
+import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
import ScalaClassLoader.URLClassLoader
import scala.tools.nsc.util.Exceptional.unwrap
import scala.collection.{ mutable, immutable }
@@ -22,7 +23,7 @@ import IMain._
import java.util.concurrent.Future
import scala.reflect.runtime.{ universe => ru }
import scala.reflect.{ ClassTag, classTag }
-import scala.tools.reflect.StdRuntimeTags._
+import StdReplTags._
/** An interpreter for Scala code.
*
@@ -80,8 +81,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
* use a lazy val to ensure that any attempt to use the compiler object waits
* on the future.
*/
- private var _classLoader: AbstractFileClassLoader = null // active classloader
- private val _compiler: Global = newCompiler(settings, reporter) // our private compiler
+ private var _classLoader: util.AbstractFileClassLoader = null // active classloader
+ private val _compiler: ReplGlobal = newCompiler(settings, reporter) // our private compiler
def compilerClasspath: Seq[URL] = (
if (isInitializeComplete) global.classPath.asURLs
@@ -271,7 +272,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
if (_classLoader == null)
_classLoader = makeClassLoader()
}
- def classLoader: AbstractFileClassLoader = {
+ def classLoader: util.AbstractFileClassLoader = {
ensureClassLoader()
_classLoader
}
@@ -318,7 +319,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
}
- private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(replOutput.dir, parent) {
+ private class TranslatingClassLoader(parent: ClassLoader) extends util.AbstractFileClassLoader(replOutput.dir, parent) {
/** Overridden here to try translating a simple name to the generated
* class name if the original attempt fails. This method is used by
* getResourceAsStream as well as findClass.
@@ -329,7 +330,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
case file => file
}
}
- private def makeClassLoader(): AbstractFileClassLoader =
+ private def makeClassLoader(): util.AbstractFileClassLoader =
new TranslatingClassLoader(parentClassLoader match {
case null => ScalaClassLoader fromURLs compilerClasspath
case p => new URLClassLoader(compilerClasspath, p)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala b/src/repl/scala/tools/nsc/interpreter/ISettings.scala
index 9541d08db1..9541d08db1 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ISettings.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/repl/scala/tools/nsc/interpreter/Imports.scala
index ff7bfd432c..ff7bfd432c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Imports.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
index 28ddf2939c..28ddf2939c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
index 19fa562234..19fa562234 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/repl/scala/tools/nsc/interpreter/JLineReader.scala
index 5d41f1bbb4..5d41f1bbb4 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JLineReader.scala
diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
new file mode 100644
index 0000000000..a895944c15
--- /dev/null
+++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
@@ -0,0 +1,693 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+import java.lang.{ ClassLoader => JavaClassLoader, Iterable => JIterable }
+import scala.tools.nsc.util.ScalaClassLoader
+import java.io.{ ByteArrayInputStream, CharArrayWriter, FileNotFoundException, PrintWriter, Writer }
+import java.util.{ Locale }
+import java.util.regex.Pattern
+import javax.tools.{ Diagnostic, DiagnosticCollector, DiagnosticListener,
+ ForwardingJavaFileManager, JavaFileManager, JavaFileObject,
+ SimpleJavaFileObject, StandardLocation }
+import scala.reflect.io.{ AbstractFile, Directory, File, Path }
+import scala.io.Source
+import scala.util.{ Try, Success, Failure }
+import scala.util.Properties.lineSeparator
+import scala.collection.JavaConverters
+import scala.collection.generic.Clearable
+import java.net.URL
+import scala.language.reflectiveCalls
+import Javap._
+
+class JavapClass(
+ val loader: ScalaClassLoader,
+ val printWriter: PrintWriter,
+ intp: Option[IMain] = None
+) extends scala.tools.util.Javap {
+ import JavapTool.ToolArgs
+ import JavapClass._
+
+ lazy val tool = JavapTool()
+
+ /** Run the tool. Option args start with "-".
+ * The default options are "-protected -verbose".
+ * Byte data for filename args is retrieved with findBytes.
+ */
+ def apply(args: Seq[String]): List[JpResult] = {
+ val (options, claases) = args partition (s => (s startsWith "-") && s.length > 1)
+ val (flags, upgraded) = upgrade(options)
+ import flags.{ app, fun, help, raw }
+ val targets = if (fun && !help) FunFinder(loader, intp).funs(claases) else claases
+ if (help || claases.isEmpty) List(JpResult(JavapTool.helper(printWriter)))
+ else if (targets.isEmpty) List(JpResult("No anonfuns found."))
+ else tool(raw, upgraded)(targets map (claas => claas -> bytesFor(claas, app)))
+ }
+
+ /** Cull our tool options. */
+ private def upgrade(options: Seq[String]): (ToolArgs, Seq[String]) = ToolArgs fromArgs options match {
+ case (t,s) if s.nonEmpty => (t,s)
+ case (t,s) => (t, JavapTool.DefaultOptions)
+ }
+
+ /** Find bytes. Handle "-", "-app", "Foo#bar" (by ignoring member), "#bar" (by taking "bar"). */
+ private def bytesFor(path: String, app: Boolean) = Try {
+ def last = intp.get.mostRecentVar // fail if no intp
+ def req = if (path == "-") last else {
+ val s = path.splitHashMember
+ if (s._1.nonEmpty) s._1
+ else s._2 getOrElse "#"
+ }
+ def asAppBody(s: String) = {
+ val (cls, fix) = s.splitSuffix
+ s"${cls}$$delayedInit$$body${fix}"
+ }
+ def todo = if (app) asAppBody(req) else req
+ val bytes = findBytes(todo)
+ if (bytes.isEmpty) throw new FileNotFoundException(s"Could not find class bytes for '${path}'")
+ else bytes
+ }
+
+ def findBytes(path: String): Array[Byte] = tryFile(path) getOrElse tryClass(path)
+
+ /** Assume the string is a path and try to find the classfile
+ * it represents.
+ */
+ def tryFile(path: String): Option[Array[Byte]] =
+ (Try (File(path.asClassResource)) filter (_.exists) map (_.toByteArray())).toOption
+
+ /** Assume the string is a fully qualified class name and try to
+ * find the class object it represents.
+ * There are other symbols of interest, too:
+ * - a definition that is wrapped in an enclosing class
+ * - a synthetic that is not in scope but its associated class is
+ */
+ def tryClass(path: String): Array[Byte] = {
+ def load(name: String) = loader classBytes name
+ def loadable(name: String) = loader resourceable name
+ // if path has an interior dollar, take it as a synthetic
+ // if the prefix up to the dollar is a symbol in scope,
+ // result is the translated prefix + suffix
+ def desynthesize(s: String) = {
+ val i = s indexOf '$'
+ if (0 until s.length - 1 contains i) {
+ val name = s substring (0, i)
+ val sufx = s substring i
+ val tran = intp flatMap (_ translatePath name)
+ def loadableOrNone(strip: Boolean) = {
+ def suffix(strip: Boolean)(x: String) =
+ (if (strip && (x endsWith "$")) x.init else x) + sufx
+ val res = tran map (suffix(strip) _)
+ if (res.isDefined && loadable(res.get)) res else None
+ }
+ // try loading translated+suffix
+ val res = loadableOrNone(strip = false)
+ // some synthetics lack a dollar, (e.g., suffix = delayedInit$body)
+ // so as a hack, if prefix$$suffix fails, also try prefix$suffix
+ if (res.isDefined) res else loadableOrNone(strip = true)
+ } else None
+ }
+ val p = path.asClassName // scrub any suffix
+ // if repl, translate the name to something replish
+ // (for translate, would be nicer to get the sym and ask .isClass,
+ // instead of translatePath and then asking did I get a class back)
+ val q = if (intp.isEmpty) p else (
+ // only simple names get the scope treatment
+ Some(p) filter (_ contains '.')
+ // take path as a Name in scope
+ orElse (intp flatMap (_ translatePath p) filter loadable)
+ // take path as a Name in scope and find its enclosing class
+ orElse (intp flatMap (_ translateEnclosingClass p) filter loadable)
+ // take path as a synthetic derived from some Name in scope
+ orElse desynthesize(p)
+ // just try it plain
+ getOrElse p
+ )
+ load(q)
+ }
+
+ /** Base class for javap tool adapters for java 6 and 7. */
+ abstract class JavapTool {
+ type ByteAry = Array[Byte]
+ type Input = Pair[String, Try[ByteAry]]
+
+ /** Run the tool. */
+ def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult]
+
+ // Since the tool is loaded by reflection, check for catastrophic failure.
+ protected def failed: Boolean
+ implicit protected class Failer[A](a: =>A) {
+ def orFailed[B >: A](b: =>B) = if (failed) b else a
+ }
+ protected def noToolError = new JpError(s"No javap tool available: ${getClass.getName} failed to initialize.")
+
+ // output filtering support
+ val writer = new CharArrayWriter
+ def written = {
+ writer.flush()
+ val w = writer.toString
+ writer.reset()
+ w
+ }
+
+ /** Create a Showable with output massage.
+ * @param raw show ugly repl names
+ * @param target attempt to filter output to show region of interest
+ * @param preamble other messages to output
+ */
+ def showWithPreamble(raw: Boolean, target: String, preamble: String = ""): Showable = new Showable {
+ // ReplStrippingWriter clips and scrubs on write(String)
+ // circumvent it by write(mw, 0, mw.length) or wrap it in withoutUnwrapping
+ def show() =
+ if (raw && intp.isDefined) intp.get withoutUnwrapping { writeLines() }
+ else writeLines()
+ private def writeLines() {
+ // take Foo# as Foo#apply for purposes of filtering. Useful for -fun Foo#;
+ // if apply is added here, it's for other than -fun: javap Foo#, perhaps m#?
+ val filterOn = target.splitHashMember._2 map { s => if (s.isEmpty) "apply" else s }
+ var filtering = false // true if in region matching filter
+ // true to output
+ def checkFilter(line: String) = if (filterOn.isEmpty) true else {
+ // cheap heuristic, todo maybe parse for the java sig.
+ // method sigs end in paren semi
+ def isAnyMethod = line.endsWith(");")
+ def isOurMethod = {
+ val lparen = line.lastIndexOf('(')
+ val blank = line.lastIndexOf(' ', lparen)
+ (blank >= 0 && line.substring(blank+1, lparen) == filterOn.get)
+ }
+ filtering = if (filtering) {
+ // next blank line terminates section
+ // for -public, next line is next method, more or less
+ line.trim.nonEmpty && !isAnyMethod
+ } else {
+ isAnyMethod && isOurMethod
+ }
+ filtering
+ }
+ for (line <- Source.fromString(preamble + written).getLines(); if checkFilter(line))
+ printWriter write line+lineSeparator
+ printWriter.flush()
+ }
+ }
+ }
+
+ class JavapTool6 extends JavapTool {
+ import JavapTool._
+ val EnvClass = loader.tryToInitializeClass[FakeEnvironment](Env).orNull
+ val PrinterClass = loader.tryToInitializeClass[FakePrinter](Printer).orNull
+ override protected def failed = (EnvClass eq null) || (PrinterClass eq null)
+
+ val PrinterCtr = PrinterClass.getConstructor(classOf[InputStream], classOf[PrintWriter], EnvClass) orFailed null
+ val printWrapper = new PrintWriter(writer)
+ def newPrinter(in: InputStream, env: FakeEnvironment): FakePrinter =
+ PrinterCtr.newInstance(in, printWrapper, env) orFailed null
+ def showable(raw: Boolean, target: String, fp: FakePrinter): Showable = {
+ fp.asInstanceOf[{ def print(): Unit }].print() // run tool and flush to buffer
+ printWrapper.flush() // just in case
+ showWithPreamble(raw, target)
+ }
+
+ lazy val parser = new JpOptions
+ def newEnv(opts: Seq[String]): FakeEnvironment = {
+ def result = {
+ val env: FakeEnvironment = EnvClass.newInstance()
+ parser(opts) foreach { case (name, value) =>
+ val field = EnvClass getDeclaredField name
+ field setAccessible true
+ field.set(env, value.asInstanceOf[AnyRef])
+ }
+ env
+ }
+ result orFailed null
+ }
+
+ override def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult] =
+ (inputs map {
+ case (claas, Success(ba)) => JpResult(showable(raw, claas, newPrinter(new ByteArrayInputStream(ba), newEnv(options))))
+ case (_, Failure(e)) => JpResult(e.toString)
+ }).toList orFailed List(noToolError)
+ }
+
+ class JavapTool7 extends JavapTool {
+
+ import JavapTool._
+ type Task = {
+ def call(): Boolean // true = ok
+ //def run(args: Array[String]): Int // all args
+ //def handleOptions(args: Array[String]): Unit // options, then run() or call()
+ }
+ // result of Task.run
+ //object TaskResult extends Enumeration {
+ // val Ok, Error, CmdErr, SysErr, Abnormal = Value
+ //}
+ val TaskClaas = loader.tryToInitializeClass[Task](JavapTool.Tool).orNull
+ override protected def failed = TaskClaas eq null
+
+ val TaskCtor = TaskClaas.getConstructor(
+ classOf[Writer],
+ classOf[JavaFileManager],
+ classOf[DiagnosticListener[_]],
+ classOf[JIterable[String]],
+ classOf[JIterable[String]]
+ ) orFailed null
+
+ class JavaReporter extends DiagnosticListener[JavaFileObject] with Clearable {
+ import scala.collection.mutable.{ ArrayBuffer, SynchronizedBuffer }
+ type D = Diagnostic[_ <: JavaFileObject]
+ val diagnostics = new ArrayBuffer[D] with SynchronizedBuffer[D]
+ override def report(d: Diagnostic[_ <: JavaFileObject]) {
+ diagnostics += d
+ }
+ override def clear() = diagnostics.clear()
+ /** All diagnostic messages.
+ * @param locale Locale for diagnostic messages, null by default.
+ */
+ def messages(implicit locale: Locale = null) = (diagnostics map (_ getMessage locale)).toList
+
+ def reportable(raw: Boolean): String = {
+ // don't filter this message if raw, since the names are likely to differ
+ val container = "Binary file .* contains .*".r
+ val m = if (raw) messages
+ else messages filter (_ match { case container() => false case _ => true })
+ clear()
+ if (m.nonEmpty) m mkString ("", lineSeparator, lineSeparator)
+ else ""
+ }
+ }
+ val reporter = new JavaReporter
+
+ // DisassemblerTool.getStandardFileManager(reporter,locale,charset)
+ val defaultFileManager: JavaFileManager =
+ (loader.tryToLoadClass[JavaFileManager]("com.sun.tools.javap.JavapFileManager").get getMethod (
+ "create",
+ classOf[DiagnosticListener[_]],
+ classOf[PrintWriter]
+ ) invoke (null, reporter, new PrintWriter(System.err, true))).asInstanceOf[JavaFileManager] orFailed null
+
+ // manages named arrays of bytes, which might have failed to load
+ class JavapFileManager(val managed: Seq[Input])(delegate: JavaFileManager = defaultFileManager)
+ extends ForwardingJavaFileManager[JavaFileManager](delegate) {
+ import JavaFileObject.Kind
+ import Kind._
+ import StandardLocation._
+ import JavaFileManager.Location
+ import java.net.URI
+ def uri(name: String): URI = new URI(name) // new URI("jfo:" + name)
+
+ def inputNamed(name: String): Try[ByteAry] = (managed find (_._1 == name)).get._2
+ def managedFile(name: String, kind: Kind) = kind match {
+ case CLASS => fileObjectForInput(name, inputNamed(name), kind)
+ case _ => null
+ }
+ // todo: just wrap it as scala abstractfile and adapt it uniformly
+ def fileObjectForInput(name: String, bytes: Try[ByteAry], kind: Kind): JavaFileObject =
+ new SimpleJavaFileObject(uri(name), kind) {
+ override def openInputStream(): InputStream = new ByteArrayInputStream(bytes.get)
+ // if non-null, ClassWriter wrongly requires scheme non-null
+ override def toUri: URI = null
+ override def getName: String = name
+ // suppress
+ override def getLastModified: Long = -1L
+ }
+ override def getJavaFileForInput(location: Location, className: String, kind: Kind): JavaFileObject =
+ location match {
+ case CLASS_PATH => managedFile(className, kind)
+ case _ => null
+ }
+ override def hasLocation(location: Location): Boolean =
+ location match {
+ case CLASS_PATH => true
+ case _ => false
+ }
+ }
+ def fileManager(inputs: Seq[Input]) = new JavapFileManager(inputs)()
+
+ // show tool messages and tool output, with output massage
+ def showable(raw: Boolean, target: String): Showable = showWithPreamble(raw, target, reporter.reportable(raw))
+
+ // eventually, use the tool interface
+ def task(options: Seq[String], claases: Seq[String], inputs: Seq[Input]): Task = {
+ //ServiceLoader.load(classOf[javax.tools.DisassemblerTool]).
+ //getTask(writer, fileManager, reporter, options.asJava, claases.asJava)
+ import JavaConverters.asJavaIterableConverter
+ TaskCtor.newInstance(writer, fileManager(inputs), reporter, options.asJava, claases.asJava)
+ .orFailed (throw new IllegalStateException)
+ }
+ // a result per input
+ private def applyOne(raw: Boolean, options: Seq[String], claas: String, inputs: Seq[Input]): Try[JpResult] =
+ Try {
+ task(options, Seq(claas), inputs).call()
+ } map {
+ case true => JpResult(showable(raw, claas))
+ case _ => JpResult(reporter.reportable(raw))
+ } recoverWith {
+ case e: java.lang.reflect.InvocationTargetException => e.getCause match {
+ case t: IllegalArgumentException => Success(JpResult(t.getMessage)) // bad option
+ case x => Failure(x)
+ }
+ } lastly {
+ reporter.clear()
+ }
+ override def apply(raw: Boolean, options: Seq[String])(inputs: Seq[Input]): List[JpResult] = (inputs map {
+ case (claas, Success(_)) => applyOne(raw, options, claas, inputs).get
+ case (_, Failure(e)) => JpResult(e.toString)
+ }).toList orFailed List(noToolError)
+ }
+
+ object JavapTool {
+ // >= 1.7
+ val Tool = "com.sun.tools.javap.JavapTask"
+
+ // < 1.7
+ val Env = "sun.tools.javap.JavapEnvironment"
+ val Printer = "sun.tools.javap.JavapPrinter"
+ // "documentation"
+ type FakeEnvironment = AnyRef
+ type FakePrinter = AnyRef
+
+ // support JavapEnvironment
+ class JpOptions {
+ private object Access {
+ final val PRIVATE = 0
+ final val PROTECTED = 1
+ final val PACKAGE = 2
+ final val PUBLIC = 3
+ }
+ private val envActionMap: Map[String, (String, Any)] = {
+ val map = Map(
+ "-l" -> (("showLineAndLocal", true)),
+ "-c" -> (("showDisassembled", true)),
+ "-s" -> (("showInternalSigs", true)),
+ "-verbose" -> (("showVerbose", true)),
+ "-private" -> (("showAccess", Access.PRIVATE)),
+ "-package" -> (("showAccess", Access.PACKAGE)),
+ "-protected" -> (("showAccess", Access.PROTECTED)),
+ "-public" -> (("showAccess", Access.PUBLIC)),
+ "-all" -> (("showallAttr", true))
+ )
+ map ++ List(
+ "-v" -> map("-verbose"),
+ "-p" -> map("-private")
+ )
+ }
+ def apply(opts: Seq[String]): Seq[(String, Any)] = {
+ opts flatMap { opt =>
+ envActionMap get opt match {
+ case Some(pair) => List(pair)
+ case _ =>
+ val charOpts = opt.tail.toSeq map ("-" + _)
+ if (charOpts forall (envActionMap contains _))
+ charOpts map envActionMap
+ else Nil
+ }
+ }
+ }
+ }
+
+ case class ToolArgs(raw: Boolean = false, help: Boolean = false, app: Boolean = false, fun: Boolean = false)
+
+ object ToolArgs {
+ def fromArgs(args: Seq[String]): (ToolArgs, Seq[String]) = ((ToolArgs(), Seq[String]()) /: (args flatMap massage)) {
+ case ((t,others), s) => s match {
+ case "-fun" => (t copy (fun=true), others)
+ case "-app" => (t copy (app=true), others)
+ case "-help" => (t copy (help=true), others)
+ case "-raw" => (t copy (raw=true), others)
+ case _ => (t, others :+ s)
+ }
+ }
+ }
+
+ val helps = List(
+ "usage" -> ":javap [opts] [path or class or -]...",
+ "-help" -> "Prints this help message",
+ "-raw" -> "Don't unmangle REPL names",
+ "-app" -> "Show the DelayedInit body of Apps",
+ "-fun" -> "Show anonfuns for class or Class#method",
+ "-verbose/-v" -> "Stack size, number of locals, method args",
+ "-private/-p" -> "Private classes and members",
+ "-package" -> "Package-private classes and members",
+ "-protected" -> "Protected classes and members",
+ "-public" -> "Public classes and members",
+ "-l" -> "Line and local variable tables",
+ "-c" -> "Disassembled code",
+ "-s" -> "Internal type signatures",
+ "-sysinfo" -> "System info of class",
+ "-constants" -> "Static final constants"
+ )
+
+ // match prefixes and unpack opts, or -help on failure
+ def massage(arg: String): Seq[String] = {
+ require(arg startsWith "-")
+ // arg matches opt "-foo/-f" if prefix of -foo or exactly -f
+ val r = """(-[^/]*)(/(-.))?""".r
+ def maybe(opt: String, s: String): Option[String] = opt match {
+ // disambiguate by preferring short form
+ case r(lf,_,sf) if s == sf => Some(sf)
+ case r(lf,_,sf) if lf startsWith s => Some(lf)
+ case _ => None
+ }
+ def candidates(s: String) = (helps map (h => maybe(h._1, s))).flatten
+ // one candidate or one single-char candidate
+ def uniqueOf(maybes: Seq[String]) = {
+ def single(s: String) = s.length == 2
+ if (maybes.length == 1) maybes
+ else if ((maybes count single) == 1) maybes filter single
+ else Nil
+ }
+ // each optchar must decode to exactly one option
+ def unpacked(s: String): Try[Seq[String]] = {
+ val ones = (s drop 1) map { c =>
+ val maybes = uniqueOf(candidates(s"-$c"))
+ if (maybes.length == 1) Some(maybes.head) else None
+ }
+ Try(ones) filter (_ forall (_.isDefined)) map (_.flatten)
+ }
+ val res = uniqueOf(candidates(arg))
+ if (res.nonEmpty) res
+ else (unpacked(arg)
+ getOrElse (Seq("-help"))) // or else someone needs help
+ }
+
+ def helper(pw: PrintWriter) = new Showable {
+ def show() = helps foreach (p => pw write "%-12.12s%s%n".format(p._1,p._2))
+ }
+
+ val DefaultOptions = List("-protected", "-verbose")
+
+ def isAvailable = Seq(Env, Tool) exists (cn => hasClass(loader, cn))
+
+ private def hasClass(cl: ScalaClassLoader, cn: String) = cl.tryToInitializeClass[AnyRef](cn).isDefined
+
+ private def isTaskable(cl: ScalaClassLoader) = hasClass(cl, Tool)
+
+ def apply() = if (isTaskable(loader)) new JavapTool7 else new JavapTool6
+ }
+}
+
+object JavapClass {
+ def apply(
+ loader: ScalaClassLoader = ScalaClassLoader.appLoader,
+ printWriter: PrintWriter = new PrintWriter(System.out, true),
+ intp: Option[IMain] = None
+ ) = new JavapClass(loader, printWriter, intp)
+
+ // We enjoy flexibility in specifying either a fully-qualified class name com.acme.Widget
+ // or a resource path com/acme/Widget.class; but not widget.out
+ implicit class MaybeClassLike(val s: String) extends AnyVal {
+ /* private[this] final val suffix = ".class" */
+ private def suffix = ".class"
+ def asClassName = (s stripSuffix suffix).replace('/', '.')
+ def asClassResource = if (s endsWith suffix) s else s.replace('.', '/') + suffix
+ def splitSuffix: (String, String) = if (s endsWith suffix) (s dropRight suffix.length, suffix) else (s, "")
+ def strippingSuffix(f: String => String): String =
+ if (s endsWith suffix) f(s dropRight suffix.length) else s
+ // e.g. Foo#bar. Foo# yields zero-length member part.
+ def splitHashMember: (String, Option[String]) = {
+ val i = s lastIndexOf '#'
+ if (i < 0) (s, None)
+ //else if (i >= s.length - 1) (s.init, None)
+ else (s take i, Some(s drop i+1))
+ }
+ }
+ implicit class ClassLoaderOps(val cl: ClassLoader) extends AnyVal {
+ private def parentsOf(x: ClassLoader): List[ClassLoader] = if (x == null) Nil else x :: parentsOf(x.getParent)
+ def parents: List[ClassLoader] = parentsOf(cl)
+ /* all file locations */
+ def locations = {
+ def alldirs = parents flatMap (_ match {
+ case ucl: ScalaClassLoader.URLClassLoader => ucl.classPathURLs
+ case jcl: java.net.URLClassLoader => jcl.getURLs
+ case _ => Nil
+ })
+ val dirs = for (d <- alldirs; if d.getProtocol == "file") yield Path(new JFile(d.toURI))
+ dirs
+ }
+ /* only the file location from which the given class is loaded */
+ def locate(k: String): Option[Path] = {
+ Try {
+ val claas = try cl loadClass k catch {
+ case _: NoClassDefFoundError => null // let it snow
+ }
+ // cf ScalaClassLoader.originOfClass
+ claas.getProtectionDomain.getCodeSource.getLocation
+ } match {
+ case Success(null) => None
+ case Success(loc) if loc.isFile => Some(Path(new JFile(loc.toURI)))
+ case _ => None
+ }
+ }
+ /* would classBytes succeed with a nonempty array */
+ def resourceable(className: String): Boolean = cl.getResource(className.asClassResource) != null
+ }
+ implicit class PathOps(val p: Path) extends AnyVal {
+ import scala.tools.nsc.io.Jar
+ def isJar = Jar isJarOrZip p
+ }
+ implicit class URLOps(val url: URL) extends AnyVal {
+ def isFile: Boolean = url.getProtocol == "file"
+ }
+ object FunFinder {
+ def apply(loader: ScalaClassLoader, intp: Option[IMain]) = new FunFinder(loader, intp)
+ }
+ class FunFinder(loader: ScalaClassLoader, intp: Option[IMain]) {
+
+ // class k, candidate f without prefix
+ def isFunOfClass(k: String, f: String) = {
+ val p = (s"${Pattern quote k}\\$$+anonfun").r
+ (p findPrefixOf f).nonEmpty
+ }
+ // class k, candidate f without prefix, method m
+ def isFunOfMethod(k: String, m: String, f: String) = {
+ val p = (s"${Pattern quote k}\\$$+anonfun\\$$${Pattern quote m}\\$$").r
+ (p findPrefixOf f).nonEmpty
+ }
+ def isFunOfTarget(k: String, m: Option[String], f: String) =
+ if (m.isEmpty) isFunOfClass(k, f)
+ else isFunOfMethod(k, m.get, f)
+ def listFunsInAbsFile(k: String, m: Option[String], d: AbstractFile) = {
+ for (f <- d; if !f.isDirectory && isFunOfTarget(k, m, f.name)) yield f.name
+ }
+ // path prefix p, class k, dir d
+ def listFunsInDir(p: String, k: String, m: Option[String])(d: Directory) = {
+ val subdir = Path(p)
+ for (f <- (d / subdir).toDirectory.list; if f.isFile && isFunOfTarget(k, m, f.name))
+ yield f.name
+ }
+ // path prefix p, class k, jar file f
+ def listFunsInJar(p: String, k: String, m: Option[String])(f: File) = {
+ import java.util.jar.JarEntry
+ import scala.tools.nsc.io.Jar
+ def maybe(e: JarEntry) = {
+ val (path, name) = {
+ val parts = e.getName split "/"
+ if (parts.length < 2) ("", e.getName)
+ else (parts.init mkString "/", parts.last)
+ }
+ if (path == p && isFunOfTarget(k, m, name)) Some(name) else None
+ }
+ (new Jar(f) map maybe).flatten
+ }
+ def loadable(name: String) = loader resourceable name
+ // translated class, optional member, opt member to filter on, whether it is repl output
+ def translate(s: String): (String, Option[String], Option[String], Boolean) = {
+ val (k0, m0) = s.splitHashMember
+ val k = k0.asClassName
+ val member = m0 filter (_.nonEmpty) // take Foo# as no member, not ""
+ val filter = m0 flatMap { case "" => Some("apply") case _ => None } // take Foo# as filter on apply
+ // class is either something replish or available to loader
+ // $line.$read$$etc$Foo#member
+ ((intp flatMap (_ translatePath k) filter (loadable) map ((_, member, filter, true)))
+ // s = "f" and $line.$read$$etc$#f is what we're after,
+ // ignoring any #member (except take # as filter on #apply)
+ orElse (intp flatMap (_ translateEnclosingClass k) map ((_, Some(k), filter, true)))
+ getOrElse (k, member, filter, false))
+ }
+ /** Find the classnames of anonfuns associated with k,
+ * where k may be an available class or a symbol in scope.
+ */
+ def funsOf(k0: String): Seq[String] = {
+ // class is either something replish or available to loader
+ val (k, member, filter, isReplish) = translate(k0)
+ val splat = k split "\\."
+ val name = splat.last
+ val prefix = if (splat.length > 1) splat.init mkString "/" else ""
+ val pkg = if (splat.length > 1) splat.init mkString "." else ""
+ // reconstitute an anonfun with a package
+ // if filtered, add the hash back, e.g. pkg.Foo#bar, pkg.Foo$anon$1#apply
+ def packaged(s: String) = {
+ val p = if (pkg.isEmpty) s else s"$pkg.$s"
+ val pm = filter map (p + "#" + _)
+ pm getOrElse p
+ }
+ // is this translated path in (usually virtual) repl outdir? or loadable from filesystem?
+ val fs = if (isReplish) {
+ def outed(d: AbstractFile, p: Seq[String]): Option[AbstractFile] = {
+ if (p.isEmpty) Option(d)
+ else Option(d.lookupName(p.head, directory = true)) flatMap (f => outed(f, p.tail))
+ }
+ outed(intp.get.replOutput.dir, splat.init) map { d =>
+ listFunsInAbsFile(name, member, d) map packaged
+ }
+ } else {
+ loader locate k map { w =>
+ if (w.isDirectory) listFunsInDir(prefix, name, member)(w.toDirectory) map packaged
+ else if (w.isJar) listFunsInJar(prefix, name, member)(w.toFile) map packaged
+ else Nil
+ }
+ }
+ fs match {
+ case Some(xs) => xs.to[Seq] // maybe empty
+ case None => Seq() // nothing found, e.g., junk input
+ }
+ }
+ def funs(ks: Seq[String]) = ks flatMap funsOf _
+ }
+}
+
+object Javap {
+ def isAvailable(cl: ScalaClassLoader = ScalaClassLoader.appLoader) = JavapClass(cl).JavapTool.isAvailable
+
+ def apply(path: String): Unit = apply(Seq(path))
+ def apply(args: Seq[String]): Unit = JavapClass() apply args foreach (_.show())
+
+ trait Showable {
+ def show(): Unit
+ }
+
+ sealed trait JpResult extends scala.tools.util.JpResult {
+ type ResultType
+ def isError: Boolean
+ def value: ResultType
+ def show(): Unit
+ // todo
+ // def header(): String
+ // def fields(): List[String]
+ // def methods(): List[String]
+ // def signatures(): List[String]
+ }
+ object JpResult {
+ def apply(msg: String) = new JpError(msg)
+ def apply(res: Showable) = new JpSuccess(res)
+ }
+ class JpError(msg: String) extends JpResult {
+ type ResultType = String
+ def isError = true
+ def value = msg
+ def show() = println(msg) // makes sense for :javap, less for -Ygen-javap
+ }
+ class JpSuccess(val value: Showable) extends JpResult {
+ type ResultType = AnyRef
+ def isError = false
+ def show() = value.show() // output to tool's PrintWriter
+ }
+ implicit class Lastly[A](val t: Try[A]) extends AnyVal {
+ private def effect[X](last: =>Unit)(a: X): Try[A] = { last; t }
+ def lastly(last: =>Unit): Try[A] = t transform (effect(last) _, effect(last) _)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Logger.scala b/src/repl/scala/tools/nsc/interpreter/Logger.scala
index 7407daf8d0..7407daf8d0 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Logger.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Logger.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
index 4bba27b714..4bba27b714 100644
--- a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
+++ b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
index 84a47311e2..84a47311e2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/repl/scala/tools/nsc/interpreter/NamedParam.scala
index 627a881cae..a0af72940a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
+++ b/src/repl/scala/tools/nsc/interpreter/NamedParam.scala
@@ -10,6 +10,7 @@ import NamedParam._
import scala.language.implicitConversions
import scala.reflect.runtime.{universe => ru}
import scala.reflect.{ClassTag, classTag}
+import scala.tools.nsc.typechecker.{ TypeStrings }
trait NamedParamCreator {
protected def freshName: () => String
diff --git a/src/compiler/scala/tools/nsc/interpreter/Naming.scala b/src/repl/scala/tools/nsc/interpreter/Naming.scala
index 57f3675ada..57f3675ada 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Naming.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Naming.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala b/src/repl/scala/tools/nsc/interpreter/Parsed.scala
index 672a6fd28f..672a6fd28f 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Parsed.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index f5db3d9e3a..f5db3d9e3a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/repl/scala/tools/nsc/interpreter/Phased.scala
index f625124e70..f625124e70 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Phased.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/repl/scala/tools/nsc/interpreter/Power.scala
index e517a16b32..e517a16b32 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Power.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala b/src/repl/scala/tools/nsc/interpreter/ReplConfig.scala
index 3392ea0b5e..3392ea0b5e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplConfig.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala b/src/repl/scala/tools/nsc/interpreter/ReplDir.scala
index 5d386b47b7..5d386b47b7 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplDir.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala
index 0eabd84234..51fab3082e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala
@@ -23,6 +23,14 @@ trait ReplGlobal extends Global {
override lazy val analyzer = new {
val global: ReplGlobal.this.type = ReplGlobal.this
} with Analyzer {
+
+ override protected def findMacroClassLoader(): ClassLoader = {
+ val loader = super.findMacroClassLoader
+ macroLogVerbose("macro classloader: initializing from a REPL classloader: %s".format(global.classPath.asURLs))
+ val virtualDirectory = globalSettings.outputDirs.getSingleOutput.get
+ new util.AbstractFileClassLoader(virtualDirectory, loader) {}
+ }
+
override def newTyper(context: Context): Typer = new Typer(context) {
override def typed(tree: Tree, mode: Mode, pt: Type): Tree = {
val res = super.typed(tree, mode, pt)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
index 2364918494..2364918494 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
index b20166d070..b20166d070 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala
index 08472bbc64..08472bbc64 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/repl/scala/tools/nsc/interpreter/ReplVals.scala
index ea100b25f2..ea100b25f2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplVals.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/Results.scala b/src/repl/scala/tools/nsc/interpreter/Results.scala
index e400906a58..e400906a58 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Results.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Results.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala b/src/repl/scala/tools/nsc/interpreter/RichClass.scala
index 36cdf65510..36cdf65510 100644
--- a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
+++ b/src/repl/scala/tools/nsc/interpreter/RichClass.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala
index 2d0917d91f..2d0917d91f 100644
--- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala
diff --git a/src/repl/scala/tools/nsc/interpreter/StdReplTags.scala b/src/repl/scala/tools/nsc/interpreter/StdReplTags.scala
new file mode 100644
index 0000000000..ebbb397a0c
--- /dev/null
+++ b/src/repl/scala/tools/nsc/interpreter/StdReplTags.scala
@@ -0,0 +1,15 @@
+package scala.tools.nsc
+package interpreter
+
+import scala.tools.reflect.StdTags
+import scala.reflect.runtime.{ universe => ru }
+
+trait StdReplTags extends StdTags {
+ lazy val tagOfStdReplVals = tagOfStaticClass[StdReplVals]
+ lazy val tagOfIMain = tagOfStaticClass[IMain]
+}
+
+object StdReplTags extends StdTags with StdReplTags {
+ val u: ru.type = ru
+ val m = u.runtimeMirror(getClass.getClassLoader)
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/repl/scala/tools/nsc/interpreter/package.scala
index 52a085080b..52a085080b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ b/src/repl/scala/tools/nsc/interpreter/package.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala b/src/repl/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
index dddfb1b8f6..dddfb1b8f6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
+++ b/src/repl/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/History.scala b/src/repl/scala/tools/nsc/interpreter/session/History.scala
index 794d41adc7..794d41adc7 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/History.scala
+++ b/src/repl/scala/tools/nsc/interpreter/session/History.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala b/src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala
index 18e0ee7c85..18e0ee7c85 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala
+++ b/src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala b/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala
index 89998e438a..89998e438a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala
+++ b/src/repl/scala/tools/nsc/interpreter/session/SimpleHistory.scala
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/package.scala b/src/repl/scala/tools/nsc/interpreter/session/package.scala
index c62cf21151..c62cf21151 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/package.scala
+++ b/src/repl/scala/tools/nsc/interpreter/session/package.scala