Skip to content

Commit

Permalink
Add debugger runner and breakpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Fantoom authored and ForNeVeR committed Aug 16, 2024
1 parent 1364eba commit 3ab332b
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.intellij.plugin.powershell.ide.debugger

import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.xdebugger.XDebugSession
import com.intellij.xdebugger.breakpoints.XBreakpointHandler
import com.intellij.xdebugger.breakpoints.XBreakpointProperties
import com.intellij.xdebugger.breakpoints.XBreakpointType
import com.intellij.xdebugger.breakpoints.XLineBreakpoint

class PowerShellBreakpointHandler(powerShellDebugProcess: PowerShellDebugProcess, breakpointTypeClass: Class<out XBreakpointType<XLineBreakpoint<XBreakpointProperties<*>>, *>>): XBreakpointHandler<XLineBreakpoint<XBreakpointProperties<*>>>(
breakpointTypeClass
) {
val myPowerShellDebugProcess = powerShellDebugProcess;

override fun registerBreakpoint(breakpoint: XLineBreakpoint<XBreakpointProperties<*>>) {
val sourcePosition = breakpoint.sourcePosition
if (sourcePosition == null || !sourcePosition.file.exists() || !sourcePosition.file.isValid) {
return
}
val file = sourcePosition.file
val project: Project = myPowerShellDebugProcess.getSession().getProject()
val fileURL: String = getFileURL(file)
val lineNumber: Int = breakpoint.line
if (lineNumber == -1) {
//myXsltDebugProcess.getSession().setBreakpointInvalid(breakpoint, "Unsupported breakpoint position")
return
}
/*try {
val manager: BreakpointManager = myPowerShellDebugProcess.getBreakpointManager()
var bp: Breakpoint
if ((manager.getBreakpoint(fileURL, lineNumber).also { bp = it }) != null) {
bp.setEnabled(true)
} else {
manager.setBreakpoint(fileURL, lineNumber)
}
} catch (ignore: DebuggerStoppedException) {
} catch (e: VMPausedException) {
val session: XDebugSession = myXsltDebugProcess.getSession()
session.reportMessage(
XsltDebuggerBundle.message("notification.content.target.vm.not.responding.breakpoint.can.not.be.set"),
MessageType.ERROR
)
session.setBreakpointInvalid(breakpoint, "Target VM is not responding. Breakpoint can not be set")
}*/
}

override fun unregisterBreakpoint(breakpoint: XLineBreakpoint<XBreakpointProperties<*>>, temporary: Boolean) {
TODO("Not yet implemented")
}

fun getFileURL(file: VirtualFile?): String {
return VfsUtil.virtualToIoFile(file!!).toURI().toASCIIString()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.intellij.plugin.powershell.ide.debugger

import com.intellij.ide.highlighter.XmlFileType
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.plugin.powershell.PowerShellFileType
import com.intellij.plugin.powershell.ide.MessagesBundle
import com.intellij.psi.PsiDocumentManager
import com.intellij.xdebugger.breakpoints.XBreakpointProperties
import com.intellij.xdebugger.breakpoints.XLineBreakpointType

//XsltDebuggerBundle.message("title.xslt.breakpoints")
class PowerShellBreakpointType : XLineBreakpointType<XBreakpointProperties<*>>("powershell", MessagesBundle.message("powershell.debugger.breakpoints.title")) {
override fun canPutAt(file: VirtualFile, line: Int, project: Project): Boolean {
val document = FileDocumentManager.getInstance().getDocument(file) ?: return false

val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return false
val fileType = psiFile.fileType
if (fileType != PowerShellFileType.INSTANCE) {
return false
}
return true
}
override fun createBreakpointProperties(file: VirtualFile, line: Int): XBreakpointProperties<*>? {
return null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.intellij.plugin.powershell.ide.debugger

import com.intellij.execution.ExecutionResult
import com.intellij.execution.ui.ExecutionConsole
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Key
import com.intellij.xdebugger.XDebugProcess
import com.intellij.xdebugger.XDebugSession
import com.intellij.xdebugger.breakpoints.XBreakpointHandler
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider

class PowerShellDebugProcess(session: XDebugSession, executionResult: ExecutionResult) : XDebugProcess(session), Disposable {

val KEY: Key<PowerShellDebugProcess> = Key.create("com.intellij.plugin.powershell.ide.debugger.PowerShellDebugProcess")

val myProcessHandler = executionResult.processHandler
init {
myProcessHandler.putUserData(KEY, this)
}
val myExecutionConsole = executionResult.executionConsole
val myEditorsProvider = PowerShellDebuggerEditorsProvider()
init {
com.intellij.openapi.util.Disposer.register(myExecutionConsole, this)
}

private val myXBreakpointHandlers = arrayOf<XBreakpointHandler<*>>(
PowerShellBreakpointHandler(
this,
PowerShellBreakpointType::class.java
),
)

override fun createConsole(): ExecutionConsole {
return myExecutionConsole
}
override fun getEditorsProvider(): XDebuggerEditorsProvider {
return myEditorsProvider
}

override fun getBreakpointHandlers(): Array<XBreakpointHandler<*>> {
return myXBreakpointHandlers
}

override fun dispose() {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.intellij.plugin.powershell.ide.debugger

import com.intellij.openapi.editor.Document
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.project.Project
import com.intellij.plugin.powershell.PowerShellFileType
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFileFactory
import com.intellij.util.LocalTimeCounter
import com.intellij.xdebugger.XExpression
import com.intellij.xdebugger.XSourcePosition
import com.intellij.xdebugger.evaluation.EvaluationMode
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider

class PowerShellDebuggerEditorsProvider: XDebuggerEditorsProvider() {
private var myFileType: PowerShellFileType = PowerShellFileType.INSTANCE

override fun getFileType(): FileType {
return myFileType
}

override fun createDocument(
project: Project,
expression: XExpression,
sourcePosition: XSourcePosition?,
mode: EvaluationMode
): Document {
val psiFile = PsiFileFactory.getInstance(project)
.createFileFromText(
"pwsh." + myFileType.getDefaultExtension(), myFileType, expression.expression,
LocalTimeCounter.currentTime(), true
)

val document = checkNotNull(PsiDocumentManager.getInstance(project).getDocument(psiFile))
return document
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.intellij.plugin.powershell.ide.debugger

import com.intellij.xdebugger.XSourcePosition
import com.intellij.xdebugger.XSourcePositionWrapper

class PowerShellSourcePosition(position: XSourcePosition) : XSourcePositionWrapper(position) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.intellij.plugin.powershell.ide.run

import com.intellij.execution.ExecutionException
import com.intellij.execution.ExecutionResult
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.runners.AsyncProgramRunner
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.rd.util.toPromise
import com.intellij.openapi.rd.util.withUiContext
import com.intellij.plugin.powershell.ide.PluginProjectRoot
import com.intellij.plugin.powershell.ide.debugger.PowerShellDebugProcess
import com.intellij.xdebugger.XDebugProcess
import com.intellij.xdebugger.XDebugProcessStarter
import com.intellij.xdebugger.XDebugSession
import com.intellij.xdebugger.XDebuggerManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import org.jetbrains.concurrency.Promise
import java.lang.Boolean
import kotlin.OptIn
import kotlin.String
import kotlin.Throws

/**
* The main purpose of this runner is to call [RunProfileState.execute] or a background thread instead of a foreground
* one, as our [RunProfileState] implementation requires FS access that's only possible from the background.
*/
class PowerShellProgramDebugRunner : AsyncProgramRunner<RunnerSettings>() {

override fun getRunnerId() = "com.intellij.plugin.powershell.ide.run.PowerShellProgramDebugRunner"

override fun canRun(executorId: String, profile: RunProfile) =
executorId == DefaultDebugExecutor.EXECUTOR_ID && profile is PowerShellRunConfiguration

@OptIn(ExperimentalCoroutinesApi::class)
override fun execute(environment: ExecutionEnvironment, state: RunProfileState): Promise<RunContentDescriptor?> =
PluginProjectRoot.getInstance(environment.project).coroutineScope.async(Dispatchers.Default) {
state as PowerShellScriptCommandLineState
withUiContext {
FileDocumentManager.getInstance().saveAllDocuments()
}
state.prepareExecution()
val executionResult = state.execute(environment.executor, this@PowerShellProgramDebugRunner)
val descriptor = withUiContext {
XDebuggerManager.getInstance(environment.project).startSession(environment, object : XDebugProcessStarter() {
@Throws(ExecutionException::class)
override fun start(session: XDebugSession): XDebugProcess {
return PowerShellDebugProcess(session, executionResult)
}
}).runContentDescriptor
}
descriptor
}.toPromise()
}
7 changes: 3 additions & 4 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@

<extensions defaultExtensionNs="com.intellij">

<toolWindow id="DebugLogWindow"
anchor="bottom"
factoryClass="com.intellij.execution."></toolWindow>

<fileType name="PowerShell" language="PowerShell" extensions="ps1;psm1;psd1"
implementationClass="com.intellij.plugin.powershell.PowerShellFileType" />

Expand Down Expand Up @@ -69,7 +65,10 @@
<runConfigurationProducer
implementation="com.intellij.plugin.powershell.ide.run.PowerShellConfigurationProducer" order="first"/>

<xdebugger.breakpointType implementation="com.intellij.plugin.powershell.ide.debugger.PowerShellBreakpointType"/>

<programRunner implementation="com.intellij.plugin.powershell.ide.run.PowerShellProgramRunner"/>
<programRunner implementation="com.intellij.plugin.powershell.ide.run.PowerShellProgramDebugRunner"/>

<targetElementEvaluator language="PowerShell"
implementationClass="com.intellij.plugin.powershell.ide.search.PowerShellTargetElementEvaluator"/>
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages/MessagesBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ wrapping.attribute.argument=Attribute arguments
wrapping.block.parameters=Block parameters
wrapping.catch,type.list=Catch type list
wrapping.pipeline=Pipeline

powershell.debugger.breakpoints.title=Breakpoints

0 comments on commit 3ab332b

Please sign in to comment.