Partial raw FIR building
This commit is contained in:
committed by
Ilya Kirillov
parent
a1b621d987
commit
6129f4bcef
@@ -44,9 +44,7 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -66,6 +64,23 @@ class RawFirBuilder(
|
|||||||
return reference.accept(Visitor(), Unit) as FirTypeRef
|
return reference.accept(Visitor(), Unit) as FirTypeRef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildFunctionWithBody(function: KtNamedFunction): FirFunction<*> {
|
||||||
|
assert(!stubMode) { "Building FIR function with body isn't supported in stub mode" }
|
||||||
|
val parentsUpToFile = function.parents
|
||||||
|
for (parent in parentsUpToFile.toList().asReversed()) {
|
||||||
|
when (parent) {
|
||||||
|
is KtFile -> {
|
||||||
|
context.packageFqName = parent.packageFqName
|
||||||
|
}
|
||||||
|
is KtClassOrObject -> {
|
||||||
|
context.className = context.className.child(parent.nameAsSafeName)
|
||||||
|
context.localBits.add(parent.isLocal || parent.getStrictParentOfType<KtEnumEntry>() != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return function.accept(Visitor(), Unit) as FirFunction<*>
|
||||||
|
}
|
||||||
|
|
||||||
override fun PsiElement.toFirSourceElement(kind: FirFakeSourceElementKind?): FirPsiSourceElement<*> {
|
override fun PsiElement.toFirSourceElement(kind: FirFakeSourceElementKind?): FirPsiSourceElement<*> {
|
||||||
val actualKind = kind ?: this@RawFirBuilder.context.forcedElementSourceKind ?: FirRealSourceElementKind
|
val actualKind = kind ?: this@RawFirBuilder.context.forcedElementSourceKind ?: FirRealSourceElementKind
|
||||||
return this.toFirPsiSourceElement(actualKind)
|
return this.toFirPsiSourceElement(actualKind)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// FUNCTION: bar
|
||||||
|
|
||||||
|
package test.locals
|
||||||
|
|
||||||
|
class Owner {
|
||||||
|
fun foo(i: Int) {
|
||||||
|
var x = true
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
baz(i, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun baz(j: Int, y: Boolean) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
local final? fun <local>/bar(): R|kotlin/Unit| {
|
||||||
|
baz#(i#, x#)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// FUNCTION: foo
|
||||||
|
|
||||||
|
package test.classes
|
||||||
|
|
||||||
|
class Outer {
|
||||||
|
inner class Inner {
|
||||||
|
fun bar()
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val outer = Outer()
|
||||||
|
val inner = outer.Inner()
|
||||||
|
inner.bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
public? final? fun test/classes/Outer.Inner.foo(): R|kotlin/Unit| {
|
||||||
|
lval <local>/outer: <implicit> = Outer#()
|
||||||
|
lval <local>/inner: <implicit> = outer#.Inner#()
|
||||||
|
inner#.bar#()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// FUNCTION: foo
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun bar(): Int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
public? final? fun test/foo(): Int {
|
||||||
|
^foo IntegerLiteral(0)
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.fir.builder
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirRenderer
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.render
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||||
|
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 file = createKtFile(filePath)
|
||||||
|
val functionToBuild = file.findDescendantOfType<KtNamedFunction> { it.name == nameToFind }!!
|
||||||
|
val firFunction = RawFirBuilder(
|
||||||
|
object : FirSession(null) {}, StubFirScopeProvider, false
|
||||||
|
).buildFunctionWithBody(functionToBuild)
|
||||||
|
val firDump = firFunction.render(FirRenderer.RenderMode.WithFqNames)
|
||||||
|
val expectedPath = filePath.replace(".kt", ".txt")
|
||||||
|
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firDump)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val prefix = "// FUNCTION: "
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -60,7 +60,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun doRawFirTest(filePath: String) {
|
protected open fun doRawFirTest(filePath: String) {
|
||||||
val file = createKtFile(filePath)
|
val file = createKtFile(filePath)
|
||||||
val firFile = file.toFirFile(stubMode = false)
|
val firFile = file.toFirFile(stubMode = false)
|
||||||
val firFileDump = StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
val firFileDump = StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.fir.builder;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class PartialRawFirBuilderTestCaseGenerated extends AbstractPartialRawFirBuilderTestCase {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doRawFirTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInPartialRawBuilder() throws Exception {
|
||||||
|
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("member.kt")
|
||||||
|
public void testMember() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/member.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simple.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -119,7 +119,9 @@ fun CFGNode<*>.render(): String =
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private object CfgRenderMode : FirRenderer.RenderMode(renderLambdaBodies = false, renderCallArguments = false)
|
private object CfgRenderMode : FirRenderer.RenderMode(
|
||||||
|
renderLambdaBodies = false, renderCallArguments = false, renderCallableFqNames = false
|
||||||
|
)
|
||||||
|
|
||||||
private fun FirFunction<*>.name(): String = when (this) {
|
private fun FirFunction<*>.name(): String = when (this) {
|
||||||
is FirSimpleFunction -> name.asString()
|
is FirSimpleFunction -> name.asString()
|
||||||
|
|||||||
@@ -50,8 +50,14 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class RenderMode(val renderLambdaBodies: Boolean, val renderCallArguments: Boolean) {
|
abstract class RenderMode(
|
||||||
object Normal : RenderMode(renderLambdaBodies = true, renderCallArguments = true)
|
val renderLambdaBodies: Boolean,
|
||||||
|
val renderCallArguments: Boolean,
|
||||||
|
val renderCallableFqNames: Boolean
|
||||||
|
) {
|
||||||
|
object Normal : RenderMode(renderLambdaBodies = true, renderCallArguments = true, renderCallableFqNames = false)
|
||||||
|
|
||||||
|
object WithFqNames: RenderMode(renderLambdaBodies = true, renderCallArguments = true, renderCallableFqNames = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val printer = Printer(builder)
|
private val printer = Printer(builder)
|
||||||
@@ -150,8 +156,20 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
|
|||||||
print(".")
|
print(".")
|
||||||
}
|
}
|
||||||
when (callableDeclaration) {
|
when (callableDeclaration) {
|
||||||
is FirSimpleFunction -> print(callableDeclaration.name)
|
is FirSimpleFunction -> {
|
||||||
is FirVariable<*> -> print(callableDeclaration.name)
|
if (!mode.renderCallableFqNames) {
|
||||||
|
print(callableDeclaration.name)
|
||||||
|
} else {
|
||||||
|
print(callableDeclaration.symbol.callableId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is FirVariable<*> -> {
|
||||||
|
if (!mode.renderCallableFqNames) {
|
||||||
|
print(callableDeclaration.name)
|
||||||
|
} else {
|
||||||
|
print(callableDeclaration.symbol.callableId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callableDeclaration is FirFunction<*>) {
|
if (callableDeclaration is FirFunction<*>) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.defaultConstructor.AbstractDefaultArgumentsR
|
|||||||
import org.jetbrains.kotlin.codegen.flags.AbstractWriteFlagsTest
|
import org.jetbrains.kotlin.codegen.flags.AbstractWriteFlagsTest
|
||||||
import org.jetbrains.kotlin.codegen.ir.*
|
import org.jetbrains.kotlin.codegen.ir.*
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.builder.AbstractPartialRawFirBuilderTestCase
|
||||||
import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase
|
import org.jetbrains.kotlin.fir.builder.AbstractRawFirBuilderTestCase
|
||||||
import org.jetbrains.kotlin.fir.java.AbstractFirOldFrontendLightClassesTest
|
import org.jetbrains.kotlin.fir.java.AbstractFirOldFrontendLightClassesTest
|
||||||
import org.jetbrains.kotlin.fir.java.AbstractFirTypeEnhancementTest
|
import org.jetbrains.kotlin.fir.java.AbstractFirTypeEnhancementTest
|
||||||
@@ -544,6 +545,12 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testGroup("compiler/fir/raw-fir/psi2fir/tests", "compiler/fir/raw-fir/psi2fir/testData") {
|
||||||
|
testClass<AbstractPartialRawFirBuilderTestCase> {
|
||||||
|
model("partialRawBuilder", testMethod = "doRawFirTest")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
testGroup("compiler/fir/raw-fir/light-tree2fir/tests", "compiler/fir/raw-fir/psi2fir/testData") {
|
testGroup("compiler/fir/raw-fir/light-tree2fir/tests", "compiler/fir/raw-fir/psi2fir/testData") {
|
||||||
testClass<AbstractLightTree2FirConverterTestCase> {
|
testClass<AbstractLightTree2FirConverterTestCase> {
|
||||||
model("rawBuilder")
|
model("rawBuilder")
|
||||||
|
|||||||
Reference in New Issue
Block a user