Skip to content

Commit

Permalink
feat(debugger): enhance debugger with breakpoint handling and UI impr…
Browse files Browse the repository at this point in the history
…ovements #183

- Add breakpoint handlers and properties for Shire debugger.
- Improve debugger UI with execution console and stack frame presentation.
- Refactor position manager and stack frame logic for better debugging support.
  • Loading branch information
phodal committed Jan 7, 2025
1 parent 47d2b71 commit 743f4ca
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package com.phodal.shirelang.debugger

import com.intellij.execution.ExecutionException
import com.intellij.execution.ExecutionManager
import com.intellij.execution.configurations.RunProfile
import com.intellij.execution.configurations.RunProfileState
import com.intellij.execution.configurations.RunnerSettings
import com.intellij.execution.executors.DefaultDebugExecutor
import com.intellij.execution.executors.DefaultRunExecutor
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.runners.GenericProgramRunner
import com.intellij.execution.ui.ExecutionConsole
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.xdebugger.XDebugProcess
import com.intellij.xdebugger.XDebugProcessStarter
import com.intellij.xdebugger.XDebugSession
import com.intellij.xdebugger.XDebuggerManager
import com.intellij.xdebugger.breakpoints.XBreakpointHandler
import com.intellij.xdebugger.breakpoints.XBreakpointProperties
import com.intellij.xdebugger.breakpoints.XLineBreakpoint
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
import com.phodal.shirelang.run.ShireConfiguration

/// refs to: https://github.com/KronicDeth/intellij-elixir/pull/643/files#diff-b1ba5c87ca6f66a455e4c1539cb2d99a62722d067a3d9e8043b290426cea5470
Expand All @@ -35,10 +37,50 @@ class ShireDebugRunner : GenericProgramRunner<RunnerSettings>() {
}
}

