blob: 72df82844d71b41a7824bf518d0dd118e920ba9f [file] [log] [blame]
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.low.level.api.fir
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
abstract class AbstractGetOrBuildFirTest : AbstractLowLevelApiSingleFileTest() {
override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder)
with(builder) {
useDirectives(Directives)
}
}
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
val selectedElement = getElementOfType(ktFile, moduleStructure, testServices) as KtElement
val actual = resolveWithClearCaches(ktFile) { state ->
val fir = selectedElement.getOrBuildFir(state)
"""|KT element: ${selectedElement::class.simpleName}
|FIR element: ${fir?.let { it::class.simpleName }}
|FIR source kind: ${fir?.source?.kind?.let { it::class.simpleName }}
|
|FIR element rendered:
|${render(fir)}""".trimMargin()
}
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
}
private fun getElementOfType(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices): PsiElement {
val selectedElement = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
val expectedType = moduleStructure.allDirectives[Directives.LOOK_UP_FOR_ELEMENT_OF_TYPE].firstOrNull() ?: return selectedElement
@Suppress("UNCHECKED_CAST") val expectedClass = Class.forName(expectedType) as Class<PsiElement>
if (expectedClass.isInstance(selectedElement)) return selectedElement
return listOfNotNull(
PsiTreeUtil.getChildOfType(selectedElement, expectedClass),
).single { it.textRange == selectedElement.textRange }
}
private fun render(firElement: FirElement?): String = when (firElement) {
null -> "null"
is FirImport -> "import ${firElement.importedFqName}"
else -> firElement.render(renderingMode)
}
private val renderingMode = FirRenderer.RenderMode.Normal.copy(
renderPackageDirective = true,
)
private object Directives : SimpleDirectivesContainer() {
val LOOK_UP_FOR_ELEMENT_OF_TYPE by stringDirective("LOOK_UP_FOR_ELEMENT_OF_TYPE")
}
}