Skip to content

Commit

Permalink
Debugger WIP 16
Browse files Browse the repository at this point in the history
  • Loading branch information
Fantoom committed Aug 2, 2024
1 parent 29f73b1 commit 350b936
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
import com.intellij.xdebugger.frame.*
import com.jetbrains.rd.framework.util.adviseSuspend
import com.jetbrains.rd.util.lifetime.Lifetime
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.apache.xml.resolver.helpers.FileURL
Expand All @@ -31,15 +34,15 @@ import javax.swing.Icon
import kotlin.collections.HashMap
import kotlin.io.path.Path

class PowerShellDebugSession(val client: PSDebugClient, val server: IDebugProtocolServer, val session: XDebugSession, val coroutineScope: CoroutineScope) {
class PowerShellDebugSession(val client: PSDebugClient, val server: IDebugProtocolServer, val session: XDebugSession, val coroutineScope: CoroutineScope, val xDebugSession: XDebugSession) {
val breakpointMap = mutableMapOf<String, MutableMap<Int, XLineBreakpoint<XBreakpointProperties<*>>>>()

init{
client.debugStopped.adviseSuspend(Lifetime.Eternal, Dispatchers.EDT){
args ->
val stack = server.stackTrace(StackTraceArguments().apply { threadId = args!!.threadId }).await()
thisLogger().info(stack.toString())
session.positionReached(PowerShellSuspendContext(stack, server, coroutineScope, args!!.threadId))
session.positionReached(PowerShellSuspendContext(stack, server, coroutineScope, args!!.threadId, xDebugSession))
}
}

Expand Down Expand Up @@ -154,18 +157,19 @@ class PowerShellDebugSession(val client: PSDebugClient, val server: IDebugProtoc

class PowerShellExecutionStack(val stackResponse: StackTraceResponse,
val server: IDebugProtocolServer,
val coroutineScope: CoroutineScope): XExecutionStack("PowerShell Debug Execution Stack") {
val coroutineScope: CoroutineScope, val xDebugSession: XDebugSession): XExecutionStack("PowerShell Debug Execution Stack") {
override fun getTopFrame(): XStackFrame? {
return stackResponse.stackFrames.firstOrNull()?.let { PowerShellStackFrame(it, server, coroutineScope) }
return stackResponse.stackFrames.firstOrNull()?.let { PowerShellStackFrame(it, server, coroutineScope, xDebugSession) }
}

override fun computeStackFrames(firstFrameIndex: Int, container: XStackFrameContainer?) {
container?.addStackFrames(stackResponse.stackFrames.drop(firstFrameIndex).map { PowerShellStackFrame(it, server, coroutineScope) }, true)
container?.addStackFrames(stackResponse.stackFrames.drop(firstFrameIndex).map { PowerShellStackFrame(it, server, coroutineScope, xDebugSession) }, true)
}

}

class PowerShellStackFrame(val stack: StackFrame, val server: IDebugProtocolServer, val coroutineScope: CoroutineScope): XStackFrame() {
class PowerShellStackFrame(val stack: StackFrame, val server: IDebugProtocolServer, val coroutineScope: CoroutineScope, val xDebugSession: XDebugSession): XStackFrame() {

override fun getSourcePosition(): XSourcePosition? {
var file = VfsUtil.findFile(Path(stack.source?.path ?: return null), false)
return XDebuggerUtil.getInstance().createPosition(file, stack.line - 1, stack.column)
Expand All @@ -190,15 +194,15 @@ class PowerShellStackFrame(val stack: StackFrame, val server: IDebugProtocolServ
val localVariables = server.variables(VariablesArguments().apply {
variablesReference = localScope.variablesReference
}).await()
localVariables.variables.forEach { list.add(it.name, PowerShellDebuggerVariableValue(it, localScope.variablesReference, server, coroutineScope)) }
localVariables.variables.forEach { list.add(it.name, PowerShellDebuggerVariableValue(it, localScope.variablesReference, server, coroutineScope, xDebugSession)) }

scopesResponse.scopes.filter { x -> x.name.lowercase() != "local" }.forEach {
val variableRef = it.variablesReference
val groupName = it.name
val variables = server.variables(VariablesArguments().apply {
variablesReference = variableRef
}).await()
val group = PowerShellVariableGroup(groupName, variables, variableRef, server, coroutineScope)
val group = PowerShellVariableGroup(groupName, variables, variableRef, server, coroutineScope, xDebugSession)
list.addBottomGroup(group)
}

Expand All @@ -209,21 +213,32 @@ class PowerShellStackFrame(val stack: StackFrame, val server: IDebugProtocolServ

class PowerShellDebuggerVariableValue(val variable: Variable, val parentReference: Int?,
val server: IDebugProtocolServer,
val coroutineScope: CoroutineScope) : XNamedValue(variable.name ?: "") {
val coroutineScope: CoroutineScope, val xDebugSession: XDebugSession) : XNamedValue(variable.name ?: "") {

init {
val variablesCache = (xDebugSession.suspendContext as PowerShellSuspendContext).variablesCache
variablesCache.getOrDefault((Pair(parentReference, variable.name)), null)?.let {
variable.value = it.value
variable.type = it.type ?: variable.type
variable.variablesReference = variable.variablesReference
variable.namedVariables = it.namedVariables
variable.indexedVariables = it.indexedVariables
}
}

override fun computePresentation(node: XValueNode, place: XValuePlace) {
//val kind = variable.presentationHint.kind
var icon: Icon? = IconManager.getInstance().getPlatformIcon(PlatformIcons.Variable)

node.setPresentation(icon, "string", variable.value, variable.variablesReference != 0)
node.setPresentation(icon, variable.type, variable.value, variable.variablesReference != 0)
}

override fun computeChildren(node: XCompositeNode) {
coroutineScope.launch {
if (variable.variablesReference != 0) {
val list = XValueChildrenList()
server.variables(VariablesArguments().apply { variablesReference = variable.variablesReference })
.await().variables.forEach { list.add(it.name, PowerShellDebuggerVariableValue(it, variable.variablesReference, server, coroutineScope)) }
.await().variables.forEach { list.add(it.name, PowerShellDebuggerVariableValue(it, variable.variablesReference, server, coroutineScope, xDebugSession)) }
node.addChildren(list, true)
}
}
Expand All @@ -243,8 +258,9 @@ class PowerShellDebuggerVariableValue(val variable: Variable, val parentReferenc
if(parentReference !is Int)
return
coroutineScope.launch {
val variablesCache = (xDebugSession.suspendContext as PowerShellSuspendContext).variablesCache
try {
var response = server.setVariable(SetVariableArguments().apply {
val response = server.setVariable(SetVariableArguments().apply {
variablesReference = parentReference
name = variable.name
value = expression.expression
Expand All @@ -254,10 +270,10 @@ class PowerShellDebuggerVariableValue(val variable: Variable, val parentReferenc
variable.variablesReference = response.variablesReference ?: variable.variablesReference
variable.namedVariables = response.namedVariables ?: variable.namedVariables
variable.indexedVariables = response.indexedVariables ?: variable.indexedVariables
variablesCache[(Pair(parentReference, variable.name))] = variable

callback.valueModified()
}
catch (e: Exception) {
} catch (e: Exception) {
callback.errorOccurred(e.message ?: e.javaClass.simpleName)
}
}
Expand All @@ -270,23 +286,29 @@ class PowerShellDebuggerVariableValue(val variable: Variable, val parentReferenc
}
}

class PowerShellVariableGroup(val groupName: String, val variable: VariablesResponse, val parentReference: Int, val server: IDebugProtocolServer, val coroutineScope: CoroutineScope): XValueGroup(groupName){
class PowerShellVariableGroup(val groupName: String, val variable: VariablesResponse, val parentReference: Int,
val server: IDebugProtocolServer,
val coroutineScope: CoroutineScope,
val xDebugSession: XDebugSession): XValueGroup(groupName){
override fun computeChildren(node: XCompositeNode) {
val list = XValueChildrenList()
variable.variables.forEach {
list.add(it.name, PowerShellDebuggerVariableValue(it, parentReference, server, coroutineScope))
list.add(it.name, PowerShellDebuggerVariableValue(it, parentReference, server, coroutineScope, xDebugSession))
}
node.addChildren(list, true)
}
}

class PowerShellSuspendContext(val stack: StackTraceResponse, val server: IDebugProtocolServer, val coroutineScope: CoroutineScope, val threadId: Int = 0):XSuspendContext(){
class PowerShellSuspendContext(val stack: StackTraceResponse, val server: IDebugProtocolServer,
val coroutineScope: CoroutineScope,
val threadId: Int = 0, val xDebugSession: XDebugSession):XSuspendContext(){

val variablesCache: MutableMap<Pair<Int, String>, Variable> = mutableMapOf()
override fun getExecutionStacks(): Array<XExecutionStack> {
return arrayOf(PowerShellExecutionStack(stack, server, coroutineScope))
return arrayOf(PowerShellExecutionStack(stack, server, coroutineScope, xDebugSession))
}

override fun getActiveExecutionStack(): XExecutionStack {
return PowerShellExecutionStack(stack, server, coroutineScope)
return PowerShellExecutionStack(stack, server, coroutineScope, xDebugSession)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class PowershellDebuggerEvaluator(val server: IDebugProtocolServer, val stackFra
type = result.type
presentationHint = result.presentationHint
}
callback.evaluated(PowerShellDebuggerVariableValue(variable, null, server, coroutineScope))
callback.evaluated(PowerShellDebuggerVariableValue(variable, null, server, coroutineScope, stackFrame.xDebugSession))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,6 @@ class PowerShellScriptCommandLineState(
val InOutPair = processRunner.establishDebuggerConnection()
val process = processRunner.getProcess() ?: return@runBlocking null
val handler = KillableProcessHandler(process, "PowerShellEditorService")
/* val handler = object:KillableProcessHandler(process, "PowerShellEditorService"){
override fun readerOptions(): BaseOutputReader.Options {
return object:BaseOutputReader.Options()
{
override fun splitToLines(): Boolean {
return true
}
override fun sendIncompleteLines(): Boolean {
return true
}
override fun policy(): BaseDataReader.SleepingPolicy {
return BaseDataReader.SleepingPolicy.NON_BLOCKING
}
}
}
}*/
val console = TerminalExecutionConsole(environment.project, handler)
handler.startNotify()
val session = environment.getUserData(XSessionKey)
Expand All @@ -167,7 +149,7 @@ class PowerShellScriptCommandLineState(
}
}
private fun processDebuging(inputStream: InputStream, outputStream: OutputStream, debugSession: XDebugSession){
val targetPath = runConfiguration.scriptPath //"""C:\Users\Sergey.Vardanyan\IdeaProjects\powershellTest\test.ps1"""
val targetPath = runConfiguration.scriptPath

val client = PSDebugClient(debugSession)
val launcher: Launcher<IDebugProtocolServer> = DSPLauncher.createClientLauncher(client, inputStream, outputStream)
Expand All @@ -184,7 +166,7 @@ class PowerShellScriptCommandLineState(

val scope = PluginProjectRoot.getInstance(environment.project).coroutineScope

val powerShellDebugSession = PowerShellDebugSession(client, remoteProxy, debugSession, scope)
val powerShellDebugSession = PowerShellDebugSession(client, remoteProxy, debugSession, scope, debugSession)
environment.putUserData(ClientSessionKey, powerShellDebugSession)
val allBreakpoints = XDebuggerManager.getInstance(environment.project).breakpointManager.getBreakpoints(PowerShellBreakpointType::class.java)
allBreakpoints.filter{x -> x.sourcePosition != null && x.sourcePosition!!.file.exists() && x.sourcePosition!!.file.isValid}
Expand Down

0 comments on commit 350b936

Please sign in to comment.