From f96d25fe8d657691782566fd5bf18ff17321ab20 Mon Sep 17 00:00:00 2001 From: Andrey Cherkasov Date: Sun, 18 Jun 2023 05:12:53 +0400 Subject: [PATCH] [devkit] Do not report service classes that contain a check on the unit test or UI-less mode IJ-CR-105402 GitOrigin-RevId: cc3e83f7e6e6f93f663c43aea66a3680e8c264b4 --- .../LightServiceMigrationCodeInspection.kt | 2 +- .../inspections/LightServiceMigrationUtil.kt | 26 +++++++++++++++++++ .../LightServiceMigrationXMLInspection.kt | 4 +++ .../HeadlessEnvironment.java | 10 +++++++ .../lightServiceMigration/UnitTestMode.java | 7 +++++ .../LightServiceMigrationInspectionTest.kt | 8 ++++++ .../HeadlessEnvironment.kt | 10 +++++++ .../lightServiceMigration/UnitTestMode.kt | 5 ++++ .../KtLightServiceMigrationInspectionTest.kt | 8 ++++++ ...LightServiceMigrationInspectionTestBase.kt | 21 +++++++++++++++ 10 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.java create mode 100644 plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/UnitTestMode.java create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.kt create mode 100644 plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/UnitTestMode.kt diff --git a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationCodeInspection.kt b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationCodeInspection.kt index 31220ca8b66e..cbae98c6ab43 100644 --- a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationCodeInspection.kt +++ b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationCodeInspection.kt @@ -33,7 +33,7 @@ internal class LightServiceMigrationCodeInspection : DevKitUastInspectionBase(UC JvmInheritanceUtil.isInheritor(aClass, PersistentStateComponent::class.java.canonicalName)) { continue } - if (serviceImplementation == psiClass) { + if (serviceImplementation == psiClass && !containsUnitTestOrHeadlessModeCheck(aClass)) { return registerProblem(aClass, level, manager, isOnTheFly) } } diff --git a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationUtil.kt b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationUtil.kt index 58313d108c83..6320cd9c823d 100644 --- a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationUtil.kt +++ b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationUtil.kt @@ -4,18 +4,23 @@ package org.jetbrains.idea.devkit.inspections +import com.intellij.openapi.application.Application import com.intellij.openapi.components.Service import com.intellij.openapi.components.ServiceDescriptor import com.intellij.openapi.module.ModuleUtilCore import com.intellij.psi.PsiClass import com.intellij.util.xml.DomElement import com.intellij.util.xml.DomUtil +import com.siyeh.ig.callMatcher.CallMatcher import org.jetbrains.annotations.Nls import org.jetbrains.idea.devkit.DevKitBundle import org.jetbrains.idea.devkit.dom.Extension import org.jetbrains.idea.devkit.util.DevKitDomUtil import org.jetbrains.idea.devkit.util.PluginPlatformInfo import org.jetbrains.idea.devkit.util.PsiUtil +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UClass +import org.jetbrains.uast.visitor.AbstractUastVisitor internal data class ServiceInfo(val aClass: PsiClass, val level: Service.Level) @@ -64,4 +69,25 @@ internal fun isVersion193OrHigher(aClass: PsiClass): Boolean { return buildNumber != null && buildNumber.baselineVersion >= 193 } +internal fun containsUnitTestOrHeadlessModeCheck(aClass: UClass): Boolean { + var result = false + + aClass.accept(object : AbstractUastVisitor() { + override fun visitCallExpression(node: UCallExpression): Boolean { + if (IS_UNIT_TEST_OR_HEADLESS_MODE.uCallMatches(node)) { + result = true + return false + } + return super.visitCallExpression(node) + } + }) + + return result +} + private val disallowedAttributes = setOf("serviceInterface", "os", "client", "overrides", "id", "preload") + +private val IS_UNIT_TEST_OR_HEADLESS_MODE = CallMatcher.anyOf( + CallMatcher.instanceCall(Application::class.java.canonicalName, "isUnitTestMode", "isHeadlessEnvironment"), + CallMatcher.staticCall("org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt", "isUnitTestMode", "isHeadlessEnvironment"), +) diff --git a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationXMLInspection.kt b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationXMLInspection.kt index ef79bb0d582f..8cd284dfacb5 100644 --- a/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationXMLInspection.kt +++ b/plugins/devkit/devkit-core/src/inspections/LightServiceMigrationXMLInspection.kt @@ -15,6 +15,8 @@ import com.intellij.util.xml.highlighting.DomElementAnnotationHolder import com.intellij.util.xml.highlighting.DomHighlightingHelper import org.jetbrains.idea.devkit.DevKitBundle import org.jetbrains.idea.devkit.dom.Extension +import org.jetbrains.uast.UClass +import org.jetbrains.uast.toUElement internal class LightServiceMigrationXMLInspection : DevKitPluginXmlInspectionBase() { @@ -30,6 +32,8 @@ internal class LightServiceMigrationXMLInspection : DevKitPluginXmlInspectionBas JvmInheritanceUtil.isInheritor(aClass, PersistentStateComponent::class.java.canonicalName)) { return } + val uClass = aClass.toUElement(UClass::class.java) + if (uClass == null || containsUnitTestOrHeadlessModeCheck(uClass)) return if (aClass.hasAnnotation(Service::class.java.canonicalName)) { val message = DevKitBundle.message("inspection.light.service.migration.already.annotated.message") holder.createProblem(element, ProblemHighlightType.ERROR, message, null) diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.java b/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.java new file mode 100644 index 000000000000..a33de71a6be7 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.java @@ -0,0 +1,10 @@ +package com.example.demo; + +import com.intellij.openapi.application.ApplicationManager; + +final class MyService { + public void foo() { + if (ApplicationManager.getApplication().isHeadlessEnvironment()) { + } + } +} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/UnitTestMode.java b/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/UnitTestMode.java new file mode 100644 index 000000000000..61ef77e4bcb7 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/inspections/lightServiceMigration/UnitTestMode.java @@ -0,0 +1,7 @@ +package com.example.demo; + +import com.intellij.openapi.application.ApplicationManager; + +final class MyService { + private final static boolean isUnitTestMode = ApplicationManager.getApplication().isUnitTestMode(); +} \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTest.kt b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTest.kt index 8a99d82f1fc5..bd8461bd027d 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTest.kt +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTest.kt @@ -44,4 +44,12 @@ internal class LightServiceMigrationInspectionTest : LightServiceMigrationInspec fun testLibraryClass() { myFixture.testHighlighting(getTestName(true) + ".xml") } + + fun testUnitTestMode() { + doTest(getCodeFilePath(), CANNOT_BE_LIGHT_SERVICE_XML) + } + + fun testHeadlessEnvironment() { + doTest(getCodeFilePath(), CANNOT_BE_LIGHT_SERVICE_XML) + } } \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.kt new file mode 100644 index 000000000000..c215321e26a4 --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/HeadlessEnvironment.kt @@ -0,0 +1,10 @@ +package com.example.demo + +import com.intellij.openapi.application.ApplicationManager + +class MyService { + fun foo() { + if (ApplicationManager.getApplication().isHeadlessEnvironment()) { + } + } +} \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/UnitTestMode.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/UnitTestMode.kt new file mode 100644 index 000000000000..3f02c3f4938b --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/lightServiceMigration/UnitTestMode.kt @@ -0,0 +1,5 @@ +package com.example.demo + +import com.intellij.openapi.application.ApplicationManager + +class MyService(val isUnitTestMode: Boolean = ApplicationManager.getApplication().isUnitTestMode) \ No newline at end of file diff --git a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtLightServiceMigrationInspectionTest.kt b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtLightServiceMigrationInspectionTest.kt index aab3f3b6ffcf..2f75660fba14 100644 --- a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtLightServiceMigrationInspectionTest.kt +++ b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtLightServiceMigrationInspectionTest.kt @@ -41,4 +41,12 @@ internal class KtLightServiceMigrationInspectionTest : LightServiceMigrationInsp fun testLightService() { doTest(getCodeFilePath(), getXmlFilePath()) } + + fun testUnitTestMode() { + doTest(getCodeFilePath(), CANNOT_BE_LIGHT_SERVICE_XML) + } + + fun testHeadlessEnvironment() { + doTest(getCodeFilePath(), CANNOT_BE_LIGHT_SERVICE_XML) + } } \ No newline at end of file diff --git a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTestBase.kt b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTestBase.kt index 0183de2e90d1..8d48af72b9d0 100644 --- a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTestBase.kt +++ b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/LightServiceMigrationInspectionTestBase.kt @@ -39,6 +39,27 @@ abstract class LightServiceMigrationInspectionTestBase : LightDevKitInspectionFi public @interface Service {} """ ) + myFixture.addClass(""" + package com.intellij.openapi.application; + + public final class ApplicationManager { + + private static Application ourApplication; + + public static Application getApplication() { + return ourApplication; + } + } + """) + + myFixture.addClass(""" + package com.intellij.openapi.application; + + public interface Application { + boolean isUnitTestMode(); + boolean isHeadlessEnvironment(); + } + """) myFixture.enableInspections(LightServiceMigrationXMLInspection::class.java, LightServiceMigrationCodeInspection::class.java) }