FIR IDE: Implement RawFirBuilder::buildPropertyWithBody, add tests

This commit is contained in:
Roman Golyshev
2020-09-07 15:14:38 +03:00
parent 5f57311015
commit 58965d1e71
15 changed files with 121 additions and 22 deletions
@@ -47,7 +47,6 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import java.util.*
class RawFirBuilder(
session: FirSession, val baseScopeProvider: FirScopeProvider, val stubMode: Boolean
@@ -63,7 +62,19 @@ class RawFirBuilder(
fun buildFunctionWithBody(function: KtNamedFunction): FirFunction<*> {
assert(!stubMode) { "Building FIR function with body isn't supported in stub mode" }
val parentsUpToFile = function.parents
setupContextForPosition(function)
return function.accept(Visitor(), Unit) as FirFunction<*>
}
fun buildPropertyWithBody(property: KtProperty): FirProperty {
require(!property.isLocal) { "Should not be used to build local properties (variables)" }
assert(!stubMode) { "Building FIR function with body isn't supported in stub mode" }
setupContextForPosition(property)
return property.accept(Visitor(), Unit) as FirProperty
}
private fun setupContextForPosition(position: KtElement) {
val parentsUpToFile = position.parents
for (parent in parentsUpToFile.toList().asReversed()) {
when (parent) {
is KtFile -> {
@@ -75,7 +86,6 @@ class RawFirBuilder(
}
}
}
return function.accept(Visitor(), Unit) as FirFunction<*>
}
override fun PsiElement.toFirSourceElement(kind: FirFakeSourceElementKind?): FirPsiSourceElement<*> {
@@ -0,0 +1,16 @@
// PROPERTY: foo
package test.classes
class Outer {
inner class Inner {
fun bar(): Int
val foo: Int
get() {
val outer = Outer()
val inner = outer.Inner()
return inner.bar()
}
}
}
@@ -0,0 +1,6 @@
public? final? val test/classes/Outer.Inner.foo: Int
public? get(): Int {
lval <local>/outer: <implicit> = Outer#()
lval <local>/inner: <implicit> = outer#.Inner#()
^ inner#.bar#()
}
@@ -0,0 +1,7 @@
// PROPERTY: foo
package test
val bar: Int = 10
val foo: Int = 0
@@ -0,0 +1,2 @@
public? final? val test/foo: Int = IntegerLiteral(0)
public? get(): Int
@@ -0,0 +1,7 @@
// PROPERTY: foo
package test
val bar: Int = 10
var foo: Int = 0
@@ -0,0 +1,3 @@
public? final? var test/foo: Int = IntegerLiteral(0)
public? get(): Int
public? set(value: Int): R|kotlin/Unit|
@@ -5,36 +5,69 @@
package org.jetbrains.kotlin.fir.builder
import junit.framework.TestCase
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractPartialRawFirBuilderTestCase : AbstractRawFirBuilderTestCase() {
override fun doRawFirTest(filePath: String) {
val nameToFind = File(filePath).useLines {
it.first().run {
assert(startsWith(Companion.prefix))
drop(Companion.prefix.length)
}
val fileText = File(filePath).readText()
val functionName = InTextDirectivesUtils.findStringWithPrefixes(fileText, FUNCTION_DIRECTIVE)
val propertyName = InTextDirectivesUtils.findStringWithPrefixes(fileText, PROPERTY_DIRECTIVE)
when {
functionName != null -> testFunctionPartialBuilding(filePath, functionName)
propertyName != null -> testPropertyPartialBuilding(filePath, propertyName)
else -> fail("No '$FUNCTION_DIRECTIVE' or '$PROPERTY_DIRECTIVE' directives found!")
}
}
private fun testFunctionPartialBuilding(filePath: String, nameToFind: String) {
testPartialBuilding(
filePath,
{ file -> file.findDescendantOfType<KtNamedFunction> { it.name == nameToFind }!! },
RawFirBuilder::buildFunctionWithBody
)
}
private fun testPropertyPartialBuilding(filePath: String, nameToFind: String) {
testPartialBuilding(
filePath,
{ file -> file.findDescendantOfType<KtProperty> { it.name == nameToFind }!! },
RawFirBuilder::buildPropertyWithBody
)
}
private fun <T : KtElement> testPartialBuilding(
filePath: String,
findPsiElement: (KtFile) -> T,
buildFirElement: (RawFirBuilder, T) -> FirElement
) {
val file = createKtFile(filePath)
val functionToBuild = file.findDescendantOfType<KtNamedFunction> { it.name == nameToFind }!!
val elementToBuild = findPsiElement(file)
val session = FirSessionFactory.createEmptySession()
val firFunction = RawFirBuilder(session, StubFirScopeProvider, false)
.buildFunctionWithBody(functionToBuild)
val firElement = buildFirElement(RawFirBuilder(session, StubFirScopeProvider, false), elementToBuild)
val firDump = firFunction.render(FirRenderer.RenderMode.WithFqNames)
val firDump = firElement.render(FirRenderer.RenderMode.WithFqNames)
val expectedPath = filePath.replace(".kt", ".txt")
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firDump)
}
companion object {
private const val prefix = "// FUNCTION: "
private const val FUNCTION_DIRECTIVE = "// FUNCTION: "
private const val PROPERTY_DIRECTIVE = "// PROPERTY: "
}
}
@@ -28,18 +28,33 @@ public class PartialRawFirBuilderTestCaseGenerated extends AbstractPartialRawFir
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("local.kt")
public void testLocal() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/local.kt");
@TestMetadata("localFunction.kt")
public void testLocalFunction() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/localFunction.kt");
}
@TestMetadata("member.kt")
public void testMember() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/member.kt");
@TestMetadata("memberFunction.kt")
public void testMemberFunction() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/memberFunction.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simple.kt");
@TestMetadata("memberProperty.kt")
public void testMemberProperty() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/memberProperty.kt");
}
@TestMetadata("simpleFunction.kt")
public void testSimpleFunction() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simpleFunction.kt");
}
@TestMetadata("simpleVal.kt")
public void testSimpleVal() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simpleVal.kt");
}
@TestMetadata("simpleVar.kt")
public void testSimpleVar() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simpleVar.kt");
}
}