Snap for 11390309 from ac89181d1ffce18454c32f76479d5a073fdc4e80 to studio-jellyfish-release
Change-Id: I807ed72a761c4690466a134c03df8649ca7ff9b7
diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml
index 7da9322..8841b08 100644
--- a/.github/workflows/build-plugin.yml
+++ b/.github/workflows/build-plugin.yml
@@ -28,7 +28,7 @@
strategy:
fail-fast: true
matrix:
- platform-version: [ 231, 232 ]
+ platform-version: [ 232, 233 ]
env:
ORG_GRADLE_PROJECT_buildNumber: ${{ needs.generate-build-number.outputs.build_number }}
ORG_GRADLE_PROJECT_platformVersion: ${{ matrix.platform-version }}
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 534d71c..2e232cc 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -20,9 +20,9 @@
cancel-in-progress: true
env:
- OLD_IDEA_VERSION: IU-2023.1
- OLD_CLION_VERSION: CL-2023.1
- OLD_NATIVE_DEBUG_PLUGIN_VERSION: 231.8109.46
+ OLD_IDEA_VERSION: IU-2023.2
+ OLD_CLION_VERSION: CL-2023.2
+ OLD_NATIVE_DEBUG_PLUGIN: "com.intellij.nativeDebug:232.8660.142"
jobs:
get-rust-versions:
@@ -85,14 +85,14 @@
# Make sequence from two outputs with version is not possible here.
# TODO: check on more rustc versions
rust-version: ${{ fromJSON(needs.get-rust-versions.outputs.matrix) }}
- platform-version: [ 231, 232 ]
+ platform-version: [ 232, 233 ]
include:
- os: ubuntu-latest
rust-version: ${{ needs.get-rust-versions.outputs.old }}
- platform-version: 231
+ platform-version: 232
- os: windows-latest
rust-version: ${{ needs.get-rust-versions.outputs.old }}
- platform-version: 231
+ platform-version: 232
runs-on: ${{ matrix.os }}
env:
@@ -116,7 +116,7 @@
run: |
echo "ORG_GRADLE_PROJECT_ideaVersion=${{ env.OLD_IDEA_VERSION }}" >> $GITHUB_ENV
echo "ORG_GRADLE_PROJECT_clionVersion=${{ env.OLD_CLION_VERSION }}" >> $GITHUB_ENV
- echo "ORG_GRADLE_PROJECT_nativeDebugPluginVersion=${{ env.OLD_NATIVE_DEBUG_PLUGIN_VERSION }}" >> $GITHUB_ENV
+ echo "ORG_GRADLE_PROJECT_nativeDebugPlugin=${{ env.OLD_NATIVE_DEBUG_PLUGIN }}" >> $GITHUB_ENV
- name: Retrieve CLion version
id: clion-version
@@ -176,7 +176,7 @@
# Make sequence from two outputs with version is not possible here.
rust-version: ${{ fromJSON(needs.get-rust-versions.outputs.matrix) }}
base-ide: [ idea, clion ]
- platform-version: [ 231, 232 ]
+ platform-version: [ 232, 233 ]
# it's enough to verify plugin structure only once per platform version
verify-plugin: [ false ]
default-edition-for-tests: [ 2021 ]
@@ -184,7 +184,7 @@
- os: ubuntu-latest
rust-version: ${{ needs.get-rust-versions.outputs.old }}
base-ide: idea
- platform-version: 231
+ platform-version: 232
verify-plugin: true
default-edition-for-tests: 2021
@@ -266,7 +266,7 @@
run: |
echo "ORG_GRADLE_PROJECT_ideaVersion=${{ env.OLD_IDEA_VERSION }}" >> $GITHUB_ENV
echo "ORG_GRADLE_PROJECT_clionVersion=${{ env.OLD_CLION_VERSION }}" >> $GITHUB_ENV
- echo "ORG_GRADLE_PROJECT_nativeDebugPluginVersion=${{ env.OLD_NATIVE_DEBUG_PLUGIN_VERSION }}" >> $GITHUB_ENV
+ echo "ORG_GRADLE_PROJECT_nativeDebugPlugin=${{ env.OLD_NATIVE_DEBUG_PLUGIN }}" >> $GITHUB_ENV
- name: Set up test env variables
run: echo "RUST_SRC_WITH_SYMLINK=$HOME/.rust-src" >> $GITHUB_ENV
diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml
deleted file mode 100644
index e98ff05..0000000
--- a/.github/workflows/code-quality.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: code quality
-on:
- pull_request:
-
-jobs:
- qodana:
- runs-on: ubuntu-latest
- timeout-minutes: 60
-
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: 0
-
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- distribution: corretto
- java-version: 17
-
- - name: Download
- uses: gradle/gradle-build-action@v2
- with:
- arguments: ":resolveDependencies -Pkotlin.incremental=false --no-daemon"
- gradle-home-cache-excludes: |
- caches/modules-2/files-2.1/com.jetbrains.intellij.idea
- caches/modules-2/files-2.1/com.jetbrains.intellij.clion
-
- - name: Generate sources
- uses: gradle/gradle-build-action@v2
- with:
- arguments: ":generateLexer :generateParser debugger:generateGrammarSource -Pkotlin.incremental=false --no-daemon"
- gradle-home-cache-excludes: |
- caches/modules-2/files-2.1/com.jetbrains.intellij.idea
- caches/modules-2/files-2.1/com.jetbrains.intellij.clion
-
- - name: Qodana
- uses: JetBrains/qodana-action@v2023.1.5
- with:
- use-caches: false
diff --git a/.github/workflows/rust-nightly.yml b/.github/workflows/rust-nightly.yml
index 55c34fa..e9ed964 100644
--- a/.github/workflows/rust-nightly.yml
+++ b/.github/workflows/rust-nightly.yml
@@ -56,7 +56,7 @@
strategy:
fail-fast: true
matrix:
- platform-version: [ 231, 232 ]
+ platform-version: [ 232, 233 ]
env:
ORG_GRADLE_PROJECT_buildNumber: ${{ needs.generate-build-number.outputs.build_number }}
ORG_GRADLE_PROJECT_platformVersion: ${{ matrix.platform-version }}
diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml
index 0a7ec44..0b9bb24 100644
--- a/.github/workflows/rust-release.yml
+++ b/.github/workflows/rust-release.yml
@@ -111,7 +111,7 @@
strategy:
fail-fast: true
matrix:
- platform-version: [ 231, 232 ]
+ platform-version: [ 232, 233 ]
env:
ORG_GRADLE_PROJECT_buildNumber: ${{ needs.generate-build-number.outputs.build_number }}
ORG_GRADLE_PROJECT_platformVersion: ${{ matrix.platform-version }}
diff --git a/.idea/runConfigurations/RunCLion.xml b/.idea/runConfigurations/RunCLion.xml
index bb55063..7190f21 100644
--- a/.idea/runConfigurations/RunCLion.xml
+++ b/.idea/runConfigurations/RunCLion.xml
@@ -1,12 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RunCLion" type="GradleRunConfiguration" factoryName="Gradle">
- <log_file alias="idea-231.log" path="$PROJECT_DIR$/plugin/build/clion-sandbox-231/system/log/idea.log" />
<log_file alias="idea-232.log" path="$PROJECT_DIR$/plugin/build/clion-sandbox-232/system/log/idea.log" />
+ <log_file alias="idea-233.log" path="$PROJECT_DIR$/plugin/build/clion-sandbox-233/system/log/idea.log" />
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
- <option name="scriptParameters" value="-PbaseIDE=clion" />
+ <option name="scriptParameters" value="-PideToRun=clion" />
<option name="taskDescriptions">
<list />
</option>
@@ -17,7 +17,10 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
- <GradleScriptDebugEnabled>false</GradleScriptDebugEnabled>
+ <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
+ <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
+ <DebugAllEnabled>false</DebugAllEnabled>
+ <RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
diff --git a/.idea/runConfigurations/RunIDEA.xml b/.idea/runConfigurations/RunIDEA.xml
index 41f4b0a..19b02d3 100644
--- a/.idea/runConfigurations/RunIDEA.xml
+++ b/.idea/runConfigurations/RunIDEA.xml
@@ -1,12 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RunIDEA" type="GradleRunConfiguration" factoryName="Gradle" singleton="true">
- <log_file alias="idea-231.log" path="$PROJECT_DIR$/plugin/build/idea-sandbox-231/system/log/idea.log" />
<log_file alias="idea-232.log" path="$PROJECT_DIR$/plugin/build/idea-sandbox-232/system/log/idea.log" />
+ <log_file alias="idea-233.log" path="$PROJECT_DIR$/plugin/build/idea-sandbox-233/system/log/idea.log" />
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
- <option name="scriptParameters" value="-PbaseIDE=idea" />
+ <option name="scriptParameters" value="-PideToRun=idea" />
<option name="taskDescriptions">
<list />
</option>
@@ -17,7 +17,10 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
- <GradleScriptDebugEnabled>false</GradleScriptDebugEnabled>
+ <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
+ <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
+ <DebugAllEnabled>false</DebugAllEnabled>
+ <RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
diff --git a/.idea/runConfigurations/RunRustRover.xml b/.idea/runConfigurations/RunRustRover.xml
new file mode 100644
index 0000000..614062d
--- /dev/null
+++ b/.idea/runConfigurations/RunRustRover.xml
@@ -0,0 +1,25 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="RunRustRover" type="GradleRunConfiguration" factoryName="Gradle">
+ <log_file alias="rr-233.log" path="$PROJECT_DIR$/plugin/build/rustRover-sandbox-233/system/log/idea.log" />
+ <ExternalSystemSettings>
+ <option name="executionName" />
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
+ <option name="externalSystemIdString" value="GRADLE" />
+ <option name="scriptParameters" value="-PideToRun=rustRover" />
+ <option name="taskDescriptions">
+ <list />
+ </option>
+ <option name="taskNames">
+ <list>
+ <option value=":plugin:runIde" />
+ </list>
+ </option>
+ <option name="vmOptions" value="" />
+ </ExternalSystemSettings>
+ <ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
+ <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
+ <DebugAllEnabled>false</DebugAllEnabled>
+ <RunAsTest>false</RunAsTest>
+ <method v="2" />
+ </configuration>
+</component>
diff --git a/build.gradle.kts b/build.gradle.kts
index 23da018..fc1da0e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,10 +3,9 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
-import org.jetbrains.intellij.tasks.PatchPluginXmlTask
-import org.jetbrains.intellij.tasks.PrepareSandboxTask
-import org.jetbrains.intellij.tasks.PublishPluginTask
-import org.jetbrains.intellij.tasks.RunIdeTask
+import org.jetbrains.intellij.tasks.*
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jsoup.Jsoup
import java.io.Writer
@@ -21,16 +20,15 @@
val channel = prop("publishChannel")
val platformVersion = prop("platformVersion").toInt()
val baseIDE = prop("baseIDE")
+val ideToRun = prop("ideToRun").ifEmpty { baseIDE }
val ideaVersion = prop("ideaVersion")
val clionVersion = prop("clionVersion")
-val baseVersion = when (baseIDE) {
- "idea" -> ideaVersion
- "clion" -> clionVersion
- else -> error("Unexpected IDE name: `$baseIDE`")
-}
+val rustRoverVersion = prop("rustRoverVersion")
+val baseVersion = versionForIde(baseIDE)
+val baseVersionForRun = versionForIde(ideToRun)
val tomlPlugin = "org.toml.lang"
-val nativeDebugPlugin: String by project
+val nativeDebugPlugin = if (baseIDE == "idea") prop("nativeDebugPlugin") else "com.intellij.nativeDebug"
val graziePlugin = "tanvd.grazi"
val psiViewerPlugin: String by project
val intelliLangPlugin = "org.intellij.intelliLang"
@@ -38,7 +36,7 @@
val javaPlugin = "com.intellij.java"
val javaIdePlugin = "com.intellij.java.ide"
val javaScriptPlugin = "JavaScript"
-val clionPlugins = listOf("com.intellij.cidr.base", "com.intellij.clion")
+val clionPlugins = listOf("com.intellij.cidr.base", "com.intellij.clion", nativeDebugPlugin)
val mlCompletionPlugin = "com.intellij.completion.ml.ranking"
val compileNativeCodeTaskName = "compileNativeCode"
@@ -49,8 +47,8 @@
plugins {
idea
- kotlin("jvm") version "1.8.22"
- id("org.jetbrains.intellij") version "1.13.1"
+ kotlin("jvm") version "1.9.0"
+ id("org.jetbrains.intellij") version "1.16.1"
id("org.jetbrains.grammarkit") version "2022.3.1"
id("net.saliman.properties") version "1.5.2"
id("org.gradle.test-retry") version "1.5.3"
@@ -91,7 +89,7 @@
updateSinceUntilBuild.set(true)
instrumentCode.set(false)
ideaDependencyCachePath.set(dependencyCachePath)
- sandboxDir.set("$buildDir/$baseIDE-sandbox-$platformVersion")
+ sandboxDir.set(layout.buildDirectory.dir("$ideToRun-sandbox-$platformVersion").map { it.asFile.absolutePath })
}
configure<JavaPluginExtension> {
@@ -101,12 +99,12 @@
tasks {
withType<KotlinCompile> {
- kotlinOptions {
- jvmTarget = VERSION_17.toString()
- languageVersion = "1.8"
+ compilerOptions {
+ jvmTarget.set(JvmTarget.JVM_17)
+ languageVersion.set(KotlinVersion.DEFAULT)
// see https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#kotlin-standard-library
- apiVersion = "1.7"
- freeCompilerArgs = listOf("-Xjvm-default=all")
+ apiVersion.set(KotlinVersion.KOTLIN_1_8)
+ freeCompilerArgs.set(listOf("-Xjvm-default=all"))
}
}
withType<PatchPluginXmlTask> {
@@ -248,15 +246,28 @@
val pluginProjects: List<Project>
get() = rootProject.allprojects.filter { it.name != grammarKitFakePsiDeps }
-val channelSuffix = if (channel.isBlank() || channel == "stable") "" else "-$channel"
-val versionSuffix = "-$platformVersion$channelSuffix"
-val majorVersion = "0.4"
-val patchVersion = prop("patchVersion").toInt()
-
-// Special module with run, build and publish tasks
+// Special module with run, build, and publish tasks
project(":plugin") {
- version = "$majorVersion.$patchVersion.${prop("buildNumber")}$versionSuffix"
+ val pluginVersion = System.getenv("BUILD_NUMBER") ?: "${platformVersion}.${prop("buildNumber")}"
+ version = if (pluginVersion.contains(".")) {
+ val split = pluginVersion.split(".").toMutableList()
+ split[0] = platformVersion.toString()
+ // From 232 branch, plugin version `232.9921` and `233.9921` were published
+ // These versions were based on IJ platform `232.9921` build
+ //
+ // From 233 branch, plugin versions are `233.8264` and `232.8264`, which are based on IJ platform `233.8264` build
+ // Since we publish versions for 2 platform versions from a single branch, plugin versions has to be hacked this way,
+ // Otherwise newly published `233.8264` version would be considered lower than `233.9921` published earlier
+ //
+ // TODO: For `241`, come up with new plugin versioning to avoid this problem
+ split[1] = (split[1].toIntOrNull()?.plus(10000))?.toString() ?: split[1]
+ split.joinToString(".")
+ } else {
+ pluginVersion
+ }
+
intellij {
+ version.set(baseVersionForRun)
pluginName.set("intellij-rust")
val pluginList = mutableListOf(
tomlPlugin,
@@ -266,7 +277,7 @@
javaScriptPlugin,
mlCompletionPlugin
)
- if (baseIDE == "idea") {
+ if (ideToRun == "idea") {
pluginList += listOf(
copyrightPlugin,
javaPlugin,
@@ -354,11 +365,16 @@
finalizedBy(mergePluginJarTask)
enabled = true
}
- buildSearchableOptions {
- // Force `mergePluginJarTask` be executed before `buildSearchableOptions`
- // Otherwise, `buildSearchableOptions` task can't load the plugin and searchable options are not built.
+ withType<RunIdeBase> {
+ // Force `mergePluginJarTask` be executed before any task based on `RunIdeBase` (for example, `runIde` or `buildSearchableOptions`).
+ // Otherwise, these tasks fail because of implicit dependency.
// Should be dropped when jar merging is implemented in `gradle-intellij-plugin` itself
dependsOn(mergePluginJarTask)
+ }
+ verifyPlugin {
+ dependsOn(mergePluginJarTask)
+ }
+ buildSearchableOptions {
enabled = prop("enableBuildSearchableOptions").toBoolean()
}
withType<PrepareSandboxTask> {
@@ -407,10 +423,10 @@
task<RunIdeTask>("buildEventsScheme") {
dependsOn(tasks.prepareSandbox)
args("buildEventsScheme", "--outputFile=${buildDir.resolve("eventScheme.json").absolutePath}", "--pluginId=org.rust.lang")
- // BACKCOMPAT: 2023.1. Update value to 232 and this comment
+ // BACKCOMPAT: 2023.2. Update value to 233 and this comment
// `IDEA_BUILD_NUMBER` variable is used by `buildEventsScheme` task to write `buildNumber` to output json.
// It will be used by TeamCity automation to set minimal IDE version for new events
- environment("IDEA_BUILD_NUMBER", "231")
+ environment("IDEA_BUILD_NUMBER", "232")
}
}
@@ -739,6 +755,12 @@
extra.properties[name] as? String
?: error("Property `$name` is not defined in gradle.properties")
+fun versionForIde(ideName: String): String = when (ideName) {
+ "idea" -> ideaVersion
+ "clion" -> clionVersion
+ "rustRover" -> rustRoverVersion
+ else -> error("Unexpected IDE name: `$baseIDE`")
+}
inline operator fun <T : Task> T.invoke(a: T.() -> Unit): T = apply(a)
diff --git a/clion/src/232/main/kotlin/org/rust/clion/valgrind/Compat.kt b/clion/src/232/main/kotlin/org/rust/clion/valgrind/Compat.kt
new file mode 100644
index 0000000..c9a83e8
--- /dev/null
+++ b/clion/src/232/main/kotlin/org/rust/clion/valgrind/Compat.kt
@@ -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.clion.valgrind
+
+typealias MemoryProfileOutputPanel = com.jetbrains.cidr.cpp.profiling.ui.MemoryProfileOutputPanel
+typealias EditValgrindSettingsAction = com.jetbrains.cidr.cpp.valgrind.actions.EditValgrindSettingsAction
+typealias CLionProfilingBundle = com.jetbrains.cidr.cpp.CLionProfilingBundle
+typealias ValgrindSettings = com.jetbrains.cidr.cpp.valgrind.ValgrindSettings
+typealias ValgrindConfigurable = com.jetbrains.cidr.cpp.valgrind.ValgrindConfigurable
+typealias ValgrindCommandLineParametersBuilder = com.jetbrains.cidr.cpp.valgrind.ValgrindCommandLineParametersBuilder
+typealias MemoryProfileTreeDataModel = com.jetbrains.cidr.cpp.profiling.MemoryProfileTreeDataModel
+typealias ValgrindUtil = com.jetbrains.cidr.cpp.valgrind.ValgrindUtil
+typealias ValgrindExecutor = com.jetbrains.cidr.cpp.valgrind.ValgrindExecutor
+typealias MemoryProfileConsoleViewWrapper = com.jetbrains.cidr.cpp.profiling.MemoryProfileConsoleViewWrapper
+typealias ValgrindHandler = com.jetbrains.cidr.cpp.valgrind.ValgrindHandler
+typealias ValgrindOutputConsumer = com.jetbrains.cidr.cpp.valgrind.ValgrindOutputConsumer
+typealias MemoryProfileStringAccumulator = com.jetbrains.cidr.cpp.profiling.MemoryProfileStringAccumulator
+typealias MemoryProfileCompositeConsumer = com.jetbrains.cidr.cpp.profiling.MemoryProfileCompositeConsumer
+typealias MemoryProfileFileReader = com.jetbrains.cidr.cpp.profiling.MemoryProfileFileReader
diff --git a/clion/src/233/main/kotlin/org/rust/clion/valgrind/Compat.kt b/clion/src/233/main/kotlin/org/rust/clion/valgrind/Compat.kt
new file mode 100644
index 0000000..1535ef6
--- /dev/null
+++ b/clion/src/233/main/kotlin/org/rust/clion/valgrind/Compat.kt
@@ -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.clion.valgrind
+
+typealias MemoryProfileOutputPanel = com.jetbrains.cidr.cpp.profiling.memory.ui.MemoryProfileOutputPanel
+typealias EditValgrindSettingsAction = com.jetbrains.cidr.cpp.profiling.valgrind.actions.EditValgrindSettingsAction
+typealias CLionProfilingBundle = com.jetbrains.cidr.cpp.profiling.CLionProfilingBundle
+typealias ValgrindSettings = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindSettings
+typealias ValgrindConfigurable = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindConfigurable
+typealias ValgrindCommandLineParametersBuilder = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindCommandLineParametersBuilder
+typealias MemoryProfileTreeDataModel = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileTreeDataModel
+typealias ValgrindUtil = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindUtil
+typealias ValgrindExecutor = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindExecutor
+typealias MemoryProfileConsoleViewWrapper = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileConsoleViewWrapper
+typealias ValgrindHandler = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindHandler
+typealias ValgrindOutputConsumer = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindOutputConsumer
+typealias MemoryProfileStringAccumulator = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileStringAccumulator
+typealias MemoryProfileCompositeConsumer = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileCompositeConsumer
+typealias MemoryProfileFileReader = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileFileReader
diff --git a/clion/src/241/main/kotlin/org/rust/clion/valgrind/Compat.kt b/clion/src/241/main/kotlin/org/rust/clion/valgrind/Compat.kt
new file mode 100644
index 0000000..1535ef6
--- /dev/null
+++ b/clion/src/241/main/kotlin/org/rust/clion/valgrind/Compat.kt
@@ -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.clion.valgrind
+
+typealias MemoryProfileOutputPanel = com.jetbrains.cidr.cpp.profiling.memory.ui.MemoryProfileOutputPanel
+typealias EditValgrindSettingsAction = com.jetbrains.cidr.cpp.profiling.valgrind.actions.EditValgrindSettingsAction
+typealias CLionProfilingBundle = com.jetbrains.cidr.cpp.profiling.CLionProfilingBundle
+typealias ValgrindSettings = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindSettings
+typealias ValgrindConfigurable = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindConfigurable
+typealias ValgrindCommandLineParametersBuilder = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindCommandLineParametersBuilder
+typealias MemoryProfileTreeDataModel = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileTreeDataModel
+typealias ValgrindUtil = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindUtil
+typealias ValgrindExecutor = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindExecutor
+typealias MemoryProfileConsoleViewWrapper = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileConsoleViewWrapper
+typealias ValgrindHandler = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindHandler
+typealias ValgrindOutputConsumer = com.jetbrains.cidr.cpp.profiling.valgrind.ValgrindOutputConsumer
+typealias MemoryProfileStringAccumulator = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileStringAccumulator
+typealias MemoryProfileCompositeConsumer = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileCompositeConsumer
+typealias MemoryProfileFileReader = com.jetbrains.cidr.cpp.profiling.memory.MemoryProfileFileReader
diff --git a/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindConfigurationExtension.kt b/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindConfigurationExtension.kt
index 940fa5c..076cd15 100644
--- a/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindConfigurationExtension.kt
+++ b/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindConfigurationExtension.kt
@@ -28,11 +28,6 @@
import com.intellij.util.ArrayUtil
import com.intellij.util.Consumer
import com.intellij.util.ui.StatusText
-import com.jetbrains.cidr.cpp.CLionProfilingBundle
-import com.jetbrains.cidr.cpp.profiling.*
-import com.jetbrains.cidr.cpp.profiling.ui.MemoryProfileOutputPanel
-import com.jetbrains.cidr.cpp.valgrind.*
-import com.jetbrains.cidr.cpp.valgrind.actions.EditValgrindSettingsAction
import com.jetbrains.cidr.lang.toolchains.CidrToolEnvironment
import org.rust.RsBundle
import org.rust.cargo.runconfig.CargoCommandConfigurationExtension
@@ -87,7 +82,7 @@
val valgrindParameters = parametersBuilder.build(outputFilePath)
valgrindParameters.add(programPath)
cmdLine.parametersList.prependAll(*ArrayUtil.toStringArray(valgrindParameters))
- toolchain.patchCommandLine(cmdLine)
+ toolchain.patchCommandLine(cmdLine, withSudo = false)
putUserData<File>(OUTPUT_FILE_PATH_KEY, outputFile, configuration, context)
} catch (e: IOException) {
throw ExecutionException(e)
diff --git a/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindRunner.kt b/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindRunner.kt
index 702dc9a..524a000 100644
--- a/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindRunner.kt
+++ b/clion/src/main/kotlin/org/rust/clion/valgrind/RsValgrindRunner.kt
@@ -6,7 +6,6 @@
package org.rust.clion.valgrind
import com.intellij.execution.configurations.RunProfile
-import com.jetbrains.cidr.cpp.valgrind.ValgrindExecutor
import org.rust.RsBundle
import org.rust.cargo.runconfig.RsExecutableRunner
import org.rust.cargo.runconfig.command.CargoCommandConfiguration
diff --git a/clion/src/main/kotlin/org/rust/clion/valgrind/legacy/RsValgrindRunnerLegacy.kt b/clion/src/main/kotlin/org/rust/clion/valgrind/legacy/RsValgrindRunnerLegacy.kt
index c211142..d73df00 100644
--- a/clion/src/main/kotlin/org/rust/clion/valgrind/legacy/RsValgrindRunnerLegacy.kt
+++ b/clion/src/main/kotlin/org/rust/clion/valgrind/legacy/RsValgrindRunnerLegacy.kt
@@ -7,12 +7,12 @@
import com.intellij.execution.configurations.RunProfile
import com.intellij.openapi.util.NlsContexts
-import com.jetbrains.cidr.cpp.valgrind.ValgrindExecutor
import org.rust.RsBundle
import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildToolWindowAvailable
import org.rust.cargo.runconfig.command.CargoCommandConfiguration
import org.rust.cargo.runconfig.legacy.RsAsyncRunner
import org.rust.clion.valgrind.RsValgrindConfigurationExtension
+import org.rust.clion.valgrind.ValgrindExecutor
@NlsContexts.DialogTitle
private val ERROR_MESSAGE_TITLE: String = RsBundle.message("dialog.title.unable.to.run.valgrind")
diff --git a/debugger/src/231/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt b/debugger/src/231/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt
deleted file mode 100644
index 6794ffa..0000000
--- a/debugger/src/231/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.debugger
-
-import com.intellij.util.system.CpuArch
-import com.intellij.util.system.OS
-import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBBinUrlProvider
-import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBBinUrlProvider.Bin
-import java.net.URL
-
-object RsDebuggerUrlProvider {
- fun lldbFrontend(os: OS, arch: CpuArch): URL? = LLDBBinUrlProvider.lldbFrontend.url(os, arch)
- fun lldb(os: OS, arch: CpuArch): URL? = LLDBBinUrlProvider.lldb.url(os, arch)
- @Suppress("UNUSED_PARAMETER")
- fun gdb(os: OS, arch: CpuArch): URL? = null
-
- private fun Bin.url(os: OS, arch: CpuArch): URL? {
- return when (os) {
- // Binaries for macos are universal, i.e. they may work on x86 and arm
- OS.macOS -> macX64
- OS.Linux -> {
- when (arch) {
- CpuArch.X86_64 -> linuxX64
- CpuArch.ARM64 -> linuxAarch64
- else -> null
- }
- }
- OS.Windows -> {
- when (arch) {
- CpuArch.X86_64 -> winX64
- CpuArch.ARM64 -> winAarch64
- else -> null
- }
- }
- else -> null
- }
- }
-}
diff --git a/debugger/src/232/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt b/debugger/src/232/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt
deleted file mode 100644
index 2969d94..0000000
--- a/debugger/src/232/main/kotlin/org/rust/debugger/RsDebuggerUrlProvider.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.debugger
-
-import com.intellij.util.system.CpuArch
-import com.intellij.util.system.OS
-import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider
-import java.net.URL
-
-// BACKCOMPAT: 2023.1. Use `UrlProvider` directly
-object RsDebuggerUrlProvider {
- fun lldbFrontend(os: OS, arch: CpuArch): URL? = UrlProvider.lldbFrontend(os, arch)
- fun lldb(os: OS, arch: CpuArch): URL? = UrlProvider.lldb(os, arch)
- fun gdb(os: OS, arch: CpuArch): URL? = UrlProvider.gdb(os, arch)
-}
diff --git a/debugger/src/241/main/resources/META-INF/org.rust.debugger.platform.xml b/debugger/src/241/main/resources/META-INF/org.rust.debugger.platform.xml
new file mode 100644
index 0000000..e51ee43
--- /dev/null
+++ b/debugger/src/241/main/resources/META-INF/org.rust.debugger.platform.xml
@@ -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>
diff --git a/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt b/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
index 465c4e4..28179a4 100644
--- a/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
+++ b/debugger/src/main/kotlin/org/rust/debugger/RsDebuggerToolchainService.kt
@@ -24,6 +24,7 @@
import com.intellij.util.system.CpuArch
import com.intellij.util.system.OS
import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager
+import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration
import org.rust.RsBundle
import org.rust.openapiext.RsPathManager
@@ -152,12 +153,12 @@
}
private fun lldbUrls(): Pair<URL, URL>? {
- val lldb = RsDebuggerUrlProvider.lldb(OS.CURRENT, CpuArch.CURRENT) ?: return null
- val lldbFrontend = RsDebuggerUrlProvider.lldbFrontend(OS.CURRENT, CpuArch.CURRENT) ?: return null
+ val lldb = UrlProvider.lldb(OS.CURRENT, CpuArch.CURRENT) ?: return null
+ val lldbFrontend = UrlProvider.lldbFrontend(OS.CURRENT, CpuArch.CURRENT) ?: return null
return lldb to lldbFrontend
}
- private fun gdbUrl(): URL? = RsDebuggerUrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT)
+ private fun gdbUrl(): URL? = UrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT)
@Throws(IOException::class)
private fun downloadAndUnarchive(baseDir: Path, binariesToDownload: List<DownloadableDebuggerBinary>) {
diff --git a/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt b/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
index 0118587..a4aa24b 100644
--- a/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
+++ b/debugger/src/test/kotlin/org/rust/debugger/RsDebuggerToolchainServiceTest.kt
@@ -5,8 +5,6 @@
package org.rust.debugger
-import com.intellij.openapi.application.ApplicationInfo
-import com.intellij.openapi.util.BuildNumber
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.registry.Registry
import com.intellij.util.PlatformUtils
@@ -44,7 +42,7 @@
}
fun `test gdb loading and update`() {
- if (ApplicationInfo.getInstance().build < BUILD_232 || SystemInfo.isMac) return
+ if (SystemInfo.isMac) return
checkDebuggerLoadingAndUpdate(DebuggerKind.GDB)
}
@@ -96,9 +94,4 @@
expectedFile.checkExistence()
}
}
-
- companion object {
- // BACKCOMPAT: 2023.1
- private val BUILD_232 = BuildNumber.fromString("232")!!
- }
}
diff --git a/gradle-232.properties b/gradle-232.properties
index 23437bd..71ea311 100644
--- a/gradle-232.properties
+++ b/gradle-232.properties
@@ -1,8 +1,9 @@
# Existent IDE versions can be found in the following repos:
# https://www.jetbrains.com/intellij-repository/releases/
# https://www.jetbrains.com/intellij-repository/snapshots/
-ideaVersion=IU-2023.2
-clionVersion=CL-2023.2
+ideaVersion=IU-2023.2.1
+clionVersion=CL-2023.2.1
+rustRoverVersion=
# https://plugins.jetbrains.com/plugin/12775-native-debugging-support/versions
nativeDebugPlugin=com.intellij.nativeDebug:232.8660.142
@@ -11,4 +12,4 @@
# please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description
sinceBuild=232.8296
-untilBuild=233.*
+untilBuild=232.*
diff --git a/gradle-231.properties b/gradle-233.properties
similarity index 61%
rename from gradle-231.properties
rename to gradle-233.properties
index 08becf7..70a7b50 100644
--- a/gradle-231.properties
+++ b/gradle-233.properties
@@ -1,14 +1,15 @@
# Existent IDE versions can be found in the following repos:
# https://www.jetbrains.com/intellij-repository/releases/
# https://www.jetbrains.com/intellij-repository/snapshots/
-ideaVersion=IU-2023.1
-clionVersion=CL-2023.1
+ideaVersion=IU-233.13135-EAP-CANDIDATE-SNAPSHOT
+clionVersion=CL-233.13135-EAP-CANDIDATE-SNAPSHOT
+rustRoverVersion=RR-233.11799-EAP-CANDIDATE-SNAPSHOT
# https://plugins.jetbrains.com/plugin/12775-native-debugging-support/versions
-nativeDebugPlugin=com.intellij.nativeDebug:231.8109.91
+nativeDebugPlugin=com.intellij.nativeDebug:233.13135.65
# https://plugins.jetbrains.com/plugin/227-psiviewer/versions
-psiViewerPlugin=PsiViewer:231-SNAPSHOT
+psiViewerPlugin=PsiViewer:233.2
# please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description
-sinceBuild=231.7515
-untilBuild=231.*
+sinceBuild=233.8264
+untilBuild=233.*
diff --git a/gradle-231.properties b/gradle-241.properties
similarity index 61%
copy from gradle-231.properties
copy to gradle-241.properties
index 08becf7..1608ff3 100644
--- a/gradle-231.properties
+++ b/gradle-241.properties
@@ -1,14 +1,15 @@
# Existent IDE versions can be found in the following repos:
# https://www.jetbrains.com/intellij-repository/releases/
# https://www.jetbrains.com/intellij-repository/snapshots/
-ideaVersion=IU-2023.1
-clionVersion=CL-2023.1
+ideaVersion=IU-233.13135-EAP-CANDIDATE-SNAPSHOT
+clionVersion=CL-233.13135-EAP-CANDIDATE-SNAPSHOT
+rustRoverVersion=RR-233.11799-EAP-CANDIDATE-SNAPSHOT
# https://plugins.jetbrains.com/plugin/12775-native-debugging-support/versions
-nativeDebugPlugin=com.intellij.nativeDebug:231.8109.91
+nativeDebugPlugin=com.intellij.nativeDebug:233.13135.65
# https://plugins.jetbrains.com/plugin/227-psiviewer/versions
-psiViewerPlugin=PsiViewer:231-SNAPSHOT
+psiViewerPlugin=PsiViewer:233.2
# please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description
-sinceBuild=231.7515
-untilBuild=231.*
+sinceBuild=241.17
+untilBuild=241.*
diff --git a/gradle.properties b/gradle.properties
index e0e5479..f7ad3b7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,11 +1,11 @@
propertiesPluginEnvironmentNameProperty=platformVersion
-# Supported platforms: 231, 232
-platformVersion=232
-# Supported IDEs: idea, clion
+# Supported platforms: 232, 233, 241
+platformVersion=233
+# Supported IDEs: idea, clion, rustRover
baseIDE=idea
+ideToRun=
-patchVersion=201
-buildNumber=SNAPSHOT
+buildNumber=999999-SNAPSHOT
publishToken=token
publishChannel=dev
@@ -20,7 +20,7 @@
org.gradle.jvmargs=-Xmx3g
# Enable Gradle Build Cache. It is also configured in settings.gradle.kts.
-org.gradle.caching=true
+org.gradle.caching=false
systemProp.org.gradle.internal.repository.max.tentatives=10
systemProp.org.gradle.internal.http.connectionTimeout=120000
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 943f0cb..7f93135 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2b22d05..d11cdd9 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 65dcd68..0adc8e1 100755
--- a/gradlew
+++ b/gradlew
@@ -83,10 +83,8 @@
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,10 +131,13 @@
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
@@ -144,7 +145,7 @@
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +153,7 @@
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -197,6 +198,10 @@
done
fi
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
diff --git a/idea/src/test/kotlin/org/rust/ide/idea/RsIdeaProjectViewTest.kt b/idea/src/test/kotlin/org/rust/ide/idea/RsIdeaProjectViewTest.kt
index 66877c1..b13fcf5 100644
--- a/idea/src/test/kotlin/org/rust/ide/idea/RsIdeaProjectViewTest.kt
+++ b/idea/src/test/kotlin/org/rust/ide/idea/RsIdeaProjectViewTest.kt
@@ -5,6 +5,8 @@
package org.rust.ide.idea
+import org.junit.Ignore
import org.rustSlowTests.RsProjectViewTestBase
+@Ignore // TODO RUST-12027 doesn't work on 233
class RsIdeaProjectViewTest : RsProjectViewTestBase()
diff --git a/profiler/src/231/main/kotlin/org/rust/profiler/perf/compatUtils.kt b/profiler/src/231/main/kotlin/org/rust/profiler/perf/compatUtils.kt
deleted file mode 100644
index ba686b3..0000000
--- a/profiler/src/231/main/kotlin/org/rust/profiler/perf/compatUtils.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.profiler.perf
-
-import com.intellij.execution.process.BaseProcessHandler
-import com.intellij.openapi.project.Project
-import com.intellij.profiler.clion.perf.PerfProfilerProcess
-import com.jetbrains.cidr.lang.toolchains.CidrToolEnvironment
-import java.nio.file.Path
-
-fun createProfilerProcess(
- handler: BaseProcessHandler<*>,
- outputPerfDataFile: Path,
- processName: String,
- project: Project,
- attachedTimestamp: Long,
- toolEnvironment: CidrToolEnvironment,
-): PerfProfilerProcess = PerfProfilerProcess(
- handler,
- false,
- outputPerfDataFile,
- processName,
- project,
- attachedTimestamp,
- toolEnvironment
-)
diff --git a/profiler/src/main/kotlin/org/rust/profiler/RsCachingStackElementReader.kt b/profiler/src/232/main/kotlin/org/rust/profiler/RsCachingStackElementReader.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/RsCachingStackElementReader.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/RsCachingStackElementReader.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/RsProfilerRunner.kt b/profiler/src/232/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/RsSymbolSearcher.kt b/profiler/src/232/main/kotlin/org/rust/profiler/RsSymbolSearcher.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/RsSymbolSearcher.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/RsSymbolSearcher.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt b/profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceNavigatableNativeCall.kt b/profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceNavigatableNativeCall.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceNavigatableNativeCall.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceNavigatableNativeCall.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt b/profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt b/profiler/src/232/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
similarity index 100%
rename from profiler/src/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
diff --git a/profiler/src/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt b/profiler/src/232/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
similarity index 97%
rename from profiler/src/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
rename to profiler/src/232/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
index f059355..123f1ac 100644
--- a/profiler/src/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
+++ b/profiler/src/232/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
@@ -15,6 +15,7 @@
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.SystemInfo
import com.intellij.profiler.ProfilerToolWindowManager
+import com.intellij.profiler.clion.perf.PerfProfilerProcess
import com.intellij.profiler.clion.perf.PerfProfilerSettings
import com.intellij.profiler.clion.perf.PerfUtils
import com.intellij.profiler.statistics.ProfilerUsageTriggerCollector
@@ -65,7 +66,7 @@
val perfPath = toolchain.toLocalPath(settings.executablePath.orEmpty())
val outputFilePath = PerfUtils.createOutputFilePath(toolEnvironment, settings.outputDirectory.nullize())
cmdLine.addPerfStarter(perfPath, settings.samplingFrequency, settings.defaultCmdArgs, outputFilePath.toString())
- toolchain.patchCommandLine(cmdLine)
+ toolchain.patchCommandLine(cmdLine, withSudo = false)
context.putUserData(PERF_OUTPUT_FILE_KEY, outputFilePath)
}
@@ -89,7 +90,7 @@
?: throw ExecutionException(RsBundle.message("dialog.message.can.t.get.output.perf.data.file"))
val project = configuration.project
- val profilerProcess = createProfilerProcess(
+ val profilerProcess = PerfProfilerProcess(
handler,
outputFile,
configuration.name,
diff --git a/profiler/src/232/main/kotlin/org/rust/profiler/perf/compatUtils.kt b/profiler/src/232/main/kotlin/org/rust/profiler/perf/compatUtils.kt
deleted file mode 100644
index 97dc93b..0000000
--- a/profiler/src/232/main/kotlin/org/rust/profiler/perf/compatUtils.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.profiler.perf
-
-import com.intellij.execution.process.BaseProcessHandler
-import com.intellij.openapi.project.Project
-import com.intellij.profiler.clion.perf.PerfProfilerProcess
-import com.jetbrains.cidr.lang.toolchains.CidrToolEnvironment
-import java.nio.file.Path
-
-// BACKCOMPAT: 2023.1. Inline it
-fun createProfilerProcess(
- handler: BaseProcessHandler<*>,
- outputPerfDataFile: Path,
- processName: String,
- project: Project,
- attachedTimestamp: Long,
- toolEnvironment: CidrToolEnvironment,
-): PerfProfilerProcess = PerfProfilerProcess(
- handler,
- outputPerfDataFile,
- processName,
- project,
- attachedTimestamp,
- toolEnvironment
-)
diff --git a/profiler/src/main/resources/org.rust.profiler.xml b/profiler/src/232/main/resources/org.rust.profiler.xml
similarity index 100%
rename from profiler/src/main/resources/org.rust.profiler.xml
rename to profiler/src/232/main/resources/org.rust.profiler.xml
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt
new file mode 100644
index 0000000..7890ebe
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt
@@ -0,0 +1,28 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.process.ProcessInfo
+import com.intellij.icons.AllIcons
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.UserDataHolder
+import com.intellij.xdebugger.attach.XAttachProcessPresentationGroup
+import org.rust.RsBundle
+import javax.swing.Icon
+
+object RsAttachPresentationGroup: XAttachProcessPresentationGroup {
+ override fun getOrder(): Int = 0
+
+ override fun getGroupName(): String = RsBundle.message("profiler.attach.default.group.title")
+
+ override fun getItemIcon(project: Project, info: ProcessInfo, dataHolder: UserDataHolder): Icon {
+ return AllIcons.RunConfigurations.Application
+ }
+
+ override fun getItemDisplayText(project: Project, info: ProcessInfo, dataHolder: UserDataHolder): String {
+ return info.executableDisplayName
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt
new file mode 100644
index 0000000..b801fc9
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt
@@ -0,0 +1,55 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.openapi.application.runReadAction
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.clion.NavigatableSymbolSearcher
+import com.intellij.psi.NavigatablePsiElement
+import com.intellij.psi.search.GlobalSearchScope
+import org.rust.lang.core.psi.RsFunction
+import org.rust.lang.core.psi.ext.qualifiedName
+import org.rust.lang.core.stubs.index.RsNamedElementIndex
+import org.rust.openapiext.getElements
+
+class RsNavigatableSymbolSearcher : NavigatableSymbolSearcher() {
+
+ override fun doFindNavigatableSymbols(qualifiedSignature: String, project: Project): Array<NavigatablePsiElement> {
+ val elements = mutableListOf<RsFunction>()
+ val searchScope = GlobalSearchScope.allScope(project)
+ val qualifiedPath = extractPath(qualifiedSignature)
+
+ runReadAction {
+ val allDeclarations = getElements(RsNamedElementIndex.KEY, qualifiedSignature, project, searchScope)
+ .filterIsInstance<RsFunction>()
+ val appropriateDeclarations = allDeclarations
+ .filter { it.qualifiedName?.substringBeforeLast("::") == qualifiedPath }
+
+ if (appropriateDeclarations.isNotEmpty()) {
+ elements.addAll(appropriateDeclarations)
+ } else {
+ // TODO: return all or nothing?
+ elements.addAll(allDeclarations)
+ }
+ }
+
+ return elements.toTypedArray()
+ }
+
+ companion object {
+ /**
+ * `_<foo::bar123::foo_bar::Qux as baz>::qux` -> `foo::bar123::foo_bar`
+ *
+ * It doesn't work for crates/modules with inappropriate names (e.g. upper-case)
+ *
+ * TODO: add tests
+ */
+ private fun extractPath(signature: String): String = signature
+ .dropWhile { !it.isLetter() }
+ .takeWhile { (it.isLetterOrDigit() && it.isLowerCase()) || it == '_' || it == ':' }
+ .removeSuffix("::")
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt
new file mode 100644
index 0000000..53d1ff6
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt
@@ -0,0 +1,128 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.ExecutionException
+import com.intellij.execution.configuration.EnvironmentVariablesData
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.PtyCommandLine
+import com.intellij.execution.process.*
+import com.intellij.openapi.progress.ProgressIndicator
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.profiler.clion.ProfilerEnvironmentHost
+import com.intellij.xdebugger.attach.WslAttachHost
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.RsCapturingProcessHandler
+import org.rust.cargo.runconfig.RsProcessHandler
+import org.rust.cargo.toolchain.BacktraceMode
+import org.rust.cargo.toolchain.RsLocalToolchain
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+import org.rust.openapiext.execute
+import org.rust.stdext.toPath
+import org.rust.stdext.toPathOrNull
+import java.nio.file.Path
+
+class RsProfilerEnvironmentHost : ProfilerEnvironmentHost {
+
+ override fun shouldCheckFilePathExist(project: Project): Boolean {
+ val toolchain = project.toolchain ?: return false
+ return toolchain is RsLocalToolchain
+ }
+
+ override fun getPath(path: String, project: Project): Path =
+ project.toolchain?.toLocalPath(path)?.toPathOrNull() ?: Path.of(path) // TODO: return null
+
+ override fun getEnvPath(path: String?, project: Project): String {
+ if (path == null) return "" // TODO: return null
+ return project.toolchain?.toRemotePath(path).toString()
+ }
+
+ override fun getTempDirectory(project: Project): Path = FileUtil.getTempDirectory().toPath()
+
+ override fun isRemote(project: Project): Boolean {
+ val toolchain = project.toolchain ?: return false
+ return toolchain !is RsLocalToolchain
+ }
+
+ override fun isWSL(project: Project): Boolean = project.toolchain is RsWslToolchain
+
+ override fun getWSLVersion(project: Project): Int {
+ val toolchain = project.toolchain as? RsWslToolchain ?: return -1
+ return toolchain.wslPath.distribution.version
+ }
+
+ override fun createProcessHandler(
+ commandLine: GeneralCommandLine,
+ project: Project,
+ colored: Boolean?,
+ usePty: Boolean?,
+ captureProcessOutput: Boolean?,
+ splitLines: Boolean?, // TODO: take it into account
+ withElevated: Boolean?
+ ): BaseProcessHandler<*> {
+ var tmpCommandLine = commandLine
+
+ if (usePty == true) {
+ tmpCommandLine = PtyCommandLine(commandLine)
+ .withInitialColumns(PtyCommandLine.MAX_COLUMNS)
+ .withConsoleMode(false)
+ }
+
+ val toolchain = project.toolchain ?: throw ExecutionException(RsBundle.message("dialog.message.rust.toolchain.is.not.set"))
+ tmpCommandLine = toolchain.patchCommandLine(tmpCommandLine, withElevated ?: false)
+
+ @Suppress("UnstableApiUsage")
+ return when {
+ withElevated == true -> ElevationService.getInstance().createProcessHandler(tmpCommandLine)
+ colored == true -> RsProcessHandler(tmpCommandLine, colored)
+ captureProcessOutput == true -> RsCapturingProcessHandler.startProcess(tmpCommandLine).unwrap()
+ else -> RsProcessHandler(tmpCommandLine, false)
+ }
+ }
+
+ override fun runProcess(
+ handler: ProcessHandler,
+ indicator: ProgressIndicator,
+ timeout: Int,
+ project: Project
+ ): ProcessOutput = CapturingProcessRunner(handler).runProcess(indicator, timeout)
+
+ override fun getProcessList(project: Project): List<ProcessInfo> =
+ when (val toolchain = project.toolchain) {
+ is RsLocalToolchain -> OSProcessUtil.getProcessList().toList()
+ is RsWslToolchain -> WslAttachHost(toolchain.wslPath.distribution).processList
+ else -> emptyList()
+ }
+
+ override fun sendSignal(pid: Int, signalName: String, project: Project): Int =
+ when (val toolchain = project.toolchain) {
+ is RsLocalToolchain -> {
+ if (SystemInfo.isWindows) {
+ throw UnsupportedOperationException("Not supported for Windows OS, use winbreak instead")
+ }
+ UnixProcessManager.sendSignal(pid, signalName)
+ }
+
+ is RsWslToolchain -> {
+ toolchain.createGeneralCommandLine(
+ Path.of("kill"),
+ Path.of("."),
+ null,
+ BacktraceMode.NO,
+ EnvironmentVariablesData.DEFAULT,
+ listOf("-s", signalName, pid.toString()),
+ emulateTerminal = false,
+ withSudo = false,
+ patchToRemote = true // ???
+ ).execute(5000)?.exitCode ?: -1
+ }
+
+ else -> -1
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt
new file mode 100644
index 0000000..4e97e96
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt
@@ -0,0 +1,14 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.clion.ProfilerEnvironmentHost
+import com.intellij.profiler.clion.ProfilerEnvironmentHostProvider
+
+class RsProfilerEnvironmentHostProvider: ProfilerEnvironmentHostProvider {
+ override fun getEnvironmentHost(project: Project): ProfilerEnvironmentHost = RsProfilerEnvironmentHost()
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt
new file mode 100644
index 0000000..b05a6d9
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt
@@ -0,0 +1,13 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.profiler.clion.ProfilerPresentationGroup
+import com.intellij.xdebugger.attach.XAttachProcessPresentationGroup
+
+class RsProfilerPresentationGroup : ProfilerPresentationGroup {
+ override fun getPresentationGroup(): XAttachProcessPresentationGroup = RsAttachPresentationGroup
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt
new file mode 100644
index 0000000..cb8781a
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt
@@ -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.profiler
+
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerRunChecker
+
+class RsProfilerRunChecker : ProfilerRunChecker {
+ override fun canRun(profile: RunProfile): Boolean = false
+ override fun isDTraceProfilerCanBeUsed(): Boolean = SystemInfo.isMac
+ override fun isPerfProfilerCanBeUsed(): Boolean = SystemInfo.isLinux || SystemInfo.isWindows
+ override fun isProfilerCompatible(configuration: RunProfile): Boolean = true
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunner.kt b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
new file mode 100644
index 0000000..2cd3009
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
@@ -0,0 +1,37 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.configurations.RunConfiguration
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerExecutor
+import com.intellij.profiler.clion.ProfilerRunChecker
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.RsExecutableRunner
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+
+class RsProfilerRunner : RsExecutableRunner(ProfilerExecutor.EXECUTOR_ID, RsBundle.message("dialog.title.unable.to.run.profiler")) {
+ override fun getRunnerId(): String = RUNNER_ID
+
+ override fun canRun(executorId: String, profile: RunProfile): Boolean {
+ if (!ProfilerRunChecker.canRun()) return false
+
+ if (SystemInfo.isWindows) {
+ val toolchain = (profile as? RunConfiguration)?.project?.toolchain
+ if (toolchain !is RsWslToolchain) return false
+ }
+
+ return super.canRun(executorId, profile)
+ }
+
+
+ companion object {
+ const val RUNNER_ID: String = "RsProfilerRunner"
+ const val IJ_RUNNER_ID: String = "ProfilerRunner"
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt b/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
new file mode 100644
index 0000000..38eb8d1
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
@@ -0,0 +1,91 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.dtrace
+
+import com.intellij.execution.ExecutionException
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.RunnerSettings
+import com.intellij.execution.impl.ExecutionManagerImpl
+import com.intellij.execution.process.BaseProcessHandler
+import com.intellij.execution.process.OSProcessUtil
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.process.UnixProcessManager
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.openapi.progress.PerformInBackgroundOption
+import com.intellij.profiler.ProfilerToolWindowManager
+import com.intellij.profiler.clion.DTraceProfilerConfigurationExtension
+import com.intellij.profiler.clion.NativeTargetProcess
+import com.intellij.profiler.clion.ProfilerConfigurationExtension
+import com.intellij.profiler.dtrace.legacyDTraceProfilerConfiguration
+import com.intellij.profiler.installErrorHandlers
+import com.intellij.profiler.statistics.ProfilerUsageTriggerCollector
+import org.rust.RsBundle
+import org.rust.cargo.runconfig.CargoCommandConfigurationExtension
+import org.rust.cargo.runconfig.ConfigurationExtensionContext
+import org.rust.cargo.runconfig.command.CargoCommandConfiguration
+import org.rust.profiler.RsProfilerEnvironmentHost
+import org.rust.profiler.RsProfilerRunner
+import org.rust.profiler.RsProfilerRunner.Companion.IJ_RUNNER_ID
+import org.rust.profiler.legacy.RsProfilerRunnerLegacy
+
+class RsDTraceConfigurationExtension : CargoCommandConfigurationExtension() {
+ private val delegate: ProfilerConfigurationExtension = DTraceProfilerConfigurationExtension()
+
+ override fun isApplicableFor(configuration: CargoCommandConfiguration): Boolean =
+ delegate.isApplicableFor(configuration)
+
+ override fun isEnabledFor(
+ applicableConfiguration: CargoCommandConfiguration,
+ runnerSettings: RunnerSettings?
+ ): Boolean = delegate.isEnabledFor(applicableConfiguration, RsProfilerEnvironmentHost(), runnerSettings)
+
+ override fun patchCommandLine(
+ configuration: CargoCommandConfiguration,
+ environment: ExecutionEnvironment,
+ cmdLine: GeneralCommandLine,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.patchCommandLine(
+ configuration,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ cmdLine,
+ IJ_RUNNER_ID,
+ context
+ )
+ }
+
+ override fun attachToProcess(
+ configuration: CargoCommandConfiguration,
+ handler: ProcessHandler,
+ environment: ExecutionEnvironment,
+ context: ConfigurationExtensionContext
+ ) {
+ val project = configuration.project
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ if (RsProfilerEnvironmentHost().isRemote(project)) return
+ val targetProcess = (handler as? BaseProcessHandler<*>)?.process
+ ?: throw ExecutionException(RsBundle.message("dialog.message.profiler.connection.error.can.t.detect.target.process.id"))
+ ProfilerUsageTriggerCollector.logRecordingStarted(
+ project,
+ legacyDTraceProfilerConfiguration.configurationTypeId,
+ configuration.type.id
+ )
+ val namedProcess = NativeTargetProcess(OSProcessUtil.getProcessID(targetProcess), configuration.name)
+ RsDTraceProfilerProcess.attach(namedProcess, PerformInBackgroundOption.ALWAYS_BACKGROUND, 10000, project)
+ .installErrorHandlers(project)
+ .onError { ExecutionManagerImpl.stopProcess(handler) }
+ .onSuccess { process ->
+ UnixProcessManager.sendSigIntToProcessTree(targetProcess) //wakeup starter and finally run targetProcess code
+ ProfilerToolWindowManager.getInstance(project).addProfilerProcessTab(process)
+ }
+ }
+
+ companion object {
+ private val PROFILER_RUNNER_IDS: List<String> = listOf(RsProfilerRunner.RUNNER_ID, RsProfilerRunnerLegacy.RUNNER_ID)
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt b/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
new file mode 100644
index 0000000..c08c55a
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
@@ -0,0 +1,91 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.dtrace
+
+import com.intellij.openapi.progress.PerformInBackgroundOption
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.DummyCallTreeBuilder
+import com.intellij.profiler.api.*
+import com.intellij.profiler.clion.NativeCallDTraceCachingStackElementReader
+import com.intellij.profiler.clion.dtrace.DTraceProfilerSettings
+import com.intellij.profiler.clion.perf.NavigatableNativeCall
+import com.intellij.profiler.dtrace.DTraceProfilerProcessBase
+import com.intellij.profiler.dtrace.FullDumpParser
+import com.intellij.profiler.dtrace.SimpleProfilerSettingsState
+import com.intellij.profiler.dtrace.cpuProfilerScript
+import com.intellij.profiler.model.NativeCall
+import com.intellij.profiler.model.NativeThread
+import com.intellij.profiler.sudo.SudoProcessHandler
+import com.intellij.profiler.ui.NativeCallStackElementRenderer
+import com.intellij.util.xmlb.XmlSerializer
+import org.jetbrains.concurrency.Promise
+import org.rust.lang.utils.RsDemangler
+
+
+class RsDTraceProfilerProcess private constructor(
+ project: Project,
+ targetProcess: AttachableTargetProcess,
+ attachedTimestamp: Long,
+ dtraceProcessHandler: SudoProcessHandler
+) : DTraceProfilerProcessBase(project, targetProcess, attachedTimestamp, dtraceProcessHandler) {
+
+ // We can't use [com.intellij.profiler.clion.ProfilerUtilsKt.CPP_PROFILER_HELP_TOPIC] directly
+ // because it has `internal` modifier
+ override val helpId: String = "procedures.profiler"
+
+ override fun createDumpParser(): FullDumpParser<BaseCallStackElement> {
+ val cachingStackElementReader = NativeCallDTraceCachingStackElementReader.getInstance(project)
+ return FullDumpParser(
+ { NativeThread(it, "thread with id $it") },
+ cachingStackElementReader::parseStackElement
+ )
+ }
+
+ override fun createDumpWriter(data: NewCallTreeOnlyProfilerData): ProfilerDumpWriter =
+ CollapsedProfilerDumpWriter(data.builder, targetProcess.fullName, attachedTimestamp, { it.fullName() }, { it.name })
+
+ override fun createProfilerData(builder: DummyCallTreeBuilder<BaseCallStackElement>): NewCallTreeOnlyProfilerData =
+ NewCallTreeOnlyProfilerData(builder, NativeCallStackElementRenderer.INSTANCE)
+
+ override fun postProcessData(builder: DummyCallTreeBuilder<BaseCallStackElement>): DummyCallTreeBuilder<BaseCallStackElement> {
+ builder.mapTreeElements {
+ if (it !is NavigatableNativeCall) return@mapTreeElements it
+ val library = it.fullName().substringBeforeLast('`')
+ val fullName = it.fullName().substringAfterLast('`')
+ val demangledName = RsDemangler.tryDemangle(fullName)?.format(skipHash = true) ?: return@mapTreeElements it
+ val path = demangledName.substringBeforeLast("::")
+ val method = demangledName.substringAfterLast("::")
+ val nativeCall = NativeCall(library, path, method)
+ NavigatableNativeCall(nativeCall)
+ }
+ return super.postProcessData(builder)
+ }
+
+ companion object {
+ fun attach(
+ targetProcess: AttachableTargetProcess,
+ backgroundOption: PerformInBackgroundOption,
+ timeoutInMilliseconds: Int,
+ project: Project
+ ): Promise<RsDTraceProfilerProcess> {
+ val settings = DTraceProfilerSettings.instance.state
+
+ // WARNING: Do not use such solution for other needs!
+ // We want to always use -xmangled option because DTrace cannot demangle Rust symbols correctly
+ val element = XmlSerializer.serialize(settings)
+ val settingsCopy = XmlSerializer.deserialize(element, SimpleProfilerSettingsState::class.java)
+ settingsCopy.defaultCmdArgs.add("-xmangled")
+
+ return attachBase(
+ targetProcess,
+ backgroundOption,
+ settingsCopy.cpuProfilerScript(),
+ timeoutInMilliseconds,
+ project
+ ) { handler, _ -> RsDTraceProfilerProcess(project, targetProcess, System.currentTimeMillis(), handler) }
+ }
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt b/profiler/src/233/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
new file mode 100644
index 0000000..2eefc88
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
@@ -0,0 +1,43 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.legacy
+
+import com.intellij.execution.configurations.RunConfiguration
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.NlsContexts
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerExecutor
+import com.intellij.profiler.clion.ProfilerRunChecker
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildToolWindowAvailable
+import org.rust.cargo.runconfig.legacy.RsAsyncRunner
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+
+@NlsContexts.DialogTitle
+private val ERROR_MESSAGE_TITLE: String = RsBundle.message("dialog.title.unable.to.run.profiler")
+
+/**
+ * This runner is used if [isBuildToolWindowAvailable] is false.
+ */
+class RsProfilerRunnerLegacy : RsAsyncRunner(ProfilerExecutor.EXECUTOR_ID, ERROR_MESSAGE_TITLE) {
+ override fun getRunnerId(): String = RUNNER_ID
+
+ override fun canRun(executorId: String, profile: RunProfile): Boolean {
+ if (!ProfilerRunChecker.canRun()) return false
+
+ if (SystemInfo.isWindows) {
+ val toolchain = (profile as? RunConfiguration)?.project?.toolchain
+ if (toolchain !is RsWslToolchain) return false
+ }
+
+ return super.canRun(executorId, profile)
+ }
+
+ companion object {
+ const val RUNNER_ID: String = "RsProfilerRunnerLegacy"
+ }
+}
diff --git a/profiler/src/233/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt b/profiler/src/233/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
new file mode 100644
index 0000000..96c20a1
--- /dev/null
+++ b/profiler/src/233/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
@@ -0,0 +1,72 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.perf
+
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.RunnerSettings
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.profiler.clion.ProfilerConfigurationExtension
+import com.intellij.profiler.clion.perf.PerfProfilerConfigurationExtension
+import org.rust.cargo.runconfig.CargoCommandConfigurationExtension
+import org.rust.cargo.runconfig.ConfigurationExtensionContext
+import org.rust.cargo.runconfig.command.CargoCommandConfiguration
+import org.rust.profiler.RsProfilerEnvironmentHost
+import org.rust.profiler.RsProfilerRunner
+import org.rust.profiler.RsProfilerRunner.Companion.IJ_RUNNER_ID
+import org.rust.profiler.legacy.RsProfilerRunnerLegacy
+
+class RsPerfConfigurationExtension : CargoCommandConfigurationExtension() {
+ private val delegate: ProfilerConfigurationExtension = PerfProfilerConfigurationExtension()
+
+ override fun isApplicableFor(configuration: CargoCommandConfiguration): Boolean =
+ delegate.isApplicableFor(configuration)
+
+ override fun isEnabledFor(
+ applicableConfiguration: CargoCommandConfiguration,
+ runnerSettings: RunnerSettings?
+ ): Boolean = delegate.isEnabledFor(applicableConfiguration, RsProfilerEnvironmentHost(), runnerSettings)
+
+ override fun patchCommandLine(
+ configuration: CargoCommandConfiguration,
+ environment: ExecutionEnvironment,
+ cmdLine: GeneralCommandLine,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.patchCommandLine(
+ configuration,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ cmdLine,
+ IJ_RUNNER_ID,
+ context
+ )
+ val toolchain = configuration.clean().ok?.toolchain ?: return
+ toolchain.patchCommandLine(cmdLine, withSudo = false)
+ }
+
+ override fun attachToProcess(
+ configuration: CargoCommandConfiguration,
+ handler: ProcessHandler,
+ environment: ExecutionEnvironment,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.attachToProcess(
+ configuration,
+ handler,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ IJ_RUNNER_ID,
+ context
+ )
+ }
+
+ companion object {
+ private val PROFILER_RUNNER_IDS = listOf(RsProfilerRunner.RUNNER_ID, RsProfilerRunnerLegacy.RUNNER_ID)
+ }
+}
diff --git a/profiler/src/233/main/resources/org.rust.profiler.xml b/profiler/src/233/main/resources/org.rust.profiler.xml
new file mode 100644
index 0000000..12d3a4b
--- /dev/null
+++ b/profiler/src/233/main/resources/org.rust.profiler.xml
@@ -0,0 +1,23 @@
+<idea-plugin package="org.rust.profiler">
+ <!--suppress PluginXmlValidity -->
+ <dependencies>
+ <module name="intellij.profiler.asyncOne"/>
+ <module name="intellij.profiler.common"/>
+ <module name="intellij.profiler.clion"/>
+ </dependencies>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <programRunner implementation="org.rust.profiler.RsProfilerRunner"/>
+ <programRunner implementation="org.rust.profiler.legacy.RsProfilerRunnerLegacy"/>
+
+ <profiler.clion.profilerRunChecker implementation="org.rust.profiler.RsProfilerRunChecker"/>
+ <profiler.clion.profilerEnvironmentHostProvider implementation="org.rust.profiler.RsProfilerEnvironmentHostProvider"/>
+ <profiler.clion.navigatableSymbolSearcher implementation="org.rust.profiler.RsNavigatableSymbolSearcher"/>
+ <profiler.clion.profilerPresentationGroup implementation="org.rust.profiler.RsProfilerPresentationGroup"/>
+ </extensions>
+
+ <extensions defaultExtensionNs="org.rust">
+ <runConfigurationExtension implementation="org.rust.profiler.perf.RsPerfConfigurationExtension"/>
+ <runConfigurationExtension implementation="org.rust.profiler.dtrace.RsDTraceConfigurationExtension"/>
+ </extensions>
+</idea-plugin>
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt
new file mode 100644
index 0000000..7890ebe
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsAttachPresentationGroup.kt
@@ -0,0 +1,28 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.process.ProcessInfo
+import com.intellij.icons.AllIcons
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.UserDataHolder
+import com.intellij.xdebugger.attach.XAttachProcessPresentationGroup
+import org.rust.RsBundle
+import javax.swing.Icon
+
+object RsAttachPresentationGroup: XAttachProcessPresentationGroup {
+ override fun getOrder(): Int = 0
+
+ override fun getGroupName(): String = RsBundle.message("profiler.attach.default.group.title")
+
+ override fun getItemIcon(project: Project, info: ProcessInfo, dataHolder: UserDataHolder): Icon {
+ return AllIcons.RunConfigurations.Application
+ }
+
+ override fun getItemDisplayText(project: Project, info: ProcessInfo, dataHolder: UserDataHolder): String {
+ return info.executableDisplayName
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt
new file mode 100644
index 0000000..b801fc9
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsNavigatableSymbolSearcher.kt
@@ -0,0 +1,55 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.openapi.application.runReadAction
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.clion.NavigatableSymbolSearcher
+import com.intellij.psi.NavigatablePsiElement
+import com.intellij.psi.search.GlobalSearchScope
+import org.rust.lang.core.psi.RsFunction
+import org.rust.lang.core.psi.ext.qualifiedName
+import org.rust.lang.core.stubs.index.RsNamedElementIndex
+import org.rust.openapiext.getElements
+
+class RsNavigatableSymbolSearcher : NavigatableSymbolSearcher() {
+
+ override fun doFindNavigatableSymbols(qualifiedSignature: String, project: Project): Array<NavigatablePsiElement> {
+ val elements = mutableListOf<RsFunction>()
+ val searchScope = GlobalSearchScope.allScope(project)
+ val qualifiedPath = extractPath(qualifiedSignature)
+
+ runReadAction {
+ val allDeclarations = getElements(RsNamedElementIndex.KEY, qualifiedSignature, project, searchScope)
+ .filterIsInstance<RsFunction>()
+ val appropriateDeclarations = allDeclarations
+ .filter { it.qualifiedName?.substringBeforeLast("::") == qualifiedPath }
+
+ if (appropriateDeclarations.isNotEmpty()) {
+ elements.addAll(appropriateDeclarations)
+ } else {
+ // TODO: return all or nothing?
+ elements.addAll(allDeclarations)
+ }
+ }
+
+ return elements.toTypedArray()
+ }
+
+ companion object {
+ /**
+ * `_<foo::bar123::foo_bar::Qux as baz>::qux` -> `foo::bar123::foo_bar`
+ *
+ * It doesn't work for crates/modules with inappropriate names (e.g. upper-case)
+ *
+ * TODO: add tests
+ */
+ private fun extractPath(signature: String): String = signature
+ .dropWhile { !it.isLetter() }
+ .takeWhile { (it.isLetterOrDigit() && it.isLowerCase()) || it == '_' || it == ':' }
+ .removeSuffix("::")
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt
new file mode 100644
index 0000000..53d1ff6
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHost.kt
@@ -0,0 +1,128 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.ExecutionException
+import com.intellij.execution.configuration.EnvironmentVariablesData
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.PtyCommandLine
+import com.intellij.execution.process.*
+import com.intellij.openapi.progress.ProgressIndicator
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.profiler.clion.ProfilerEnvironmentHost
+import com.intellij.xdebugger.attach.WslAttachHost
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.RsCapturingProcessHandler
+import org.rust.cargo.runconfig.RsProcessHandler
+import org.rust.cargo.toolchain.BacktraceMode
+import org.rust.cargo.toolchain.RsLocalToolchain
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+import org.rust.openapiext.execute
+import org.rust.stdext.toPath
+import org.rust.stdext.toPathOrNull
+import java.nio.file.Path
+
+class RsProfilerEnvironmentHost : ProfilerEnvironmentHost {
+
+ override fun shouldCheckFilePathExist(project: Project): Boolean {
+ val toolchain = project.toolchain ?: return false
+ return toolchain is RsLocalToolchain
+ }
+
+ override fun getPath(path: String, project: Project): Path =
+ project.toolchain?.toLocalPath(path)?.toPathOrNull() ?: Path.of(path) // TODO: return null
+
+ override fun getEnvPath(path: String?, project: Project): String {
+ if (path == null) return "" // TODO: return null
+ return project.toolchain?.toRemotePath(path).toString()
+ }
+
+ override fun getTempDirectory(project: Project): Path = FileUtil.getTempDirectory().toPath()
+
+ override fun isRemote(project: Project): Boolean {
+ val toolchain = project.toolchain ?: return false
+ return toolchain !is RsLocalToolchain
+ }
+
+ override fun isWSL(project: Project): Boolean = project.toolchain is RsWslToolchain
+
+ override fun getWSLVersion(project: Project): Int {
+ val toolchain = project.toolchain as? RsWslToolchain ?: return -1
+ return toolchain.wslPath.distribution.version
+ }
+
+ override fun createProcessHandler(
+ commandLine: GeneralCommandLine,
+ project: Project,
+ colored: Boolean?,
+ usePty: Boolean?,
+ captureProcessOutput: Boolean?,
+ splitLines: Boolean?, // TODO: take it into account
+ withElevated: Boolean?
+ ): BaseProcessHandler<*> {
+ var tmpCommandLine = commandLine
+
+ if (usePty == true) {
+ tmpCommandLine = PtyCommandLine(commandLine)
+ .withInitialColumns(PtyCommandLine.MAX_COLUMNS)
+ .withConsoleMode(false)
+ }
+
+ val toolchain = project.toolchain ?: throw ExecutionException(RsBundle.message("dialog.message.rust.toolchain.is.not.set"))
+ tmpCommandLine = toolchain.patchCommandLine(tmpCommandLine, withElevated ?: false)
+
+ @Suppress("UnstableApiUsage")
+ return when {
+ withElevated == true -> ElevationService.getInstance().createProcessHandler(tmpCommandLine)
+ colored == true -> RsProcessHandler(tmpCommandLine, colored)
+ captureProcessOutput == true -> RsCapturingProcessHandler.startProcess(tmpCommandLine).unwrap()
+ else -> RsProcessHandler(tmpCommandLine, false)
+ }
+ }
+
+ override fun runProcess(
+ handler: ProcessHandler,
+ indicator: ProgressIndicator,
+ timeout: Int,
+ project: Project
+ ): ProcessOutput = CapturingProcessRunner(handler).runProcess(indicator, timeout)
+
+ override fun getProcessList(project: Project): List<ProcessInfo> =
+ when (val toolchain = project.toolchain) {
+ is RsLocalToolchain -> OSProcessUtil.getProcessList().toList()
+ is RsWslToolchain -> WslAttachHost(toolchain.wslPath.distribution).processList
+ else -> emptyList()
+ }
+
+ override fun sendSignal(pid: Int, signalName: String, project: Project): Int =
+ when (val toolchain = project.toolchain) {
+ is RsLocalToolchain -> {
+ if (SystemInfo.isWindows) {
+ throw UnsupportedOperationException("Not supported for Windows OS, use winbreak instead")
+ }
+ UnixProcessManager.sendSignal(pid, signalName)
+ }
+
+ is RsWslToolchain -> {
+ toolchain.createGeneralCommandLine(
+ Path.of("kill"),
+ Path.of("."),
+ null,
+ BacktraceMode.NO,
+ EnvironmentVariablesData.DEFAULT,
+ listOf("-s", signalName, pid.toString()),
+ emulateTerminal = false,
+ withSudo = false,
+ patchToRemote = true // ???
+ ).execute(5000)?.exitCode ?: -1
+ }
+
+ else -> -1
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt
new file mode 100644
index 0000000..4e97e96
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerEnvironmentHostProvider.kt
@@ -0,0 +1,14 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.clion.ProfilerEnvironmentHost
+import com.intellij.profiler.clion.ProfilerEnvironmentHostProvider
+
+class RsProfilerEnvironmentHostProvider: ProfilerEnvironmentHostProvider {
+ override fun getEnvironmentHost(project: Project): ProfilerEnvironmentHost = RsProfilerEnvironmentHost()
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt
new file mode 100644
index 0000000..b05a6d9
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerPresentationGroup.kt
@@ -0,0 +1,13 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.profiler.clion.ProfilerPresentationGroup
+import com.intellij.xdebugger.attach.XAttachProcessPresentationGroup
+
+class RsProfilerPresentationGroup : ProfilerPresentationGroup {
+ override fun getPresentationGroup(): XAttachProcessPresentationGroup = RsAttachPresentationGroup
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt
new file mode 100644
index 0000000..cb8781a
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunChecker.kt
@@ -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.profiler
+
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerRunChecker
+
+class RsProfilerRunChecker : ProfilerRunChecker {
+ override fun canRun(profile: RunProfile): Boolean = false
+ override fun isDTraceProfilerCanBeUsed(): Boolean = SystemInfo.isMac
+ override fun isPerfProfilerCanBeUsed(): Boolean = SystemInfo.isLinux || SystemInfo.isWindows
+ override fun isProfilerCompatible(configuration: RunProfile): Boolean = true
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunner.kt b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
new file mode 100644
index 0000000..2cd3009
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/RsProfilerRunner.kt
@@ -0,0 +1,37 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler
+
+import com.intellij.execution.configurations.RunConfiguration
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerExecutor
+import com.intellij.profiler.clion.ProfilerRunChecker
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.RsExecutableRunner
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+
+class RsProfilerRunner : RsExecutableRunner(ProfilerExecutor.EXECUTOR_ID, RsBundle.message("dialog.title.unable.to.run.profiler")) {
+ override fun getRunnerId(): String = RUNNER_ID
+
+ override fun canRun(executorId: String, profile: RunProfile): Boolean {
+ if (!ProfilerRunChecker.canRun()) return false
+
+ if (SystemInfo.isWindows) {
+ val toolchain = (profile as? RunConfiguration)?.project?.toolchain
+ if (toolchain !is RsWslToolchain) return false
+ }
+
+ return super.canRun(executorId, profile)
+ }
+
+
+ companion object {
+ const val RUNNER_ID: String = "RsProfilerRunner"
+ const val IJ_RUNNER_ID: String = "ProfilerRunner"
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt b/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
new file mode 100644
index 0000000..38eb8d1
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceConfigurationExtension.kt
@@ -0,0 +1,91 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.dtrace
+
+import com.intellij.execution.ExecutionException
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.RunnerSettings
+import com.intellij.execution.impl.ExecutionManagerImpl
+import com.intellij.execution.process.BaseProcessHandler
+import com.intellij.execution.process.OSProcessUtil
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.process.UnixProcessManager
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.openapi.progress.PerformInBackgroundOption
+import com.intellij.profiler.ProfilerToolWindowManager
+import com.intellij.profiler.clion.DTraceProfilerConfigurationExtension
+import com.intellij.profiler.clion.NativeTargetProcess
+import com.intellij.profiler.clion.ProfilerConfigurationExtension
+import com.intellij.profiler.dtrace.legacyDTraceProfilerConfiguration
+import com.intellij.profiler.installErrorHandlers
+import com.intellij.profiler.statistics.ProfilerUsageTriggerCollector
+import org.rust.RsBundle
+import org.rust.cargo.runconfig.CargoCommandConfigurationExtension
+import org.rust.cargo.runconfig.ConfigurationExtensionContext
+import org.rust.cargo.runconfig.command.CargoCommandConfiguration
+import org.rust.profiler.RsProfilerEnvironmentHost
+import org.rust.profiler.RsProfilerRunner
+import org.rust.profiler.RsProfilerRunner.Companion.IJ_RUNNER_ID
+import org.rust.profiler.legacy.RsProfilerRunnerLegacy
+
+class RsDTraceConfigurationExtension : CargoCommandConfigurationExtension() {
+ private val delegate: ProfilerConfigurationExtension = DTraceProfilerConfigurationExtension()
+
+ override fun isApplicableFor(configuration: CargoCommandConfiguration): Boolean =
+ delegate.isApplicableFor(configuration)
+
+ override fun isEnabledFor(
+ applicableConfiguration: CargoCommandConfiguration,
+ runnerSettings: RunnerSettings?
+ ): Boolean = delegate.isEnabledFor(applicableConfiguration, RsProfilerEnvironmentHost(), runnerSettings)
+
+ override fun patchCommandLine(
+ configuration: CargoCommandConfiguration,
+ environment: ExecutionEnvironment,
+ cmdLine: GeneralCommandLine,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.patchCommandLine(
+ configuration,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ cmdLine,
+ IJ_RUNNER_ID,
+ context
+ )
+ }
+
+ override fun attachToProcess(
+ configuration: CargoCommandConfiguration,
+ handler: ProcessHandler,
+ environment: ExecutionEnvironment,
+ context: ConfigurationExtensionContext
+ ) {
+ val project = configuration.project
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ if (RsProfilerEnvironmentHost().isRemote(project)) return
+ val targetProcess = (handler as? BaseProcessHandler<*>)?.process
+ ?: throw ExecutionException(RsBundle.message("dialog.message.profiler.connection.error.can.t.detect.target.process.id"))
+ ProfilerUsageTriggerCollector.logRecordingStarted(
+ project,
+ legacyDTraceProfilerConfiguration.configurationTypeId,
+ configuration.type.id
+ )
+ val namedProcess = NativeTargetProcess(OSProcessUtil.getProcessID(targetProcess), configuration.name)
+ RsDTraceProfilerProcess.attach(namedProcess, PerformInBackgroundOption.ALWAYS_BACKGROUND, 10000, project)
+ .installErrorHandlers(project)
+ .onError { ExecutionManagerImpl.stopProcess(handler) }
+ .onSuccess { process ->
+ UnixProcessManager.sendSigIntToProcessTree(targetProcess) //wakeup starter and finally run targetProcess code
+ ProfilerToolWindowManager.getInstance(project).addProfilerProcessTab(process)
+ }
+ }
+
+ companion object {
+ private val PROFILER_RUNNER_IDS: List<String> = listOf(RsProfilerRunner.RUNNER_ID, RsProfilerRunnerLegacy.RUNNER_ID)
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt b/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
new file mode 100644
index 0000000..c08c55a
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/dtrace/RsDTraceProfilerProcess.kt
@@ -0,0 +1,91 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.dtrace
+
+import com.intellij.openapi.progress.PerformInBackgroundOption
+import com.intellij.openapi.project.Project
+import com.intellij.profiler.DummyCallTreeBuilder
+import com.intellij.profiler.api.*
+import com.intellij.profiler.clion.NativeCallDTraceCachingStackElementReader
+import com.intellij.profiler.clion.dtrace.DTraceProfilerSettings
+import com.intellij.profiler.clion.perf.NavigatableNativeCall
+import com.intellij.profiler.dtrace.DTraceProfilerProcessBase
+import com.intellij.profiler.dtrace.FullDumpParser
+import com.intellij.profiler.dtrace.SimpleProfilerSettingsState
+import com.intellij.profiler.dtrace.cpuProfilerScript
+import com.intellij.profiler.model.NativeCall
+import com.intellij.profiler.model.NativeThread
+import com.intellij.profiler.sudo.SudoProcessHandler
+import com.intellij.profiler.ui.NativeCallStackElementRenderer
+import com.intellij.util.xmlb.XmlSerializer
+import org.jetbrains.concurrency.Promise
+import org.rust.lang.utils.RsDemangler
+
+
+class RsDTraceProfilerProcess private constructor(
+ project: Project,
+ targetProcess: AttachableTargetProcess,
+ attachedTimestamp: Long,
+ dtraceProcessHandler: SudoProcessHandler
+) : DTraceProfilerProcessBase(project, targetProcess, attachedTimestamp, dtraceProcessHandler) {
+
+ // We can't use [com.intellij.profiler.clion.ProfilerUtilsKt.CPP_PROFILER_HELP_TOPIC] directly
+ // because it has `internal` modifier
+ override val helpId: String = "procedures.profiler"
+
+ override fun createDumpParser(): FullDumpParser<BaseCallStackElement> {
+ val cachingStackElementReader = NativeCallDTraceCachingStackElementReader.getInstance(project)
+ return FullDumpParser(
+ { NativeThread(it, "thread with id $it") },
+ cachingStackElementReader::parseStackElement
+ )
+ }
+
+ override fun createDumpWriter(data: NewCallTreeOnlyProfilerData): ProfilerDumpWriter =
+ CollapsedProfilerDumpWriter(data.builder, targetProcess.fullName, attachedTimestamp, { it.fullName() }, { it.name })
+
+ override fun createProfilerData(builder: DummyCallTreeBuilder<BaseCallStackElement>): NewCallTreeOnlyProfilerData =
+ NewCallTreeOnlyProfilerData(builder, NativeCallStackElementRenderer.INSTANCE)
+
+ override fun postProcessData(builder: DummyCallTreeBuilder<BaseCallStackElement>): DummyCallTreeBuilder<BaseCallStackElement> {
+ builder.mapTreeElements {
+ if (it !is NavigatableNativeCall) return@mapTreeElements it
+ val library = it.fullName().substringBeforeLast('`')
+ val fullName = it.fullName().substringAfterLast('`')
+ val demangledName = RsDemangler.tryDemangle(fullName)?.format(skipHash = true) ?: return@mapTreeElements it
+ val path = demangledName.substringBeforeLast("::")
+ val method = demangledName.substringAfterLast("::")
+ val nativeCall = NativeCall(library, path, method)
+ NavigatableNativeCall(nativeCall)
+ }
+ return super.postProcessData(builder)
+ }
+
+ companion object {
+ fun attach(
+ targetProcess: AttachableTargetProcess,
+ backgroundOption: PerformInBackgroundOption,
+ timeoutInMilliseconds: Int,
+ project: Project
+ ): Promise<RsDTraceProfilerProcess> {
+ val settings = DTraceProfilerSettings.instance.state
+
+ // WARNING: Do not use such solution for other needs!
+ // We want to always use -xmangled option because DTrace cannot demangle Rust symbols correctly
+ val element = XmlSerializer.serialize(settings)
+ val settingsCopy = XmlSerializer.deserialize(element, SimpleProfilerSettingsState::class.java)
+ settingsCopy.defaultCmdArgs.add("-xmangled")
+
+ return attachBase(
+ targetProcess,
+ backgroundOption,
+ settingsCopy.cpuProfilerScript(),
+ timeoutInMilliseconds,
+ project
+ ) { handler, _ -> RsDTraceProfilerProcess(project, targetProcess, System.currentTimeMillis(), handler) }
+ }
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt b/profiler/src/241/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
new file mode 100644
index 0000000..2eefc88
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/legacy/RsProfilerRunnerLegacy.kt
@@ -0,0 +1,43 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.legacy
+
+import com.intellij.execution.configurations.RunConfiguration
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.openapi.util.NlsContexts
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.profiler.clion.ProfilerExecutor
+import com.intellij.profiler.clion.ProfilerRunChecker
+import org.rust.RsBundle
+import org.rust.cargo.project.settings.toolchain
+import org.rust.cargo.runconfig.buildtool.CargoBuildManager.isBuildToolWindowAvailable
+import org.rust.cargo.runconfig.legacy.RsAsyncRunner
+import org.rust.cargo.toolchain.wsl.RsWslToolchain
+
+@NlsContexts.DialogTitle
+private val ERROR_MESSAGE_TITLE: String = RsBundle.message("dialog.title.unable.to.run.profiler")
+
+/**
+ * This runner is used if [isBuildToolWindowAvailable] is false.
+ */
+class RsProfilerRunnerLegacy : RsAsyncRunner(ProfilerExecutor.EXECUTOR_ID, ERROR_MESSAGE_TITLE) {
+ override fun getRunnerId(): String = RUNNER_ID
+
+ override fun canRun(executorId: String, profile: RunProfile): Boolean {
+ if (!ProfilerRunChecker.canRun()) return false
+
+ if (SystemInfo.isWindows) {
+ val toolchain = (profile as? RunConfiguration)?.project?.toolchain
+ if (toolchain !is RsWslToolchain) return false
+ }
+
+ return super.canRun(executorId, profile)
+ }
+
+ companion object {
+ const val RUNNER_ID: String = "RsProfilerRunnerLegacy"
+ }
+}
diff --git a/profiler/src/241/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt b/profiler/src/241/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
new file mode 100644
index 0000000..96c20a1
--- /dev/null
+++ b/profiler/src/241/main/kotlin/org/rust/profiler/perf/RsPerfConfigurationExtension.kt
@@ -0,0 +1,72 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.profiler.perf
+
+import com.intellij.execution.configurations.GeneralCommandLine
+import com.intellij.execution.configurations.RunnerSettings
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.profiler.clion.ProfilerConfigurationExtension
+import com.intellij.profiler.clion.perf.PerfProfilerConfigurationExtension
+import org.rust.cargo.runconfig.CargoCommandConfigurationExtension
+import org.rust.cargo.runconfig.ConfigurationExtensionContext
+import org.rust.cargo.runconfig.command.CargoCommandConfiguration
+import org.rust.profiler.RsProfilerEnvironmentHost
+import org.rust.profiler.RsProfilerRunner
+import org.rust.profiler.RsProfilerRunner.Companion.IJ_RUNNER_ID
+import org.rust.profiler.legacy.RsProfilerRunnerLegacy
+
+class RsPerfConfigurationExtension : CargoCommandConfigurationExtension() {
+ private val delegate: ProfilerConfigurationExtension = PerfProfilerConfigurationExtension()
+
+ override fun isApplicableFor(configuration: CargoCommandConfiguration): Boolean =
+ delegate.isApplicableFor(configuration)
+
+ override fun isEnabledFor(
+ applicableConfiguration: CargoCommandConfiguration,
+ runnerSettings: RunnerSettings?
+ ): Boolean = delegate.isEnabledFor(applicableConfiguration, RsProfilerEnvironmentHost(), runnerSettings)
+
+ override fun patchCommandLine(
+ configuration: CargoCommandConfiguration,
+ environment: ExecutionEnvironment,
+ cmdLine: GeneralCommandLine,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.patchCommandLine(
+ configuration,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ cmdLine,
+ IJ_RUNNER_ID,
+ context
+ )
+ val toolchain = configuration.clean().ok?.toolchain ?: return
+ toolchain.patchCommandLine(cmdLine, withSudo = false)
+ }
+
+ override fun attachToProcess(
+ configuration: CargoCommandConfiguration,
+ handler: ProcessHandler,
+ environment: ExecutionEnvironment,
+ context: ConfigurationExtensionContext
+ ) {
+ if (environment.runner.runnerId !in PROFILER_RUNNER_IDS) return
+ delegate.attachToProcess(
+ configuration,
+ handler,
+ RsProfilerEnvironmentHost(),
+ environment.runnerSettings,
+ IJ_RUNNER_ID,
+ context
+ )
+ }
+
+ companion object {
+ private val PROFILER_RUNNER_IDS = listOf(RsProfilerRunner.RUNNER_ID, RsProfilerRunnerLegacy.RUNNER_ID)
+ }
+}
diff --git a/profiler/src/241/main/resources/org.rust.profiler.xml b/profiler/src/241/main/resources/org.rust.profiler.xml
new file mode 100644
index 0000000..12d3a4b
--- /dev/null
+++ b/profiler/src/241/main/resources/org.rust.profiler.xml
@@ -0,0 +1,23 @@
+<idea-plugin package="org.rust.profiler">
+ <!--suppress PluginXmlValidity -->
+ <dependencies>
+ <module name="intellij.profiler.asyncOne"/>
+ <module name="intellij.profiler.common"/>
+ <module name="intellij.profiler.clion"/>
+ </dependencies>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <programRunner implementation="org.rust.profiler.RsProfilerRunner"/>
+ <programRunner implementation="org.rust.profiler.legacy.RsProfilerRunnerLegacy"/>
+
+ <profiler.clion.profilerRunChecker implementation="org.rust.profiler.RsProfilerRunChecker"/>
+ <profiler.clion.profilerEnvironmentHostProvider implementation="org.rust.profiler.RsProfilerEnvironmentHostProvider"/>
+ <profiler.clion.navigatableSymbolSearcher implementation="org.rust.profiler.RsNavigatableSymbolSearcher"/>
+ <profiler.clion.profilerPresentationGroup implementation="org.rust.profiler.RsProfilerPresentationGroup"/>
+ </extensions>
+
+ <extensions defaultExtensionNs="org.rust">
+ <runConfigurationExtension implementation="org.rust.profiler.perf.RsPerfConfigurationExtension"/>
+ <runConfigurationExtension implementation="org.rust.profiler.dtrace.RsDTraceConfigurationExtension"/>
+ </extensions>
+</idea-plugin>
diff --git a/qodana.yaml b/qodana.yaml
deleted file mode 100644
index c83ad3e..0000000
--- a/qodana.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-version: "1.0"
-linter: jetbrains/qodana-jvm-community:2023.1
-profile:
- name: qodana.recommended
-exclude:
- - name: DialogTitleCapitalization
- - name: IncompleteDestructuring
- - name: UnstableApiUsage
- - name: UnstableTypeUsedInSignature
- - name: PropertyName
- - name: PrivatePropertyName
diff --git a/scripts/run_pretty_printer_tests.py b/scripts/run_pretty_printer_tests.py
index dee39dd..1bed6a3 100644
--- a/scripts/run_pretty_printer_tests.py
+++ b/scripts/run_pretty_printer_tests.py
@@ -1,3 +1,4 @@
+import argparse
import os
import platform
import stat
@@ -5,8 +6,6 @@
from enum import Enum, auto
from os import path
-import argparse
-
from common import execute_command
@@ -70,12 +69,6 @@
python = "python3"
elif host_os == OS.Windows:
lldb_bundle_path = path.abspath(f"deps/clion-{clion_version}/bin/lldb/win/{arch_name}")
- # Create symlink to allow `lldb` Python module perform `import _lldb` inside
- # BACKCOMPAT: 2023.1. `lib/site-packages/lldb/_lldb.pyd` exists since CLion 2023.1
- lldb_pyd = f"{lldb_bundle_path}/lib/site-packages/lldb/_lldb.pyd"
- if not path.exists(lldb_pyd):
- os.symlink(f"{lldb_bundle_path}/bin/liblldb.dll", f"{lldb_bundle_path}/lib/site-packages/lldb/_lldb.pyd")
-
lldb_path = f"{lldb_bundle_path}/lib/site-packages"
python = f"{lldb_bundle_path}/bin/python.exe"
else:
diff --git a/src/231/main/kotlin/org/rust/ide/navigation/compatUtils.kt b/src/231/main/kotlin/org/rust/ide/navigation/compatUtils.kt
deleted file mode 100644
index c63b065..0000000
--- a/src/231/main/kotlin/org/rust/ide/navigation/compatUtils.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.ide.navigation
-
-import com.intellij.codeInsight.navigation.NavigationUtil
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.ui.popup.JBPopup
-import com.intellij.openapi.util.NlsContexts
-import com.intellij.psi.PsiElement
-
-fun getPsiElementPopup(elements: Array<PsiElement>, title: @NlsContexts.PopupTitle String?): JBPopup {
- return NavigationUtil.getPsiElementPopup(elements, title)
-}
-
-fun hidePopupIfDumbModeStarts(popup: JBPopup, project: Project) {
- NavigationUtil.hidePopupIfDumbModeStarts(popup, project)
-}
diff --git a/src/231/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt b/src/231/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt
deleted file mode 100644
index d9d666e..0000000
--- a/src/231/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.ide.wordSelection
-
-class RsBlocksAndBodiesSelectionHandlerTest : RsSelectionHandlerTestBase() {
- fun `test fn body basic`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- |<caret> let x = 1;
- |}
- |""",
-
- """
- |fn foo() {
- |<selection> let x = 1;
- |</selection>}
- |""",
-
- """
- |fn foo() <selection>{
- | let x = 1;
- |}
- |</selection>""")
-
- fun `test fun body multiline`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let x = 1;
- |
- |<caret> let x = 1;
- | let x = 1;
- |
- | let x = 1;
- |}
- |""",
-
- """
- |fn foo() {
- | let x = 1;
- |
- |<selection> let x = 1;
- |</selection> let x = 1;
- |
- | let x = 1;
- |}
- |""",
-
- """
- |fn foo() {
- | let x = 1;
- |
- |<selection> let x = 1;
- | let x = 1;
- |</selection>
- | let x = 1;
- |}
- |""",
-
- """
- |fn foo() {
- |<selection> let x = 1;
- |
- | let x = 1;
- | let x = 1;
- |
- | let x = 1;
- |</selection>}
- |""")
-
- fun `test fun body line comments`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | // foo
- |
- |<caret> // foo
- | // foo
- |
- | // foo
- |}
- |""",
-
- """
- |fn foo() {
- | // foo
- |
- |<selection> // foo
- |</selection> // foo
- |
- | // foo
- |}
- |""",
-
- """
- |fn foo() {
- | // foo
- |
- |<selection> // foo
- | // foo
- |</selection>
- | // foo
- |}
- |""",
-
- """
- |fn foo() {
- |<selection> // foo
- |
- | // foo
- | // foo
- |
- | // foo
- |</selection>}
- |""")
-
- fun `test fun block expression`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let block = {
- | let x = 1;
- |
- |<caret> let x = 1;
- | let x = 1;
- |
- | let x = 1;
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let block = {
- | let x = 1;
- |
- |<selection> let x = 1;
- |</selection> let x = 1;
- |
- | let x = 1;
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let block = {
- | let x = 1;
- |
- |<selection> let x = 1;
- | let x = 1;
- |</selection>
- | let x = 1;
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let block = {
- |<selection> let x = 1;
- |
- | let x = 1;
- | let x = 1;
- |
- | let x = 1;
- |</selection> };
- |}
- |""")
-
- fun `test struct body`() = doTestWithTrimmedMargins(
- """
- |struct Point {
- | a : i32,
- |
- |<caret> a : i32,
- | a : i32,
- |
- | a : i32
- |}
- |""",
-
- """
- |struct Point {
- | a : i32,
- |
- |<selection> a : i32,
- |</selection> a : i32,
- |
- | a : i32
- |}
- |""",
-
- """
- |struct Point {
- | a : i32,
- |
- |<selection> a : i32,
- | a : i32,
- |</selection>
- | a : i32
- |}
- |""",
-
- """
- |struct Point {
- |<selection> a : i32,
- |
- | a : i32,
- | a : i32,
- |
- | a : i32
- |</selection>}
- |""")
-
- fun `test struct literal body`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let x = Point {
- | a: 0,
- |
- |<caret> a: 0,
- | a: 0,
- |
- | a: 0
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- | a: 0,
- |
- |<selection> a: 0,
- |</selection> a: 0,
- |
- | a: 0
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- | a: 0,
- |
- |<selection> a: 0,
- | a: 0,
- |</selection>
- | a: 0
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- |<selection> a: 0,
- |
- | a: 0,
- | a: 0,
- |
- | a: 0
- |</selection> };
- |}
- |""")
-
- fun `test struct body last field`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let x = Point {
- | a : i32,
- |
- |<caret> a : i32
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- | a : i32,
- |
- |<selection> a : i32
- |</selection> };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- |<selection> a : i32,
- |
- | a : i32
- |</selection> };
- |}
- |""")
-
- fun `test struct literal body last field`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let x = Point {
- | a: 0,
- |
- |<caret> a: 0
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- | a: 0,
- |
- |<selection> a: 0
- |</selection> };
- |}
- |""",
-
- """
- |fn foo() {
- | let x = Point {
- |<selection> a: 0,
- |
- | a: 0
- |</selection> };
- |}
- |""")
-
- fun `test enum body`() = doTestWithTrimmedMargins(
- """
- |enum E {
- | A,
- |
- |<caret> A,
- | A,
- |
- | A
- |}
- |""",
-
- """
- |enum E {
- | A,
- |
- |<selection> A,
- |</selection> A,
- |
- | A
- |}
- |""",
-
- """
- |enum E {
- | A,
- |
- |<selection> A,
- | A,
- |</selection>
- | A
- |}
- |""",
-
- """
- |enum E {
- |<selection> A,
- |
- | A,
- | A,
- |
- | A
- |</selection>}
- |""")
-
- fun `test trait body`() = doTestWithTrimmedMargins(
- """
- |trait Trait<T> {
- | fn f();
- |
- |<caret> fn f();
- | fn f();
- |
- | fn f();
- |}
- |""",
-
- """
- |trait Trait<T> {
- | fn f();
- |
- |<selection> fn f();
- |</selection> fn f();
- |
- | fn f();
- |}
- |""",
-
- """
- |trait Trait<T> {
- | fn f();
- |
- |<selection> fn f();
- | fn f();
- |</selection>
- | fn f();
- |}
- |""",
-
- """
- |trait Trait<T> {
- |<selection> fn f();
- |
- | fn f();
- | fn f();
- |
- | fn f();
- |</selection>}
- |""")
-
-
- fun `test match expression`() = doTestWithTrimmedMargins(
- """
- |fn foo() {
- | let a = match 1 {
- | 1 => 1,
- |
- |<caret> 2 => 2,
- | 3 => {
- | 3
- | },
- |
- | _ => 0,
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let a = match 1 {
- | 1 => 1,
- |
- |<selection> 2 => 2,
- |</selection> 3 => {
- | 3
- | },
- |
- | _ => 0,
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let a = match 1 {
- | 1 => 1,
- |
- |<selection> 2 => 2,
- | 3 => {
- | 3
- | },
- |</selection>
- | _ => 0,
- | };
- |}
- |""",
-
- """
- |fn foo() {
- | let a = match 1 {
- |<selection> 1 => 1,
- |
- | 2 => 2,
- | 3 => {
- | 3
- | },
- |
- | _ => 0,
- |</selection> };
- |}
- |""")
-}
diff --git a/src/232/main/kotlin/org/rust/ide/navigation/compatUtils.kt b/src/232/main/kotlin/org/rust/ide/navigation/compatUtils.kt
deleted file mode 100644
index 4af06b7..0000000
--- a/src/232/main/kotlin/org/rust/ide/navigation/compatUtils.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Use of this source code is governed by the MIT license that can be
- * found in the LICENSE file.
- */
-
-package org.rust.ide.navigation
-
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.ui.popup.JBPopup
-import com.intellij.openapi.util.NlsContexts
-import com.intellij.psi.PsiElement
-
-// BACKCOMPAT: 2023.1. Inline it
-fun getPsiElementPopup(elements: Array<PsiElement>, title: @NlsContexts.PopupTitle String?): JBPopup {
- return com.intellij.codeInsight.navigation.getPsiElementPopup(elements, title)
-}
-
-// BACKCOMPAT: 2023.1. Inline it
-fun hidePopupIfDumbModeStarts(popup: JBPopup, project: Project) {
- com.intellij.codeInsight.navigation.hidePopupIfDumbModeStarts(popup, project)
-}
diff --git a/src/232/test/kotlin/org/rust/DumbModeTestUtil.kt b/src/232/test/kotlin/org/rust/DumbModeTestUtil.kt
new file mode 100644
index 0000000..4eb009e
--- /dev/null
+++ b/src/232/test/kotlin/org/rust/DumbModeTestUtil.kt
@@ -0,0 +1,28 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import com.intellij.openapi.project.DumbServiceImpl
+import com.intellij.openapi.project.Project
+
+@Suppress("UnstableApiUsage")
+object DumbModeTestUtil {
+ fun startEternalDumbModeTask(project: Project): Token {
+ val dumbService = DumbServiceImpl.getInstance(project)
+ val oldValue = dumbService.isDumb
+ dumbService.isDumb = true
+ return Token(dumbService, oldValue)
+ }
+
+ class Token(
+ private val dumbService: DumbServiceImpl,
+ private val oldValue: Boolean,
+ ) : AutoCloseable {
+ override fun close() {
+ dumbService.isDumb = oldValue
+ }
+ }
+}
diff --git a/src/232/test/kotlin/org/rust/TestCompat.kt b/src/232/test/kotlin/org/rust/TestCompat.kt
new file mode 100644
index 0000000..cb50afa
--- /dev/null
+++ b/src/232/test/kotlin/org/rust/TestCompat.kt
@@ -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
+
+import com.intellij.openapi.util.Key
+
+val Key<*>.escapeSequence: String
+ get() = toString()
diff --git a/src/test/kotlin/org/rust/ide/MockBrowserLauncher.kt b/src/232/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
similarity index 100%
rename from src/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
rename to src/232/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
diff --git a/src/233/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt b/src/233/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt
new file mode 100644
index 0000000..cbfeff5
--- /dev/null
+++ b/src/233/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt
@@ -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.ide.debugger.runconfig
+
+import com.intellij.ide.plugins.IdeaPluginDescriptor
+import com.intellij.ide.plugins.PluginManagerCore
+
+fun PluginManagerCore.getLoadedPlugins(): List<IdeaPluginDescriptor> = loadedPlugins
diff --git a/src/233/test/kotlin/org/rust/DumbModeTestUtil.kt b/src/233/test/kotlin/org/rust/DumbModeTestUtil.kt
new file mode 100644
index 0000000..8f7fd69
--- /dev/null
+++ b/src/233/test/kotlin/org/rust/DumbModeTestUtil.kt
@@ -0,0 +1,24 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import com.intellij.openapi.project.Project
+import com.intellij.testFramework.DumbModeTestUtils
+
+object DumbModeTestUtil {
+ fun startEternalDumbModeTask(project: Project): Token {
+ return Token(project, DumbModeTestUtils.startEternalDumbModeTask(project))
+ }
+
+ class Token(
+ private val project: Project,
+ private val token: DumbModeTestUtils.EternalTaskShutdownToken
+ ) : AutoCloseable {
+ override fun close() {
+ DumbModeTestUtils.endEternalDumbModeTaskAndWaitForSmartMode(project, token)
+ }
+ }
+}
diff --git a/src/233/test/kotlin/org/rust/TestCompat.kt b/src/233/test/kotlin/org/rust/TestCompat.kt
new file mode 100644
index 0000000..58321a7
--- /dev/null
+++ b/src/233/test/kotlin/org/rust/TestCompat.kt
@@ -0,0 +1,13 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import com.intellij.execution.process.ProcessOutputType
+import com.intellij.openapi.util.Key
+
+// BACKCOMPAT 2023.2: move to the RsAnsiEscapeDecoderTest companion
+val Key<*>.escapeSequence: String
+ get() = (this as? ProcessOutputType)?.escapeSequence ?: toString()
diff --git a/src/233/test/kotlin/org/rust/ide/MockBrowserLauncher.kt b/src/233/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
new file mode 100644
index 0000000..ce47a7f
--- /dev/null
+++ b/src/233/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
@@ -0,0 +1,39 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.ide
+
+import com.intellij.ide.browsers.BrowserLauncher
+import com.intellij.ide.browsers.WebBrowser
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.project.Project
+import com.intellij.testFramework.replaceService
+import java.io.File
+import java.nio.file.Path
+
+class MockBrowserLauncher : BrowserLauncher() {
+ private var lastFile: File? = null
+ private var lastPath: Path? = null
+ var lastUrl: String? = null
+
+ override fun browse(file: File) {
+ lastFile = file
+ }
+
+ override fun browse(file: Path) {
+ lastPath = file
+ }
+
+ override fun browse(url: String, browser: WebBrowser?, project: Project?) {
+ lastUrl = url
+ }
+
+ override fun open(url: String) {}
+
+ fun replaceService(disposable: Disposable) {
+ ApplicationManager.getApplication().replaceService(BrowserLauncher::class.java, this, disposable)
+ }
+}
diff --git a/src/241/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt b/src/241/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt
new file mode 100644
index 0000000..cbfeff5
--- /dev/null
+++ b/src/241/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt
@@ -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.ide.debugger.runconfig
+
+import com.intellij.ide.plugins.IdeaPluginDescriptor
+import com.intellij.ide.plugins.PluginManagerCore
+
+fun PluginManagerCore.getLoadedPlugins(): List<IdeaPluginDescriptor> = loadedPlugins
diff --git a/src/241/test/kotlin/org/rust/DumbModeTestUtil.kt b/src/241/test/kotlin/org/rust/DumbModeTestUtil.kt
new file mode 100644
index 0000000..8f7fd69
--- /dev/null
+++ b/src/241/test/kotlin/org/rust/DumbModeTestUtil.kt
@@ -0,0 +1,24 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import com.intellij.openapi.project.Project
+import com.intellij.testFramework.DumbModeTestUtils
+
+object DumbModeTestUtil {
+ fun startEternalDumbModeTask(project: Project): Token {
+ return Token(project, DumbModeTestUtils.startEternalDumbModeTask(project))
+ }
+
+ class Token(
+ private val project: Project,
+ private val token: DumbModeTestUtils.EternalTaskShutdownToken
+ ) : AutoCloseable {
+ override fun close() {
+ DumbModeTestUtils.endEternalDumbModeTaskAndWaitForSmartMode(project, token)
+ }
+ }
+}
diff --git a/src/241/test/kotlin/org/rust/TestCompat.kt b/src/241/test/kotlin/org/rust/TestCompat.kt
new file mode 100644
index 0000000..58321a7
--- /dev/null
+++ b/src/241/test/kotlin/org/rust/TestCompat.kt
@@ -0,0 +1,13 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import com.intellij.execution.process.ProcessOutputType
+import com.intellij.openapi.util.Key
+
+// BACKCOMPAT 2023.2: move to the RsAnsiEscapeDecoderTest companion
+val Key<*>.escapeSequence: String
+ get() = (this as? ProcessOutputType)?.escapeSequence ?: toString()
diff --git a/src/241/test/kotlin/org/rust/ide/MockBrowserLauncher.kt b/src/241/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
new file mode 100644
index 0000000..ce47a7f
--- /dev/null
+++ b/src/241/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
@@ -0,0 +1,39 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.ide
+
+import com.intellij.ide.browsers.BrowserLauncher
+import com.intellij.ide.browsers.WebBrowser
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.project.Project
+import com.intellij.testFramework.replaceService
+import java.io.File
+import java.nio.file.Path
+
+class MockBrowserLauncher : BrowserLauncher() {
+ private var lastFile: File? = null
+ private var lastPath: Path? = null
+ var lastUrl: String? = null
+
+ override fun browse(file: File) {
+ lastFile = file
+ }
+
+ override fun browse(file: Path) {
+ lastPath = file
+ }
+
+ override fun browse(url: String, browser: WebBrowser?, project: Project?) {
+ lastUrl = url
+ }
+
+ override fun open(url: String) {}
+
+ fun replaceService(disposable: Disposable) {
+ ApplicationManager.getApplication().replaceService(BrowserLauncher::class.java, this, disposable)
+ }
+}
diff --git a/src/main/kotlin/org/rust/cargo/project/settings/RsExternalLinterProjectSettingsService.kt b/src/main/kotlin/org/rust/cargo/project/settings/RsExternalLinterProjectSettingsService.kt
index d83dc35..1bdddcd 100644
--- a/src/main/kotlin/org/rust/cargo/project/settings/RsExternalLinterProjectSettingsService.kt
+++ b/src/main/kotlin/org/rust/cargo/project/settings/RsExternalLinterProjectSettingsService.kt
@@ -29,16 +29,6 @@
val envs: Map<String, String> get() = state.envs
val runOnTheFly: Boolean get() = state.runOnTheFly
- override fun noStateLoaded() {
- val rustSettings = project.rustSettings
- state.tool = rustSettings.state.externalLinter
- rustSettings.state.externalLinter = ExternalLinter.DEFAULT
- state.additionalArguments = rustSettings.state.externalLinterArguments
- rustSettings.state.externalLinterArguments = ""
- state.runOnTheFly = rustSettings.state.runExternalLinterOnTheFly
- rustSettings.state.runExternalLinterOnTheFly = false
- }
-
class RsExternalLinterProjectSettings : RsProjectSettingsBase<RsExternalLinterProjectSettings>() {
@AffectsHighlighting
var tool by enum(ExternalLinter.DEFAULT)
diff --git a/src/main/kotlin/org/rust/cargo/project/settings/RustProjectSettingsService.kt b/src/main/kotlin/org/rust/cargo/project/settings/RustProjectSettingsService.kt
index 06fb55f..0310afb 100644
--- a/src/main/kotlin/org/rust/cargo/project/settings/RustProjectSettingsService.kt
+++ b/src/main/kotlin/org/rust/cargo/project/settings/RustProjectSettingsService.kt
@@ -16,7 +16,6 @@
import com.intellij.util.xmlb.annotations.Transient
import org.rust.cargo.project.configurable.RsProjectConfigurable
import org.rust.cargo.project.settings.RustProjectSettingsService.RustProjectSettings
-import org.rust.cargo.toolchain.ExternalLinter
import org.rust.cargo.toolchain.RsToolchainBase
import org.rust.cargo.toolchain.RsToolchainProvider
import org.rust.openapiext.isUnitTestMode
@@ -64,12 +63,6 @@
// provide path to stdlib explicitly.
@AffectsCargoMetadata
var explicitPathToStdlib by string()
- // BACKCOMPAT: 2023.1
- var externalLinter by enum(ExternalLinter.DEFAULT)
- // BACKCOMPAT: 2023.1
- var runExternalLinterOnTheFly by property(false)
- // BACKCOMPAT: 2023.1
- var externalLinterArguments by property("") { it.isEmpty() }
@AffectsHighlighting
var compileAllTargets by property(true)
var useOffline by property(false)
diff --git a/src/main/kotlin/org/rust/cargo/runconfig/command/CargoCommandConfiguration.kt b/src/main/kotlin/org/rust/cargo/runconfig/command/CargoCommandConfiguration.kt
index 3ca182a..8dd593f 100644
--- a/src/main/kotlin/org/rust/cargo/runconfig/command/CargoCommandConfiguration.kt
+++ b/src/main/kotlin/org/rust/cargo/runconfig/command/CargoCommandConfiguration.kt
@@ -9,7 +9,6 @@
import com.intellij.execution.InputRedirectAware
import com.intellij.execution.configuration.EnvironmentVariablesData
import com.intellij.execution.configurations.*
-import com.intellij.execution.impl.statistics.FusAwareRunConfiguration
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.target.LanguageRuntimeType
import com.intellij.execution.target.TargetEnvironmentAwareRunProfile
@@ -17,7 +16,6 @@
import com.intellij.execution.testframework.actions.ConsolePropertiesProvider
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties
import com.intellij.execution.util.ProgramParametersUtil
-import com.intellij.internal.statistic.eventLog.events.EventPair
import com.intellij.openapi.options.SettingsEditor
import com.intellij.openapi.options.advanced.AdvancedSettings
import com.intellij.openapi.project.Project
@@ -212,7 +210,9 @@
override fun createTestConsoleProperties(executor: Executor): SMTRunnerConsoleProperties? {
val config = clean().ok ?: return null
return if (showTestToolWindow(config.cmd)) {
- CargoTestConsoleProperties(this, executor)
+ val cargoProject = findCargoProject(project, config.cmd.additionalArguments, config.cmd.workingDirectory)
+ val version = cargoProject?.rustcInfo?.version?.semver
+ CargoTestConsoleProperties(this, executor, version)
} else {
null
}
diff --git a/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestConsoleProperties.kt b/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestConsoleProperties.kt
index ee672fb..68825a9 100644
--- a/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestConsoleProperties.kt
+++ b/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestConsoleProperties.kt
@@ -14,10 +14,12 @@
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties
import com.intellij.execution.testframework.sm.runner.SMTestLocator
import com.intellij.execution.ui.ConsoleViewContentType
+import com.intellij.util.text.SemVer
class CargoTestConsoleProperties(
config: RunConfiguration,
- executor: Executor
+ executor: Executor,
+ private val rustcVersion: SemVer?
) : SMTRunnerConsoleProperties(config, TEST_FRAMEWORK_NAME, executor), SMCustomMessagesParsing {
init {
@@ -29,7 +31,11 @@
override fun createTestEventsConverter(
testFrameworkName: String,
consoleProperties: TestConsoleProperties
- ): OutputToGeneralTestEventsConverter = CargoTestEventsConverter(testFrameworkName, consoleProperties)
+ ): OutputToGeneralTestEventsConverter = CargoTestEventsConverter(
+ testFrameworkName,
+ consoleProperties,
+ rustcVersion
+ )
override fun printExpectedActualHeader(printer: Printer, expected: String, actual: String) {
printer.print("\n", ConsoleViewContentType.ERROR_OUTPUT)
diff --git a/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestEventsConverter.kt b/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestEventsConverter.kt
index 6729cd0..18cf47c 100644
--- a/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestEventsConverter.kt
+++ b/src/main/kotlin/org/rust/cargo/runconfig/test/CargoTestEventsConverter.kt
@@ -15,6 +15,8 @@
import com.intellij.openapi.util.text.StringUtil.unescapeStringCharacters
import com.intellij.openapi.util.text.StringUtil.unquoteString
import com.intellij.util.execution.ParametersListUtil
+import com.intellij.util.text.SemVer
+import com.intellij.util.text.nullize
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageVisitor
import org.rust.cargo.project.model.cargoProjects
import org.rust.cargo.project.model.impl.allPackages
@@ -22,6 +24,7 @@
import org.rust.cargo.project.workspace.CargoWorkspace
import org.rust.cargo.project.workspace.PackageOrigin
import org.rust.cargo.runconfig.test.CargoTestEventsConverter.State.*
+import org.rust.cargo.util.parseSemVer
import org.rust.openapiext.JsonUtils.tryParseJsonObject
import org.rust.stdext.removeLast
import java.io.File
@@ -30,7 +33,8 @@
class CargoTestEventsConverter(
testFrameworkName: String,
- consoleProperties: TestConsoleProperties
+ consoleProperties: TestConsoleProperties,
+ private val rustcVersion: SemVer?
) : OutputToGeneralTestEventsConverter(testFrameworkName, consoleProperties) {
private val project: Project = consoleProperties.project
private var converterState: State = START_MESSAGE
@@ -165,7 +169,7 @@
val duration = getTestDuration(testMessage.name)
val (stdout, failedMessage) = parseFailedTestOutput(testMessage.stdout ?: "")
if (stdout.isNotEmpty()) messages.add(createTestStdOutMessage(testMessage.name, stdout + '\n'))
- messages.add(createTestFailedMessage(testMessage.name, failedMessage))
+ messages.add(createTestFailedMessage(testMessage.name, failedMessage, rustcVersion))
messages.add(createTestFinishedMessage(testMessage.name, duration))
recordSuiteChildFinished(testMessage.name)
processFinishedSuites(messages)
@@ -268,6 +272,8 @@
}
companion object {
+ private val RUSTC_1_73_BETA: SemVer = "1.73.0-beta".parseSemVer()
+
private const val TARGET_PATH_PART: String = "/target/"
private const val ROOT_SUITE: String = "0"
@@ -278,8 +284,12 @@
private val LINE_NUMBER_RE: Regex = """\s+\(line\s+(?<line>\d+)\)\s*""".toRegex()
+ private val ERROR_MESSAGE_RE_OLD: Regex =
+ """thread '.*' panicked at '(?<fullMessage>(assertion failed: `\(left (?<sign>.*) right\)`\s*left: `(?<left>.*?)`,\s*right: `(?<right>.*?)`(: )?)?(?<message>.*))',"""
+ .toRegex(setOf(RegexOption.MULTILINE, RegexOption.DOT_MATCHES_ALL))
+
private val ERROR_MESSAGE_RE: Regex =
- """thread '.*' panicked at '(assertion failed: `\(left (?<sign>.*) right\)`\s*left: `(?<left>.*?)`,\s*right: `(?<right>.*?)`(: )?)?(?<message>.*)',"""
+ """thread '.*' panicked at (\S*)\n(?<fullMessage>(assertion `left (?<sign>.*) right` failed(: )?)?(?<message>.*?)\n\s*(left: (?<left>.*?)\n\s*right: (?<right>.*?)\n)?)(note|stack backtrace):"""
.toRegex(setOf(RegexOption.MULTILINE, RegexOption.DOT_MATCHES_ALL))
private val NodeId.name: String
@@ -321,12 +331,12 @@
.addAttribute("locationHint", CargoTestLocator.getTestUrl(name))
}
- private fun createTestFailedMessage(test: NodeId, failedMessage: String): ServiceMessageBuilder {
+ private fun createTestFailedMessage(test: NodeId, failedMessage: String, rustcVersion: SemVer?): ServiceMessageBuilder {
val builder = ServiceMessageBuilder.testFailed(test.name)
.addAttribute("nodeId", test)
// TODO: pass backtrace here
.addAttribute("details", failedMessage)
- val parseResult = parseErrorMessage(failedMessage)
+ val parseResult = parseErrorMessage(failedMessage, rustcVersion)
if (parseResult == null) {
builder.addAttribute("message", "")
} else {
@@ -366,9 +376,11 @@
return FailedTestOutput(stdout, failedMessage)
}
- private fun parseErrorMessage(failedMessage: String): ErrorMessage? {
- val groups = ERROR_MESSAGE_RE.find(failedMessage)?.groups ?: return null
- val message = groups["message"]?.value ?: error("Failed to find `message` capturing group")
+ private fun parseErrorMessage(failedMessage: String, rustcVersion: SemVer?): ErrorMessage? {
+ val regex = if (rustcVersion == null || rustcVersion < RUSTC_1_73_BETA) ERROR_MESSAGE_RE_OLD else ERROR_MESSAGE_RE
+ val groups = regex.find(failedMessage)?.groups ?: return null
+ val message = groups["message"]?.value.nullize() ?: groups["fullMessage"]?.value
+ ?: error("Failed to find `message` or `fullMessage` capturing group")
val diff = if (groups["sign"]?.value == "==") {
val left = groups["left"]?.value?.let(::unescape)
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/RsLocalToolchain.kt b/src/main/kotlin/org/rust/cargo/toolchain/RsLocalToolchain.kt
index 81c605b..6d0b6d2 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/RsLocalToolchain.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/RsLocalToolchain.kt
@@ -19,7 +19,7 @@
override val executionTimeoutInMilliseconds: Int = 1000
- override fun patchCommandLine(commandLine: GeneralCommandLine): GeneralCommandLine = commandLine
+ override fun patchCommandLine(commandLine: GeneralCommandLine, withSudo: Boolean): GeneralCommandLine = commandLine
override fun toLocalPath(remotePath: String): String = remotePath
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/RsToolchainBase.kt b/src/main/kotlin/org/rust/cargo/toolchain/RsToolchainBase.kt
index 7ceeae6..779335c 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/RsToolchainBase.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/RsToolchainBase.kt
@@ -34,7 +34,7 @@
/**
* Patches passed command line to make it runnable in remote context.
*/
- abstract fun patchCommandLine(commandLine: GeneralCommandLine): GeneralCommandLine
+ abstract fun patchCommandLine(commandLine: GeneralCommandLine, withSudo: Boolean): GeneralCommandLine
abstract fun toLocalPath(remotePath: String): String
@@ -110,7 +110,7 @@
}
if (patchToRemote) {
- commandLine = patchCommandLine(commandLine)
+ commandLine = patchCommandLine(commandLine, withSudo)
}
return commandLine
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/tools/RsTool.kt b/src/main/kotlin/org/rust/cargo/toolchain/tools/RsTool.kt
index a4611a8..cec0947 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/tools/RsTool.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/tools/RsTool.kt
@@ -33,7 +33,7 @@
.withParameters(parameters)
.withEnvironment(environment)
.withCharset(Charsets.UTF_8)
- .also { toolchain.patchCommandLine(it) }
+ .also { toolchain.patchCommandLine(it, withSudo = false) }
}
abstract class CargoBinary(binaryName: String, toolchain: RsToolchainBase) : RsTool(binaryName, toolchain) {
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/wsl/RsWslToolchain.kt b/src/main/kotlin/org/rust/cargo/toolchain/wsl/RsWslToolchain.kt
index 7c44d3e..6a877bd 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/wsl/RsWslToolchain.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/wsl/RsWslToolchain.kt
@@ -28,7 +28,7 @@
override val executionTimeoutInMilliseconds: Int = 5000
- override fun patchCommandLine(commandLine: GeneralCommandLine): GeneralCommandLine {
+ override fun patchCommandLine(commandLine: GeneralCommandLine, withSudo: Boolean): GeneralCommandLine {
commandLine.exePath = toRemotePath(commandLine.exePath)
val parameters = commandLine.parametersList.list.map { toRemotePath(it) }
@@ -49,6 +49,7 @@
val remoteWorkDir = commandLine.workDirectory?.absolutePath
?.let { toRemotePath(it) }
val options = WSLCommandLineOptions()
+ .setSudo(withSudo)
.setRemoteWorkingDirectory(remoteWorkDir)
.addInitCommand("export PATH=\"${linuxPath.systemIndependentPath}:\$PATH\"")
return distribution.patchCommandLine(commandLine, null, options)
diff --git a/src/main/kotlin/org/rust/ide/actions/RustfmtFileAction.kt b/src/main/kotlin/org/rust/ide/actions/RustfmtFileAction.kt
index 76fcea7..6da4ecb 100644
--- a/src/main/kotlin/org/rust/ide/actions/RustfmtFileAction.kt
+++ b/src/main/kotlin/org/rust/ide/actions/RustfmtFileAction.kt
@@ -24,7 +24,9 @@
class RustfmtFileAction : DumbAwareAction() {
- override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
+ override fun getActionUpdateThread(): ActionUpdateThread {
+ return ActionUpdateThread.BGT
+ }
override fun update(e: AnActionEvent) {
super.update(e)
diff --git a/src/main/kotlin/org/rust/ide/annotator/RsExternalLinterUtils.kt b/src/main/kotlin/org/rust/ide/annotator/RsExternalLinterUtils.kt
index 82d9cae..d550e55 100644
--- a/src/main/kotlin/org/rust/ide/annotator/RsExternalLinterUtils.kt
+++ b/src/main/kotlin/org/rust/ide/annotator/RsExternalLinterUtils.kt
@@ -31,7 +31,7 @@
import com.intellij.util.PathUtil
import com.intellij.util.io.URLUtil
import com.intellij.util.messages.MessageBus
-import org.apache.commons.lang.StringEscapeUtils
+import org.apache.commons.lang3.StringEscapeUtils
import org.jetbrains.annotations.Nls
import org.rust.RsBundle
import org.rust.cargo.project.workspace.PackageOrigin
@@ -277,7 +277,7 @@
val textRange = span.toTextRange(document) ?: return null
@NlsSafe val tooltip = buildString {
- append(formatMessage(StringEscapeUtils.escapeHtml(message.message)).escapeUrls())
+ append(formatMessage(StringEscapeUtils.escapeHtml4(message.message)).escapeUrls())
val code = message.code.formatAsLink()
if (code != null) {
append(" [$code]")
@@ -285,12 +285,12 @@
with(mutableListOf<String>()) {
if (span.label != null && !message.message.startsWith(span.label)) {
- add(StringEscapeUtils.escapeHtml(span.label))
+ add(StringEscapeUtils.escapeHtml4(span.label))
}
message.children
.filter { it.message.isNotBlank() }
- .map { "${it.level.capitalized()}: ${StringEscapeUtils.escapeHtml(it.message)}" }
+ .map { "${it.level.capitalized()}: ${StringEscapeUtils.escapeHtml4(it.message)}" }
.forEach { add(it) }
append(joinToString(prefix = "<br>", separator = "<br>") { formatMessage(it) }.escapeUrls())
diff --git a/src/main/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProvider.kt b/src/main/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProvider.kt
index 839c20d..f1db72a 100644
--- a/src/main/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProvider.kt
+++ b/src/main/kotlin/org/rust/ide/hints/type/RsChainMethodTypeHintsProvider.kt
@@ -37,6 +37,7 @@
import org.rust.lang.core.types.ty.TyUnknown
import org.rust.lang.core.types.type
import org.rust.openapiext.escaped
+import java.lang.ref.WeakReference
import javax.swing.JComponent
import javax.swing.JPanel
@@ -78,11 +79,8 @@
return object : FactoryInlayHintsCollector(editor) {
val typeHintsFactory = RsTypeHintsPresentationFactory(factory, true)
- private val lookupAndIteratorTrait: Pair<ImplLookup?, BoundElement<RsTraitItem>?> by lazy(LazyThreadSafetyMode.PUBLICATION) {
- val (lookup, items) = (file as? RsFile)?.implLookupAndKnownItems ?: (null to null)
- val iterator = items?.Iterator?.let { BoundElement(it) }
- lookup to iterator
- }
+ val lookupAndIteratorTrait: ThreadLocal<WeakReference<Pair<ImplLookup?, BoundElement<RsTraitItem>?>>?> =
+ ThreadLocal()
override fun collect(element: PsiElement, editor: Editor, sink: InlayHintsSink): Boolean {
if (DumbService.isDumb(project)) return true
@@ -94,7 +92,13 @@
else -> false
}
- val (lookup, iterator) = lookupAndIteratorTrait
+ val (lookup, iterator) = lookupAndIteratorTrait.get()?.get() ?: run {
+ val (lookup, items) = (file as? RsFile)?.implLookupAndKnownItems ?: (null to null)
+ val iterator = items?.Iterator?.let { BoundElement(it) }
+ val result = lookup to iterator
+ lookupAndIteratorTrait.set(WeakReference(result))
+ result
+ }
val chain = collectChain(element)
val chainExpanded = if (isAttrProcMacro) {
diff --git a/src/main/kotlin/org/rust/ide/inspections/RsWithMacrosInspectionVisitor.kt b/src/main/kotlin/org/rust/ide/inspections/RsWithMacrosInspectionVisitor.kt
index dbb88f4..329ac19 100644
--- a/src/main/kotlin/org/rust/ide/inspections/RsWithMacrosInspectionVisitor.kt
+++ b/src/main/kotlin/org/rust/ide/inspections/RsWithMacrosInspectionVisitor.kt
@@ -15,7 +15,7 @@
* expanded from the macro. This visitor is intended to be used in [RsLocalInspectionTool] implementations.
*/
abstract class RsWithMacrosInspectionVisitor : RsVisitor() {
- private var processingMacros: Boolean = false
+ private var processingMacros: ThreadLocal<Boolean> = ThreadLocal.withInitial { false }
final override fun visitConstant(o: RsConstant) {
visitConstant2(o)
@@ -153,12 +153,13 @@
}
private fun visitMacroExpansion(item: RsAttrProcMacroOwner) {
- if (processingMacros) return
+ if (processingMacros.get()) return
val preparedMacro = item.procMacroAttribute?.attr?.prepareForExpansionHighlighting() ?: return
val macros = mutableListOf(preparedMacro)
- processingMacros = true
+ processingMacros.set(true)
+ println(Thread.currentThread().name)
while (macros.isNotEmpty()) {
val macro = macros.removeLast()
@@ -170,6 +171,6 @@
}
}
- processingMacros = false
+ processingMacros.set(false)
}
}
diff --git a/src/main/kotlin/org/rust/ide/inspections/import/ui.kt b/src/main/kotlin/org/rust/ide/inspections/import/ui.kt
index 06146b1..bff865f 100644
--- a/src/main/kotlin/org/rust/ide/inspections/import/ui.kt
+++ b/src/main/kotlin/org/rust/ide/inspections/import/ui.kt
@@ -5,6 +5,7 @@
package org.rust.ide.inspections.import
+import com.intellij.codeInsight.navigation.hidePopupIfDumbModeStarts
import com.intellij.ide.util.DefaultPsiElementCellRenderer
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.project.Project
@@ -20,7 +21,6 @@
import org.rust.cargo.icons.CargoIcons
import org.rust.cargo.project.workspace.PackageOrigin
import org.rust.ide.icons.RsIcons
-import org.rust.ide.navigation.hidePopupIfDumbModeStarts
import org.rust.ide.utils.import.ImportCandidate
import org.rust.openapiext.isUnitTestMode
import java.awt.BorderLayout
diff --git a/src/main/kotlin/org/rust/ide/lineMarkers/CargoExecutableRunLineMarkerContributor.kt b/src/main/kotlin/org/rust/ide/lineMarkers/CargoExecutableRunLineMarkerContributor.kt
index 84dc6ab..a8dd300 100644
--- a/src/main/kotlin/org/rust/ide/lineMarkers/CargoExecutableRunLineMarkerContributor.kt
+++ b/src/main/kotlin/org/rust/ide/lineMarkers/CargoExecutableRunLineMarkerContributor.kt
@@ -13,6 +13,7 @@
import org.rust.lang.core.psi.RsElementTypes.IDENTIFIER
import org.rust.lang.core.psi.RsFunction
import org.rust.lang.core.psi.ext.elementType
+import org.rust.openapiext.isUnitTestMode
class CargoExecutableRunLineMarkerContributor : RunLineMarkerContributor() {
override fun getInfo(element: PsiElement): Info? {
@@ -23,7 +24,14 @@
val actions = ExecutorAction.getActions(0)
return Info(
AllIcons.RunConfigurations.TestState.Run,
- { psiElement -> actions.mapNotNull { getText(it, psiElement) }.joinToString("\n") },
+ { psiElement ->
+ val texts = actions.mapNotNull { getText(it, psiElement) }
+ if (isUnitTestMode) {
+ texts.firstOrNull().orEmpty()
+ } else {
+ texts.joinToString("\n")
+ }
+ },
*actions
)
}
diff --git a/src/main/kotlin/org/rust/ide/navigation/goto/RsGotoSuperHandler.kt b/src/main/kotlin/org/rust/ide/navigation/goto/RsGotoSuperHandler.kt
index f9b9e20..efe653b 100644
--- a/src/main/kotlin/org/rust/ide/navigation/goto/RsGotoSuperHandler.kt
+++ b/src/main/kotlin/org/rust/ide/navigation/goto/RsGotoSuperHandler.kt
@@ -6,6 +6,7 @@
package org.rust.ide.navigation.goto
import com.google.common.annotations.VisibleForTesting
+import com.intellij.codeInsight.navigation.getPsiElementPopup
import com.intellij.lang.LanguageCodeInsightActionHandler
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
@@ -14,7 +15,6 @@
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
import org.rust.RsBundle
-import org.rust.ide.navigation.getPsiElementPopup
import org.rust.lang.core.psi.RsFile
import org.rust.lang.core.psi.ext.*
import org.rust.openapiext.toPsiFile
diff --git a/src/main/kotlin/org/rust/ide/newProject/RsNewProjectWizard.kt b/src/main/kotlin/org/rust/ide/newProject/RsNewProjectWizard.kt
index d249c76..8d5d2b4 100644
--- a/src/main/kotlin/org/rust/ide/newProject/RsNewProjectWizard.kt
+++ b/src/main/kotlin/org/rust/ide/newProject/RsNewProjectWizard.kt
@@ -14,8 +14,8 @@
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.vfs.VfsUtil
+import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Panel
-import com.intellij.ui.dsl.gridLayout.HorizontalAlign
import org.rust.ide.module.RsModuleBuilder
import org.rust.stdext.toPathOrNull
import java.nio.file.Path
@@ -35,9 +35,9 @@
with(builder) {
row {
cell(peer.component)
- .horizontalAlign(HorizontalAlign.FILL)
+ .align(AlignX.FILL)
.validationRequestor { peer.checkValid = Runnable(it) }
- .validation { peer.validate() }
+ .validationInfo { peer.validate() }
}
}
}
diff --git a/src/main/kotlin/org/rust/ide/refactoring/RsMemberSelectionPanel.kt b/src/main/kotlin/org/rust/ide/refactoring/RsMemberSelectionPanel.kt
index 5f38706..1fe36f7 100644
--- a/src/main/kotlin/org/rust/ide/refactoring/RsMemberSelectionPanel.kt
+++ b/src/main/kotlin/org/rust/ide/refactoring/RsMemberSelectionPanel.kt
@@ -11,7 +11,7 @@
import com.intellij.refactoring.ui.AbstractMemberSelectionTable
import com.intellij.refactoring.ui.MemberSelectionPanelBase
import com.intellij.ui.RowIcon
-import org.apache.commons.lang.StringEscapeUtils
+import org.apache.commons.lang3.StringEscapeUtils
import org.rust.ide.docs.signature
import org.rust.lang.core.psi.RsModItem
import org.rust.lang.core.psi.ext.RsItemElement
@@ -26,8 +26,7 @@
AbstractMemberSelectionTable<RsItemElement, RsMemberInfo>
>(title, RsMemberSelectionTable(memberInfo))
-class RsMemberSelectionTable(memberInfo: List<RsMemberInfo>)
- : AbstractMemberSelectionTable<RsItemElement, RsMemberInfo>(memberInfo, null, null) {
+class RsMemberSelectionTable(memberInfo: List<RsMemberInfo>) : AbstractMemberSelectionTable<RsItemElement, RsMemberInfo>(memberInfo, null, null) {
init {
setTableHeader(null)
@@ -54,7 +53,7 @@
"mod ${member.modName}"
} else {
val description = buildString { member.signature(this) }
- StringEscapeUtils.unescapeHtml(StringUtil.removeHtmlTags(description))
+ StringEscapeUtils.unescapeHtml4(StringUtil.removeHtmlTags(description))
}
}
}
diff --git a/src/main/kotlin/org/rust/ide/refactoring/introduceParameter/ui.kt b/src/main/kotlin/org/rust/ide/refactoring/introduceParameter/ui.kt
index be145dd..ca06351 100644
--- a/src/main/kotlin/org/rust/ide/refactoring/introduceParameter/ui.kt
+++ b/src/main/kotlin/org/rust/ide/refactoring/introduceParameter/ui.kt
@@ -4,13 +4,13 @@
*/
package org.rust.ide.refactoring.introduceParameter
+import com.intellij.codeInsight.navigation.hidePopupIfDumbModeStarts
import com.intellij.codeInsight.unwrap.ScopeHighlighter
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.ui.popup.JBPopupListener
import com.intellij.openapi.ui.popup.LightweightWindowEvent
import org.rust.RsBundle
-import org.rust.ide.navigation.hidePopupIfDumbModeStarts
import org.rust.ide.refactoring.MOCK
import org.rust.lang.core.psi.RsFunction
import org.rust.lang.core.psi.ext.title
diff --git a/src/main/kotlin/org/rust/ide/refactoring/move/RsMoveTopLevelItemsDialog.kt b/src/main/kotlin/org/rust/ide/refactoring/move/RsMoveTopLevelItemsDialog.kt
index 707cea0..81dc2ea 100644
--- a/src/main/kotlin/org/rust/ide/refactoring/move/RsMoveTopLevelItemsDialog.kt
+++ b/src/main/kotlin/org/rust/ide/refactoring/move/RsMoveTopLevelItemsDialog.kt
@@ -23,12 +23,12 @@
import com.intellij.ui.ColoredTreeCellRenderer
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.components.JBTextField
+import com.intellij.ui.dsl.builder.AlignY
import com.intellij.ui.dsl.builder.bindSelected
import com.intellij.ui.dsl.builder.panel
-import com.intellij.ui.dsl.gridLayout.VerticalAlign
import com.intellij.util.IncorrectOperationException
import com.intellij.util.ui.JBUI
-import org.apache.commons.lang.StringEscapeUtils
+import org.apache.commons.lang3.StringEscapeUtils
import org.jetbrains.annotations.Nls
import org.rust.RsBundle
import org.rust.ide.docs.signature
@@ -113,7 +113,7 @@
row {
resizableRow()
fullWidthCell(memberPanel)
- .verticalAlign(VerticalAlign.FILL)
+ .align(AlignY.FILL)
}
row {
checkBox(RefactoringBundle.message("search.for.references"))
@@ -203,7 +203,7 @@
RsBundle.message("mod.0", member.modName?:"")
} else {
val descriptionHTML = buildString { member.signature(this) }
- val description = StringEscapeUtils.unescapeHtml(StringUtil.removeHtmlTags(descriptionHTML))
+ val description = StringEscapeUtils.unescapeHtml4(StringUtil.removeHtmlTags(descriptionHTML))
description.replace("(?U)\\s+".toRegex(), " ")
}
renderer.append(description, SimpleTextAttributes.REGULAR_ATTRIBUTES)
diff --git a/src/main/kotlin/org/rust/ide/typing/paste/RsImportCopyPasteProcessor.kt b/src/main/kotlin/org/rust/ide/typing/paste/RsImportCopyPasteProcessor.kt
index f00ac01..05f7328 100644
--- a/src/main/kotlin/org/rust/ide/typing/paste/RsImportCopyPasteProcessor.kt
+++ b/src/main/kotlin/org/rust/ide/typing/paste/RsImportCopyPasteProcessor.kt
@@ -18,7 +18,6 @@
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
-import com.intellij.psi.impl.source.tree.injected.changesHandler.range
import org.rust.ide.fixes.QualifyPathFix
import org.rust.ide.inspections.import.AutoImportFix
import org.rust.ide.settings.RsCodeInsightSettings
@@ -69,8 +68,8 @@
override fun getOffsetCount(): Int = 0
- override fun getOffsets(offsets: IntArray?, index: Int): Int = index
- override fun setOffsets(offsets: IntArray?, index: Int): Int = index
+ override fun getOffsets(offsets: IntArray, index: Int): Int = index
+ override fun setOffsets(offsets: IntArray, index: Int): Int = index
}
class RsImportCopyPasteProcessor : CopyPastePostProcessor<RsTextBlockTransferableData>() {
@@ -124,12 +123,12 @@
?.containingModOrSelf ?: return
val importCtx = containingMod.firstItem ?: return
- val importOffset = bounds.range.startOffset
+ val importOffset = bounds.textRange.startOffset
val processor = ImportingProcessor(importOffset, data.importMap)
runWriteAction {
- processElementsInRange(file, bounds.range, processor)
+ processElementsInRange(file, bounds.textRange, processor)
// We need to import the candidates after visiting all elements, otherwise the relative offsets could be
// invalidated after an import has been added
for (candidate in processor.importCandidates) {
diff --git a/src/main/kotlin/org/rust/ide/wordSelection/RsMacroCallSelectionHandler.kt b/src/main/kotlin/org/rust/ide/wordSelection/RsMacroCallSelectionHandler.kt
index fc21d58..c5d82f5 100644
--- a/src/main/kotlin/org/rust/ide/wordSelection/RsMacroCallSelectionHandler.kt
+++ b/src/main/kotlin/org/rust/ide/wordSelection/RsMacroCallSelectionHandler.kt
@@ -118,7 +118,7 @@
override fun getScrollPane(): JScrollPane { throw notImplemented() }
override fun isRendererMode(): Boolean { throw notImplemented() }
override fun setRendererMode(isRendererMode: Boolean) { throw notImplemented() }
- override fun setFile(vFile: VirtualFile?) { throw notImplemented() }
+ override fun setFile(vFile: VirtualFile) { throw notImplemented() }
override fun getDataContext(): DataContext { throw notImplemented() }
override fun processKeyTyped(e: KeyEvent): Boolean { throw notImplemented() }
override fun setFontSize(fontSize: Int) { throw notImplemented() }
diff --git a/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt b/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
index e62cca1..60362fc 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ImplLookup.kt
@@ -248,7 +248,8 @@
private val containingCrate: Crate,
val items: KnownItems,
private val paramEnv: ParamEnv,
- context: RsElement? = null
+ context: RsElement? = null,
+ options: TypeInferenceOptions = TypeInferenceOptions.DEFAULT
) {
// Non-concurrent HashMap and lazy(NONE) are safe here because this class isn't shared between threads
private val traitSelectionCache: MutableMap<TraitRef, SelectionResult<SelectionCandidate>> = hashMapOf()
@@ -284,8 +285,47 @@
ancestorItem.implsFromNestedMacros
}
+ /**
+ * Returns `ImplsFilter.ConstBodyInsideImplSignatureFilter` during type inference in such const bodies:
+ *
+ * ```rust
+ * impl Foo< {0} > for Bar< {0} > {}
+ * // ~~~ ~~~
+ * ```
+ *
+ * TODO RUST-12502 this is a hack to deal with infinite recursion in const eval (issues like RUST-11763)
+ */
+ private val implsFilter: ImplsFilter by lazy(NONE) {
+ val contextPath = context?.inferenceContextOwner as? RsPath ?: return@lazy ImplsFilter.AllowAll
+ val ancestorImpl = contextPath.contexts.withPrevious().find { (it, prev) ->
+ it is RsImplItem && (prev is RsTraitRef || prev == it.typeReference)
+ }?.first as? RsImplItem ?: return@lazy ImplsFilter.AllowAll
+
+ val isInsideTraitImpl = ancestorImpl.traitRef != null
+ ImplsFilter.ConstBodyInsideImplSignatureFilter(containingCrate, allowInherentImpls = isInsideTraitImpl)
+ }
+
+ // TODO RUST-12502 this is a hack to deal with infinite recursion in const eval (issues like RUST-11763)
+ private sealed interface ImplsFilter {
+ fun canProcessImpl(impl: RsCachedImplItem): Boolean
+
+ class ConstBodyInsideImplSignatureFilter(
+ private val containingCrate: Crate,
+ private val allowInherentImpls: Boolean,
+ ) : ImplsFilter {
+ override fun canProcessImpl(impl: RsCachedImplItem): Boolean {
+ return allowInherentImpls && impl.isInherent
+ || containingCrate !in impl.containingCrates
+ }
+ }
+
+ data object AllowAll : ImplsFilter {
+ override fun canProcessImpl(impl: RsCachedImplItem): Boolean = true
+ }
+ }
+
val ctx: RsInferenceContext by lazy(NONE) {
- RsInferenceContext(project, this, items)
+ RsInferenceContext(project, this, items, options)
}
fun getEnvBoundTransitivelyFor(ty: Ty): Sequence<BoundElement<RsTraitItem>> {
@@ -398,6 +438,7 @@
.asSequence()
.filter { useImplsFromCrate(it.containingCrates) }
.plus(implsFromNestedMacros[tyf].orEmpty())
+ .filter(implsFilter::canProcessImpl)
private fun findPotentialAliases(tyf: TyFingerprint): List<String> =
indexCache.findPotentialAliases(tyf)
@@ -494,18 +535,18 @@
private fun selectCandidate(ref: TraitRef, recursionDepth: Int): SelectionResult<SelectionCandidate> {
if (ref.selfTy is TyInfer.TyVar) {
- return SelectionResult.Ambiguous
+ return SelectionResult.Ambiguous()
}
if (ref.selfTy is TyReference && ref.selfTy.referenced is TyInfer.TyVar) {
// This condition is related to TyFingerprint internals: TyFingerprint should not be created for
// TyInfer.TyVar, and TyReference is a single special case: it unwraps during TyFingerprint creation
- return SelectionResult.Ambiguous
+ return SelectionResult.Ambiguous()
}
val candidateSet = assembleCandidates(ref)
if (candidateSet.ambiguous) {
- return SelectionResult.Ambiguous
+ return SelectionResult.Ambiguous()
}
val candidates = candidateSet.list.filter { it !is ImplCandidate.ExplicitImpl || !it.isNegativeImpl }
@@ -531,13 +572,13 @@
} else {
i++
if (i > 1) {
- return SelectionResult.Ambiguous
+ return SelectionResult.Ambiguous(filtered)
}
}
}
filtered.singleOrNull()
?.let { SelectionResult.Ok(it) }
- ?: SelectionResult.Ambiguous
+ ?: SelectionResult.Ambiguous(filtered)
}
}
}
@@ -1414,7 +1455,9 @@
sealed class SelectionResult<out T> {
object Err : SelectionResult<Nothing>()
- object Ambiguous : SelectionResult<Nothing>()
+ class Ambiguous(
+ val candidates: List<SelectionCandidate> = emptyList()
+ ) : SelectionResult<Nothing>()
data class Ok<out T>(
val result: T
) : SelectionResult<T>()
@@ -1425,13 +1468,13 @@
inline fun <R> map(action: (T) -> R): SelectionResult<R> = when (this) {
is Err -> Err
- is Ambiguous -> Ambiguous
+ is Ambiguous -> this
is Ok -> Ok(action(result))
}
inline fun <R> andThen(action: (T) -> SelectionResult<R>): SelectionResult<R> = when (this) {
is Err -> Err
- is Ambiguous -> Ambiguous
+ is Ambiguous -> this
is Ok -> action(result)
}
}
@@ -1442,7 +1485,7 @@
val subst: Substitution = emptySubstitution
)
-private sealed class SelectionCandidate {
+sealed class SelectionCandidate {
data class BuiltinCandidate(
/** `false` if there are no *further* obligations */
val hasNested: Boolean
diff --git a/src/main/kotlin/org/rust/lang/core/types/infer/Fulfillment.kt b/src/main/kotlin/org/rust/lang/core/types/infer/Fulfillment.kt
index ed30cb5..0753f6c 100644
--- a/src/main/kotlin/org/rust/lang/core/types/infer/Fulfillment.kt
+++ b/src/main/kotlin/org/rust/lang/core/types/infer/Fulfillment.kt
@@ -24,6 +24,8 @@
override fun superVisitWith(visitor: TypeVisitor): Boolean =
trait.visitWith(visitor)
+
+ override fun toString(): String = trait.toString()
}
/** where <T as TraitRef>::Name == X */
@@ -86,7 +88,9 @@
* [registerObligationAt] and to remove satisfied obligations
* as a side effect of [processObligations].
*/
-class ObligationForest {
+class ObligationForest(
+ private val traceObligations: Boolean
+) {
enum class NodeState {
/** Obligations for which selection had not yet returned a non-ambiguous result */
Pending,
@@ -110,13 +114,27 @@
private val nodes: MutableList<Node> = mutableListOf()
private val doneCache: MutableSet<Predicate> = HashSet()
+ /** Filled only if [traceObligations] == `true` */
+ val roots: MutableList<Node> = mutableListOf()
+ /** Filled only if [traceObligations] == `true` */
+ val parentToChildren: HashMap<Node, MutableList<Node>> = hashMapOf()
+
val pendingObligations: Sequence<PendingPredicateObligation> =
nodes.asSequence().filter { it.state == NodeState.Pending }.map { it.obligation }
- @Suppress("UNUSED_PARAMETER") // TODO use `parent`
fun registerObligationAt(obligation: PendingPredicateObligation, parent: Node?) {
- if (doneCache.add(obligation.obligation.predicate))
- nodes.add(Node(obligation))
+ if (doneCache.add(obligation.obligation.predicate)) {
+ val node = Node(obligation)
+ nodes.add(node)
+
+ if (traceObligations) {
+ if (parent == null) {
+ roots += node
+ } else {
+ parentToChildren.getOrPut(parent) { mutableListOf() } += node
+ }
+ }
+ }
}
fun processObligations(
@@ -156,13 +174,24 @@
}
}
-class FulfillmentContext(val ctx: RsInferenceContext, val lookup: ImplLookup) {
+class FulfillmentContext(
+ val ctx: RsInferenceContext,
+ val lookup: ImplLookup,
+ traceObligations: Boolean = false,
+) {
- private val obligations: ObligationForest = ObligationForest()
+ private val obligations: ObligationForest = ObligationForest(traceObligations)
val pendingObligations: Sequence<PendingPredicateObligation> =
obligations.pendingObligations
+ /** Non-empty only if `traceObligations == true` */
+ val rootNodes: List<ObligationForest.Node> get() = obligations.roots
+
+ /** Non-empty only if `traceObligations == true` */
+ val parentToChildren: Map<ObligationForest.Node, List<ObligationForest.Node>>
+ get() = obligations.parentToChildren
+
fun registerPredicateObligation(obligation: Obligation) {
obligations.registerObligationAt(
PendingPredicateObligation(ctx.resolveTypeVarsIfPossible(obligation)),
diff --git a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
index b28dfdc..47f6142 100644
--- a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
+++ b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInference.kt
@@ -34,12 +34,30 @@
import org.rust.stdext.RsResult.Err
import org.rust.stdext.RsResult.Ok
-fun inferTypesIn(element: RsInferenceContextOwner): RsInferenceResult {
+fun inferTypesIn(element: RsInferenceContextOwner): RsInferenceResult =
+ inferTypesInWithOptions(element, TypeInferenceOptions.DEFAULT).second
+
+fun inferTypesInWithOptions(
+ element: RsInferenceContextOwner,
+ options: TypeInferenceOptions,
+): Pair<RsInferenceContext, RsInferenceResult> {
val items = element.knownItems
val paramEnv = if (element is RsItemElement) ParamEnv.buildFor(element) else ParamEnv.EMPTY
- val lookup = ImplLookup(element.project, element.containingCrate, items, paramEnv, element)
- return recursionGuard(element, { lookup.ctx.infer(element) }, memoize = false)
- ?: error("Can not run nested type inference")
+ val lookup = ImplLookup(element.project, element.containingCrate, items, paramEnv, element, options)
+ return recursionGuard(element, { lookup.ctx to lookup.ctx.infer(element) }, memoize = false)
+ ?: (lookup.ctx to RsInferenceResult.EMPTY)
+}
+
+data class TypeInferenceOptions(
+ /**
+ * If `true`, fills [FulfillmentContext.rootNodes] and [FulfillmentContext.parentToChildren],
+ * so that they can be used later.
+ */
+ val traceObligations: Boolean = false
+) {
+ companion object {
+ val DEFAULT = TypeInferenceOptions()
+ }
}
sealed class Adjustment: TypeFoldable<Adjustment> {
@@ -206,9 +224,10 @@
class RsInferenceContext(
val project: Project,
val lookup: ImplLookup,
- val items: KnownItems
+ val items: KnownItems,
+ options: TypeInferenceOptions
) : RsInferenceData {
- val fulfill: FulfillmentContext = FulfillmentContext(this, lookup)
+ val fulfill: FulfillmentContext = FulfillmentContext(this, lookup, options.traceObligations)
private val exprTypes: MutableMap<RsExpr, Ty> = hashMapOf()
private val patTypes: MutableMap<RsPat, Ty> = hashMapOf()
private val patFieldTypes: MutableMap<RsPatField, Ty> = hashMapOf()
@@ -869,7 +888,7 @@
when (val selection = lookup.select(predicate.trait, obligation.recursionDepth)) {
SelectionResult.Err -> return null
is SelectionResult.Ok -> queue += selection.result.nestedObligations
- SelectionResult.Ambiguous -> if (predicate.trait.trait.element == unsizeTrait) {
+ is SelectionResult.Ambiguous -> if (predicate.trait.trait.element == unsizeTrait) {
val selfTy = predicate.trait.selfTy
val unsizeTy = predicate.trait.trait.singleParamValue
if (selfTy is TyInfer.TyVar && unsizeTy is TyTraitObject && typeVarIsSized(selfTy)) {
diff --git a/src/main/kotlin/org/rust/openapiext/utils.kt b/src/main/kotlin/org/rust/openapiext/utils.kt
index f86cee9..18fe3f2 100644
--- a/src/main/kotlin/org/rust/openapiext/utils.kt
+++ b/src/main/kotlin/org/rust/openapiext/utils.kt
@@ -319,8 +319,13 @@
return ProgressManager.getInstance().runProcessWithProgressSynchronously(process, title, true, this)
}
-inline fun <T : Any> UserDataHolderEx.getOrPut(key: Key<T>, defaultValue: () -> T): T =
- getUserData(key) ?: putUserDataIfAbsent(key, defaultValue())
+inline fun <T : Any> UserDataHolder.getOrPut(key: Key<T>, defaultValue: () -> T): T {
+ val data = getUserData(key)
+ if (data != null) return data
+ val value = defaultValue()
+ putUserData(key, value)
+ return value
+}
const val PLUGIN_ID: String = "org.rust.lang"
diff --git a/src/main/kotlin/org/rust/stdext/Utils.kt b/src/main/kotlin/org/rust/stdext/Utils.kt
index 7a843e9..8391989 100644
--- a/src/main/kotlin/org/rust/stdext/Utils.kt
+++ b/src/main/kotlin/org/rust/stdext/Utils.kt
@@ -10,7 +10,7 @@
import com.intellij.openapi.util.NlsActions
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile
-import org.apache.commons.lang.RandomStringUtils
+import org.apache.commons.lang3.RandomStringUtils
import java.nio.file.Files
import java.nio.file.InvalidPathException
import java.nio.file.Path
diff --git a/src/main/resources/messages/RsBundle.properties b/src/main/resources/messages/RsBundle.properties
index 38b7773..c4fd022 100644
--- a/src/main/resources/messages/RsBundle.properties
+++ b/src/main/resources/messages/RsBundle.properties
@@ -90,6 +90,7 @@
dialog.create.project.custom.add.template.title=Add Custom Template
dialog.create.project.custom.add.template.url.description=cargo-generate supported template. <a href="https://github.com/cargo-generate/cargo-generate/blob/master/TEMPLATES.md">Available templates</a>
dialog.create.project.custom.add.template.url=Template URL:
+dialog.message.rust.toolchain.is.not.set=The Rust toolchain is not set
# for example: Debug action is not available for `cargo help` command
notification.0.action.is.not.available.for.1.command={0} action is not available for `{1}` command
@@ -526,6 +527,7 @@
external.linter=External Linter
extra.semicolon=Extra semicolon
from=From:
+profiler.attach.default.group.title=Native
hint.text.html.table.tr.td.style.color.type.td.td.style.font.family.monospace.td.tr.tr.td.style.color.coerced.type.td.td.style.font.family.monospace.td.tr.table.html=\n <html>\n <table>\n <tr>\n <td style="color: #909090">Type:</td>\n <td style="font-family: monospace;">{0}</td>\n </tr>\n <tr>\n <td style="color: #909090">Coerced type:</td>\n <td style="font-family: monospace;">{1}</td>\n </tr>\n </table>\n </html>\n
hint.text.no.members.to.implement.have.been.found=No members to implement have been found
hint.text.please.convert.innermost.impl.trait.first=Please convert innermost `impl Trait` first
@@ -1454,7 +1456,6 @@
discriminant.on.a.non.unit.variant=discriminant on a non-unit variant
or.patterns.syntax=or-patterns syntax
macro=`macro`
-intention.family.name.replace.with.inclusive.range=Replace with inclusive range
error.message.struct.inheritance.is.not.supported=Struct inheritance is not supported in Rust
inspection.message.main.is.async=`{0}` function is not allowed to be `async`
intention.family.name.replace.with.inclusive.range=Replace with inclusive range
diff --git a/src/test/kotlin/org/rust/RsTestBase.kt b/src/test/kotlin/org/rust/RsTestBase.kt
index 8092e42..9326092 100644
--- a/src/test/kotlin/org/rust/RsTestBase.kt
+++ b/src/test/kotlin/org/rust/RsTestBase.kt
@@ -66,6 +66,9 @@
private var shouldSkipTestWithCurrentWrapping: Boolean = false
protected var testWrappingUnwrapper: TestUnwrapper? = null
+ open val runInMode: WithDumbMode.SmartDumbMode get() = WithDumbMode.SmartDumbMode.SMART
+ private var dumbModeToken: DumbModeTestUtil.Token? = null
+
override fun isWriteActionRequired(): Boolean = false
open val dataPath: String = ""
@@ -90,6 +93,11 @@
mgr.setMacroExpansionEnabled(true)
}
}
+ val mode = findAnnotationInstance<WithDumbMode>()?.mode ?: runInMode
+ if (mode == WithDumbMode.SmartDumbMode.DUMB) {
+ dumbModeToken = DumbModeTestUtil.startEternalDumbModeTask(project)
+ }
+
RecursionManager.disableMissedCacheAssertions(testRootDisposable)
tempDirRoot = myFixture.findFileInTempDir(".")
tempDirRootUrl = tempDirRoot?.url
@@ -100,6 +108,7 @@
val newTempDirRootUrl = tempDirRoot?.url
com.intellij.testFramework.common.runAll(
+ { dumbModeToken?.close() },
{
// Fixes flaky tests
(ProjectLevelVcsManagerEx.getInstance(project) as ProjectLevelVcsManagerImpl).waitForInitialized()
diff --git a/src/test/kotlin/org/rust/WithDumbMode.kt b/src/test/kotlin/org/rust/WithDumbMode.kt
new file mode 100644
index 0000000..d017c5f
--- /dev/null
+++ b/src/test/kotlin/org/rust/WithDumbMode.kt
@@ -0,0 +1,15 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust
+
+import java.lang.annotation.Inherited
+
+@Inherited
+@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
+@Retention(AnnotationRetention.RUNTIME)
+annotation class WithDumbMode(val mode: SmartDumbMode = SmartDumbMode.DUMB) {
+ enum class SmartDumbMode { SMART, DUMB }
+}
diff --git a/src/test/kotlin/org/rust/cargo/commands/RustfmtTest.kt b/src/test/kotlin/org/rust/cargo/commands/RustfmtTest.kt
index 808ad46..d19188e 100644
--- a/src/test/kotlin/org/rust/cargo/commands/RustfmtTest.kt
+++ b/src/test/kotlin/org/rust/cargo/commands/RustfmtTest.kt
@@ -18,7 +18,7 @@
import org.rust.cargo.toolchain.RustChannel
import org.rust.fileTree
import org.rust.ide.formatter.RustfmtTestmarks
-import org.rust.launchAction
+import org.rust.launchAnAction
import org.rust.openapiext.RsProcessExecutionException
import org.rust.openapiext.saveAllDocuments
@@ -530,11 +530,11 @@
}
private fun reformatFile() {
- myFixture.launchAction("Cargo.RustfmtFile")
+ myFixture.launchAnAction("Cargo.RustfmtFile")
}
private fun reformatCargoProject() {
- myFixture.launchAction("Cargo.RustfmtCargoProject")
+ myFixture.launchAnAction("Cargo.RustfmtCargoProject")
}
/**
diff --git a/src/test/kotlin/org/rust/cargo/project/RustProjectSettingsServiceTest.kt b/src/test/kotlin/org/rust/cargo/project/RustProjectSettingsServiceTest.kt
index d8bcc70..a99b3de 100644
--- a/src/test/kotlin/org/rust/cargo/project/RustProjectSettingsServiceTest.kt
+++ b/src/test/kotlin/org/rust/cargo/project/RustProjectSettingsServiceTest.kt
@@ -20,10 +20,7 @@
<option name="compileAllTargets" value="false" />
<option name="doctestInjectionEnabled" value="false" />
<option name="explicitPathToStdlib" value="/stdlib" />
- <option name="externalLinter" value="Clippy" />
- <option name="externalLinterArguments" value="--no-default-features" />
<option name="macroExpansionEngine" value="DISABLED" />
- <option name="runExternalLinterOnTheFly" value="true" />
<option name="toolchainHomeDirectory" value="/" />
<option name="useOffline" value="true" />
</RustProjectSettings>
@@ -49,10 +46,8 @@
<option name="externalLinterArguments" value="--no-default-features" />
<option name="macroExpansionEngine" value="DISABLED" />
<option name="runExternalLinterOnTheFly" value="true" />
- <option name="runRustfmtOnSave" value="true" /> <!-- Old field -->
<option name="toolchainHomeDirectory" value="/" />
<option name="useOffline" value="true" />
- <option name="useRustfmt" value="true" /> <!-- Old field -->
</RustProjectSettings>
""", """
<RustProjectSettings>
@@ -60,10 +55,7 @@
<option name="compileAllTargets" value="false" />
<option name="doctestInjectionEnabled" value="false" />
<option name="explicitPathToStdlib" value="/stdlib" />
- <option name="externalLinter" value="Clippy" />
- <option name="externalLinterArguments" value="--no-default-features" />
<option name="macroExpansionEngine" value="DISABLED" />
- <option name="runExternalLinterOnTheFly" value="true" />
<option name="toolchainHomeDirectory" value="/" />
<option name="useOffline" value="true" />
</RustProjectSettings>
diff --git a/src/test/kotlin/org/rust/cargo/project/model/impl/SyncToolWindowTest.kt b/src/test/kotlin/org/rust/cargo/project/model/impl/SyncToolWindowTest.kt
index 8387b0e..dac3ad3 100644
--- a/src/test/kotlin/org/rust/cargo/project/model/impl/SyncToolWindowTest.kt
+++ b/src/test/kotlin/org/rust/cargo/project/model/impl/SyncToolWindowTest.kt
@@ -482,11 +482,11 @@
}
private fun attachCargoProject(cargoProjectRoot: VirtualFile) {
- myFixture.launchAction("Cargo.AttachCargoProject", PlatformDataKeys.VIRTUAL_FILE to cargoProjectRoot)
+ myFixture.launchAnAction("Cargo.AttachCargoProject", PlatformDataKeys.VIRTUAL_FILE to cargoProjectRoot)
}
private fun detachCargoProject(cargoProject: CargoProject) {
- myFixture.launchAction("Cargo.DetachCargoProject", CargoToolWindow.SELECTED_CARGO_PROJECT to cargoProject)
+ myFixture.launchAnAction("Cargo.DetachCargoProject", CargoToolWindow.SELECTED_CARGO_PROJECT to cargoProject)
}
private fun checkSyncViewTree(expected: String) {
diff --git a/src/test/kotlin/org/rust/cargo/runconfig/RsAnsiEscapeDecoderTest.kt b/src/test/kotlin/org/rust/cargo/runconfig/RsAnsiEscapeDecoderTest.kt
index 4cf67ec..186390d 100644
--- a/src/test/kotlin/org/rust/cargo/runconfig/RsAnsiEscapeDecoderTest.kt
+++ b/src/test/kotlin/org/rust/cargo/runconfig/RsAnsiEscapeDecoderTest.kt
@@ -13,6 +13,7 @@
import org.rust.cargo.runconfig.RsAnsiEscapeDecoder.Companion.ANSI_24_BIT_COLOR_FORMAT
import org.rust.cargo.runconfig.RsAnsiEscapeDecoder.Companion.ANSI_8_BIT_COLOR_FORMAT
import org.rust.cargo.runconfig.RsAnsiEscapeDecoder.Companion.CSI
+import org.rust.escapeSequence
class RsAnsiEscapeDecoderTest : HeavyPlatformTestCase() {
@@ -277,7 +278,7 @@
val decoder = RsAnsiEscapeDecoder()
val actualColoredChunks = mutableListOf<Pair<String, String>>()
val acceptor = AnsiEscapeDecoder.ColoredTextAcceptor { s, attrs ->
- actualColoredChunks.add(Pair(s, attrs.toString()))
+ actualColoredChunks.add(Pair(s, attrs.escapeSequence))
}
decoder.escapeText(text.rawText, text.outputType, acceptor)
val expectedColoredChunks = mutableListOf<Pair<String, String>>()
diff --git a/src/test/kotlin/org/rust/common.kt b/src/test/kotlin/org/rust/common.kt
index f4dd615..8a3945f 100644
--- a/src/test/kotlin/org/rust/common.kt
+++ b/src/test/kotlin/org/rust/common.kt
@@ -201,7 +201,7 @@
}
-fun CodeInsightTestFixture.launchAction(
+fun CodeInsightTestFixture.launchAnAction(
actionId: String,
vararg context: Pair<DataKey<*>, *>,
shouldBeEnabled: Boolean = true
diff --git a/src/test/kotlin/org/rust/ide/actions/RsCreateCrateActionTest.kt b/src/test/kotlin/org/rust/ide/actions/RsCreateCrateActionTest.kt
index 0a4f601..4280031 100644
--- a/src/test/kotlin/org/rust/ide/actions/RsCreateCrateActionTest.kt
+++ b/src/test/kotlin/org/rust/ide/actions/RsCreateCrateActionTest.kt
@@ -13,7 +13,7 @@
import org.rust.ide.actions.ui.CargoNewCrateSettings
import org.rust.ide.actions.ui.CargoNewCrateUI
import org.rust.ide.actions.ui.withMockCargoNewCrateUi
-import org.rust.launchAction
+import org.rust.launchAnAction
class RsCreateCrateActionTest : RsWithToolchainTestBase() {
fun `test create with file context`() {
@@ -39,7 +39,7 @@
return CargoNewCrateSettings(binary, name)
}
}) {
- myFixture.launchAction("Rust.NewCargoCrate", CommonDataKeys.VIRTUAL_FILE to file)
+ myFixture.launchAnAction("Rust.NewCargoCrate", CommonDataKeys.VIRTUAL_FILE to file)
}
val src = if (binary) "main" else "lib"
diff --git a/src/test/kotlin/org/rust/ide/actions/ShareInPlaygroundActionTest.kt b/src/test/kotlin/org/rust/ide/actions/ShareInPlaygroundActionTest.kt
index 45815c9..4cdc269 100644
--- a/src/test/kotlin/org/rust/ide/actions/ShareInPlaygroundActionTest.kt
+++ b/src/test/kotlin/org/rust/ide/actions/ShareInPlaygroundActionTest.kt
@@ -123,7 +123,7 @@
}
private fun actionLauncher() {
- myFixture.launchAction("Rust.ShareInPlayground")
+ myFixture.launchAnAction("Rust.ShareInPlayground")
}
companion object {
diff --git a/src/test/kotlin/org/rust/ide/annotator/AnnotationTestFixtureBase.kt b/src/test/kotlin/org/rust/ide/annotator/AnnotationTestFixtureBase.kt
index 309b5ff..a34fff6 100644
--- a/src/test/kotlin/org/rust/ide/annotator/AnnotationTestFixtureBase.kt
+++ b/src/test/kotlin/org/rust/ide/annotator/AnnotationTestFixtureBase.kt
@@ -12,6 +12,7 @@
import com.intellij.codeInspection.InspectionProfileEntry
import com.intellij.codeInspection.SuppressIntentionActionFromFix
import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.openapi.application.ApplicationInfo
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.testFramework.ExtensionTestUtil
@@ -195,6 +196,13 @@
checkInfo: Boolean = false,
checkWeakWarn: Boolean = false,
) {
+ if (ApplicationInfo.getInstance().build.baselineVersion == 233) {
+ // BACKCOMPAT: 2023.2; in 233 a quick-fix is available withing the whole line, so
+ // `checkFixAvailableInSelectionOnly` tests start behaving differently.
+ // Also, because of that we probably should stop care about QF availability ranges
+ // and just remove all tests that use `checkFixAvailableInSelectionOnly`
+ return // Pass
+ }
configureByText(before.replace("<selection>", "<selection><caret>"))
checkHighlighting(checkWarn, checkInfo, checkWeakWarn, ignoreExtraHighlighting = false)
val selections = codeInsightFixture.editor.selectionModel.let { model ->
diff --git a/src/232/test/kotlin/org/rust/ide/hints/codeVision/RsImplementationsCodeVisionTest.kt b/src/test/kotlin/org/rust/ide/hints/codeVision/RsImplementationsCodeVisionTest.kt
similarity index 100%
rename from src/232/test/kotlin/org/rust/ide/hints/codeVision/RsImplementationsCodeVisionTest.kt
rename to src/test/kotlin/org/rust/ide/hints/codeVision/RsImplementationsCodeVisionTest.kt
diff --git a/src/232/test/kotlin/org/rust/ide/hints/codeVision/RsReferenceCodeVisionTest.kt b/src/test/kotlin/org/rust/ide/hints/codeVision/RsReferenceCodeVisionTest.kt
similarity index 100%
rename from src/232/test/kotlin/org/rust/ide/hints/codeVision/RsReferenceCodeVisionTest.kt
rename to src/test/kotlin/org/rust/ide/hints/codeVision/RsReferenceCodeVisionTest.kt
diff --git a/src/232/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt b/src/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt
similarity index 98%
rename from src/232/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt
rename to src/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt
index bafc793..2284e5f 100644
--- a/src/232/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt
+++ b/src/test/kotlin/org/rust/ide/hints/codeVision/RsVcsCodeVisionTestCase.kt
@@ -93,6 +93,6 @@
""")
private fun doTest(@Language("Rust") text: String) {
- testProviders(text.trimIndent(), "main.rs", VcsCodeVisionProvider.id)
+ testProviders(text.trimIndent(), "main.rs", VcsCodeVisionProvider().groupId)
}
}
diff --git a/src/test/kotlin/org/rust/ide/intentions/ExtractInlineModuleIntentionTest.kt b/src/test/kotlin/org/rust/ide/intentions/ExtractInlineModuleIntentionTest.kt
index ba5d447..a9615bc 100644
--- a/src/test/kotlin/org/rust/ide/intentions/ExtractInlineModuleIntentionTest.kt
+++ b/src/test/kotlin/org/rust/ide/intentions/ExtractInlineModuleIntentionTest.kt
@@ -128,27 +128,14 @@
)
}
- fun `test invalid extract inline module`() {
- doTest(fileTree {
- rust("main.rs", """
- mod foo {
- // function
- fn a() {}
- }
+ fun `test invalid extract inline module`() = doUnavailableTest("""
+ mod foo {
+ // function
+ fn a() {}
+ }
- fn /*caret*/main() {}
- """)
- }, fileTree {
- rust("main.rs", """
- mod foo {
- // function
- fn a() {}
- }
-
- fn main() {}
- """)
- })
- }
+ fn /*caret*/main() {}
+ """)
private fun doTest(before: FileTree, after: FileTree) {
val testProject = before.create()
diff --git a/src/test/kotlin/org/rust/ide/refactoring/ConvertToNamedFieldsRefactoringTest.kt b/src/test/kotlin/org/rust/ide/refactoring/ConvertToNamedFieldsRefactoringTest.kt
index ed420dd..561e4f6 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/ConvertToNamedFieldsRefactoringTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/ConvertToNamedFieldsRefactoringTest.kt
@@ -7,7 +7,7 @@
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
-import org.rust.launchAction
+import org.rust.launchAnAction
class ConvertToNamedFieldsRefactoringTest : RsTestBase() {
@@ -232,7 +232,7 @@
private fun doAvailableTest(@Language("Rust") before: String, @Language("Rust") after: String) {
InlineFile(before.trimIndent()).withCaret()
- myFixture.launchAction("Rust.RsConvertToNamedFields")
+ myFixture.launchAnAction("Rust.RsConvertToNamedFields")
myFixture.checkResult(replaceCaretMarker(after.trimIndent()))
}
}
diff --git a/src/test/kotlin/org/rust/ide/refactoring/ConvertToTupleRefactoringTest.kt b/src/test/kotlin/org/rust/ide/refactoring/ConvertToTupleRefactoringTest.kt
index 426abf2..13fd937 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/ConvertToTupleRefactoringTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/ConvertToTupleRefactoringTest.kt
@@ -7,7 +7,7 @@
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
-import org.rust.launchAction
+import org.rust.launchAnAction
class ConvertToTupleRefactoringTest : RsTestBase() {
fun `test simple`() = doAvailableTest("""
@@ -190,7 +190,7 @@
private fun doAvailableTest(@Language("Rust") before: String, @Language("Rust") after: String) {
InlineFile(before.trimIndent()).withCaret()
- myFixture.launchAction("Rust.RsConvertToTuple")
+ myFixture.launchAnAction("Rust.RsConvertToTuple")
myFixture.checkResult(replaceCaretMarker(after.trimIndent()))
}
}
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsDowngradeModuleToFileTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RsDowngradeModuleToFileTest.kt
index 6701296..2aeac00 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsDowngradeModuleToFileTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsDowngradeModuleToFileTest.kt
@@ -10,7 +10,7 @@
import org.rust.FileTree
import org.rust.RsTestBase
import org.rust.fileTree
-import org.rust.launchAction
+import org.rust.launchAnAction
class RsDowngradeModuleToFileTest : RsTestBase() {
fun `test works on file`() = checkAvailable(
@@ -71,7 +71,7 @@
}
private fun testActionOnElement(element: PsiElement, shouldBeEnabled: Boolean) {
- myFixture.launchAction(
+ myFixture.launchAnAction(
"Rust.RsDowngradeModuleToFile",
CommonDataKeys.PSI_ELEMENT to element,
shouldBeEnabled = shouldBeEnabled
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsExtractEnumVariantTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RsExtractEnumVariantTest.kt
index 56c0c27..41c5971 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsExtractEnumVariantTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsExtractEnumVariantTest.kt
@@ -7,7 +7,7 @@
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
-import org.rust.launchAction
+import org.rust.launchAnAction
class RsExtractEnumVariantTest : RsTestBase() {
fun `test not available on empty variant`() = doUnavailableTest("""
@@ -644,6 +644,6 @@
private fun doUnavailableTest(@Language("Rust") code: String) {
InlineFile(code.trimIndent()).withCaret()
- myFixture.launchAction("Rust.RsExtractEnumVariant", shouldBeEnabled = false)
+ myFixture.launchAnAction("Rust.RsExtractEnumVariant", shouldBeEnabled = false)
}
}
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsExtractStructFieldsTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RsExtractStructFieldsTest.kt
index 7896519..cbb43ba 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsExtractStructFieldsTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsExtractStructFieldsTest.kt
@@ -13,7 +13,7 @@
import org.rust.ide.refactoring.generate.RsStructMemberChooserObject
import org.rust.ide.refactoring.generate.StructMemberChooserUi
import org.rust.ide.refactoring.generate.withMockStructMemberChooserUi
-import org.rust.launchAction
+import org.rust.launchAnAction
class RsExtractStructFieldsTest : RsTestBase() {
fun `test unavailable on tuple struct`() = doUnavailableTest("""
@@ -607,6 +607,6 @@
private fun doUnavailableTest(@Language("Rust") code: String) {
InlineFile(code.trimIndent()).withCaret()
- myFixture.launchAction("Rust.RsExtractStructFields", shouldBeEnabled = false)
+ myFixture.launchAnAction("Rust.RsExtractStructFields", shouldBeEnabled = false)
}
}
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsInlineTestBase.kt b/src/test/kotlin/org/rust/ide/refactoring/RsInlineTestBase.kt
index 5c68d16..4bd01b4 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsInlineTestBase.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsInlineTestBase.kt
@@ -8,7 +8,7 @@
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
import org.rust.hasCaretMarker
-import org.rust.launchAction
+import org.rust.launchAnAction
abstract class RsInlineTestBase : RsTestBase() {
@@ -21,7 +21,7 @@
protected fun doUnavailableTest(@Language("Rust") code: String) {
InlineFile(code.trimIndent()).withCaret()
- myFixture.launchAction("Inline", shouldBeEnabled = false)
+ myFixture.launchAnAction("Inline", shouldBeEnabled = false)
}
protected inline fun <reified T : Throwable> expectError(code: String) {
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RsPromoteModuleToDirectoryActionTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RsPromoteModuleToDirectoryActionTest.kt
index 9c8bfaf..dad64f4 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RsPromoteModuleToDirectoryActionTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RsPromoteModuleToDirectoryActionTest.kt
@@ -10,7 +10,7 @@
import org.rust.FileTree
import org.rust.RsTestBase
import org.rust.fileTree
-import org.rust.launchAction
+import org.rust.launchAnAction
class RsPromoteModuleToDirectoryActionTest : RsTestBase() {
@@ -159,7 +159,7 @@
}
private fun testActionOnElement(element: PsiElement, shouldBeEnabled: Boolean) {
- myFixture.launchAction(
+ myFixture.launchAnAction(
"Rust.RsPromoteModuleToDirectoryAction",
CommonDataKeys.PSI_ELEMENT to element,
shouldBeEnabled = shouldBeEnabled
diff --git a/src/232/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt b/src/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt
similarity index 100%
rename from src/232/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt
rename to src/test/kotlin/org/rust/ide/wordSelection/RsBlocksAndBodiesSelectionHandlerTest.kt
diff --git a/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestBase.kt b/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestBase.kt
index 4fa0231..7e925b9 100644
--- a/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestBase.kt
+++ b/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestBase.kt
@@ -113,6 +113,14 @@
completionChar: Char = '\n'
) = completionFixture.checkCompletion(lookupString, before, after, completionChar)
+ protected fun checkCompletion(
+ lookupString: String,
+ tailText: String,
+ @Language("Rust") before: String,
+ @Language("Rust") after: String,
+ completionChar: Char = '\n'
+ ) = completionFixture.checkCompletion(lookupString, tailText, before, after, completionChar)
+
fun checkCompletionWithLiveTemplate(
lookupString: String,
@Language("Rust") before: String,
diff --git a/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestFixtureBase.kt b/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestFixtureBase.kt
index 3e35f8d..646e438 100644
--- a/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestFixtureBase.kt
+++ b/src/test/kotlin/org/rust/lang/core/completion/RsCompletionTestFixtureBase.kt
@@ -66,6 +66,24 @@
}
}
+ fun checkCompletion(
+ lookupString: String,
+ tailText: String,
+ before: IN,
+ @Language("Rust") after: String,
+ completionChar: Char,
+ ) {
+ checkByText(before, after.trimIndent()) {
+ val items = myFixture.completeBasic()
+ ?: return@checkByText // single completion was inserted
+ val lookupItem = items
+ .find { it.lookupString == lookupString && it.presentation.tailText == tailText }
+ ?: error("Lookup string $lookupString not found")
+ myFixture.lookup.currentItem = lookupItem
+ myFixture.type(completionChar)
+ }
+ }
+
fun checkNoCompletion(code: IN) {
prepare(code)
noCompletionCheck()
diff --git a/src/test/kotlin/org/rust/lang/core/completion/RsImplForCompletionTest.kt b/src/test/kotlin/org/rust/lang/core/completion/RsImplForCompletionTest.kt
index 7f19b99..6afbe9d 100644
--- a/src/test/kotlin/org/rust/lang/core/completion/RsImplForCompletionTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/completion/RsImplForCompletionTest.kt
@@ -5,13 +5,12 @@
package org.rust.lang.core.completion
-import com.intellij.openapi.project.DumbServiceImpl
import org.intellij.lang.annotations.Language
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameter
import org.rust.RsJUnit4ParameterizedTestRunner
-import java.util.concurrent.atomic.AtomicBoolean
+import org.rust.WithDumbMode
@RunWith(RsJUnit4ParameterizedTestRunner::class)
@Parameterized.UseParametersRunnerFactory(RsJUnit4ParameterizedTestRunner.RsRunnerForParameters.Factory::class)
@@ -21,24 +20,12 @@
@JvmStatic
@Parameterized.Parameters
fun data(): Iterable<Any> {
- return listOf(AtomicBoolean(false), AtomicBoolean(true))
+ return listOf(WithDumbMode.SmartDumbMode.SMART, WithDumbMode.SmartDumbMode.DUMB)
}
}
- // @Parameter doesn't work properly for primitive Kotlin types,
- // throws `can't assign to a private member` exception even when the field is public
@Parameter(0)
- lateinit var isDumbMode: AtomicBoolean
-
- override fun setUp() {
- super.setUp()
- DumbServiceImpl.getInstance(project).isDumb = isDumbMode.get()
- }
-
- override fun tearDown() {
- DumbServiceImpl.getInstance(project).isDumb = false
- super.tearDown()
- }
+ override lateinit var runInMode: WithDumbMode.SmartDumbMode
fun `test impl trait for completion`() = checkCompletion("for", """
trait A {}
@@ -200,7 +187,7 @@
@Language("Rust") after: String,
completionChar: Char = '\n'
) {
- if (isDumbMode.get()) {
+ if (runInMode == WithDumbMode.SmartDumbMode.DUMB) {
checkCompletion(lookupString, before, after, completionChar)
} else {
checkNotContainsCompletion(lookupString, before)
diff --git a/src/test/kotlin/org/rust/lang/core/completion/RsKeywordCompletionContributorTest.kt b/src/test/kotlin/org/rust/lang/core/completion/RsKeywordCompletionContributorTest.kt
index 4ea80be..83f3e4b 100644
--- a/src/test/kotlin/org/rust/lang/core/completion/RsKeywordCompletionContributorTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/completion/RsKeywordCompletionContributorTest.kt
@@ -5,22 +5,14 @@
package org.rust.lang.core.completion
-import com.intellij.openapi.project.DumbServiceImpl
import org.intellij.lang.annotations.Language
+import org.rust.WithDumbMode
+import org.rust.WithDumbMode.SmartDumbMode.DUMB
+import org.rust.WithDumbMode.SmartDumbMode.SMART
import org.rust.lang.core.completion.RsKeywordCompletionContributor.Companion.CONDITION_KEYWORDS
+@WithDumbMode(DUMB)
class RsKeywordCompletionContributorTest : RsCompletionTestBase() {
-
- override fun setUp() {
- super.setUp()
- DumbServiceImpl.getInstance(project).isDumb = true
- }
-
- override fun tearDown() {
- DumbServiceImpl.getInstance(project).isDumb = false
- super.tearDown()
- }
-
fun `test break in for loop`() = checkCompletion("break", """
fn foo() {
for _ in 0..4 {
@@ -63,6 +55,7 @@
}
""")
+ @WithDumbMode(SMART)
fun `test break not applied if doesnt start stmt`() = checkNoCompletion("""
fn foo() {
while true {
@@ -71,12 +64,14 @@
}
""")
+ @WithDumbMode(SMART)
fun `test break not applied outside loop`() = checkNoCompletion("""
fn foo() {
bre/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test break not applied within closure`() = checkNoCompletion("""
fn bar() {
loop {
@@ -141,6 +136,7 @@
}
""")
+ @WithDumbMode(SMART)
fun `test continue expression outside loop`() = checkNoCompletion("""
fn foo() {
let x = cont/*caret*/;
@@ -218,18 +214,21 @@
}
""")
+ @WithDumbMode(SMART)
fun `test enum not applied if doesnt start stmt within fn`() = checkNoCompletion("""
fn foo() {
let en/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test enum not applied within struct`() = checkNoCompletion("""
struct Foo {
en/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test enum not applied if doesnt start stmt`() = checkNoCompletion("""
mod en/*caret*/
""")
@@ -422,18 +421,22 @@
}
""")
+ @WithDumbMode(SMART)
fun `test return not applied on file level`() = checkNoCompletion("""
retu/*caret*/
""")
+ @WithDumbMode(SMART)
fun `test return not applied within parameters list`() = checkNoCompletion("""
fn foo(retu/*caret*/) {}
""")
+ @WithDumbMode(SMART)
fun `test return not applied before block`() = checkNoCompletion("""
fn foo() retu/*caret*/ {}
""")
+ @WithDumbMode(SMART)
fun `test return not applied if doesnt start statement`() = checkNoCompletion("""
const retu/*caret*/
""")
@@ -556,12 +559,14 @@
}
""")
+ @WithDumbMode(SMART)
fun `test let else after semicolon`() = checkNoCompletion("""
fn main() {
let x = 0; els/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test let else without expression`() = checkNoCompletion("""
fn main() {
let x = els/*caret*/
@@ -595,10 +600,12 @@
fn foo<T>(t: T) -> i32 where /*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in not generic function`() = checkNoCompletion("""
fn foo() whe/*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in not generic function with ret type`() = checkNoCompletion("""
fn foo() -> i32 whe/*caret*/
""")
@@ -635,6 +642,7 @@
struct Foo<T>(T) where /*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in not generic struct`() = checkNoCompletion("""
struct Foo whe/*caret*/
""")
@@ -645,6 +653,7 @@
enum Foo<T> where /*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in not generic enum`() = checkNoCompletion("""
enum Foo whe/*caret*/
""")
@@ -655,16 +664,19 @@
type Foo<T> where /*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in not generic type alias`() = checkNoCompletion("""
type Foo whe/*caret*/
""")
+ @WithDumbMode(SMART)
fun `test where in trait assoc type`() = checkNoCompletion("""
trait Foo {
type Bar whe/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test where in impl block assoc type`() = checkNoCompletion("""
impl Foo for Bar {
type FooBar whe/*caret*/
@@ -762,12 +774,14 @@
"fn foo<const /*caret*/>() {}"
)
+ @WithDumbMode(SMART)
fun `test const parameter before lifetime parameter`() = checkNoCompletion("""
- "fn foo</*caret*/, 'a>() {}"
+ fn foo</*caret*/, 'a>() {}
""")
+ @WithDumbMode(SMART)
fun `test const parameter before type parameter`() = checkNoCompletion("""
- "fn foo</*caret*/, A>() {}"
+ fn foo</*caret*/, A>() {}
""")
fun `test const parameter before const parameter`() = checkCompletion("const",
@@ -790,8 +804,9 @@
"fn foo<const C: i32, const /*caret*/>() {}"
)
+ @WithDumbMode(SMART)
fun `test const parameter before comma`() = checkNoCompletion("""
- "fn foo<T /*caret*/>() {}"
+ fn foo<T /*caret*/>() {}
""")
fun `test inside trait`() = checkCompletion(MEMBERS_KEYWORDS, """
@@ -818,12 +833,14 @@
}
""")
+ @WithDumbMode(SMART)
fun `test enum inside trait`() = checkNoCompletion("""
pub trait Bar {
en/*caret*/
}
""")
+ @WithDumbMode(SMART)
fun `test trait inside trait`() = checkNoCompletion("""
pub trait Bar {
tra/*caret*/
@@ -854,6 +871,7 @@
}
""")
+ @WithDumbMode(SMART)
fun `test impl inside impl`() = checkNoCompletion("""
impl Bar for Foo {
imp/*caret*/
@@ -890,6 +908,7 @@
"pub union /*caret*/"
)
+ @WithDumbMode(SMART)
fun `test no union in expr`() = checkNoCompletion("""
fn foo() {
let x = 42 + unio/*caret*/;
@@ -1312,18 +1331,15 @@
}
""")
- // Smart mode is used for not completion tests to disable additional results
- // from language agnostic `com.intellij.codeInsight.completion.WordCompletionContributor`
- override fun checkNoCompletion(@Language("Rust") code: String) {
- val dumbService = DumbServiceImpl.getInstance(project)
- val oldValue = dumbService.isDumb
- try {
- dumbService.isDumb = false
- super.checkNoCompletion(code)
- } finally {
- dumbService.isDumb = oldValue
+ fun `test keyword completion triggered by spacebar adds only 1 space`() = checkCompletion("l", """
+ fn main() {
+ le/*caret*/;
}
- }
+ """, """
+ fn main() {
+ let /*caret*/;
+ }
+ """, completionChar = ' ')
private fun checkCompletion(
lookupStrings: List<String>,
diff --git a/src/test/kotlin/org/rust/lang/core/type/RsStubOnlyTypeInferenceTest.kt b/src/test/kotlin/org/rust/lang/core/type/RsStubOnlyTypeInferenceTest.kt
index 313de89..a653823 100644
--- a/src/test/kotlin/org/rust/lang/core/type/RsStubOnlyTypeInferenceTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/type/RsStubOnlyTypeInferenceTest.kt
@@ -5,6 +5,8 @@
package org.rust.lang.core.type
+import org.junit.Test
+
class RsStubOnlyTypeInferenceTest : RsTypificationTestBase() {
fun `test const expr`() = stubOnlyTypeInfer("""
@@ -374,4 +376,271 @@
f;
} //^ unsafe fn(i8) -> u64
""")
+
+ // TODO RUST-12502
+ @Test(expected = IllegalStateException::class)
+ fun `test infinite recursion in const evaluation 1`() = stubOnlyTypeInfer("""
+ //- foo.rs
+ pub struct Uint<const LIMBS: usize> { }
+
+ impl<const LIMBS: usize> Uint<LIMBS> {
+ pub const LIMBS: usize = LIMBS;
+ }
+
+ pub type U896 = Uint<{ 896 / 64 }>;
+
+ pub trait Tr<T> {}
+
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{14}> {}
+ //- main.rs
+ mod foo;
+ use foo::*;
+
+ fn main() {
+ let a = foo(U896{});
+ a;
+ } //^ Uint<7>
+
+ fn foo<A: Tr<B>, B>(a: A) -> B { todo!() }
+ """)
+
+ // TODO RUST-12502
+ @Test(expected = IllegalStateException::class)
+ fun `test infinite recursion in const evaluation 2`() = stubOnlyTypeInfer("""
+ //- foo.rs
+ pub struct Uint<const LIMBS: usize> { }
+
+ impl<const LIMBS: usize> Uint<LIMBS> {
+ pub const LIMBS: usize = LIMBS;
+ }
+
+ pub type U896 = Uint<{ 896 / 64 }>;
+
+ pub trait Tr<T> {}
+
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS}> {}
+
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 1}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 2}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 3}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 4}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 5}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 6}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 7}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 8}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 9}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 10}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 11}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 12}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 13}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 14}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 15}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 16}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 17}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 18}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 19}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 20}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 21}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 22}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 23}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 24}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 25}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 26}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 27}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 28}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 29}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 30}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 31}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 32}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 33}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 34}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 35}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 36}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 37}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 38}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 39}> {}
+ impl Tr<Uint<{<U896>::LIMBS / 2}>> for Uint<{<U896>::LIMBS + 40}> {}
+
+ //- main.rs
+ mod foo;
+ use foo::*;
+
+ fn main() {
+ let a = foo(U896{});
+ a;
+ } //^ Uint<7>
+
+ fn foo<A: Tr<B>, B>(a: A) -> B { todo!() }
+ """)
+
+ // Issue RUST-11763. Here we test that there isn't a StackOverflowError.
+ // The code is invalid (it does not compile). The inferred types doesn't matter
+ fun `test no StackOverflow with infinite recursion in const evaluation`() = stubOnlyTypeInfer("""
+ //- foo.rs
+ pub struct Uint<const LIMBS: usize> { }
+
+ pub type U128 = Uint<{ 128 }>;
+
+ impl Uint<0> {
+ const NEXT: usize = 32;
+ }
+
+ impl Uint<32> {
+ const NEXT: usize = 64;
+ }
+
+ impl Uint<{ <Uint<{32}>>::NEXT }> { // Uint<64>
+ const NEXT: usize = 128;
+ }
+
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ impl Uint<{ <Uint<{64}>>::NEXT }> { const NEXT: usize = 256; }
+ //- main.rs
+ mod foo;
+ use foo::*;
+
+ fn main() {
+ let a = Uint::<{ <Uint::<{ 64 }>>::NEXT }>{};
+ a;
+ } //^ Uint<<unknown>>
+ """)
}
diff --git a/src/test/kotlin/org/rustSlowTests/cargo/runconfig/test/CargoTestNodeInfoTest.kt b/src/test/kotlin/org/rustSlowTests/cargo/runconfig/test/CargoTestNodeInfoTest.kt
index 951519a..9e46323 100644
--- a/src/test/kotlin/org/rustSlowTests/cargo/runconfig/test/CargoTestNodeInfoTest.kt
+++ b/src/test/kotlin/org/rustSlowTests/cargo/runconfig/test/CargoTestNodeInfoTest.kt
@@ -12,48 +12,120 @@
import com.intellij.execution.testframework.sm.runner.SMTestProxy
import com.intellij.execution.ui.ConsoleViewContentType
import org.intellij.lang.annotations.Language
+import org.rust.MaxRustcVersion
+import org.rust.MinRustcVersion
import org.rust.cargo.toolchain.RustChannel
class CargoTestNodeInfoTest : CargoTestRunnerTestBase() {
- fun `test int diff`() = checkErrors("""
- assert_eq!(1, 2);
- """, "", Diff("1", "2"))
+ @MaxRustcVersion("1.72.1")
+ fun `test int diff (old)`() = checkErrors("""
+ assert_eq!(1, 2);
+ """, """
+ assertion failed: `(left == right)`
+ left: `1`,
+ right: `2`
+ """, Diff("1", "2"))
- fun `test char diff`() = checkErrors("""
- assert_eq!('a', 'c');
- """, "", Diff("a", "c"))
+ @MinRustcVersion("1.73.0")
+ fun `test int diff (new)`() = checkErrors("""
+ assert_eq!(1, 2);
+ """, """
+ assertion `left == right` failed
+ left: 1
+ right: 2
+ """, Diff("1", "2"))
- fun `test string diff`() = checkErrors("""
- assert_eq!("aaa", "bbb");
- """, "", Diff("aaa", "bbb"))
+ @MaxRustcVersion("1.72.1")
+ fun `test char diff (old)`() = checkErrors("""
+ assert_eq!('a', 'c');
+ """, """
+ assertion failed: `(left == right)`
+ left: `'a'`,
+ right: `'c'`
+ """, Diff("a", "c"))
- fun `test multiline string diff`() = checkErrors("""
- assert_eq!("a\naa", "bbb");
- """, "", Diff("a\naa", "bbb"))
+ @MinRustcVersion("1.73.0")
+ fun `test char diff (new)`() = checkErrors("""
+ assert_eq!('a', 'c');
+ """, """
+ assertion `left == right` failed
+ left: 'a'
+ right: 'c'
+ """, Diff("a", "c"))
+
+ @MaxRustcVersion("1.72.1")
+ fun `test string diff (old)`() = checkErrors("""
+ assert_eq!("aaa", "bbb");
+ """, """
+ assertion failed: `(left == right)`
+ left: `"aaa"`,
+ right: `"bbb"`
+ """, Diff("aaa", "bbb"))
+
+ @MinRustcVersion("1.73.0")
+ fun `test string diff (new)`() = checkErrors("""
+ assert_eq!("aaa", "bbb");
+ """, """
+ assertion `left == right` failed
+ left: "aaa"
+ right: "bbb"
+ """, Diff("aaa", "bbb"))
+
+ @MaxRustcVersion("1.72.1")
+ fun `test multiline string diff (old)`() = checkErrors("""
+ assert_eq!("a\naa", "bbb");
+ """, """
+ assertion failed: `(left == right)`
+ left: `"a\naa"`,
+ right: `"bbb"`
+ """, Diff("a\naa", "bbb"))
+
+ @MinRustcVersion("1.73.0")
+ fun `test multiline string diff (new)`() = checkErrors("""
+ assert_eq!("a\naa", "bbb");
+ """, """
+ assertion `left == right` failed
+ left: "a\naa"
+ right: "bbb"
+ """, Diff("a\naa", "bbb"))
fun `test assert_eq with message`() = checkErrors("""
- assert_eq!(1, 2, "`1` != `2`");
+ assert_eq!(1, 2, "`1` != `2`");
""", "`1` != `2`", Diff("1", "2"))
fun `test no diff`() = checkErrors("""
- assert!(1 != 1);
+ assert!(1 != 1);
""", """assertion failed: 1 != 1""")
fun `test assert with message`() = checkErrors("""
- assert!("aaa" != "aaa", "message");
+ assert!("aaa" != "aaa", "message");
""", "message")
- fun `test assert_ne`() = checkErrors("""
- assert_ne!(123, 123);
- """, "")
+ @MaxRustcVersion("1.72.1")
+ fun `test assert_ne (old)`() = checkErrors("""
+ assert_ne!(123, 123);
+ """, """
+ assertion failed: `(left != right)`
+ left: `123`,
+ right: `123`
+ """)
+
+ @MinRustcVersion("1.73.0")
+ fun `test assert_ne (new)`() = checkErrors("""
+ assert_ne!(123, 123);
+ """, """
+ assertion `left != right` failed
+ left: 123
+ right: 123
+ """)
fun `test assert_ne with message`() = checkErrors("""
- assert_ne!(123, 123, "123 == 123");
+ assert_ne!(123, 123, "123 == 123");
""", "123 == 123")
fun `test unescape error messages`() = checkErrors("""
- assert_eq!("a\\\\b", "a\\b", "`a\\\\b` != `a\\b`");
+ assert_eq!("a\\\\b", "a\\b", "`a\\\\b` != `a\\b`");
""", "`a\\\\b` != `a\\b`", Diff("a\\\\b", "a\\b"))
fun `test don't unescape test output`() = checkOutput("""
@@ -185,7 +257,7 @@
shouldPass: Boolean = false
) {
val testNode = getTestNode(testFnText, shouldPass)
- assertEquals(message, testNode.errorMessage)
+ assertEquals(message.trimIndent(), testNode.errorMessage?.trimEnd())
if (diff != null) {
val diffProvider = testNode.diffViewerProvider ?: error("Diff should be not null")
assertEquals(diff.actual, diffProvider.left)