Fix class run configuration applicability (KT-33787)

The bug appeared when we turned “ultra light classes” on by default.
  The difference with the old implementation is that
  PsiClass.getTextRange() returns the correct non-null value.
  This triggers JavaExecutionUtil#stepIntoSingleClass() to return
  a light class instead of the original location (of a PsiIdentifier).
  So AbstractJavaTestConfigurationProducer#isConfigurationFromContext()
  returns true, and the wrong configuration is reused instead of
  creating the new one.

By the way, for Java it also returns an identifier because of the
  PsiTreeUtil.getParentOfType(element, PsiClass.class) != null check.

The proper fix should land in the newer versions of IDEA, however this
  (hopefully, temporary) hack will fix test method gutters for
  all platform versions.
This commit is contained in:
Yan Zhulanow
2020-02-14 17:51:42 +09:00
parent b360fb5119
commit 390d062721
6 changed files with 33 additions and 18 deletions
@@ -81,7 +81,7 @@ abstract class KtLightClassForSourceDeclaration(
override fun getText() = kotlinOrigin.text ?: ""
override fun getTextRange(): TextRange = kotlinOrigin.textRange ?: TextRange.EMPTY_RANGE
override fun getTextRange(): TextRange? = kotlinOrigin.textRange ?: TextRange.EMPTY_RANGE
override fun getTextOffset() = kotlinOrigin.textOffset
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.PsiClassImplUtil
@@ -475,4 +477,12 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
override fun isDeprecated(): Boolean = _deprecated
override fun copy(): KtLightClassImpl = KtUltraLightClass(classOrObject.copy() as KtClassOrObject, support)
override fun getTextRange(): TextRange? {
if (Registry.`is`("kotlin.ultra.light.classes.empty.text.range", true)) {
return null
}
return super.getTextRange()
}
}
@@ -34,20 +34,20 @@ class GradleTestRunConfigurationCustomTest : GradleImportingTestCase() {
val kotlinFile = files.first { it.name == "MyKotlinTest.kt" }
val javaClassConfiguration = getConfiguration(javaFile, myProject, "MyTest")
javaClassConfiguration.isProducedBy(TestClassGradleConfigurationProducer::class.java)
assert(javaClassConfiguration.configuration !is KotlinGradleRunConfiguration)
assert(javaClassConfiguration.isProducedBy(TestClassGradleConfigurationProducer::class.java))
assert(javaClassConfiguration.configuration.name == "MyTest")
val javaMethodConfiguration = getConfiguration(javaFile, myProject, "testA")
javaMethodConfiguration.isProducedBy(TestMethodGradleConfigurationProducer::class.java)
assert(javaMethodConfiguration.configuration !is KotlinGradleRunConfiguration)
assert(javaMethodConfiguration.isProducedBy(TestMethodGradleConfigurationProducer::class.java))
assert(javaMethodConfiguration.configuration.name == "MyTest.testA")
val kotlinClassConfiguration = getConfiguration(kotlinFile, myProject, "MyKotlinTest")
kotlinClassConfiguration.isProducedBy(KotlinJvmTestClassGradleConfigurationProducer::class.java)
assert(kotlinClassConfiguration.configuration is KotlinGradleRunConfiguration)
assert(kotlinClassConfiguration.isProducedBy(KotlinJvmTestClassGradleConfigurationProducer::class.java))
assert(kotlinClassConfiguration.configuration.name == "MyKotlinTest")
val kotlinFunctionConfiguration = getConfiguration(kotlinFile, myProject, "testA")
kotlinFunctionConfiguration.isProducedBy(KotlinJvmTestMethodGradleConfigurationProducer::class.java)
assert(kotlinFunctionConfiguration.configuration is KotlinGradleRunConfiguration)
assert(kotlinFunctionConfiguration.isProducedBy(KotlinJvmTestMethodGradleConfigurationProducer::class.java))
assert(kotlinFunctionConfiguration.configuration.name == "MyKotlinTest.testA")
}
}
}
+5
View File
@@ -175,6 +175,11 @@
defaultValue="true"
restartRequired="false"/>
<registryKey key="kotlin.ultra.light.classes.empty.text.range"
description="Return 'null' text range as in old light class implementation"
defaultValue="true"
restartRequired="false"/>
<registryKey key="kotlin.uast.force.uinjectionhost"
description="Whether to convert `KtStringTemplateExpression` to `KotlinStringTemplateUPolyadicExpression` in all cases"
defaultValue="true"
@@ -43,7 +43,7 @@ class LightClassFromTextTest : KotlinLightCodeInsightFixtureTestCase() {
val classC = classes[0]
assertEquals("C", classC.qualifiedName)
assertEquals("class C", classC.text)
assertEquals(TextRange(17, 24), classC.textRange)
assertEquals(null, classC.textRange)
assertEquals(23, classC.textOffset)
assertEquals(17, classC.startOffsetInParent)
assertTrue(classC.isWritable)
@@ -44,20 +44,20 @@ class KotlinJUnitRunConfigurationTest : AbstractRunConfigurationTest() {
val kotlinFile = testDir.findChild("MyKotlinTest.kt")!!
val javaClassConfiguration = getConfiguration(javaFile, project, "MyTest")
javaClassConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java)
assert(javaClassConfiguration.configuration !is KotlinJUnitConfiguration)
assert(javaClassConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java))
assert(javaClassConfiguration.configuration.name == "MyJavaTest")
val javaMethodConfiguration = getConfiguration(javaFile, project, "testA")
javaMethodConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java)
assert(javaMethodConfiguration.configuration !is KotlinJUnitConfiguration)
assert(javaMethodConfiguration.isProducedBy(TestInClassConfigurationProducer::class.java))
assert(javaMethodConfiguration.configuration.name == "MyJavaTest.testA")
val kotlinClassConfiguration = getConfiguration(kotlinFile, project, "MyKotlinTest")
kotlinClassConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java)
assert(kotlinClassConfiguration.configuration is KotlinJUnitConfiguration)
assert(kotlinClassConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java))
assert(kotlinClassConfiguration.configuration.name == "MyKotlinTest")
val kotlinFunctionConfiguration = getConfiguration(kotlinFile, project, "testA")
kotlinFunctionConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java)
assert(kotlinFunctionConfiguration.configuration is KotlinJUnitConfiguration)
assert(kotlinFunctionConfiguration.isProducedBy(KotlinJUnitRunConfigurationProducer::class.java))
assert(kotlinFunctionConfiguration.configuration.name == "MyKotlinTest.testA")
} finally {
detachJUnitLibrary()
}