diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml
index e1ee0d4c94..a2e6cd4c28 100644
--- a/.github/workflows/build-plugin.yml
+++ b/.github/workflows/build-plugin.yml
@@ -28,7 +28,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- platform-version: [ 241 ]
+ platform-version: [ 241, 242 ]
env:
ORG_GRADLE_PROJECT_buildNumber: ${{ needs.generate-build-number.outputs.build_number }}
ORG_GRADLE_PROJECT_platformVersion: ${{ matrix.platform-version }}
diff --git a/.gitignore b/.gitignore
index deaffe8ab4..f6081b6f9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.idea
.intellijPlatform
+.kotlin
.fleet
*.iml
.gradle
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 911f847d07..17eb8fcc8a 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -22,6 +22,6 @@
-
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 6f314a86f5..02215060b8 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -204,6 +204,8 @@ allprojects {
compileOnly(kotlin("stdlib-jdk8"))
implementation("junit:junit:4.13.2") // used in kotlin/org/rust/openapiext/Testmark.kt
+ // https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-faq.html#missing-opentest4j-dependency-in-test-framework
+ testImplementation("org.opentest4j:opentest4j:1.3.0")
testOutput(sourceSets.getByName("test").output.classesDirs)
}
diff --git a/gradle-242.properties b/gradle-242.properties
new file mode 100644
index 0000000000..70124e4b61
--- /dev/null
+++ b/gradle-242.properties
@@ -0,0 +1,19 @@
+# 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=2024.2
+
+# https://plugins.jetbrains.com/plugin/8195-toml/versions
+tomlPlugin=org.toml.lang:242.20224.155
+# https://plugins.jetbrains.com/plugin/12775-native-debugging-support/versions
+nativeDebugPlugin=com.intellij.nativeDebug:242.20224.155
+# https://plugins.jetbrains.com/plugin/12175-grazie-lite/versions
+graziePlugin=tanvd.grazi:242.20224.155
+# https://plugins.jetbrains.com/plugin/227-psiviewer/versions
+psiViewerPlugin=PsiViewer:242.4697
+# https://plugins.jetbrains.com/plugin/13114-copyright/versions
+copyrightPlugin=com.intellij.copyright:242.20224.237
+
+# please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description
+sinceBuild=242
+untilBuild=242.*
diff --git a/gradle.properties b/gradle.properties
index 6e16322f46..9812039c9a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,6 @@
propertiesPluginEnvironmentNameProperty=platformVersion
-# Supported platforms: 241
-platformVersion=241
+# Supported platforms: 241, 242
+platformVersion=242
# Supported IDEs: IU
baseIDE=IU
ideToRun=
diff --git a/src/241/test/kotlin/org/rust/TestCompat.kt b/src/241/test/kotlin/org/rust/TestCompat.kt
index 58321a7957..8206da6d35 100644
--- a/src/241/test/kotlin/org/rust/TestCompat.kt
+++ b/src/241/test/kotlin/org/rust/TestCompat.kt
@@ -6,8 +6,17 @@
package org.rust
import com.intellij.execution.process.ProcessOutputType
+import com.intellij.ide.navbar.tests.contextNavBarPathStrings
+import com.intellij.ide.util.treeView.smartTree.Sorter
+import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.util.Key
// BACKCOMPAT 2023.2: move to the RsAnsiEscapeDecoderTest companion
val Key<*>.escapeSequence: String
get() = (this as? ProcessOutputType)?.escapeSequence ?: toString()
+
+val alphaSorterId = Sorter.ALPHA_SORTER_ID
+
+fun contextNavBarPathStringsCompat(ctx: DataContext): List {
+ return contextNavBarPathStrings(ctx)
+}
diff --git a/src/242/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt b/src/242/main/kotlin/org/rust/ide/debugger/runconfig/comparUtils.kt
new file mode 100644
index 0000000000..cbfeff51b2
--- /dev/null
+++ b/src/242/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 = loadedPlugins
diff --git a/src/242/test/kotlin/org/rust/DumbModeTestUtil.kt b/src/242/test/kotlin/org/rust/DumbModeTestUtil.kt
new file mode 100644
index 0000000000..8f7fd69b5c
--- /dev/null
+++ b/src/242/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/242/test/kotlin/org/rust/TestCompat.kt b/src/242/test/kotlin/org/rust/TestCompat.kt
new file mode 100644
index 0000000000..7185f435eb
--- /dev/null
+++ b/src/242/test/kotlin/org/rust/TestCompat.kt
@@ -0,0 +1,45 @@
+/*
+ * 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.ide.util.treeView.smartTree.Sorter
+import com.intellij.openapi.actionSystem.DataContext
+import com.intellij.openapi.util.Key
+import com.intellij.platform.navbar.NavBarItemPresentationData
+import com.intellij.platform.navbar.backend.NavBarItem
+import com.intellij.platform.navbar.backend.impl.pathToItem
+import com.intellij.util.concurrency.annotations.RequiresReadLock
+import org.jetbrains.annotations.TestOnly
+
+// BACKCOMPAT 2023.2: move to the RsAnsiEscapeDecoderTest companion
+val Key<*>.escapeSequence: String
+ get() = (this as? ProcessOutputType)?.escapeSequence ?: toString()
+
+val alphaSorterId = Sorter.getAlphaSorterId()
+
+@Suppress("UnstableApiUsage")
+@TestOnly
+@RequiresReadLock
+fun contextNavBarPathStrings(ctx: DataContext): List {
+ // Navigation bar implementation was split into several modules, which made `navbar.testFramework` test scope only.
+ //
+ // See https://youtrack.jetbrains.com/issue/IJPL-850/Split-navigation-bar-implementation-into-several-modules,
+ // https://github.com/JetBrains/intellij-community/commit/a9e1406257b330d17d2a3f78f47b2d2113eca97c and
+ // https://github.com/JetBrains/intellij-community/commit/bfa6619891699658f86a7bf8bdf7726a67bc6efd
+
+ // Code copied from [platform/navbar/testFramework/src/testFramework.kt](https://github.com/JetBrains/intellij-community/blob/d161fd043392998e10c4551df92634dbda5a06b5/platform/navbar/testFramework/src/testFramework.kt#L34).
+ val contextItem = NavBarItem.NAVBAR_ITEM_KEY.getData(ctx)
+ ?.dereference()
+ ?: return emptyList()
+ return contextItem.pathToItem().map {
+ (it.presentation() as NavBarItemPresentationData).text
+ }
+}
+
+fun contextNavBarPathStringsCompat(ctx: DataContext): List {
+ return contextNavBarPathStrings(ctx)
+}
diff --git a/src/242/test/kotlin/org/rust/ide/MockBrowserLauncher.kt b/src/242/test/kotlin/org/rust/ide/MockBrowserLauncher.kt
new file mode 100644
index 0000000000..ce47a7fdd6
--- /dev/null
+++ b/src/242/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/ide/miscExtensions/RsFileTabTitleProvider.kt b/src/main/kotlin/org/rust/ide/miscExtensions/RsFileTabTitleProvider.kt
index 74a568f0e3..4424539f9f 100644
--- a/src/main/kotlin/org/rust/ide/miscExtensions/RsFileTabTitleProvider.kt
+++ b/src/main/kotlin/org/rust/ide/miscExtensions/RsFileTabTitleProvider.kt
@@ -5,16 +5,12 @@
package org.rust.ide.miscExtensions
-import com.intellij.ide.ui.UISettings
-import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder
import com.intellij.openapi.fileEditor.impl.UniqueNameEditorTabTitleProvider
-import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.rust.cargo.CargoConstants
import org.rust.lang.RsConstants
import org.rust.lang.core.psi.isRustFile
-import java.io.File
class RsFileTabTitleProvider : UniqueNameEditorTabTitleProvider() {
override fun getEditorTabTitle(project: Project, file: VirtualFile): String? {
@@ -22,14 +18,7 @@ class RsFileTabTitleProvider : UniqueNameEditorTabTitleProvider() {
return null
}
- val uiSettings = UISettings.instanceOrNull
- if (uiSettings == null || !uiSettings.showDirectoryForNonUniqueFilenames || DumbService.isDumb(project)) {
- return null
- }
-
- val uniqueName = UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePath(project, file)
- val tabText = getEditorTabText(uniqueName, File.separator, uiSettings.hideKnownExtensionInTabs)
- return tabText.takeUnless { it == file.name }
+ return super.getEditorTabTitle(project, file)
}
companion object {
diff --git a/src/main/kotlin/org/rust/lang/core/macros/MacroExpansionManager.kt b/src/main/kotlin/org/rust/lang/core/macros/MacroExpansionManager.kt
index c8260af436..732805e201 100644
--- a/src/main/kotlin/org/rust/lang/core/macros/MacroExpansionManager.kt
+++ b/src/main/kotlin/org/rust/lang/core/macros/MacroExpansionManager.kt
@@ -29,6 +29,7 @@ import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
+import com.intellij.testFramework.IndexingTestUtil
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.util.io.DataOutputStream
import com.intellij.util.io.createDirectories
@@ -720,7 +721,10 @@ private class MacroExpansionServiceImplInner(
private fun processMacros(taskType: RsTask.TaskType) {
if (!isExpansionModeNew || !enabledInUnitTests) return
- if (isUnitTestMode && DumbService.isDumb(project)) return
+ if (isUnitTestMode) {
+ IndexingTestUtil.waitUntilIndexesAreReady(project)
+ if (DumbService.isDumb(project)) return
+ }
val task = MacroExpansionTask(
project,
@@ -730,6 +734,7 @@ private class MacroExpansionServiceImplInner(
taskType,
)
submitTask(task)
+ if (isUnitTestMode) IndexingTestUtil.waitUntilIndexesAreReady(project)
}
private fun isTemplateActiveInAnyEditor(): Boolean {
diff --git a/src/main/kotlin/org/rust/lang/core/macros/VfsInternals.kt b/src/main/kotlin/org/rust/lang/core/macros/VfsInternals.kt
index 19ea04897b..1460b67aa8 100644
--- a/src/main/kotlin/org/rust/lang/core/macros/VfsInternals.kt
+++ b/src/main/kotlin/org/rust/lang/core/macros/VfsInternals.kt
@@ -33,7 +33,7 @@ object VfsInternals {
@Throws(IOException::class)
fun reloadFileIfNeeded(file: VirtualFile) {
if (isMarkedForContentReload(file)) {
- file.contentsToByteArray(false)
+ file.contentsToByteArray(true)
}
}
diff --git a/src/main/kotlin/org/rust/lang/core/psi/ext/RsDocAndAttributeOwner.kt b/src/main/kotlin/org/rust/lang/core/psi/ext/RsDocAndAttributeOwner.kt
index f5dda95bde..9cb8f30fc7 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/ext/RsDocAndAttributeOwner.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/ext/RsDocAndAttributeOwner.kt
@@ -185,7 +185,6 @@ fun RsDocAndAttributeOwner.getQueryAttributes(
stub: RsAttributeOwnerStub? = attributeStub,
outerAttrsOnly: Boolean = false
): QueryAttributes {
- testAssert { !DumbService.isDumb(project) }
return if (stub != null) {
QueryAttributes(stub.getQueryAttributes(explicitCrate, outerAttrsOnly).metaItems.map { it.psi })
} else {
diff --git a/src/main/kotlin/org/rust/openapiext/utils.kt b/src/main/kotlin/org/rust/openapiext/utils.kt
index 18fe3f2dab..1cb00940d6 100644
--- a/src/main/kotlin/org/rust/openapiext/utils.kt
+++ b/src/main/kotlin/org/rust/openapiext/utils.kt
@@ -52,6 +52,7 @@ import com.intellij.psi.impl.PsiDocumentManagerBase
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.stubs.StubIndexKey
+import com.intellij.testFramework.IndexingTestUtil
import com.intellij.util.concurrency.AppExecutorUtil
import com.intellij.util.ui.UIUtil
import org.jdom.Element
@@ -154,6 +155,7 @@ fun checkIsBackgroundThread() {
}
fun checkIsSmartMode(project: Project) {
+ if (isUnitTestMode) IndexingTestUtil.waitUntilIndexesAreReady(project)
if (DumbService.getInstance(project).isDumb) throw IndexNotReadyException.create()
}
@@ -163,6 +165,7 @@ fun checkCommitIsNotInProgress(project: Project) {
if ((PsiDocumentManager.getInstance(project) as PsiDocumentManagerBase).isCommitInProgress) {
error("Accessing indices during PSI event processing can lead to typing performance issues")
}
+ IndexingTestUtil.waitUntilIndexesAreReady(project)
}
}
diff --git a/src/test/kotlin/org/rust/cargo/RsWithToolchainTestBase.kt b/src/test/kotlin/org/rust/cargo/RsWithToolchainTestBase.kt
index 38e7f7aff0..f821b42d8f 100644
--- a/src/test/kotlin/org/rust/cargo/RsWithToolchainTestBase.kt
+++ b/src/test/kotlin/org/rust/cargo/RsWithToolchainTestBase.kt
@@ -12,6 +12,7 @@ import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
+import com.intellij.testFramework.IndexingTestUtil
import com.intellij.testFramework.builders.ModuleFixtureBuilder
import com.intellij.testFramework.common.runAll
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase
@@ -58,6 +59,7 @@ abstract class RsWithToolchainTestBase : CodeInsightFixtureTestCase) {
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 1ad3abafdf..cf589bea77 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
@@ -9,6 +9,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.testFramework.IndexingTestUtil
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.fixtures.BuildViewTestFixture
import org.rust.*
@@ -495,6 +496,7 @@ class SyncToolWindowTest : RsWithToolchainTestBase() {
}
private fun attachCargoProject(cargoProjectRoot: VirtualFile) {
+ IndexingTestUtil.waitUntilIndexesAreReady(project)
myFixture.launchAnAction("Cargo.AttachCargoProject", PlatformDataKeys.VIRTUAL_FILE to cargoProjectRoot)
}
diff --git a/src/test/kotlin/org/rust/ide/structure/RsNavBarTest.kt b/src/test/kotlin/org/rust/ide/structure/RsNavBarTest.kt
index 838b1f5db6..7fd7613bc6 100644
--- a/src/test/kotlin/org/rust/ide/structure/RsNavBarTest.kt
+++ b/src/test/kotlin/org/rust/ide/structure/RsNavBarTest.kt
@@ -5,10 +5,10 @@
package org.rust.ide.structure
-import com.intellij.ide.navbar.tests.contextNavBarPathStrings
import com.intellij.openapi.editor.ex.EditorEx
import org.intellij.lang.annotations.Language
import org.rust.RsTestBase
+import org.rust.contextNavBarPathStringsCompat
class RsNavBarTest : RsTestBase() {
fun `test struct`() = doTest("""
@@ -140,7 +140,7 @@ class RsNavBarTest : RsTestBase() {
val dataContext = (myFixture.editor as EditorEx).dataContext
- val actualItems = contextNavBarPathStrings(dataContext)
+ val actualItems = contextNavBarPathStringsCompat(dataContext)
val expected = listOf("src", "main.rs", *items)
assertEquals(expected, actualItems)
}
diff --git a/src/test/kotlin/org/rust/ide/structure/RsVisibilitySorterTest.kt b/src/test/kotlin/org/rust/ide/structure/RsVisibilitySorterTest.kt
index e34aa0adac..01705b8640 100644
--- a/src/test/kotlin/org/rust/ide/structure/RsVisibilitySorterTest.kt
+++ b/src/test/kotlin/org/rust/ide/structure/RsVisibilitySorterTest.kt
@@ -7,6 +7,7 @@ package org.rust.ide.structure
import com.intellij.ide.util.treeView.smartTree.Sorter
import org.intellij.lang.annotations.Language
+import org.rust.alphaSorterId
class RsVisibilitySorterTest : RsStructureViewToggleableActionTest(){
override val actionId: String = RsVisibilitySorter.ID
@@ -499,6 +500,6 @@ class RsCombinedVisibilityAlphaSorterTest: RsStructureViewTestBase() {
| Zar visibility=private
""") {
setActionActive(RsVisibilitySorter.ID, true)
- setActionActive(Sorter.ALPHA_SORTER_ID, true)
+ setActionActive(alphaSorterId, true)
}
}