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) } }