[FIR IDE] Add Fir lightclasses tests and fix FindUsages tests
This commit is contained in:
committed by
Ilya Kirillov
parent
3cefef03ff
commit
dbb54c87bc
+17
-28
@@ -10,51 +10,40 @@ import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.PsiClassRenderer
|
||||
import org.jetbrains.kotlin.asJava.PsiClassRenderer.renderClass
|
||||
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
|
||||
import org.jetbrains.kotlin.idea.perf.UltraLightChecker.checkByJavaFile
|
||||
import org.jetbrains.kotlin.idea.perf.UltraLightChecker.checkDescriptorsLeak
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
|
||||
fun doTest(testDataPath: String) {
|
||||
open fun doTest(testDataPath: String) {
|
||||
val sourceText = File(testDataPath).readText()
|
||||
val file = myFixture.addFileToProject(testDataPath, sourceText) as KtFile
|
||||
|
||||
UltraLightChecker.checkForReleaseCoroutine(sourceText, module)
|
||||
|
||||
val expectedTextFile = File(testDataPath.replaceFirst("\\.kt\$".toRegex(), ".java"))
|
||||
if (expectedTextFile.exists()) {
|
||||
val renderedResult =
|
||||
UltraLightChecker.allClasses(file).mapNotNull { ktClass ->
|
||||
LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass)?.let { it to ktClass }
|
||||
}.joinToString("\n\n") { (ultraLightClass, ktClass) ->
|
||||
with(UltraLightChecker) {
|
||||
val extendedTypeRendererOld = PsiClassRenderer.extendedTypeRenderer
|
||||
try {
|
||||
PsiClassRenderer.extendedTypeRenderer = file.name == "typeAnnotations.kt"
|
||||
ultraLightClass.renderClass()
|
||||
} finally {
|
||||
PsiClassRenderer.extendedTypeRenderer = extendedTypeRendererOld
|
||||
}.also {
|
||||
checkDescriptorsLeak(ultraLightClass)
|
||||
}
|
||||
}
|
||||
val checkByJavaFile = InTextDirectivesUtils.isDirectiveDefined(sourceText, "CHECK_BY_JAVA_FILE")
|
||||
|
||||
val ktClassOrObjects = UltraLightChecker.allClasses(file)
|
||||
|
||||
if (checkByJavaFile) {
|
||||
val classFabric = LightClassGenerationSupport.getInstance(project)
|
||||
val classList = ktClassOrObjects.mapNotNull { classFabric.createUltraLightClass(it) }
|
||||
checkByJavaFile(testDataPath, classList)
|
||||
classList.forEach { checkDescriptorsLeak(it) }
|
||||
} else {
|
||||
for (ktClass in ktClassOrObjects) {
|
||||
val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass)
|
||||
if (ultraLightClass != null) {
|
||||
checkDescriptorsLeak(ultraLightClass)
|
||||
}
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(expectedTextFile, renderedResult)
|
||||
return
|
||||
}
|
||||
|
||||
for (ktClass in UltraLightChecker.allClasses(file)) {
|
||||
val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass)
|
||||
if (ultraLightClass != null) {
|
||||
checkDescriptorsLeak(ultraLightClass)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -18,7 +18,7 @@ import java.io.File
|
||||
abstract class AbstractUltraLightFacadeClassTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
|
||||
fun doTest(testDataPath: String) {
|
||||
open fun doTest(testDataPath: String) {
|
||||
val sourceText = File(testDataPath).readText()
|
||||
myFixture.addFileToProject(testDataPath, sourceText) as KtFile
|
||||
|
||||
@@ -32,6 +32,10 @@ abstract class AbstractUltraLightFacadeClassTest : KotlinLightCodeInsightFixture
|
||||
val scope = GlobalSearchScope.allScope(project)
|
||||
val facades = KotlinAsJavaSupport.getInstance(project).getFacadeNames(FqName.ROOT, scope)
|
||||
|
||||
checkLightFacades(testDataPath, facades, scope)
|
||||
}
|
||||
|
||||
protected open fun checkLightFacades(testDataPath: String, facades: Collection<String>, scope: GlobalSearchScope) {
|
||||
for (facadeName in facades) {
|
||||
val ultraLightClass = UltraLightChecker.checkFacadeEquivalence(FqName(facadeName), scope, project)
|
||||
if (ultraLightClass != null) {
|
||||
|
||||
@@ -49,6 +49,6 @@ abstract class AbstractFindUsagesMultiModuleTest : AbstractMultiModuleTest() {
|
||||
UsefulTestCase.assertInstanceOf(caretElement!!, caretElementClass)
|
||||
|
||||
val options = parser?.parse(mainFileText, project)
|
||||
findUsagesAndCheckResults(mainFileText, prefix, rootPath, caretElement, options, project, alwaysAppendFileName = true)
|
||||
findUsagesAndCheckResults(mainFileText, prefix, rootPath, caretElement, options, project, alwaysAppendFileName = true, isFirPlugin = isFirPlugin)
|
||||
}
|
||||
}
|
||||
@@ -194,14 +194,41 @@ abstract class AbstractFindUsagesTest : KotlinLightCodeInsightFixtureTestCase()
|
||||
val prefixForCheck = prefix + prefixForResults
|
||||
if (isLibraryElement) {
|
||||
val originalElement = caretElement.originalElement
|
||||
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, originalElement, options, project)
|
||||
findUsagesAndCheckResults(
|
||||
mainFileText,
|
||||
prefixForCheck,
|
||||
rootPath,
|
||||
originalElement,
|
||||
options,
|
||||
project,
|
||||
alwaysAppendFileName = false,
|
||||
isFirPlugin = isFirPlugin
|
||||
)
|
||||
|
||||
val navigationElement = caretElement.navigationElement
|
||||
if (navigationElement !== originalElement) {
|
||||
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, navigationElement, options, project)
|
||||
findUsagesAndCheckResults(
|
||||
mainFileText,
|
||||
prefixForCheck,
|
||||
rootPath,
|
||||
navigationElement,
|
||||
options,
|
||||
project,
|
||||
alwaysAppendFileName = false,
|
||||
isFirPlugin = isFirPlugin
|
||||
)
|
||||
}
|
||||
} else {
|
||||
findUsagesAndCheckResults(mainFileText, prefixForCheck, rootPath, caretElement, options, project)
|
||||
findUsagesAndCheckResults(
|
||||
mainFileText,
|
||||
prefixForCheck,
|
||||
rootPath,
|
||||
caretElement,
|
||||
options,
|
||||
project,
|
||||
alwaysAppendFileName = false,
|
||||
isFirPlugin = isFirPlugin
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
fixtureClasses.forEach { TestFixtureExtension.unloadFixture(it) }
|
||||
@@ -259,7 +286,8 @@ internal fun <T : PsiElement> findUsagesAndCheckResults(
|
||||
caretElement: T,
|
||||
options: FindUsagesOptions?,
|
||||
project: Project,
|
||||
alwaysAppendFileName: Boolean = false
|
||||
alwaysAppendFileName: Boolean = false,
|
||||
isFirPlugin: Boolean = false
|
||||
) {
|
||||
val highlightingMode = InTextDirectivesUtils.isDirectiveDefined(mainFileText, "// HIGHLIGHTING")
|
||||
|
||||
@@ -277,7 +305,7 @@ internal fun <T : PsiElement> findUsagesAndCheckResults(
|
||||
val searchSuperDeclaration =
|
||||
InTextDirectivesUtils.findLinesWithPrefixesRemoved(mainFileText, "$CHECK_SUPER_METHODS_YES_NO_DIALOG:").firstOrNull() != "no"
|
||||
|
||||
findUsages(caretElement, options, highlightingMode, project, searchSuperDeclaration)
|
||||
findUsages(caretElement, options, highlightingMode, project, searchSuperDeclaration, isFirPlugin)
|
||||
} finally {
|
||||
ExpressionsOfTypeProcessor.testLog = null
|
||||
if (logList.size > 0) {
|
||||
@@ -332,7 +360,16 @@ internal fun <T : PsiElement> findUsagesAndCheckResults(
|
||||
try {
|
||||
ExpressionsOfTypeProcessor.mode = ExpressionsOfTypeProcessor.Mode.ALWAYS_PLAIN
|
||||
|
||||
findUsagesAndCheckResults(mainFileText, prefix, rootPath, caretElement, options, project)
|
||||
findUsagesAndCheckResults(
|
||||
mainFileText,
|
||||
prefix,
|
||||
rootPath,
|
||||
caretElement,
|
||||
options,
|
||||
project,
|
||||
alwaysAppendFileName = false,
|
||||
isFirPlugin = isFirPlugin
|
||||
)
|
||||
} finally {
|
||||
ExpressionsOfTypeProcessor.mode = ExpressionsOfTypeProcessor.Mode.ALWAYS_SMART
|
||||
}
|
||||
@@ -344,7 +381,8 @@ internal fun findUsages(
|
||||
options: FindUsagesOptions?,
|
||||
highlightingMode: Boolean,
|
||||
project: Project,
|
||||
searchSuperDeclaration: Boolean = true
|
||||
searchSuperDeclaration: Boolean = true,
|
||||
isFirPlugin: Boolean = false
|
||||
): Collection<UsageInfo> {
|
||||
try {
|
||||
val handler: FindUsagesHandler = if (targetElement is PsiMember)
|
||||
@@ -367,9 +405,23 @@ internal fun findUsages(
|
||||
val processor = CommonProcessors.CollectProcessor<UsageInfo>()
|
||||
for (psiElement in handler.primaryElements + handler.secondaryElements) {
|
||||
if (highlightingMode) {
|
||||
project.runReadActionInSmartMode {
|
||||
for (reference in handler.findReferencesToHighlight(psiElement, options.searchScope)) {
|
||||
processor.process(UsageInfo(reference))
|
||||
if (isFirPlugin) {
|
||||
ProgressManager.getInstance().run(
|
||||
object : Task.Modal(project, "", false) {
|
||||
override fun run(indicator: ProgressIndicator) {
|
||||
project.runReadActionInSmartMode {
|
||||
for (reference in handler.findReferencesToHighlight(psiElement, options.searchScope)) {
|
||||
processor.process(UsageInfo(reference))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
project.runReadActionInSmartMode {
|
||||
for (reference in handler.findReferencesToHighlight(psiElement, options.searchScope)) {
|
||||
processor.process(UsageInfo(reference))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -128,8 +128,7 @@ abstract class AbstractIdeCompiledLightClassTest : KotlinDaemonAnalyzerTestCase(
|
||||
}
|
||||
|
||||
private fun testLightClass(expected: File, testData: File, normalize: (String) -> String, findLightClass: (String) -> PsiClass?) {
|
||||
LightClassTestCommon.testLightClass(
|
||||
expected,
|
||||
val actual = LightClassTestCommon.getActualLightClassText(
|
||||
testData,
|
||||
findLightClass = findLightClass,
|
||||
normalizeText = { text ->
|
||||
@@ -144,9 +143,10 @@ private fun testLightClass(expected: File, testData: File, normalize: (String) -
|
||||
.run(normalize)
|
||||
}
|
||||
)
|
||||
KotlinTestUtils.assertEqualsToFile(expected, actual)
|
||||
}
|
||||
|
||||
private fun findClass(fqName: String, ktFile: KtFile?, project: Project): PsiClass? {
|
||||
fun findClass(fqName: String, ktFile: KtFile?, project: Project): PsiClass? {
|
||||
ktFile?.script?.let {
|
||||
return it.toLightClass()
|
||||
}
|
||||
|
||||
@@ -20,16 +20,20 @@ import com.intellij.util.ref.DebugReflectionUtil
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.PsiClassRenderer
|
||||
import org.jetbrains.kotlin.asJava.PsiClassRenderer.renderClass
|
||||
import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
import kotlin.test.assertFails
|
||||
|
||||
fun UsefulTestCase.forceUsingOldLightClassesForTest() {
|
||||
@@ -76,6 +80,29 @@ object UltraLightChecker {
|
||||
return ultraLightClass
|
||||
}
|
||||
|
||||
|
||||
fun checkByJavaFile(testDataPath: String, lightClasses: List<KtLightClass>) {
|
||||
val expectedTextFile = getJavaFileForTest(testDataPath)
|
||||
val renderedResult = renderLightClasses(testDataPath, lightClasses)
|
||||
KotlinTestUtils.assertEqualsToFile(expectedTextFile, renderedResult)
|
||||
}
|
||||
|
||||
fun getJavaFileForTest(testDataPath: String): File {
|
||||
val expectedTextFile = KotlinTestUtils.replaceExtension(File(testDataPath), "java")
|
||||
KotlinLightCodeInsightFixtureTestCaseBase.assertTrue(expectedTextFile.exists())
|
||||
return expectedTextFile
|
||||
}
|
||||
|
||||
fun renderLightClasses(testDataPath: String, lightClasses: List<KtLightClass>): String {
|
||||
val extendedTypeRendererOld = PsiClassRenderer.extendedTypeRenderer
|
||||
return try {
|
||||
PsiClassRenderer.extendedTypeRenderer = testDataPath.endsWith("typeAnnotations.kt")
|
||||
lightClasses.joinToString("\n\n") { it.renderClass() }
|
||||
} finally {
|
||||
PsiClassRenderer.extendedTypeRenderer = extendedTypeRendererOld
|
||||
}
|
||||
}
|
||||
|
||||
fun checkClassEquivalence(ktClass: KtClassOrObject): KtUltraLightClass? {
|
||||
val gold = KtLightClassForSourceDeclaration.createNoCache(ktClass, forceUsingOldLightClasses = true)
|
||||
val ultraLightClass = LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass) ?: return null
|
||||
|
||||
Reference in New Issue
Block a user