Skip to content

Commit

Permalink
DBG: Load Rust pretty-printers via RsDebugProcessConfigurator
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmukhin committed Jul 30, 2019
1 parent 64c8f60 commit 8fd3d49
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 152 deletions.
@@ -0,0 +1,23 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger.runconfig

import com.intellij.execution.filters.TextConsoleBuilder
import com.intellij.xdebugger.XDebugSession
import com.jetbrains.cidr.execution.RunParameters
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess
import org.rust.cargo.runconfig.CargoRunStateBase

class RsLocalDebugProcess(
parameters: RunParameters,
debugSession: XDebugSession,
consoleBuilder: TextConsoleBuilder
) : CidrLocalDebugProcess(parameters, debugSession, consoleBuilder) {

fun setupDebugSession(state: CargoRunStateBase) {
RsExtraDebugDataLoader(this, state.cargoProject).load()
}
}
@@ -0,0 +1,2 @@
<idea-plugin>
</idea-plugin>
@@ -0,0 +1,17 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger.runconfig

import com.jetbrains.cidr.execution.debugger.CidrDebugProcess
import com.jetbrains.cidr.execution.debugger.CidrDebugProcessConfigurator
import org.rust.cargo.project.model.cargoProjects

class RsDebugProcessConfigurator : CidrDebugProcessConfigurator {
override fun configure(process: CidrDebugProcess) {
val cargoProject = process.project.cargoProjects.allProjects.firstOrNull()
RsExtraDebugDataLoader(process, cargoProject).load()
}
}
@@ -0,0 +1,22 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger.runconfig

import com.intellij.execution.filters.TextConsoleBuilder
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.xdebugger.XDebugSession
import com.jetbrains.cidr.execution.RunParameters
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess
import org.rust.cargo.runconfig.CargoRunStateBase

class RsLocalDebugProcess(
parameters: RunParameters,
debugSession: XDebugSession,
consoleBuilder: TextConsoleBuilder
) : CidrLocalDebugProcess(parameters, debugSession, consoleBuilder) {

fun setupDebugSession(state: CargoRunStateBase) {}
}
@@ -0,0 +1,5 @@
<idea-plugin>
<extensions defaultExtensionNs="cidr.debugger">
<debugProcessConfigurator implementation="org.rust.debugger.runconfig.RsDebugProcessConfigurator"/>
</extensions>
</idea-plugin>
Expand Up @@ -24,7 +24,6 @@ import com.jetbrains.cidr.toolchains.OSType
import org.jetbrains.concurrency.AsyncPromise
import org.rust.cargo.runconfig.CargoRunStateBase
import org.rust.cargo.runconfig.RsAsyncRunner
import org.rust.debugger.settings.RsDebuggerSettings

const val ERROR_MESSAGE_TITLE: String = "Debugging is not possible"

