Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: debugger #31

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 90 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ val tomlPlugin: String by project
val graziePlugin: String by project
val psiViewerPlugin: String by project
val copyrightPlugin: String by project
val nativeDebugPlugin: String by project //if (baseIDE == "idea") prop("nativeDebugPlugin") else "com.intellij.nativeDebug"
val javaPlugin = "com.intellij.java"
val javaIdePlugin = "com.intellij.java.ide"
val javaScriptPlugin = "JavaScript"
Expand Down Expand Up @@ -311,6 +312,7 @@ project(":plugin") {
bundledPlugins(bundledPluginList)

pluginModule(implementation(project(":idea")))
pluginModule(implementation(project(":debugger")))
pluginModule(implementation(project(":copyright")))
pluginModule(implementation(project(":coverage")))
pluginModule(implementation(project(":duplicates")))
Expand All @@ -322,11 +324,43 @@ project(":plugin") {
implementation(project(":"))
}

// Collects all jars produced by compilation of project modules and merges them into singe one.
// We need to put all plugin manifest files into single jar to make new plugin model work
val mergePluginJarTask = task<Jar>("mergePluginJars") {
duplicatesStrategy = DuplicatesStrategy.FAIL
archiveBaseName.set(basePluginArchiveName)

exclude("META-INF/MANIFEST.MF")
exclude("**/classpath.index")

val pluginLibDir by lazy {
val sandboxTask = tasks.prepareSandbox.get()
sandboxTask.destinationDir.resolve("${intellijPlatform.pluginConfiguration.name}/lib")
}

val pluginJars by lazy {
pluginLibDir.listFiles().orEmpty().filter { it.isPluginJar() }
}

destinationDirectory.set(project.layout.dir(provider { pluginLibDir }))

doFirst {
for (file in pluginJars) {
from(zipTree(file))
}
}

doLast {
delete(pluginJars)
}
}

// Add plugin sources to the plugin ZIP.
// gradle-intellij-plugin will use it as a plugin sources if the plugin is used as a dependency
val createSourceJar = task<Jar>("createSourceJar") {
dependsOn(":generateLexer")
dependsOn(":generateParser")
dependsOn(":debugger:generateGrammarSource")

for (prj in pluginProjects) {
from(prj.kotlin.sourceSets.main.get().kotlin) {
Expand Down Expand Up @@ -490,6 +524,61 @@ project(":idea") {
}
}


project(":debugger") {
apply {
plugin("antlr")
}



// intellij {
// if (baseIDE == "idea") {
// plugins.set(listOf(nativeDebugPlugin))
// } else {
// version.set(clionVersion)
// plugins.set(clionPlugins)
// }
// }

// Kotlin Gradle support doesn't generate proper extensions if the plugin is not declared in `plugin` block.
// But if we do it, `antlr` plugin will be applied to root project as well that we want to avoid.
// So, let's define all necessary things manually
val antlr by configurations
val generateGrammarSource: AntlrTask by tasks
val generateTestGrammarSource: AntlrTask by tasks

dependencies {
intellijPlatform {
create(baseIDE, baseVersion)

plugins(listOf(nativeDebugPlugin))
}
implementation(project(":"))
antlr("org.antlr:antlr4:4.13.0")
implementation("org.antlr:antlr4-runtime:4.13.0")
testImplementation(project(":", "testOutput"))
}
tasks {
compileKotlin {
dependsOn(generateGrammarSource)
}
compileTestKotlin {
dependsOn(generateTestGrammarSource)
}

generateGrammarSource {
arguments.add("-no-listener")
arguments.add("-visitor")
outputDirectory = file("src/gen/org/rust/debugger/lang")
}
}
// Exclude antlr4 from transitive dependencies of `:debugger:api` configuration (https://github.com/gradle/gradle/issues/820)
configurations.api {
setExtendsFrom(extendsFrom.filter { it.name != "antlr" })
}
}

project(":copyright") {
dependencies {
intellijPlatform {
Expand Down Expand Up @@ -667,7 +756,7 @@ fun prop(name: String): String =

fun versionForIde(ideName: String): String = when (ideName) {
"IU", "IC" -> ideaVersion
else -> error("Unexpected IDE name: `$baseIDE`")
else -> ideaVersion//error("Unexpected IDE name: `$baseIDE`")
}

inline operator fun <T : Task> T.invoke(a: T.() -> Unit): T = apply(a)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<idea-plugin >
<extensions defaultExtensionNs="com.intellij">
<registryKey key="org.rust.debugger.gdb.windows"
defaultValue="true"
description="Enables Rust debugging with GDB on Windows"/>
<registryKey key="org.rust.debugger.gdb.wsl"
defaultValue="true"
description="Enables Rust debugging with GDB on WSL"/>
</extensions>
</idea-plugin>
192 changes: 192 additions & 0 deletions debugger/src/main/antlr/RsTypeName.g4
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Grammar rules for type names generated by rustc for the debug info.
*
* For the details about debug info type names, see:
* https://github.com/rust-lang/rust/blob/9da4644d5685aa0c4daa4aea6ddc9eb834ae51cc/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
* https://github.com/rust-lang/rust/blob/9da4644d5685aa0c4daa4aea6ddc9eb834ae51cc/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
*/

grammar RsTypeName;

@header {
package org.rust.debugger.lang;
}

parseTypeName : typeName EOF ;

typeName
: msvcTypeName
| commonTypeName
;

msvcTypeName
: msvcStr
| msvcStrDollar
| msvcNever
| msvcTuple
| msvcPtr_const
| msvcPtr_mut
| msvcRef
| msvcRef_mut
| msvcArray
| msvcSlice
| msvcSlice2
| msvcEnum
| msvcEnum2
;

//BACKCOMPAT: Rust 1.66
msvcStr: STR ;

msvcStrDollar: STR_DOLLAR ;

msvcNever: NEVER ;

msvcTuple
: TUPLE LT items=commaSeparatedList? GT
;

msvcPtr_const
: PTR_CONST LT type=typeName GT
;

msvcPtr_mut
: PTR_MUT LT type=typeName GT
;

msvcRef
: REF LT type=typeName GT
;

msvcRef_mut
: REF_MUT LT type=typeName GT
;

msvcArray
: ARRAY LT type=typeName COMMA length=WORD GT
;

//BACKCOMPAT: Rust 1.66
msvcSlice
: SLICE LT type=typeName GT
;

msvcSlice2
: SLICE2 LT type=typeName GT
;

//BACKCOMPAT: Rust 1.64
msvcEnum
: ENUM LT type=typeName GT
| ENUM LT type=typeName COMMA variant=WORD GT
| ENUM LT type=typeName COMMA typeName COMMA typeName COMMA variant=WORD GT
;

// Since Rust 1.65, introduced in https://github.com/rust-lang/rust/pull/98393
msvcEnum2
: ENUM2 LT type=typeName GT
;


commonTypeName
: str
| never
| tuple
| ptrConst
| ptrMut
| ref
| refMut
| array
| slice
| qualifiedName
;

str: AND STR ;

never : EXCL ;

tuple
: LPAREN items=commaSeparatedList? RPAREN
;

ptrConst
: MUL CONST type=typeName
;

ptrMut
: MUL MUT type=typeName
;

ref
: AND type=typeName
;

refMut
: AND MUT type=typeName
;

array
: LBRACK type=typeName SEMICOLON length=WORD RBRACK
;

slice
: LBRACK type=typeName RBRACK
;

qualifiedName
: ( namespaceSegments+=qualifiedNameSegment COLONCOLON )* namespaceSegments+=qualifiedNameSegment
;

qualifiedNameSegment
: name=WORD (LT items=commaSeparatedList GT)?
;

commaSeparatedList
: items+=typeName ( COMMA items+=typeName )*
;

STR : 'str' ;
STR_DOLLAR : 'str$' ;
NEVER: 'never$' ;
TUPLE : 'tuple$' ;
PTR_CONST: 'ptr_const$' ;
PTR_MUT: 'ptr_mut$' ;
REF: 'ref$' ;
REF_MUT: 'ref_mut$' ;
ARRAY : 'array$' ;
SLICE : 'slice$' ;
SLICE2 : 'slice2$' ;
ENUM: 'enum$' ;
ENUM2: 'enum2$' ;

// Currently not fully supported
DYN: 'dyn$' ;
IMPL: 'impl$' ;
ASSOC: 'assoc$' ;
ASYNC_BLOCK_ENV: 'async_block_env$' ;
ASYNC_FN_ENV: 'async_fn_env$' ;
GENERATOR_FN_ENV: 'generator_env$' ;
CLOSURE_FN_ENV: 'closure_env$' ;

LT: '<' ;
GT: '>' ;
LPAREN: '(' ;
RPAREN: ')' ;
LBRACK: '[' ;
RBRACK: ']' ;
COMMA: ',' ;
EQ: '=' ;
ARROW: '->' ;
EXCL: '!' ;
COLONCOLON: '::' ;
SEMICOLON: ';' ;
AND: '&' ;
MUL: '*' ;
CONST: 'const' ;
MUT: 'mut' ;

WORD : (LETTER | DIGIT)+ ;
fragment LETTER : 'a'..'z' | 'A'..'Z' | '_' ;
fragment DIGIT : '0'..'9' ;

WS : [ \t]+ -> skip ;
19 changes: 19 additions & 0 deletions debugger/src/main/kotlin/org/rust/debugger/DebuggerAvailability.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger

import java.nio.file.Path

sealed class DebuggerAvailability<out T> {
object Unavailable : DebuggerAvailability<Nothing>()
object NeedToDownload : DebuggerAvailability<Nothing>()
object NeedToUpdate : DebuggerAvailability<Nothing>()
object Bundled: DebuggerAvailability<Nothing>()
data class Binaries<T>(val binaries: T) : DebuggerAvailability<T>()
}

data class LLDBBinaries(val frameworkFile: Path, val frontendFile: Path)
data class GDBBinaries(val gdbFile: Path)
11 changes: 11 additions & 0 deletions debugger/src/main/kotlin/org/rust/debugger/DebuggerKind.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Use of this source code is governed by the MIT license that can be
* found in the LICENSE file.
*/

package org.rust.debugger

enum class DebuggerKind {
LLDB,
GDB
}
Loading