Skip to content

Commit 8d0ca5c

Browse files
committed
Apply suggested changes
1 parent 95bd38e commit 8d0ca5c

File tree

8 files changed

+40
-33
lines changed

8 files changed

+40
-33
lines changed

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/EvaluationProvider.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ private[internal] class EvaluationProvider(
9797
thisContext: ObjectReference,
9898
methodName: String,
9999
methodSignature: String,
100-
rawArgs: Array[Value],
100+
args: Array[Value],
101101
thread: ThreadReference,
102102
invokeSuper: Boolean
103103
): CompletableFuture[Value] = {
104104
val obj = JdiObject(thisContext, thread)
105-
val args = if (rawArgs == null) Seq.empty else rawArgs.toSeq.map(JdiValue(_, thread))
105+
val wrappedArgs = if (args == null) Seq.empty else args.toSeq.map(JdiValue(_, thread))
106106
val invocation = evaluationBlock {
107107
obj
108-
.invoke(methodName, methodSignature, args)
108+
.invoke(methodName, methodSignature, wrappedArgs)
109109
.recover {
110110
// if invocation throws an exception, we return that exception as the result
111111
case MethodInvocationFailed(msg, exception) => exception

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiArray.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import com.sun.jdi.Value
66

77
import scala.jdk.CollectionConverters.*
88

9-
class JdiArray(reference: ArrayReference, thread: ThreadReference) extends JdiObject(reference, thread) {
9+
class JdiArray(arrayRef: ArrayReference, thread: ThreadReference) extends JdiObject(arrayRef, thread) {
1010
def setValue(index: Int, value: Value): Unit =
11-
reference.setValue(index, value)
11+
arrayRef.setValue(index, value)
1212

13-
def setValues(values: Seq[JdiValue]): Unit = reference.setValues(values.map(_.value).asJava)
13+
def setValues(values: Seq[JdiValue]): Unit = arrayRef.setValues(values.map(_.value).asJava)
1414

15-
def getValues: Seq[JdiValue] = reference.getValues.asScala.toSeq.map(JdiValue(_, thread))
15+
def getValues: Seq[JdiValue] = arrayRef.getValues.asScala.toSeq.map(JdiValue(_, thread))
1616
}
1717

1818
object JdiArray {
19-
def apply(value: Value, thread: ThreadReference): JdiArray =
20-
new JdiArray(value.asInstanceOf[ArrayReference], thread)
19+
def apply(arrayValue: Value, thread: ThreadReference): JdiArray =
20+
new JdiArray(arrayValue.asInstanceOf[ArrayReference], thread)
2121
}

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiClass.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ private[internal] class JdiClass(
5252
Safe(cls.getValue(cls.fieldByName(fieldName))).map(JdiValue(_, thread))
5353

5454
def invokeStatic(methodName: String, args: Seq[JdiValue]): Safe[JdiValue] = {
55-
cls.methodsByName(methodName).forEach(m => println(m.signature))
5655
val method = cls.methodsByName(methodName).asScala.head
5756
invokeStatic(method, args)
5857
}
@@ -62,16 +61,16 @@ private[internal] class JdiClass(
6261
invokeStatic(method, args)
6362
}
6463

65-
protected def invokeStatic(method: Method, args: Seq[JdiValue]): Safe[JdiValue] =
64+
private def invokeStatic(method: Method, args: Seq[JdiValue]): Safe[JdiValue] =
6665
Safe(cls.invokeMethod(thread, method, args.map(_.value).asJava, ObjectReference.INVOKE_SINGLE_THREADED))
6766
.map(JdiValue(_, thread))
6867
.recoverWith(recoverInvocationException(thread))
6968
}
7069

7170
object JdiClass {
72-
def apply(classType: ReferenceType, thread: ThreadReference): JdiClass =
71+
def apply(classType: Type, thread: ThreadReference): JdiClass =
7372
new JdiClass(classType.asInstanceOf[ClassType], thread)
7473

75-
def apply(classObject: ClassObjectReference, thread: ThreadReference): JdiClass =
76-
new JdiClass(classObject.reflectedType.asInstanceOf[ClassType], thread)
74+
def apply(classObject: Value, thread: ThreadReference): JdiClass =
75+
JdiClass(classObject.asInstanceOf[ClassObjectReference].reflectedType, thread)
7776
}

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiClassLoader.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,6 @@ private[internal] class JdiClassLoader(
9090
}
9191

9292
private[internal] object JdiClassLoader {
93-
def apply(ref: ClassLoaderReference, thread: ThreadReference): JdiClassLoader =
94-
new JdiClassLoader(ref, thread)
93+
def apply(ref: Value, thread: ThreadReference): JdiClassLoader =
94+
new JdiClassLoader(ref.asInstanceOf[ClassLoaderReference], thread)
9595
}

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiFrame.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ final case class JdiFrame(thread: ThreadReference, depth: Int) {
1111
def current(): StackFrame = thread.frame(depth)
1212

1313
// it's a Safe because it can fail, but it could also be a Try
14-
def classLoader(): Safe[JdiClassLoader] = Safe {
14+
def classLoader(): Safe[JdiClassLoader] = {
1515
def getClassLoaderRecursively(depth: Int): Option[ClassLoaderReference] =
1616
if (depth == thread.frameCount) None
1717
else {
1818
Option(thread.frame(depth).location.method.declaringType.classLoader)
1919
.orElse(getClassLoaderRecursively(depth + 1))
2020
}
2121

22-
val classLoader = getClassLoaderRecursively(depth)
23-
.getOrElse(throw new Exception("Cannot find any classloader in the stack trace"))
24-
JdiClassLoader(classLoader, thread)
22+
Safe {
23+
val classLoader = getClassLoaderRecursively(depth)
24+
.getOrElse(throw new Exception("Cannot find any classloader in the stack trace"))
25+
JdiClassLoader(classLoader, thread)
26+
}
2527
}
2628

2729
// this object can be null

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiObject.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ private[internal] class JdiObject(
4545
.map(_.asString.stringValue)
4646
.recover { case _ => "" }
4747

48+
// we use a Seq instead of a Map because the ScalaEvaluator rely on the order of the fields
4849
def fields: Seq[(String, JdiValue)] =
4950
reference.referenceType.fields.asScala.toSeq
5051
.map(f => (f.name, JdiValue(reference.getValue(f), thread)))

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/JdiValue.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package ch.epfl.scala.debugadapter.internal.evaluator
33
import com.sun.jdi._
44

55
private[internal] class JdiValue(val value: Value, val thread: ThreadReference) {
6-
def asObject: JdiObject = JdiObject(value.asInstanceOf[ObjectReference], thread)
7-
def asClass: JdiClass = JdiClass(value.asInstanceOf[ClassObjectReference], thread)
8-
def asClassLoader: JdiClassLoader = JdiClassLoader(value.asInstanceOf[ClassLoaderReference], thread)
9-
def asArray: JdiArray = JdiArray(value.asInstanceOf[ArrayReference], thread)
6+
def asObject: JdiObject = JdiObject(value, thread)
7+
def asClass: JdiClass = JdiClass(value, thread)
8+
def asClassLoader: JdiClassLoader = JdiClassLoader(value, thread)
9+
def asArray: JdiArray = JdiArray(value, thread)
1010
def asString: JdiString = new JdiString(value.asInstanceOf[StringReference], thread)
1111

1212
def unboxIfPrimitive: Safe[JdiValue] = {
@@ -15,12 +15,13 @@ private[internal] class JdiValue(val value: Value, val thread: ThreadReference)
1515
val typeName = ref.referenceType.name
1616
JdiValue.unboxMethods
1717
.get(typeName)
18-
.map(methodName => asObject.invoke(methodName, Nil))
18+
.map(methodName => JdiObject(ref, thread).invoke(methodName, Nil))
1919
.getOrElse(Safe(this))
2020
case _ => Safe(this)
2121
}
2222
}
2323

24+
// The ref types are used by the compiler to mutate local vars in nested methods
2425
def derefIfRef: JdiValue =
2526
value match {
2627
case ref: ObjectReference if JdiValue.refTypes.contains(ref.referenceType.name) =>

modules/core/src/main/scala/ch/epfl/scala/debugadapter/internal/evaluator/ScalaEvaluator.scala

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ private[internal] class ScalaEvaluator(
106106
): Safe[(Seq[JdiString], Seq[JdiValue])] = {
107107
def extractVariablesFromFrame(): Safe[(Seq[JdiString], Seq[JdiValue])] = {
108108
val localVariables = frameRef.variablesAndValues().map { case (variable, value) => (variable.name, value) }
109+
// Exclude the this object if there already is a local $this variable
110+
// The Scala compiler uses `$this` in the extension methods of AnyVal classes
109111
val thisObject = frameRef.thisObject().filter(_ => !localVariables.contains("$this")).map("$this".->)
110112
(localVariables ++ thisObject)
111113
.map { case (name, value) =>
@@ -148,17 +150,19 @@ private[internal] class ScalaEvaluator(
148150
}
149151

150152
private def updateVariables(variableArray: JdiArray, frame: JdiFrame): Safe[Unit] = {
151-
val unboxedValues = frame
153+
frame
152154
.variables()
153155
.zip(variableArray.getValues)
154-
.map { case (variable, value) =>
155-
if (variable.`type`.isInstanceOf[PrimitiveType]) value.unboxIfPrimitive
156-
else Safe(value)
156+
.map {
157+
case (variable, value) if variable.`type`.isInstanceOf[PrimitiveType] => value.unboxIfPrimitive
158+
case (_, value) => Safe(value)
157159
}
158160
.traverse
159-
160-
for (values <- unboxedValues)
161-
yield for ((variable, value) <- frame.variables().zip(values))
162-
frame.setVariable(variable, value)
161+
.map { values =>
162+
frame
163+
.variables()
164+
.zip(values)
165+
.foreach { case (variable, value) => frame.setVariable(variable, value) }
166+
}
163167
}
164168
}

0 commit comments

Comments
 (0)