From b48bcfa6f7b57e03a91cbaf063c2e89477bf8388 Mon Sep 17 00:00:00 2001 From: Maciej Procyk Date: Mon, 16 Jun 2025 18:44:11 +0200 Subject: [PATCH] [KMT-549][kmp][compose] add tests for `ComposeColorLineMarkerProviderDescriptorTest` (cherry picked from commit 26c94e199170b6f7a70626ae524dcfb7aee803e7) GitOrigin-RevId: d97303768ab6bf599b36ca8b21545a0718642c85 --- .../BUILD.bazel | 4 + .../intellij.compose.ide.plugin.k1.tests.iml | 4 + ...seColorLineMarkerProviderDescriptorTest.kt | 15 + .../BUILD.bazel | 4 + .../intellij.compose.ide.plugin.k2.tests.iml | 4 + ...seColorLineMarkerProviderDescriptorTest.kt | 15 + .../BUILD.bazel | 7 + ...tellij.compose.ide.plugin.shared.tests.iml | 7 + ...seColorLineMarkerProviderDescriptorTest.kt | 459 ++++++++++++++++++ .../plugin/shared/util/ComposeTestUtils.kt | 54 +++ 10 files changed, 573 insertions(+) create mode 100644 plugins/compose/intellij.compose.ide.plugin.k1/tests/com/intellij/compose/ide/plugin/k1/K1ComposeColorLineMarkerProviderDescriptorTest.kt create mode 100644 plugins/compose/intellij.compose.ide.plugin.k2/tests/com/intellij/compose/ide/plugin/k2/K2ComposeColorLineMarkerProviderDescriptorTest.kt create mode 100644 plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/ComposeColorLineMarkerProviderDescriptorTest.kt diff --git a/plugins/compose/intellij.compose.ide.plugin.k1/BUILD.bazel b/plugins/compose/intellij.compose.ide.plugin.k1/BUILD.bazel index 6064ff3ddf67..d90c4f57dc97 100644 --- a/plugins/compose/intellij.compose.ide.plugin.k1/BUILD.bazel +++ b/plugins/compose/intellij.compose.ide.plugin.k1/BUILD.bazel @@ -55,6 +55,7 @@ jvm_library( associates = ["//plugins/compose/intellij.compose.ide.plugin.k1:ide-plugin-k1"], deps = [ "//plugins/compose/intellij.compose.ide.plugin.shared:ide-plugin-shared-tests_test_lib", + "//plugins/compose/intellij.compose.ide.plugin.shared:ide-plugin-shared", "//platform/core-api:core", "//platform/editor-ui-api:editor-ui", "//plugins/kotlin/base/fe10/analysis", @@ -72,6 +73,9 @@ jvm_library( "@lib//:kotlinc-kotlin-compiler-common", "@lib//:kotlinc-kotlin-compiler-fe10", "@lib//:kotlinc-compose-compiler-plugin", + "//plugins/kotlin/gradle/gradle-java/tests.shared:tests.shared_test_lib", + "//plugins/gradle:gradle-tests_test_lib", + "//platform/external-system-impl:externalSystem-tests_test_lib", ] ) diff --git a/plugins/compose/intellij.compose.ide.plugin.k1/intellij.compose.ide.plugin.k1.tests.iml b/plugins/compose/intellij.compose.ide.plugin.k1/intellij.compose.ide.plugin.k1.tests.iml index bac2f96224d9..89b26cc3f812 100644 --- a/plugins/compose/intellij.compose.ide.plugin.k1/intellij.compose.ide.plugin.k1.tests.iml +++ b/plugins/compose/intellij.compose.ide.plugin.k1/intellij.compose.ide.plugin.k1.tests.iml @@ -9,6 +9,7 @@ + @@ -24,6 +25,9 @@ + + + \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.k1/tests/com/intellij/compose/ide/plugin/k1/K1ComposeColorLineMarkerProviderDescriptorTest.kt b/plugins/compose/intellij.compose.ide.plugin.k1/tests/com/intellij/compose/ide/plugin/k1/K1ComposeColorLineMarkerProviderDescriptorTest.kt new file mode 100644 index 000000000000..3e73a678a870 --- /dev/null +++ b/plugins/compose/intellij.compose.ide.plugin.k1/tests/com/intellij/compose/ide/plugin/k1/K1ComposeColorLineMarkerProviderDescriptorTest.kt @@ -0,0 +1,15 @@ +package com.intellij.compose.ide.plugin.k1 + +import com.intellij.compose.ide.plugin.shared.ComposeColorLineMarkerProviderDescriptor +import com.intellij.compose.ide.plugin.shared.ComposeColorLineMarkerProviderDescriptorTest +import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode +import kotlin.reflect.KClass + +internal class K1ComposeColorLineMarkerProviderDescriptorTest : ComposeColorLineMarkerProviderDescriptorTest() { + + override val pluginMode: KotlinPluginMode + get() = KotlinPluginMode.K1 + + override val expectedComposeColorLineMarkerProviderDescriptorClass: KClass + get() = K1ComposeColorLineMarkerProviderDescriptor::class +} \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.k2/BUILD.bazel b/plugins/compose/intellij.compose.ide.plugin.k2/BUILD.bazel index b629bd0b854c..0ebb05a22461 100644 --- a/plugins/compose/intellij.compose.ide.plugin.k2/BUILD.bazel +++ b/plugins/compose/intellij.compose.ide.plugin.k2/BUILD.bazel @@ -55,6 +55,7 @@ jvm_library( kotlinc_opts = ":custom_ide-plugin-k2-tests", associates = ["//plugins/compose/intellij.compose.ide.plugin.k2:ide-plugin-k2"], deps = [ + "//plugins/compose/intellij.compose.ide.plugin.shared:ide-plugin-shared", "//plugins/compose/intellij.compose.ide.plugin.shared:ide-plugin-shared-tests_test_lib", "//platform/core-api:core", "//platform/editor-ui-api:editor-ui", @@ -72,6 +73,9 @@ jvm_library( "@lib//:kotlinc-kotlin-compiler-common-provided", "@lib//:kotlinc-analysis-api-provided", "@lib//:kotlin-test-assertions-core-jvm", + "//plugins/kotlin/gradle/gradle-java/tests.shared:tests.shared_test_lib", + "//plugins/gradle:gradle-tests_test_lib", + "//platform/external-system-impl:externalSystem-tests_test_lib", ] ) diff --git a/plugins/compose/intellij.compose.ide.plugin.k2/intellij.compose.ide.plugin.k2.tests.iml b/plugins/compose/intellij.compose.ide.plugin.k2/intellij.compose.ide.plugin.k2.tests.iml index 4d0cceabf4c8..5290edb4567f 100644 --- a/plugins/compose/intellij.compose.ide.plugin.k2/intellij.compose.ide.plugin.k2.tests.iml +++ b/plugins/compose/intellij.compose.ide.plugin.k2/intellij.compose.ide.plugin.k2.tests.iml @@ -24,6 +24,7 @@ + @@ -38,6 +39,9 @@ + + + \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.k2/tests/com/intellij/compose/ide/plugin/k2/K2ComposeColorLineMarkerProviderDescriptorTest.kt b/plugins/compose/intellij.compose.ide.plugin.k2/tests/com/intellij/compose/ide/plugin/k2/K2ComposeColorLineMarkerProviderDescriptorTest.kt new file mode 100644 index 000000000000..ad35fe5599a8 --- /dev/null +++ b/plugins/compose/intellij.compose.ide.plugin.k2/tests/com/intellij/compose/ide/plugin/k2/K2ComposeColorLineMarkerProviderDescriptorTest.kt @@ -0,0 +1,15 @@ +package com.intellij.compose.ide.plugin.k2 + +import com.intellij.compose.ide.plugin.shared.ComposeColorLineMarkerProviderDescriptor +import com.intellij.compose.ide.plugin.shared.ComposeColorLineMarkerProviderDescriptorTest +import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode +import kotlin.reflect.KClass + +internal class K2ComposeColorLineMarkerProviderDescriptorTest : ComposeColorLineMarkerProviderDescriptorTest() { + + override val pluginMode: KotlinPluginMode + get() = KotlinPluginMode.K2 + + override val expectedComposeColorLineMarkerProviderDescriptorClass: KClass + get() = K2ComposeColorLineMarkerProviderDescriptor::class +} \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.shared/BUILD.bazel b/plugins/compose/intellij.compose.ide.plugin.shared/BUILD.bazel index e0729bcf0779..3dc7601e2bfe 100644 --- a/plugins/compose/intellij.compose.ide.plugin.shared/BUILD.bazel +++ b/plugins/compose/intellij.compose.ide.plugin.shared/BUILD.bazel @@ -55,7 +55,9 @@ jvm_library( "//platform/core-api:core", "//platform/core-impl", "//platform/editor-ui-api:editor-ui", + "//platform/projectModel-api:projectModel", "//platform/util", + "//platform/util/jdom", "//plugins/kotlin/base/test:test_test_lib", "//plugins/kotlin/base/plugin", "//plugins/kotlin/base/plugin:plugin_test_lib", @@ -70,6 +72,11 @@ jvm_library( "@lib//:io-mockk", "@lib//:io-mockk-jvm", "@lib//:kotlin-test", + "//plugins/kotlin/gradle/gradle-java/tests.shared:tests.shared_test_lib", + "//plugins/gradle:gradle-tests_test_lib", + "//platform/external-system-impl:externalSystem-tests_test_lib", + "@lib//:kotlinc-kotlin-compiler-tests", + "//plugins/gradle/tooling-extension-impl:toolingExtension-tests_test_lib", ] ) diff --git a/plugins/compose/intellij.compose.ide.plugin.shared/intellij.compose.ide.plugin.shared.tests.iml b/plugins/compose/intellij.compose.ide.plugin.shared/intellij.compose.ide.plugin.shared.tests.iml index a172d81d19ad..1be7fad70363 100644 --- a/plugins/compose/intellij.compose.ide.plugin.shared/intellij.compose.ide.plugin.shared.tests.iml +++ b/plugins/compose/intellij.compose.ide.plugin.shared/intellij.compose.ide.plugin.shared.tests.iml @@ -12,7 +12,9 @@ + + @@ -25,6 +27,11 @@ + + + + + \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/ComposeColorLineMarkerProviderDescriptorTest.kt b/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/ComposeColorLineMarkerProviderDescriptorTest.kt new file mode 100644 index 000000000000..03dffc3b05ff --- /dev/null +++ b/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/ComposeColorLineMarkerProviderDescriptorTest.kt @@ -0,0 +1,459 @@ +package com.intellij.compose.ide.plugin.shared + +import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl +import com.intellij.codeInsight.daemon.impl.LineMarkersPass +import com.intellij.compose.ide.plugin.shared.util.moveCaret +import com.intellij.openapi.application.runReadAction +import com.intellij.openapi.application.runWriteActionAndWait +import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.vfs.writeText +import com.intellij.testFramework.common.runAll +import com.intellij.testFramework.fixtures.CodeInsightTestFixture +import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory +import com.intellij.testFramework.runInEdtAndGet +import com.intellij.testFramework.runInEdtAndWait +import com.intellij.testFramework.utils.vfs.createFile +import org.intellij.lang.annotations.Language +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode +import org.jetbrains.kotlin.idea.base.test.TestRoot +import org.jetbrains.kotlin.idea.codeInsight.gradle.KotlinGradleImportingTestCase +import org.jetbrains.kotlin.test.TestMetadata +import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions +import org.junit.Test +import org.junit.runners.Parameterized.Parameter +import org.junit.runners.Parameterized.Parameters +import java.awt.Color +import kotlin.reflect.KClass +import kotlin.test.assertEquals as kAssertEquals +import kotlin.test.assertNotNull as kAssertNotNull + +private const val TARGET_GRADLE_VERSION = "8.9" + +@TestRoot("../../../community/plugins/compose/intellij.compose.ide.plugin.shared/testData") +@TestMetadata("") +abstract class ComposeColorLineMarkerProviderDescriptorTest : KotlinGradleImportingTestCase() { + + abstract override val pluginMode: KotlinPluginMode + + private var _codeInsightTestFixture: CodeInsightTestFixture? = null + + private val codeInsightTestFixture: CodeInsightTestFixture + get() = kAssertNotNull(_codeInsightTestFixture, "_codeInsightTestFixture was not initialized") + + @Parameter(1) + lateinit var sourceSetName: String + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorLong() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xFFC20029) + fun () { + val primary = Color(0xA84A8A7B) + val secondary = Color(0xFF4A8A7B) + val primaryVariant = Color(color = 0xFF57AD28) + val secondaryVariant = Color(color = 0x8057AD28) + } + } + """, + expectedColorIcons = listOf( + Color(194, 0, 41, 255), + Color(74, 138, 123, 168), + Color(74, 138, 123, 255), + Color(87, 173, 40, 255), + Color(87, 173, 40, 128), + ), + setColors = listOf( + "Co|lor(0xFF4A8A7B)" to Color(0xFFAABBCC.toInt()), + "Co|lor(color = 0xFF57AD28)" to Color(0xFFAABBCC.toInt()), + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xFFC20029) + fun () { + val primary = Color(0xA84A8A7B) + val secondary = Color(0xFFAABBCC) + val primaryVariant = Color(color = 0xFFAABBCC) + val secondaryVariant = Color(color = 0x8057AD28) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorWithLeadingZero() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xFFFF0000) + } + """, + expectedColorIcons = listOf( + Color(255, 0, 0, 255), + ), + setColors = listOf( + "Co|lor(0xFFFF0000)" to Color(0x0DFF0000, true), + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0x0DFF0000) + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorInt() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC20029) + fun () { + val primary = Color(0x4A8A7B) + val secondary = Color(0x804A8A7B) + val primaryVariant = Color(color = 0x57AD28) + val secondaryVariant = Color(color = 0x4057AD28) + } + } + """, + expectedColorIcons = listOf( + Color(194, 0, 41, 0), + Color(74, 138, 123, 0), + Color(74, 138, 123, 128), + Color(87, 173, 40, 0), + Color(87, 173, 40, 64), + ), + setColors = listOf( + "Co|lor(0x4A8A7B)" to Color(0xFFAABBCC.toInt()), + "Co|lor(color = 0x57AD28)" to Color(0xFFAABBCC.toInt()) + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC20029) + fun () { + val primary = Color(0xFFAABBCC) + val secondary = Color(0x804A8A7B) + val primaryVariant = Color(color = 0xFFAABBCC) + val secondaryVariant = Color(color = 0x4057AD28) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorInt_X3() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC2, 0x00, 0x29) + fun () { + val primary = Color(0x4A, 0x8A, 0x7B) + val secondary = Color(170, 187, 204) + val primaryVariant = Color(red = 0x57, green = 0xAD, blue = 0x28) + val secondaryVariant = Color(green = 200, red = 180, blue = 120) + } + } + """, + expectedColorIcons = listOf( + Color(194, 0, 41), + Color(74, 138, 123), + Color(170, 187, 204), + Color(87, 173, 40), + Color(180, 200, 120), + ), + setColors = listOf( + "Co|lor(0x4A, 0x8A, 0x7B)" to Color(0xFFAABBCC.toInt()), + "Co|lor(170, 187, 204)" to Color(0xFF406080.toInt()), + "Co|lor(red = 0x57, green = 0xAD, blue = 0x28)" to Color(0xFFAABBCC.toInt()), + "Co|lor(green = 200, red = 180, blue = 120)" to Color(0x80112233.toInt()), + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC2, 0x00, 0x29) + fun () { + val primary = Color(0xAA, 0xBB, 0xCC, 0xFF) + val secondary = Color(64, 96, 128, 255) + val primaryVariant = Color(red = 0xAA, green = 0xBB, blue = 0xCC, alpha = 0xFF) + val secondaryVariant = Color(red = 17, green = 34, blue = 51, alpha = 255) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorInt_X4() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC2, 0x00, 0x29, 0xFF) + fun () { + val primary = Color(0x4A, 0x8A, 0x7B, 0xFF) + val secondary = Color(170, 187, 204, 255) + val primaryVariant = Color(red = 0x57, green = 0xAD, blue = 0x28, alpha = 0xFF) + val secondaryVariant = Color(green = 120, red = 64, alpha = 255, blue = 192) + } + } + """, + expectedColorIcons = listOf( + Color(194, 0, 41), + Color(74, 138, 123), + Color(170, 187, 204), + Color(87, 173, 40), + Color(64, 120, 192), + ), + setColors = listOf( + "Co|lor(0x4A, 0x8A, 0x7B, 0xFF)" to Color(0xFFAABBCC.toInt()), + "Co|lor(green = 120, red = 64, alpha = 255, blue = 192)" to Color(0xFFAABBCC.toInt()) + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0xC2, 0x00, 0x29, 0xFF) + fun () { + val primary = Color(0xAA, 0xBB, 0xCC, 0xFF) + val secondary = Color(170, 187, 204, 255) + val primaryVariant = Color(red = 0x57, green = 0xAD, blue = 0x28, alpha = 0xFF) + val secondaryVariant = Color(red = 170, green = 187, blue = 204, alpha = 255) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorFloat_X3() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0.14f, 0.0f, 0.16f) + fun () { + val primary = Color(0.3f, 0.54f, 0.48f) + val primary = Color(0.3f, 0.54f, 0.48f) + val primaryVariant = Color(red = 0.34f, green = 0.68f, blue = 0.15f) + val primaryVariant = Color(green = 0.68f, red = 0.34f, blue = 0.15f) + } + } + """, + expectedColorIcons = listOf( + Color(36, 0, 41), + Color(77, 138, 122), + Color(77, 138, 122), + Color(87, 173, 38), + Color(87, 173, 38), + ), + setColors = listOf( + "Co|lor(0.3f, 0.54f, 0.48f)" to Color(0xFFAABBCC.toInt()), + "Co|lor(green = 0.68f, red = 0.34f, blue = 0.15f)" to Color(0xFFAABBCC.toInt()) + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0.14f, 0.0f, 0.16f) + fun () { + val primary = Color(0.667f, 0.733f, 0.8f, 1.0f) + val primary = Color(0.3f, 0.54f, 0.48f) + val primaryVariant = Color(red = 0.34f, green = 0.68f, blue = 0.15f) + val primaryVariant = Color(red = 0.667f, green = 0.733f, blue = 0.8f, alpha = 1.0f) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorFloat_X4() = doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0.194f, 0f, 0.41f, 0.5f) + fun () { + val primary = Color(0.74f, 0.138f, 0.3f, 0.845f) + val primary = Color(0.74f, 0.138f, 0.3f, 0.845f) + val primaryVariant = Color(red = 0.87f, green = 0.173f, blue = 0.4f, alpha = 0.25f) + val primaryVariant = Color(alpha = 0.25f, green = 0.173f, blue = 0.4f, red = 0.87f) + } + } + """, + expectedColorIcons = listOf( + Color(49, 0, 105, 128), + Color(189, 35, 77, 215), + Color(189, 35, 77, 215), + Color(222, 44, 102, 64), + Color(222, 44, 102, 64), + ), + setColors = listOf( + "Co|lor(0.74f, 0.138f, 0.3f, 0.845f)" to Color(0xFFAABBCC.toInt()), + "Co|lor(alpha = 0.25f, green = 0.173f, blue = 0.4f, red = 0.87f)" to Color(0xFFAABBCC.toInt()) + ), + expectedSetColorCode = """ + package org.example.project + import androidx.compose.ui.graphics.Color + class A { + val other = Color(0.194f, 0f, 0.41f, 0.5f) + fun () { + val primary = Color(0.667f, 0.733f, 0.8f, 1.0f) + val primary = Color(0.74f, 0.138f, 0.3f, 0.845f) + val primaryVariant = Color(red = 0.87f, green = 0.173f, blue = 0.4f, alpha = 0.25f) + val primaryVariant = Color(red = 0.667f, green = 0.733f, blue = 0.8f, alpha = 1.0f) + } + } + """ + ) + + @TargetVersions(TARGET_GRADLE_VERSION) + @Test + @TestMetadata("ComposeColorLineMarker") + fun testColorFloat_X4_ColorSpace() { + // Note: We don't offer neither color preview nor picker for Color(Float, Float, Float, Float, + // ColorSpace) function. + doTest( + code = """ + package org.example.project + import androidx.compose.ui.graphics.Color + import androidx.compose.ui.graphics.colorspace.ColorSpaces + class A { + val other = Color(0.194f, 0f, 0.41f, 0.5f, ColorSpaces.LinearSrgb) + fun () { + val primary = Color(0.74f, 0.138f, 0.3f, 0.845f, ColorSpaces.LinearSrgb) + val primary = Color(0f, 0f, 0f, 0f, ColorSpaces.LinearSrgb) + val primaryVariant = Color(red = 0.87f, green = 0.173f, blue = 0.4f, alpha = 0.25f, colorSpace = ColorSpaces.LinearSrgb) + val primaryVariant = Color(red = 1.0f, green = 1.0f, blue = 1.0f, alpha = 1.0f, colorSpace = ColorSpaces.LinearSrgb) + } + } + """, + expectedColorIcons = listOf(), + ) + } + + private fun doTest( + @Language("kotlin") code: String, + expectedColorIcons: List, + setColors: List> = emptyList(), + @Language("kotlin") expectedSetColorCode: String? = null, + ) { + importProjectFromTestData() + + val colorFile = runWriteActionAndWait { + projectRoot.createFile("composeApp/src/$sourceSetName/kotlin/org/example/project/A.kt").apply { + writeText(code.trimIndent()) + } + } + + val countExpectedProviders = LineMarkersPass.getMarkerProviders(KotlinLanguage.INSTANCE, project).count { + expectedComposeColorLineMarkerProviderDescriptorClass.isInstance(it) + } + kAssertEquals(1, countExpectedProviders, "Expected single ${expectedComposeColorLineMarkerProviderDescriptorClass.java.name} provider") + + codeInsightTestFixture.configureFromExistingVirtualFile(colorFile) + + checkGutterIconInfos(expectedColorIcons) + + setColors.forEach { (window, newColor) -> + setNewColor(window, newColor) + } + + expectedSetColorCode?.let { + kAssertEquals(it.trimIndent(), codeInsightTestFixture.editor.document.text) + } + } + + private fun checkGutterIconInfos(expectedColorIcons: List) { + codeInsightTestFixture.doHighlighting() + + val highlightInfos = runReadAction { + DaemonCodeAnalyzerImpl.getLineMarkers(codeInsightTestFixture.editor.document, project) + .filter { lineMarkerInfo -> lineMarkerInfo.navigationHandler is ColorIconRenderer } + .sortedBy { it.startOffset } + } + + assertEquals(expectedColorIcons.size, highlightInfos.size) + highlightInfos.forEach { + kAssertNotNull(it.icon) + kAssertNotNull(it.navigationHandler) + } + + assertEquals(expectedColorIcons, highlightInfos.map { (it.navigationHandler as ColorIconRenderer).color }) + } + + private fun setNewColor(window: String, newColor: Color) { + val element = runInEdtAndGet { codeInsightTestFixture.moveCaret(window) } + + codeInsightTestFixture.doHighlighting() + val highlightInfo = runReadAction { + DaemonCodeAnalyzerImpl.getLineMarkers(codeInsightTestFixture.editor.document, project) + .single { lineMarkerInfo -> + lineMarkerInfo.navigationHandler is ColorIconRenderer && lineMarkerInfo.element == element + } + } + + runInEdtAndWait { + val setColorTask = + (highlightInfo.navigationHandler as ColorIconRenderer).getSetColorTask() + ?: return@runInEdtAndWait + WriteCommandAction.runWriteCommandAction( + project, + ComposeIdeBundle.message("compose.color.picker.action.name"), + null, + { setColorTask.invoke(newColor) }, + ) + } + } + + protected abstract val expectedComposeColorLineMarkerProviderDescriptorClass: KClass + + override fun setUpFixtures() { + myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).fixture + _codeInsightTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(myTestFixture) + codeInsightTestFixture.setUp() + } + + override fun tearDownFixtures() { + runAll( + { _codeInsightTestFixture?.tearDown() }, + { _codeInsightTestFixture = null }, + { myTestFixture = null }, + ) + } + + companion object { + + @JvmStatic + @Suppress("ACCIDENTAL_OVERRIDE") + @Parameters(name = "source set {1} with Gradle {0}") + fun data() = listOf( + "commonMain", + "desktopMain", + "wasmJsMain", + ).map { arrayOf(TARGET_GRADLE_VERSION, it) } + } +} \ No newline at end of file diff --git a/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/util/ComposeTestUtils.kt b/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/util/ComposeTestUtils.kt index ecb9250d7e26..1550a10d1526 100644 --- a/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/util/ComposeTestUtils.kt +++ b/plugins/compose/intellij.compose.ide.plugin.shared/tests/com/intellij/compose/ide/plugin/shared/util/ComposeTestUtils.kt @@ -1,13 +1,31 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.compose.ide.plugin.shared.util import com.intellij.compose.ide.plugin.shared.isComposeEnabledInModule +import com.intellij.psi.PsiElement import com.intellij.testFramework.EditorTestUtil import com.intellij.testFramework.PlatformTestUtil +import com.intellij.testFramework.fixtures.CodeInsightTestFixture import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.psi.KtFile import java.nio.file.Path import java.nio.file.Paths +import kotlin.test.assertTrue /** * Enables Compose in the tests by adding Composable annotation to the test classpath. @@ -54,3 +72,39 @@ fun JavaCodeInsightTestFixture.configureByText(text: String): KtFile { @ApiStatus.Internal const val CARET = EditorTestUtil.CARET_TAG + +private fun String.offsetForWindow(window: String, startIndex: Int = 0): Int { + require(window.count { it == '|' } == 1) { + "Must provide exactly one '|' character in window. Got \"$window\"" + } + val delta = window.indexOf("|") + val target = window.substring(0, delta) + window.substring(delta + 1) + val start = indexOf(target, startIndex - delta) + assertTrue(start >= 0, "Didn't find the string $target in the source of $this") + return start + delta +} + +/** + * Returns the offset of the caret in the currently open editor as indicated by the [window] string. + * + * The [window] string needs to contain a `|` character surrounded by a prefix and/or suffix to be + * found in the file. The file is searched for the concatenation of prefix and suffix strings and + * the caret is placed at the first matching offset, between the prefix and suffix. + */ +fun CodeInsightTestFixture.offsetForWindow(window: String, startIndex: Int = 0): Int = + editor.document.text.offsetForWindow(window, startIndex) + + +/** + * Moves caret in the currently open editor to position indicated by the [window] string. + * + * The [window] string needs to contain a `|` character surrounded by a prefix and/or suffix to be + * found in the file. The file is searched for the concatenation of prefix and suffix strings and + * the caret is placed at the first matching offset, between the prefix and suffix. + */ +fun CodeInsightTestFixture.moveCaret(window: String): PsiElement { + val offset = offsetForWindow(window) + editor.caretModel.moveToOffset(offset) + // myFixture.elementAtCaret seems to do something else + return file.findElementAt(offset)!! +}