All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scaladebugger.api.lowlevel.wrappers.StackFrameWrapper.scala Maven / Gradle / Ivy

package org.scaladebugger.api.lowlevel.wrappers

import org.scaladebugger.api.utils.Logging
import com.sun.jdi._

import scala.collection.JavaConverters._
import scala.util.{ Failure, Success, Try }

/**
 * Represents a wrapper around a stack frame, providing additional methods.
 *
 * @param _stackFrame The stack frame to wrap
 */
class StackFrameWrapper(private val _stackFrame: StackFrame) extends Logging {
  require(_stackFrame != null, "Stack frame cannot be null!")

  /**
   * Attempts to retrieve the "this" object for the underlying stack frame.
   *
   * @return Some object reference if retrieved, otherwise None
   */
  def thisObjectAsOption: Option[ObjectReference] =
    Try(_stackFrame.thisObject()).toOption

  /**
   * Extracts the value out of the try, or returns null if not available.
   *
   * @param value The value (wrapped in a Try) to extract
   *
   * @return The value instance if available, otherwise null
   */
  private def extractValue(value: Try[Value]): Value = value match {
    // Successfully retrieved local variable value, so just return it
    case Success(v) => v

    // Failed to retrieve value of local variable, so log and return null
    case Failure(ex) =>
      logger.throwable(ex)
      null
  }

  /**
   * Retrieves the specified local variable and its value for the underlying
   * stack frame.
   *
   * @param name The name of the local variable to retrieve
   *
   * @return Some tuple of local variable and value if available, otherwise None
   */
  def localVisibleVariable(name: String): Option[(LocalVariable, Value)] =
    Try(_stackFrame.visibleVariableByName(name)).toOption.map(variable =>
      variable -> extractValue(Try(_stackFrame.getValue(variable)))
    )

  /**
   * Retrieves local variables and their values for the underlying stack frame.
   *
   * @return The map of local variables paired with their respective values
   */
  def localVisibleVariableMap(): Map[LocalVariable, Value] =
    Try(_stackFrame.visibleVariables()).map(_.asScala).getOrElse(Nil)
      .map(variable =>
        variable -> extractValue(Try(_stackFrame.getValue(variable)))
      ).toMap

  /**
   * Retrieves local variables that are arguments and their values for the
   * underlying stack frame.
   *
   * @return The map of local variables paired with their respective values
   */
  def localArgumentMap(): Map[LocalVariable, Value] =
    localVisibleVariableMap().filterKeys(_.isArgument)

  /**
   * Retrieves local variables that are not arguments and their values for the
   * underlying stack frame.
   *
   * @return The map of local variables paired with their respective values
   */
  def localNonArgumentMap(): Map[LocalVariable, Value] =
    localVisibleVariableMap().filterKeys(k => !k.isArgument)

  /**
   * Retrieves the specified local variable and its value for the underlying
   * stack frame.
   *
   * @param name The name of the local variable to retrieve
   *
   * @return Some tuple of local variable and value if available, otherwise None
   */
  def thisVisibleField(name: String): Option[(Field, Value)] = {
    val stackThisObject = thisObjectAsOption.map(_.referenceType())

    stackThisObject.flatMap(stackThisObject =>
      Try(stackThisObject.fieldByName(name)).toOption
    ).map(field =>
      (field, Try(stackThisObject.get.getValue(field)).getOrElse(null))
    )
  }

  /**
   * Retrieves fields and values for the "this" object contained in the
   * underlying stack frame.
   *
   * @return The map of fields paired with their respective values
   */
  def thisVisibleFieldMap(): Map[Field, Value] = {
    val stackThisObject = thisObjectAsOption match {
      case Some(obj) => obj

      // Failed to get "this" object, so exit early
      case _ => return Map()
    }

    // Attempt to retrieve all visible fields and build a map of field -> value
    Try(stackThisObject.referenceType().visibleFields())
      .map(_.asScala).getOrElse(Nil)
      .map(field => field -> extractValue(Try(stackThisObject.getValue(field))))
      .toMap
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy