Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework JDI based implementation #1

Merged
merged 1 commit into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
addSbtPlugin("org.scala-debugger" % "sbt-jdi-tools" % "1.1.1")
20 changes: 0 additions & 20 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JavaReflection.scala

This file was deleted.

43 changes: 43 additions & 0 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiClass.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ch.epfl.scala.decoder.jdi

import ch.epfl.scala.decoder.binary.*

import java.util as ju
import scala.jdk.CollectionConverters.*
import scala.util.control.NonFatal

/* A class or interface */
class JdiClass(ref: com.sun.jdi.ReferenceType) extends JdiType(ref) with ClassType:
override def classLoader: BinaryClassLoader = JdiClassLoader(ref.classLoader)

override def superclass: Option[ClassType] = ref match
case cls: com.sun.jdi.ClassType => Some(JdiClass(cls.superclass))
case _ => None

override def interfaces: Seq[ClassType] = ref match
case cls: com.sun.jdi.ClassType => cls.interfaces.asScala.toSeq.map(JdiClass.apply)
case interface: com.sun.jdi.InterfaceType => interface.superinterfaces.asScala.toSeq.map(JdiClass.apply)

override def isInterface = ref.isInstanceOf[com.sun.jdi.InterfaceType]

override def sourceLines: Option[SourceLines] = Some(SourceLines(sourceName, allLineLocations.map(_.lineNumber)))

override def method(name: String, sig: String): Option[Method] =
visibleMethods.find(_.signedName == SignedName(name, sig))

override def declaredMethod(name: String, sig: String): Option[Method] =
declaredMethods.find(_.signedName == SignedName(name, sig))

override def declaredMethods: Seq[Method] = ref.methods.asScala.map(JdiMethod(_)).toSeq

override def declaredField(name: String): Option[Field] = None

private[jdi] def constantPool: ConstantPool = ConstantPool(ref.constantPool)

private def allLineLocations: Seq[com.sun.jdi.Location] =
try ref.allLineLocations.asScala.toSeq
catch case e: com.sun.jdi.AbsentInformationException => Seq.empty

private[jdi] def sourceName: String = ref.sourceName

private def visibleMethods: Seq[JdiMethod] = ref.visibleMethods.asScala.map(JdiMethod(_)).toSeq
15 changes: 4 additions & 11 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiClassLoader.scala
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
package ch.epfl.scala.decoder.jdi

import ch.epfl.scala.decoder.binary
import ch.epfl.scala.decoder.binary.ClassType

import java.util as ju
import scala.jdk.CollectionConverters.*
import ch.epfl.scala.decoder.binary.BinaryClassLoader

class JdiClassLoader(obj: Any)
extends binary.BinaryClassLoader
with JavaReflection(obj, "com.sun.jdi.ClassLoaderReference"):
override def loadClass(name: String): ClassType =
visibleClasses.find(_.name == name).get

private def visibleClasses: Seq[JdiReferenceType] =
invokeMethod[ju.List[Any]]("visibleClasses").asScala.map(JdiReferenceType.apply(_)).toSeq
class JdiClassLoader(classLoader: com.sun.jdi.ClassLoaderReference) extends BinaryClassLoader:
override def loadClass(name: String): JdiClass =
JdiClass(classLoader.visibleClasses.asScala.find(_.name == name).get)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ch.epfl.scala.decoder.jdi

import ch.epfl.scala.decoder.binary.*

class JdiLocalVariable(obj: Any) extends JavaReflection(obj, "com.sun.jdi.LocalVariable") with Parameter:
override def name: String = invokeMethod("name")
class JdiLocalVariable(localVariable: com.sun.jdi.LocalVariable) extends Parameter:
override def name: String = localVariable.name
override def sourceLines: Option[SourceLines] = None
override def `type`: Type = JdiType(invokeMethod("type"))
override def `type`: Type = JdiType(localVariable.`type`)
4 changes: 0 additions & 4 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiLocation.scala

This file was deleted.

33 changes: 15 additions & 18 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiMethod.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,37 @@ import java.lang.reflect.InvocationTargetException
import scala.jdk.CollectionConverters.*
import java.util as ju

class JdiMethod(val obj: Any) extends JavaReflection(obj, "com.sun.jdi.Method") with Method:
override def name: String = invokeMethod("name")
class JdiMethod(method: com.sun.jdi.Method) extends Method:
override def name: String = method.name

override def declaringClass: JdiReferenceType =
JdiReferenceType(invokeMethod("declaringType"))
override def declaringClass: JdiClass = JdiClass(method.declaringType)

override def allParameters: Seq[Parameter] =
invokeMethod[java.util.List[Object]]("arguments").asScala.toSeq.map(JdiLocalVariable.apply(_))
method.arguments.asScala.toSeq.map(JdiLocalVariable.apply(_))

override def returnType: Option[Type] =
try Some(JdiType(invokeMethod("returnType")))
catch case e: Exception if e.getClass.getName == "com.sun.jdi.ClassNotLoadedException" => None
try Some(JdiType(method.returnType))
catch case e: com.sun.jdi.ClassNotLoadedException => None

override def returnTypeName: String = invokeMethod("returnTypeName")
override def returnTypeName: String = method.returnTypeName

override def isBridge: Boolean = invokeMethod("isBridge")
override def isBridge: Boolean = method.isBridge

override def isStatic: Boolean = invokeMethod("isStatic")
override def isStatic: Boolean = method.isStatic

override def isFinal: Boolean = invokeMethod("isFinal")
override def isFinal: Boolean = method.isFinal

override def isConstructor: Boolean = invokeMethod("isConstructor")
override def isConstructor: Boolean = method.isConstructor

override def sourceLines: Option[SourceLines] =
Some(SourceLines(declaringClass.sourceName, allLineLocations.map(_.lineNumber)))

override def signedName: SignedName = SignedName(name, signature)

override def instructions: Seq[Instruction] =
ByteCodes.parse(bytecodes, declaringClass.constantPool)
override def instructions: Seq[Instruction] = ByteCodes.parse(bytecodes, declaringClass.constantPool)

private def allLineLocations: Seq[JdiLocation] =
invokeMethod[ju.List[Any]]("allLineLocations").asScala.map(JdiLocation.apply(_)).toSeq
private def allLineLocations: Seq[com.sun.jdi.Location] = method.allLineLocations.asScala.toSeq

private def signature: String = invokeMethod("signature")
private def signature: String = method.signature

private def bytecodes: Array[Byte] = invokeMethod("bytecodes")
private def bytecodes: Array[Byte] = method.bytecodes
55 changes: 0 additions & 55 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiReferenceType.scala

This file was deleted.

4 changes: 2 additions & 2 deletions src/main/scala/ch/epfl/scala/decoder/jdi/JdiType.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ch.epfl.scala.decoder.jdi
import ch.epfl.scala.decoder.binary.*

class JdiType(obj: Any, className: String = "com.sun.jdi.Type") extends JavaReflection(obj, className) with Type:
override def name: String = invokeMethod("name")
class JdiType(tpe: com.sun.jdi.Type) extends Type:
override def name: String = tpe.name
override def sourceLines: Option[SourceLines] = None