Expand All @@ -41,14 +40,9 @@ class RsDebugRunner : RsAsyncRunner(DefaultDebugExecutor.EXECUTOR_ID, ERROR_MESS
return XDebuggerManager.getInstance(environment.project)
.startSession(environment, object : XDebugProcessConfiguratorStarter() {
override fun start(session: XDebugSession): XDebugProcess =
RsLocalDebugProcess(runParameters, session, state.consoleBuilder, state::computeSysroot).apply {
RsLocalDebugProcess(runParameters, session, state.consoleBuilder).apply {
ProcessTerminatedListener.attach(processHandler, environment.project)
val settings = RsDebuggerSettings.getInstance()
loadPrettyPrinters(settings.lldbRenderers, settings.gdbRenderers)
val commitHash = state.cargoProject?.rustcInfo?.version?.commitHash
if (commitHash != null) {
loadRustcSources(commitHash)
}
setupDebugSession(state)
start()
}

Expand Down
@@ -0,0 +1,137 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger.runconfig

import com.intellij.notification.NotificationType
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.jetbrains.cidr.execution.debugger.CidrDebugProcess
import com.jetbrains.cidr.execution.debugger.backend.DebuggerCommandException
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver
import com.jetbrains.cidr.execution.debugger.backend.gdb.GDBDriver
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriver
import org.rust.cargo.project.model.CargoProject
import org.rust.cargo.project.settings.toolchain
import org.rust.cargo.runconfig.command.workingDirectory
import org.rust.debugger.*
import org.rust.debugger.settings.RsDebuggerSettings
import org.rust.ide.notifications.showBalloon
import java.nio.file.InvalidPathException

class RsExtraDebugDataLoader(private val process: CidrDebugProcess, cargoProject: CargoProject?) {
private val settings = RsDebuggerSettings.getInstance()
private val project = process.project
private val toolchain = process.project.toolchain
private val threadId = process.currentThreadId
private val frameIndex = process.currentFrameIndex

private val commitHash = cargoProject?.rustcInfo?.version?.commitHash

private val sysroot: String? by lazy {
cargoProject?.workingDirectory?.let { toolchain?.getSysroot(it) }
}

fun load() {
process.postCommand { driver ->
try {
driver.loadRustcSources()
driver.loadPrettyPrinters()
} catch (e: DebuggerCommandException) {
process.printlnToConsole(e.message)
LOG.warn(e)
} catch (e: InvalidPathException) {
LOG.warn(e)
}
}
}

private fun DebuggerDriver.loadRustcSources() {
if (commitHash == null) return

val sysroot = checkSysroot(sysroot, "Cannot load rustc sources") ?: return
val sourceMapCommand = when (this) {
is LLDBDriver -> "settings set target.source-map"
is GDBDriver -> "set substitute-path"
else -> return
}
val rustcHash = "/rustc/$commitHash/".systemDependentAndEscaped()
val rustcSources = "$sysroot/lib/rustlib/src/rust/".systemDependentAndEscaped()
val fullCommand = """$sourceMapCommand "$rustcHash" "$rustcSources" """
executeConsoleCommand(threadId, frameIndex, fullCommand)
}

private fun DebuggerDriver.loadPrettyPrinters() {
when (this) {
is LLDBDriver -> loadPrettyPrinters()
is GDBDriver -> loadPrettyPrinters()
}
}

private fun LLDBDriver.loadPrettyPrinters() {
when (settings.lldbRenderers) {
LLDBRenderers.COMPILER -> {
val sysroot = checkSysroot(sysroot, "Cannot load rustc renderers") ?: return
val path = "$sysroot/lib/rustlib/etc/lldb_rust_formatters.py".systemDependentAndEscaped()
executeConsoleCommand(threadId, frameIndex, """command script import "$path" """)
executeConsoleCommand(threadId, frameIndex, """type summary add --no-value --python-function lldb_rust_formatters.print_val -x ".*" --category Rust""")
executeConsoleCommand(threadId, frameIndex, """type category enable Rust""")
}

LLDBRenderers.BUNDLED -> {
val path = PP_PATH.systemDependentAndEscaped()
executeConsoleCommand(threadId, frameIndex, """command script import "$path/$LLDB_LOOKUP.py" """)
executeConsoleCommand(threadId, frameIndex, """type synthetic add -l $LLDB_LOOKUP.synthetic_lookup -x ".*" --category Rust""")
executeConsoleCommand(threadId, frameIndex, """type summary add -F $LLDB_LOOKUP.summary_lookup -e -x -h ".*" --category Rust""")
executeConsoleCommand(threadId, frameIndex, """type category enable Rust""")
}

LLDBRenderers.NONE -> {
}
}
}

private fun GDBDriver.loadPrettyPrinters() {
when (settings.gdbRenderers) {
GDBRenderers.COMPILER -> {
val sysroot = checkSysroot(sysroot, "Cannot load rustc renderers") ?: return
val path = "$sysroot/lib/rustlib/etc".systemDependentAndEscaped()
// Avoid multiline Python scripts due to https://youtrack.jetbrains.com/issue/CPP-9090
val command = """python """ +
"""sys.path.insert(0, "$path"); """ +
"""import gdb_rust_pretty_printing; """ +
"""gdb_rust_pretty_printing.register_printers(gdb); """
executeConsoleCommand(threadId, frameIndex, command)
}

GDBRenderers.BUNDLED -> {
val path = PP_PATH.systemDependentAndEscaped()
val command = """python """ +
"""sys.path.insert(0, "$path"); """ +
"""import $GDB_LOOKUP; """ +
"""$GDB_LOOKUP.register_printers(gdb); """
executeConsoleCommand(threadId, frameIndex, command)
}

GDBRenderers.NONE -> {
}
}
}

private fun checkSysroot(sysroot: String?, message: String): String? {
if (sysroot == null) {
project.showBalloon(message, NotificationType.WARNING)
}
return sysroot
}

private fun String.systemDependentAndEscaped(): String =
StringUtil.escapeStringCharacters(FileUtil.toSystemDependentName(this))

companion object {
private val LOG: Logger = Logger.getInstance(RsExtraDebugDataLoader::class.java)
}
}

This file was deleted.

4 changes: 3 additions & 1 deletion debugger/src/main/resources/META-INF/debugger-only.xml
@@ -1,4 +1,6 @@
<idea-plugin>
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" allow-bundled-update="true">
<xi:include href="/META-INF/platform-debugger-only.xml" xpointer="xpointer(/idea-plugin/*)"/>

<extensions defaultExtensionNs="cidr.debugger">
<languageSupport language="Rust" implementationClass="org.rust.debugger.lang.RsDebuggerLanguageSupport"/>
<editorsExtension implementation="org.rust.debugger.lang.RsDebuggerEditorsExtension"/>
Expand Down
2 changes: 0 additions & 2 deletions src/main/kotlin/org/rust/cargo/runconfig/CargoRunStateBase.kt
Expand Up @@ -56,8 +56,6 @@ abstract class CargoRunStateBase(

fun cargo(): Cargo = toolchain.cargoOrWrapper(workingDirectory)

fun computeSysroot(): String? = workingDirectory?.let { toolchain.getSysroot(it) }

fun rustVersion(): RustToolchain.VersionInfo = toolchain.queryVersions()

fun prepareCommandLine(): CargoCommandLine {
Expand Down

0 comments on commit 8fd3d49

Please sign in to comment.