diff options
author | Paul Phillips <paulp@improving.org> | 2011-02-07 06:52:02 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-02-07 06:52:02 +0000 |
commit | 5c18620fa475d32de62472de55a6bcec3da1b515 (patch) | |
tree | 8d9363ddf785f94d610892684a5d44bf3d6986a3 | |
parent | 1065c911a1b896132b54d2573d80152b5fe7404f (diff) | |
download | scala-5c18620fa475d32de62472de55a6bcec3da1b515.tar.gz scala-5c18620fa475d32de62472de55a6bcec3da1b515.tar.bz2 scala-5c18620fa475d32de62472de55a6bcec3da1b515.zip |
Added all the javap command line options to :ja...
Added all the javap command line options to :javap. No review.
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ILoop.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/package.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/util/Javap.scala | 163 | ||||
-rw-r--r-- | test/files/run/javap.check | 18 | ||||
-rw-r--r-- | test/files/run/javap.scala | 24 |
5 files changed, 157 insertions, 70 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index b7cd227efc..f663bfd1be 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -304,17 +304,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter) p("") } } + + private object javap extends Javap(intp.classLoader, new IMain.ReplStrippingWriter(intp)) { + override def tryClass(path: String): Array[Byte] = super.tryClass(intp pathToFlatName path) + } + private def javapCommand(line: String): Result = { if (line == "") - return ":javap <filename or classname>" - val javap = new Javap(intp.classLoader) { - override def defaultPrintWriter = new IMain.ReplStrippingWriter(intp) - } - val path = intp.pathToFlatName(line) - val result = javap guess path + return ":javap [-lcsvp] [path1 path2 ...]" - if (result.isError) "Failed: " + result.value - else result.show() + javap(words(line)) foreach { res => + if (res.isError) return "Failed: " + res.value + else res.show() + } } private def keybindingsCommand(line: String): Result = { if (in.keyBindings.isEmpty) "Key bindings unavailable." diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala index 5f231190eb..42826e9c6d 100644 --- a/src/compiler/scala/tools/nsc/interpreter/package.scala +++ b/src/compiler/scala/tools/nsc/interpreter/package.scala @@ -23,12 +23,13 @@ package scala.tools.nsc * IMain contains { global: Global } */ package object interpreter { + type JClass = java.lang.Class[_] + private[nsc] val DebugProperty = "scala.repl.debug" private[nsc] val TraceProperty = "scala.repl.trace" private[nsc] val PowerProperty = "scala.repl.power" private[nsc] var isReplDebug = sys.props contains DebugProperty // Also set by -Yrepl-debug - type JClass = java.lang.Class[_] private[nsc] implicit def enrichClass[T](clazz: Class[T]) = new RichClass[T](clazz) /** Debug output */ @@ -42,6 +43,7 @@ package object interpreter { x } + private[nsc] def words(s: String) = s.trim split "\\s+" toList private[nsc] def isQuoted(s: String) = (s.length >= 2) && (s.head == s.last) && ("\"'" contains s.head) diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala index b31683b1f7..48971d6de0 100644 --- a/src/compiler/scala/tools/util/Javap.scala +++ b/src/compiler/scala/tools/util/Javap.scala @@ -6,53 +6,55 @@ package scala.tools package util -import java.io.{ InputStream, PrintWriter, ByteArrayInputStream, FileNotFoundException } import java.lang.reflect.{ GenericSignatureFormatError, Method, Constructor } import java.lang.{ ClassLoader => JavaClassLoader } import scala.tools.nsc.util.ScalaClassLoader +import java.io.{ InputStream, PrintWriter, ByteArrayInputStream, FileNotFoundException } import scala.tools.nsc.io.{ File, NullPrintStream } +import Javap._ -trait JavapResult { - 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] -} -class JavapError(msg: String) extends JavapResult { - type ResultType = String - def isError = true - def value = msg - def show() = println(msg) -} -class JavapSuccess(val value: AnyRef) extends JavapResult { - type ResultType = AnyRef - def isError = false - def show() = value.asInstanceOf[{ def print(): Unit }].print() -} +class Javap( + val loader: ScalaClassLoader = ScalaClassLoader.getSystemLoader(), + val printWriter: PrintWriter = new PrintWriter(System.out, true) +) { + + lazy val parser = new JpOptions + + def apply(args: Seq[String]): List[JpResult] = { + args.toList filterNot (_ startsWith "-") map { path => + val bytes = tryFile(path) getOrElse tryClass(path) + if (bytes.isEmpty) new JpError("Could not find class bytes for '%s'".format(path)) + else new JpSuccess(newPrinter(new ByteArrayInputStream(bytes), newEnv(args))) + } + } + + // "documentation" + type FakeEnvironment = AnyRef + type FakePrinter = AnyRef + + val Env = "sun.tools.javap.JavapEnvironment" + val EnvClass = loader.tryToInitializeClass[FakeEnvironment](Env).orNull + val EnvCtr = EnvClass.getConstructor(List[Class[_]](): _*) -class Javap(val loader: ScalaClassLoader) { - def this() = this(ScalaClassLoader.getSystemLoader()) - def defaultPrintWriter = new PrintWriter(System.out, true) - - private val envFieldsToSet = List[(String, Any)]( - // "showLineAndLocal" -> true, - "showDisassembled" -> true, - "showVerbose" -> true, - "showInternalSigs" -> true - ) - val Env = "sun.tools.javap.JavapEnvironment" - val Printer = "sun.tools.javap.JavapPrinter" - - val EnvClass = loader.tryToInitializeClass[AnyRef](Env).orNull - val PrinterClass = loader.tryToInitializeClass[AnyRef](Printer).orNull - val EnvCtr = EnvClass.getConstructor(List[Class[_]](): _*) + val Printer = "sun.tools.javap.JavapPrinter" + val PrinterClass = loader.tryToInitializeClass[FakePrinter](Printer).orNull val PrinterCtr = PrinterClass.getConstructor(classOf[InputStream], classOf[PrintWriter], EnvClass) + def newPrinter(in: InputStream, env: FakeEnvironment): FakePrinter = + PrinterCtr.newInstance(in, printWriter, env) + + def newEnv(opts: Seq[String]): FakeEnvironment = { + 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 + } + /** Assume the string is a path and try to find the classfile * it represents. */ @@ -74,31 +76,70 @@ class Javap(val loader: ScalaClassLoader) { ) loader.findBytesForClassName(extName) } +} - def newEnv(): AnyRef = { - val env = EnvClass.newInstance() - envFieldsToSet foreach { case (name, value) => - val x = EnvClass getDeclaredField name - x setAccessible true - x.set(env, value.asInstanceOf[AnyRef]) - } - env +object Javap { + def apply(path: String): Unit = apply(Seq(path)) + def apply(args: Seq[String]): Unit = new Javap() apply args foreach (_.show()) + + 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] } - def newPrinter( - in: InputStream, - pw: PrintWriter = defaultPrintWriter, - env: AnyRef = newEnv() - ): AnyRef = { - PrinterCtr.newInstance(in, pw, env) + class JpError(msg: String) extends JpResult { + type ResultType = String + def isError = true + def value = msg + def show() = println(msg) } - - def guess(path: String): JavapResult = { - val bytes = tryFile(path) getOrElse tryClass(path) - if (bytes.length > 0) new JavapSuccess(newPrinter(new ByteArrayInputStream(bytes))) - else new JavapError("Could not find class bytes for '%s'".format(path)) + class JpSuccess(val value: AnyRef) extends JpResult { + type ResultType = AnyRef + def isError = false + def show() = value.asInstanceOf[{ def print(): Unit }].print() } -} -object Javap extends Javap(ScalaClassLoader.getSystemLoader()) { - def apply(path: String): AnyRef = guess(path) + 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 + } + } + } + } } diff --git a/test/files/run/javap.check b/test/files/run/javap.check new file mode 100644 index 0000000000..1985fd611d --- /dev/null +++ b/test/files/run/javap.check @@ -0,0 +1,18 @@ +Arguments: '' +public class Bippy extends java.lang.Object implements scala.ScalaObject{ +public scala.collection.immutable.List f(scala.collection.immutable.List); +public Bippy(); +Arguments: '-v' +public class Bippy extends java.lang.Object implements scala.ScalaObject +public #28= #25 of #27; //Bippy=class Bippy of class +public scala.collection.immutable.List f(scala.collection.immutable.List); +public Bippy(); +Arguments: '-s' +public class Bippy extends java.lang.Object implements scala.ScalaObject{ +public scala.collection.immutable.List f(scala.collection.immutable.List); +public Bippy(); +Arguments: '-private' +public class Bippy extends java.lang.Object implements scala.ScalaObject{ +private int privateMethod(); +public scala.collection.immutable.List f(scala.collection.immutable.List); +public Bippy(); diff --git a/test/files/run/javap.scala b/test/files/run/javap.scala new file mode 100644 index 0000000000..241a83fa6f --- /dev/null +++ b/test/files/run/javap.scala @@ -0,0 +1,24 @@ +import scala.tools.nsc.interpreter._ + +object Test { + def run(args: String) = { + println("Arguments: '" + args + "'") + ILoop.run(""" + |class Bippy { + | private def privateMethod = 5 + | def f[T <: List[_]](x: T): T = x + |} + | + |:javap %s Bippy + """.stripMargin.format(args)).lines map (_.trim) filter { line => + (line startsWith "private") || (line startsWith "public") + } foreach println + } + + def main(args: Array[String]): Unit = { + run("") + run("-v") + run("-s") + run("-private") + } +} |