Permalink
Browse files

Implemented trait for field acces and method invocation

  • Loading branch information...
1 parent 8e00d0b commit f05f89052b6320f9386e763f2ef6fcf20806c60d @skyluc skyluc committed Dec 11, 2012
@@ -289,6 +289,8 @@ class ScalaDebugTestSession(launchConfiguration: ILaunchConfiguration) extends H
// access data in the current stackframe
+ /** Return the current value of a local variable.
+ */
def getLocalVariable(name: String): ScalaValue = {
assertEquals("Bad state before getLocalVariable", SUSPENDED, state)
@@ -1,10 +1,17 @@
package scala.tools.eclipse.debug.model
-import scala.tools.eclipse.debug.ScalaDebugger.modelProvider
+import scala.tools.eclipse.debug.ScalaDebugPlugin
import scala.tools.eclipse.debug.ScalaDebugger
+import scala.tools.eclipse.debug.ScalaDebugger.modelProvider
import scala.tools.eclipse.logging.HasLogger
-import org.eclipse.debug.core.model.{IDebugTarget, ITerminate, DebugElement}
-import scala.tools.eclipse.debug.ScalaDebugPlugin
+
+import org.eclipse.debug.core.model.{ITerminate, DebugElement}
+
+import com.sun.jdi.ClassType
+import com.sun.jdi.Field
+import com.sun.jdi.Method
+import com.sun.jdi.ReferenceType
+import com.sun.jdi.Value
/**
* Base class for debug elements in the Scala debug model
@@ -37,4 +44,64 @@ abstract class ScalaDebugElement(debugTarget: ScalaDebugTarget) extends DebugEle
// ----
+}
+
+trait HasFieldValue {
+ self: ScalaDebugElement =>
+
+ protected[model] def referenceType(): ReferenceType
+
+ /** Return the JDI value for the given field.
+ */
+ protected[model] def jdiFieldValue(field: Field): Value
+
+ /** Return the value of the field with the given name.
+ *
+ * @throws IllegalArgumentException if the no field with the given name exists.
+ */
+ def fieldValue(fieldName: String): ScalaValue = {
+ val field = referenceType().fieldByName(fieldName)
+ if (field == null) {
+ throw new IllegalArgumentException("Field '%s' doesn't exist for '%s'".format(fieldName, referenceType().name()))
+ }
+ ScalaValue(jdiFieldValue(field), getDebugTarget)
+ }
+}
+
+trait HasMethodInvocation {
+ self: ScalaDebugElement =>
+
+ protected[model] def classType(): ClassType
+
+ /** Invoke the given method.
+ */
+ protected[model] def jdiInvokeMethod(method: Method, thread: ScalaThread, args: Value*): Value
+
+ /** Invoke the method with given name, using the given arguments.
+ *
+ * @throws IllegalArgumentException if no method with given name exists, or more than one.
+ */
+ def invokeMethod(methodName: String, thread: ScalaThread, args: ScalaValue*): ScalaValue = {
+ val methods = classType().methodsByName(methodName)
+ methods.size match {
+ case 0 =>
+ throw new IllegalArgumentException("Method '%s(..)' doesn't exist for '%s'".format(methodName, classType.name()))
+ case 1 =>
+ ScalaValue(jdiInvokeMethod(methods.get(0), thread, args.map(_.value): _*), getDebugTarget)
+ case _ =>
+ throw new IllegalArgumentException("More than on method '%s(..)' for '%s'".format(methodName, classType.name()))
+ }
+ }
+
+ /** Invoke the method with given name and signature, using the given arguments.
+ *
+ * @throws IllegalArgumentException if no method with given name and signature exists.
+ */
+ def invokeMethod(methodName: String, methodSignature: String, thread: ScalaThread, args: ScalaValue*): ScalaValue = {
+ val method = classType().concreteMethodByName(methodName, methodSignature)
+ if (method == null) {
+ throw new IllegalArgumentException("Method '%s%s' doesn't exist for '%s'".format(methodName, methodSignature, classType().name()))
+ }
+ ScalaValue(jdiInvokeMethod(method, thread, args.map(_.value): _*), getDebugTarget)
+ }
}
@@ -117,32 +117,31 @@ abstract class ScalaThread private (target: ScalaDebugTarget, private[model] val
def terminatedFromScala(): Unit = dispose()
/** Invoke the given method on the given instance with the given arguments.
- *
- * This method should not be called directly.
- * Use [[ScalaObjectReference.invokeMethod(String, ScalaThread, ScalaValue*)]]
- * or [[ScalaObjectReference.invokeMethod(String, String, ScalaThread, ScalaValue*)]] instead.
+ *
+ * This method should not be called directly.
+ * Use [[ScalaObjectReference.invokeMethod(String, ScalaThread, ScalaValue*)]]
+ * or [[ScalaObjectReference.invokeMethod(String, String, ScalaThread, ScalaValue*)]] instead.
*/
- def invokeMethod(objectReference: ObjectReference, method: Method, args: ScalaValue*): ScalaValue = {
- companionActor !? InvokeMethod(objectReference, method, args.toList) match {
- case Right(res: ScalaValue) =>
- res
- case Left(e: Exception) =>
- throw e
- }
+ def invokeMethod(objectReference: ObjectReference, method: Method, args: Value*): Value = {
+ processMethodInvocationResult(companionActor !? InvokeMethod(objectReference, method, args.toList))
}
/** Invoke the given static method on the given type with the given arguments.
- *
- * This method should not be called directly.
- * Use [[ScalaClassType.invokeMethod(String, ScalaThread,ScalaValue*)]] instead.
+ *
+ * This method should not be called directly.
+ * Use [[ScalaClassType.invokeMethod(String, ScalaThread,ScalaValue*)]] instead.
*/
- def invokeStaticMethod(classType: ClassType, method: Method, args: ScalaValue*): ScalaValue = {
- companionActor !? InvokeStaticMethod(classType, method, args.toList) match {
- case Right(res: ScalaValue) =>
- res
- case Left(e: Exception) =>
- throw e
- }
+ def invokeStaticMethod(classType: ClassType, method: Method, args: Value*): Value = {
+ processMethodInvocationResult(companionActor !? InvokeStaticMethod(classType, method, args.toList))
+ }
+
+ private def processMethodInvocationResult(res: Any): Value = res match {
+ case Right(null) =>
+ null
+ case Right(res: Value) =>
+ res
+ case Left(e: Exception) =>
+ throw e
}
/**
@@ -195,8 +194,8 @@ abstract class ScalaThread private (target: ScalaDebugTarget, private[model] val
private[model] object ScalaThreadActor {
case class SuspendedFromScala(eventDetail: Int)
case class ResumeFromScala(step: Option[ScalaStep], eventDetail: Int)
- case class InvokeMethod(objectReference: ObjectReference, method: Method, args: List[ScalaValue])
- case class InvokeStaticMethod(classType: ClassType, method: Method, args: List[ScalaValue])
+ case class InvokeMethod(objectReference: ObjectReference, method: Method, args: List[Value])
+ case class InvokeStaticMethod(classType: ClassType, method: Method, args: List[Value])
case object TerminatedFromScala
def apply(thread: ScalaThread): BaseDebuggerActor = {
@@ -236,16 +235,15 @@ private[model] class ScalaThreadActor private(thread: ScalaThread) extends BaseD
try {
import scala.collection.JavaConverters._
// invoke the method
- val result = objectReference.invokeMethod(thread.threadRef, method, args.map(_.value).asJava, ObjectReference.INVOKE_SINGLE_THREADED)
+ val result = objectReference.invokeMethod(thread.threadRef, method, args.asJava, ObjectReference.INVOKE_SINGLE_THREADED)
// update the stack frames
thread.rebindScalaStackFrames()
- Right(ScalaValue(result, thread.getDebugTarget()))
+ Right(result)
} catch {
case e: Exception =>
Left(e)
}
- }
- )
+ })
case InvokeStaticMethod(classType, method, args) =>
reply(
if (!thread.isSuspended) {
@@ -255,16 +253,15 @@ private[model] class ScalaThreadActor private(thread: ScalaThread) extends BaseD
try {
import scala.collection.JavaConverters._
// invoke the method
- val result = classType.invokeMethod(thread.threadRef, method, args.map(_.value).asJava, ObjectReference.INVOKE_SINGLE_THREADED)
+ val result = classType.invokeMethod(thread.threadRef, method, args.asJava, ObjectReference.INVOKE_SINGLE_THREADED)
// update the stack frames
thread.rebindScalaStackFrames()
- Right(ScalaValue(result, thread.getDebugTarget()))
+ Right(result)
} catch {
case e: Exception =>
Left(e)
}
- }
- )
+ })
case TerminatedFromScala =>
currentStep.foreach(_.stop())
currentStep = None
@@ -3,45 +3,32 @@ package scala.tools.eclipse.debug.model
import com.sun.jdi.ClassType
import com.sun.jdi.ReferenceType
import com.sun.jdi.Type
+import com.sun.jdi.Field
+import com.sun.jdi.Value
+import com.sun.jdi.Method
/** A Reference type in the Scala debug model. Represente an array, an interface or a class type.
*/
-class ScalaReferenceType(jdiType: ReferenceType, debugTarget: ScalaDebugTarget) extends ScalaDebugElement(debugTarget) {
-
- /** Return the value of the static field with the given name.
- *
- * @throws IllegalArgumentException if the no field with the given name exists.
- */
- def fieldValue(fieldName: String): ScalaValue = {
- val field= jdiType.fieldByName(fieldName)
- if (field == null) {
- throw new IllegalArgumentException("Field '%s' doesn't exist for '%s'".format(fieldName, jdiType.name()))
- }
- ScalaValue(jdiType.getValue(field), debugTarget)
- }
+class ScalaReferenceType(jdiType: ReferenceType, debugTarget: ScalaDebugTarget) extends ScalaDebugElement(debugTarget) with HasFieldValue {
+ // Members declared in scala.tools.eclipse.debug.model.HasFieldValue
+
+ protected[model] override def referenceType = jdiType
+
+ protected[model] override def jdiFieldValue(field: Field) = jdiType.getValue(field)
+
}
/** A Class type in the Scala debug model
*/
-class ScalaClassType(jdiType: ClassType, debugTarget: ScalaDebugTarget) extends ScalaReferenceType(jdiType, debugTarget) {
+class ScalaClassType(jdiType: ClassType, debugTarget: ScalaDebugTarget) extends ScalaReferenceType(jdiType, debugTarget) with HasMethodInvocation {
+
+ // Members declared in scala.tools.eclipse.debug.model.HasMethodInvocation
+
+ protected[model] def classType() = jdiType
+
+ protected[model] def jdiInvokeMethod(method: Method, thread: ScalaThread, args: Value*) = thread.invokeStaticMethod(jdiType, method, args:_*)
- /** Invoke the static method with given name, using the given arguments.
- *
- * @throws IllegalArgumentException if no method with given name exists, or more than one.
- */
- def invokeMethod(methodName: String, thread: ScalaThread, args: ScalaValue*): ScalaValue = {
- val methods= jdiType.methodsByName(methodName)
- methods.size match {
- case 0 =>
- throw new IllegalArgumentException("Method '%s(..)' doesn't exist for '%s'".format(methodName, jdiType.name()))
- case 1 =>
- thread.invokeStaticMethod(jdiType, methods.get(0), args:_*)
- case _ =>
- throw new IllegalArgumentException("More than on method '%s(..)' for '%s'".format(methodName, jdiType.name()))
-
- }
- }
}
object ScalaType {
@@ -7,6 +7,8 @@ import org.eclipse.debug.core.model.IVariable
import com.sun.jdi.{ VoidValue, Value, StringReference, ShortValue, ObjectReference, LongValue, IntegerValue, FloatValue, DoubleValue, CharValue, ByteValue, BooleanValue, ArrayReference }
import com.sun.jdi.ClassType
import com.sun.jdi.PrimitiveValue
+import com.sun.jdi.Field
+import com.sun.jdi.Method
object ScalaValue {
@@ -127,7 +129,7 @@ class ScalaStringReference(val stringReference: StringReference, target: ScalaDe
}
-class ScalaObjectReference(val objectReference: ObjectReference, target: ScalaDebugTarget) extends ScalaValue(target) {
+class ScalaObjectReference(val objectReference: ObjectReference, target: ScalaDebugTarget) extends ScalaValue(target) with HasFieldValue with HasMethodInvocation {
import ScalaValue._
// Members declared in org.eclipse.debug.core.model.IValue
@@ -154,6 +156,18 @@ class ScalaObjectReference(val objectReference: ObjectReference, target: ScalaDe
// Members declared in scala.tools.eclipse.debug.model.ScalaValue
override def value = objectReference
+
+ // Members declared in scala.tools.eclipse.debug.model.HasFieldValue
+
+ protected[model] override def referenceType = objectReference.referenceType()
+
+ protected[model] override def jdiFieldValue(field: Field) = objectReference.getValue(field)
+
+ // Members declared in scala.tools.eclipse.debug.model.HasMethodInvocation
+
+ protected[model] override def classType = objectReference.referenceType.asInstanceOf[ClassType]
+
+ protected[model] def jdiInvokeMethod(method: Method, thread: ScalaThread, args: Value*) = thread.invokeMethod(objectReference, method, args:_*)
// -----
@@ -164,47 +178,6 @@ class ScalaObjectReference(val objectReference: ObjectReference, target: ScalaDe
ScalaDebugModelPresentation.computeDetail(fieldValue("value"))
}
- /** Invoke the method with given name, using the given arguments.
- *
- * @throws IllegalArgumentException if no method with given name exists, or more than one.
- */
- def invokeMethod(methodName: String, thread: ScalaThread, args: ScalaValue*): ScalaValue = {
- val methods= objectReference.referenceType().methodsByName(methodName)
- methods.size match {
- case 0 =>
- throw new IllegalArgumentException("Method '%s(..)' doesn't exist for '%s'".format(methodName, objectReference.referenceType().name()))
- case 1 =>
- thread.invokeMethod(objectReference, methods.get(0), args:_*)
- case _ =>
- throw new IllegalArgumentException("More than on method '%s(..)' for '%s'".format(methodName, objectReference.referenceType().name()))
- }
- }
-
- /** Invoke the method with given name and signature, using the given arguments.
- *
- * @throws IllegalArgumentException if no method with given name exists.
- */
- def invokeMethod(methodName: String, methodSignature: String, thread: ScalaThread, args: ScalaValue*): ScalaValue = {
- val method= objectReference.referenceType().asInstanceOf[ClassType].concreteMethodByName(methodName, methodSignature)
- if (method == null) {
- throw new IllegalArgumentException("Method '%s%s' doesn't exist for '%s'".format(methodName, methodSignature, objectReference.referenceType().name()))
- }
- thread.invokeMethod(objectReference, method, args:_*)
- }
-
- /** Return the value of the field with the given name.
- *
- * @throws IllegalArgumentException if the no field with the given name exists.
- */
- def fieldValue(fieldName: String): ScalaValue = {
- val field= objectReference.referenceType().fieldByName(fieldName)
- if (field == null) {
- throw new IllegalArgumentException("Field '%s' doesn't exist for '%s'".format(fieldName, objectReference.referenceType.name()))
- }
- ScalaValue(objectReference.getValue(field), target)
- }
-
-
}
class ScalaNullValue(target: ScalaDebugTarget) extends ScalaValue(target) {

0 comments on commit f05f890

Please sign in to comment.