class ShireDebugProcess(session: XDebugSession, environment: ExecutionEnvironment) : XDebugProcess(session) {
class ShireDebugProcess(private val xDebugSession: XDebugSession, private val environment: ExecutionEnvironment) :
XDebugProcess(xDebugSession) {
override fun createConsole(): ExecutionConsole = debuggedExecutionResult.executionConsole

private val debuggableConfiguration: ShireConfiguration get() = xDebugSession.runProfile as ShireConfiguration
private val debuggedExecutionResult by lazy {
environment.executor.let { executor ->
debuggableConfiguration
.getState(executor, environment)
.execute(executor, environment.runner)!!
}
}

private val breakpointHandlers = arrayOf<XBreakpointHandler<*>>(ShireBreakpointHandler(this))
override fun getBreakpointHandlers(): Array<XBreakpointHandler<*>> = breakpointHandlers

fun addBreakpoint(breakpoint: XLineBreakpoint<ShireBpProperties>) {

}

fun removeBreakpoint(breakpoint: XLineBreakpoint<ShireBpProperties>) {

}

override fun getEditorsProvider(): XDebuggerEditorsProvider {
return ShireDebuggerEditorsProvider()
}
}

class ShireBreakpointHandler(val process: ShireDebugProcess) :
XBreakpointHandler<XLineBreakpoint<ShireBpProperties>>(ShireLineBreakpointType::class.java) {
override fun registerBreakpoint(breakpoint: XLineBreakpoint<ShireBpProperties>) {
process.addBreakpoint(breakpoint)
}

override fun unregisterBreakpoint(breakpoint: XLineBreakpoint<ShireBpProperties>, temporary: Boolean) {
process.removeBreakpoint(breakpoint)
}
}

class ShireBpProperties : XBreakpointProperties<ShireBpProperties>() {
override fun getState(): ShireBpProperties = this
override fun loadState(state: ShireBpProperties) {}
}


val RUNNER_ID: String = "ShireProgramRunner"
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ class ShireDebugSettings : XDebuggerSettings<ShireDebugSettings>("shire"), Gette

var breakOnPanic: Boolean = true
override fun createConfigurables(category: DebuggerSettingsCategory): MutableCollection<out Configurable> {
// when(category) {
// DebuggerSettingsCategory.ROOT -> TODO()
// DebuggerSettingsCategory.GENERAL -> TODO()
// DebuggerSettingsCategory.DATA_VIEWS -> TODO()
// DebuggerSettingsCategory.STEPPING -> TODO()
// DebuggerSettingsCategory.HOTSWAP -> TODO()
// }

val config = SimpleConfigurable.create(
"ShireDebugSettings",
"Shire Debugger",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ShireDebuggerEditorsProvider: XDebuggerEditorsProviderBase() {
override fun getFileType(): FileType = ShireFileType.INSTANCE

override fun createExpressionCodeFragment(project: Project, text: String, context: PsiElement?, isPhysical: Boolean): PsiFile {
val name = "fragment" + ShireFileType.INSTANCE.defaultExtension
val name = "fragment" + "." + ShireFileType.INSTANCE.defaultExtension
val viewProvider = PsiManagerEx.getInstanceEx(project).fileManager.createFileViewProvider(
LightVirtualFile(name, ShireFileType.INSTANCE, text), isPhysical)
return ShireFile(viewProvider)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ package com.phodal.shirelang.debugger
import com.intellij.openapi.fileTypes.FileTypeRegistry
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.xdebugger.breakpoints.XLineBreakpointTypeBase
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
import com.phodal.shirelang.ShireFileType

class ShireLineBreakpointType : XLineBreakpointTypeBase(ID, TITLE, ShireDebuggerEditorsProvider()) {
class ShireLineBreakpointType : XLineBreakpointType<ShireBpProperties>(ID, TITLE) {
override fun canPutAt(file: VirtualFile, line: Int, project: Project): Boolean {
return canPutAt(project, file, line)
}

override fun createBreakpointProperties(file: VirtualFile, line: Int): ShireBpProperties = ShireBpProperties()


fun canPutAt(project: Project, file: VirtualFile, line: Int): Boolean {
// val shireFile = PsiManager.getInstance(project).findFile(file) as? ShireFile ?: return false
// val findLeafElementAt = shireFile.node.findLeafElementAt(line)?.elementType
// findLeafElementAt?.let {
// return true
// }
//
// return false
return (FileTypeRegistry.getInstance().isFileOfType(file, ShireFileType.INSTANCE))
}


companion object {
private const val ID = "the-shire-line"
private const val TITLE = "Shire Breakpoints"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
package com.phodal.shirelang.debugger

import com.intellij.debugger.MultiRequestPositionManager
import com.intellij.debugger.PositionManager
import com.intellij.debugger.PositionManagerFactory
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.*
import com.intellij.debugger.engine.DebugProcess
import com.intellij.debugger.engine.PositionManagerWithMultipleStackFrames
import com.intellij.debugger.engine.evaluation.EvaluationContext
import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.debugger.requests.ClassPrepareRequestor
import com.intellij.openapi.fileTypes.FileType
import com.intellij.util.ThreeState
import com.phodal.shirelang.ShireFileType
import com.phodal.shirelang.psi.ShireFile
import com.sun.jdi.Location
import com.sun.jdi.ReferenceType
import com.sun.jdi.request.ClassPrepareRequest
import com.phodal.shirelang.ShireFileType

class ShirePositionManagerFactory : PositionManagerFactory() {
override fun createPositionManager(process: DebugProcess): PositionManager? {
return ShirePositionManager(process)
}
}

class ShirePositionManager(private val process: DebugProcess) : MultiRequestPositionManager,
class ShirePositionManager(private val debugProcess: DebugProcess) : MultiRequestPositionManager,
PositionManagerWithMultipleStackFrames {
override fun getAcceptedFileTypes(): Set<FileType> = setOf(ShireFileType.INSTANCE)
override fun getSourcePosition(location: Location?): SourcePosition? {
// return SourcePosition.createFromLine(debugProcess.project, location?.sourcePath, location?.lineNumber)
return null
}

Expand All @@ -38,25 +37,28 @@ class ShirePositionManager(private val process: DebugProcess) : MultiRequestPosi
}

override fun createPrepareRequest(
requestor: ClassPrepareRequestor,
classPrepareRequestor: ClassPrepareRequestor,
sourcePosition: SourcePosition,
): ClassPrepareRequest? {
return null
}
): ClassPrepareRequest? = createPrepareRequests(classPrepareRequestor, sourcePosition).firstOrNull()

override fun evaluateCondition(
context: EvaluationContext,
frame: StackFrameProxyImpl,
location: Location,
expression: String,
): ThreeState {
return ThreeState.UNSURE
}
): ThreeState = ThreeState.UNSURE

override fun createPrepareRequests(
requestor: ClassPrepareRequestor, position: SourcePosition,
): MutableList<ClassPrepareRequest> {
// val file = position.file
val file = position.file
if (file !is ShireFile) {
throw NoDataException.INSTANCE
}

// val xBreakpoint = requestor.asSafely<Breakpoint<*>>()?.xBreakpoint
// val xSession = debugProcess.asSafely<DebugProcessImpl>()?.xdebugProcess?.session.asSafely<XDebugSessionImpl>()

return mutableListOf()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,53 @@
package com.phodal.shirelang.debugger

import com.intellij.icons.AllIcons
import com.intellij.openapi.Disposable
import com.intellij.ui.ColoredTextContainer
import com.intellij.ui.SimpleTextAttributes
import com.intellij.xdebugger.XSourcePosition
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
import com.intellij.xdebugger.frame.XExecutionStack
import com.intellij.xdebugger.frame.XStackFrame
import com.intellij.xdebugger.frame.XSuspendContext

class ShireStackFrame(
val functionName: String,
val shireStackFrame: ShireStackFrame?,
val process: ShireDebugProcess,
) : XStackFrame(), Disposable {
override fun customizePresentation(component: ColoredTextContainer) {
// todo
component.append("some title", SimpleTextAttributes.REGULAR_ATTRIBUTES)
component.setIcon(AllIcons.Debugger.Frame)
}

override fun dispose() {

}
}
}

class ShireDebugEvaluator : XDebuggerEvaluator() {
override fun evaluate(expression: String, callback: XEvaluationCallback, expressionPosition: XSourcePosition?) {
//// todo
}
}

class ShireSuspendContext(val process: ShireDebugProcess): XSuspendContext() {
private val executionStacks: Array<XExecutionStack> = arrayOf(
ExecutionStack(process)
)

override fun getActiveExecutionStack(): XExecutionStack? = executionStacks.firstOrNull()
override fun getExecutionStacks(): Array<XExecutionStack> = executionStacks
}

class ExecutionStack(private val process: ShireDebugProcess) :
XExecutionStack("SomeId") {
private val stackFrames: List<ShireStackFrame> = listOf(
ShireStackFrame(process)
)

override fun getTopFrame(): XStackFrame? = stackFrames.firstOrNull()

override fun computeStackFrames(firstFrameIndex: Int, container: XStackFrameContainer) {
container.addStackFrames(stackFrames, true)
}
}

0 comments on commit 743f4ca

Please sign in to comment.