[FIR IDE] RawFirBuilder for lazy bodies
This commit is contained in:
+5
@@ -116,6 +116,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/genericProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initBlockWithDeclarations.kt")
|
||||
public void testInitBlockWithDeclarations() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/initBlockWithDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/nestedClass.kt");
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.fir.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.containingClassAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.isInner
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class RawFirFragmentForLazyBodiesBuilder private constructor(
|
||||
session: FirSession,
|
||||
baseScopeProvider: FirScopeProvider,
|
||||
private val declaration: KtDeclaration,
|
||||
) : RawFirBuilder(session, baseScopeProvider, RawFirBuilderMode.NORMAL) {
|
||||
|
||||
companion object {
|
||||
fun build(
|
||||
session: FirSession,
|
||||
baseScopeProvider: FirScopeProvider,
|
||||
designation: List<FirDeclaration>,
|
||||
declaration: KtDeclaration,
|
||||
): FirDeclaration {
|
||||
require(declaration is KtNamedFunction || declaration is KtProperty) { "Not implemented for ${declaration::class.qualifiedName}" }
|
||||
val builder = RawFirFragmentForLazyBodiesBuilder(session, baseScopeProvider, declaration)
|
||||
builder.context.packageFqName = declaration.containingKtFile.packageFqName
|
||||
return builder.moveNext(designation.iterator())
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveNext(iterator: Iterator<FirDeclaration>): FirDeclaration {
|
||||
if (!iterator.hasNext()) {
|
||||
return if (declaration is KtProperty) {
|
||||
with(Visitor()) {
|
||||
declaration.toFirProperty(null)
|
||||
}
|
||||
} else {
|
||||
declaration.accept(Visitor(), Unit) as FirDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
val parent = iterator.next()
|
||||
if (parent !is FirRegularClass) return moveNext(iterator)
|
||||
|
||||
val classOrObject = parent.psi
|
||||
check(classOrObject is KtClassOrObject)
|
||||
|
||||
withChildClassName(classOrObject.nameAsSafeName, false) {
|
||||
withCapturedTypeParameters {
|
||||
if (!parent.isInner) context.capturedTypeParameters = context.capturedTypeParameters.clear()
|
||||
addCapturedTypeParameters(parent.typeParameters.take(classOrObject.typeParameters.size))
|
||||
registerSelfType(classOrObject.toDelegatedSelfType(parent))
|
||||
return moveNext(iterator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement?.toDelegatedSelfType(firClass: FirRegularClass): FirResolvedTypeRef =
|
||||
toDelegatedSelfType(firClass.typeParameters, firClass.symbol)
|
||||
}
|
||||
|
||||
+37
-56
@@ -49,12 +49,25 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
class RawFirBuilder(
|
||||
session: FirSession, val baseScopeProvider: FirScopeProvider, val mode: RawFirBuilderMode = RawFirBuilderMode.NORMAL
|
||||
open class RawFirBuilder(
|
||||
session: FirSession, val baseScopeProvider: FirScopeProvider, builderMode: RawFirBuilderMode = RawFirBuilderMode.NORMAL
|
||||
) : BaseFirBuilder<PsiElement>(session) {
|
||||
|
||||
private val stubMode get() = mode == RawFirBuilderMode.STUBS
|
||||
|
||||
var mode: RawFirBuilderMode = builderMode
|
||||
private set
|
||||
|
||||
private inline fun <T> disabledLazyMode(body: () -> T): T {
|
||||
if (mode != RawFirBuilderMode.LAZY_BODIES) return body()
|
||||
return try {
|
||||
mode = RawFirBuilderMode.NORMAL
|
||||
body()
|
||||
} finally {
|
||||
mode = RawFirBuilderMode.LAZY_BODIES
|
||||
}
|
||||
}
|
||||
|
||||
fun buildFirFile(file: KtFile): FirFile {
|
||||
return file.accept(Visitor(), Unit) as FirFile
|
||||
}
|
||||
@@ -63,49 +76,6 @@ class RawFirBuilder(
|
||||
return reference.accept(Visitor(), Unit) as FirTypeRef
|
||||
}
|
||||
|
||||
fun buildFunctionWithBody(function: KtNamedFunction, original: FirFunction<*>?): FirFunction<*> {
|
||||
return buildDeclaration(function, original) as FirFunction<*>
|
||||
}
|
||||
|
||||
fun buildSecondaryConstructor(secondaryConstructor: KtSecondaryConstructor, original: FirConstructor?): FirConstructor {
|
||||
return buildDeclaration(secondaryConstructor, original) as FirConstructor
|
||||
}
|
||||
|
||||
fun buildPropertyWithBody(property: KtProperty, original: FirProperty?): FirProperty {
|
||||
require(!property.isLocal) { "Should not be used to build local properties (variables)" }
|
||||
return buildDeclaration(property, original) as FirProperty
|
||||
}
|
||||
|
||||
private fun buildDeclaration(declaration: KtDeclaration, original: FirDeclaration?): FirDeclaration {
|
||||
assert(mode == RawFirBuilderMode.NORMAL) { "Building FIR declarations isn't supported in stub or lazy mode mode" }
|
||||
setupContextForPosition(declaration,)
|
||||
val firDeclaration = declaration.accept(Visitor(), Unit) as FirDeclaration
|
||||
original?.let { firDeclaration.copyContainingClassAttrFrom(it) }
|
||||
return firDeclaration
|
||||
}
|
||||
|
||||
// TODO this is a (temporary) hack, instead we should properly initialize [context]
|
||||
private fun FirDeclaration.copyContainingClassAttrFrom(from: FirDeclaration) {
|
||||
(this as? FirCallableMemberDeclaration<*>)?.let {
|
||||
it.containingClassAttr = (from as? FirCallableMemberDeclaration<*>)?.containingClass()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupContextForPosition(position: KtElement) {
|
||||
val parentsUpToFile = position.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun PsiElement.toFirSourceElement(kind: FirFakeSourceElementKind?): FirPsiSourceElement<*> {
|
||||
val actualKind = kind ?: this@RawFirBuilder.context.forcedElementSourceKind ?: FirRealSourceElementKind
|
||||
return this.toFirPsiSourceElement(actualKind)
|
||||
@@ -178,7 +148,7 @@ class RawFirBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
private inner class Visitor : KtVisitor<FirElement, Unit>() {
|
||||
protected inner class Visitor : KtVisitor<FirElement, Unit>() {
|
||||
private inline fun <reified R : FirElement> KtElement?.convertSafe(): R? =
|
||||
this?.accept(this@Visitor, Unit) as? R
|
||||
|
||||
@@ -237,12 +207,14 @@ class RawFirBuilder(
|
||||
): FirDeclaration {
|
||||
return when (this) {
|
||||
is KtSecondaryConstructor -> {
|
||||
toFirConstructor(
|
||||
delegatedSuperType,
|
||||
delegatedSelfType,
|
||||
owner,
|
||||
ownerTypeParameters
|
||||
)
|
||||
disabledLazyMode {
|
||||
toFirConstructor(
|
||||
delegatedSuperType,
|
||||
delegatedSelfType,
|
||||
owner,
|
||||
ownerTypeParameters
|
||||
)
|
||||
}
|
||||
}
|
||||
is KtEnumEntry -> {
|
||||
val primaryConstructor = owner.primaryConstructor
|
||||
@@ -250,7 +222,9 @@ class RawFirBuilder(
|
||||
primaryConstructor?.valueParameters?.isEmpty() ?: owner.secondaryConstructors.let { constructors ->
|
||||
constructors.isEmpty() || constructors.any { it.valueParameters.isEmpty() }
|
||||
}
|
||||
toFirEnumEntry(delegatedSelfType, ownerClassHasDefaultConstructor)
|
||||
disabledLazyMode {
|
||||
toFirEnumEntry(delegatedSelfType, ownerClassHasDefaultConstructor)
|
||||
}
|
||||
}
|
||||
is KtProperty -> {
|
||||
toFirProperty(ownerClassBuilder)
|
||||
@@ -548,7 +522,7 @@ class RawFirBuilder(
|
||||
container.argumentList = argumentList
|
||||
}
|
||||
|
||||
private fun KtClassOrObject.extractSuperTypeListEntriesTo(
|
||||
fun KtClassOrObject.extractSuperTypeListEntriesTo(
|
||||
container: FirClassBuilder,
|
||||
delegatedSelfTypeRef: FirTypeRef?,
|
||||
delegatedEnumSuperTypeRef: FirTypeRef?,
|
||||
@@ -790,6 +764,12 @@ class RawFirBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClassInitializer(initializer: KtClassInitializer, data: Unit?): FirElement {
|
||||
return disabledLazyMode {
|
||||
super.visitClassInitializer(initializer, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Unit): FirElement {
|
||||
return withChildClassName(
|
||||
classOrObject.nameAsSafeName,
|
||||
@@ -874,7 +854,8 @@ class RawFirBuilder(
|
||||
}
|
||||
|
||||
if (classOrObject.hasModifier(DATA_KEYWORD) && firPrimaryConstructor != null) {
|
||||
val zippedParameters = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() } zip declarations.filterIsInstance<FirProperty>()
|
||||
val zippedParameters =
|
||||
classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() } zip declarations.filterIsInstance<FirProperty>()
|
||||
DataClassMembersGenerator(
|
||||
baseSession,
|
||||
classOrObject,
|
||||
@@ -1215,7 +1196,7 @@ class RawFirBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtProperty.toFirProperty(ownerClassBuilder: FirClassBuilder?): FirProperty {
|
||||
fun KtProperty.toFirProperty(ownerClassBuilder: FirClassBuilder?): FirProperty {
|
||||
val propertyType = typeReference.toFirOrImplicitType()
|
||||
val propertyName = nameAsSafeName
|
||||
val isVar = isVar
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// FUNCTION: foo
|
||||
|
||||
package test.classes
|
||||
|
||||
class Outer<X> {
|
||||
fun foo() {
|
||||
val z = object { }
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public? final? fun test/classes/Outer.foo(): R|kotlin/Unit| {
|
||||
lval <local>/z: <implicit> = object : R|kotlin/Any| {
|
||||
private constructor(): R|<anonymous><X>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+9
-3
@@ -30,7 +30,9 @@ FILE: enums.kt
|
||||
super<R|Planet|>(Double(1.0), Double(2.0))
|
||||
}
|
||||
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| {
|
||||
println#(String(Hello!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +41,9 @@ FILE: enums.kt
|
||||
super<R|Planet|>(Double(3.0), Double(4.0))
|
||||
}
|
||||
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| {
|
||||
println#(String(Ola!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +52,9 @@ FILE: enums.kt
|
||||
super<R|Planet|>(Double(5.0), Double(6.0))
|
||||
}
|
||||
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| { LAZY_BLOCK }
|
||||
public? open? override fun sayHello(): R|kotlin/Unit| {
|
||||
println#(String(Privet!!!))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -26,7 +26,9 @@ FILE: enums2.kt
|
||||
super<R|SomeEnum|>(O1#)
|
||||
}
|
||||
|
||||
public? open? override fun check(y: Some): Boolean { LAZY_BLOCK }
|
||||
public? open? override fun check(y: Some): Boolean {
|
||||
^check Boolean(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +37,9 @@ FILE: enums2.kt
|
||||
super<R|SomeEnum|>(O2#)
|
||||
}
|
||||
|
||||
public? open? override fun check(y: Some): Boolean { LAZY_BLOCK }
|
||||
public? open? override fun check(y: Some): Boolean {
|
||||
^check ==(y#, O2#)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
|
||||
class X {
|
||||
init {
|
||||
class classInInit {
|
||||
fun funInClassInInit() {
|
||||
}
|
||||
}
|
||||
fun funInInit() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object {
|
||||
init {
|
||||
class classInInit {
|
||||
fun funInClassInInit() {
|
||||
}
|
||||
}
|
||||
fun funInInit() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
FILE: initBlockWithDeclarations.kt
|
||||
public? final? class X : R|kotlin/Any| {
|
||||
public? constructor(): R|X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
init {
|
||||
local final? class classInInit : R|kotlin/Any| {
|
||||
public? constructor(): R|X.classInInit| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun funInClassInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
local final? fun funInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public? final? object <no name provided> : R|kotlin/Any| {
|
||||
private constructor(): R|<no name provided>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
init {
|
||||
local final? class classInInit : R|kotlin/Any| {
|
||||
public? constructor(): R|<no name provided>.classInInit| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun funInClassInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
local final? fun funInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
FILE: initBlockWithDeclarations.kt
|
||||
public? final? class X : R|kotlin/Any| {
|
||||
public? constructor(): R|X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
init {
|
||||
local final? class classInInit : R|kotlin/Any| {
|
||||
public? constructor(): R|X.classInInit| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun funInClassInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
local final? fun funInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public? final? object <no name provided> : R|kotlin/Any| {
|
||||
private constructor(): R|<no name provided>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
init {
|
||||
local final? class classInInit : R|kotlin/Any| {
|
||||
public? constructor(): R|<no name provided>.classInInit| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public? final? fun funInClassInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
local final? fun funInInit(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+4
-1
@@ -3,7 +3,10 @@ FILE: noPrimaryConstructor.kt
|
||||
public? final? val x: String
|
||||
public? get(): String
|
||||
|
||||
public? constructor(x: String): R|NoPrimary| { LAZY_BLOCK }
|
||||
public? constructor(x: String): R|NoPrimary| {
|
||||
super<R|kotlin/Any|>()
|
||||
this#.x# = x#
|
||||
}
|
||||
|
||||
public? constructor(): R|NoPrimary| {
|
||||
this<R|NoPrimary|>(String())
|
||||
|
||||
+5
@@ -44,6 +44,11 @@ public class PartialRawFirBuilderTestCaseGenerated extends AbstractPartialRawFir
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/memberProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("paramemtersCatching.kt")
|
||||
public void testParamemtersCatching() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/paramemtersCatching.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFunction.kt")
|
||||
public void testSimpleFunction() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/simpleFunction.kt");
|
||||
|
||||
+5
@@ -116,6 +116,11 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/genericProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initBlockWithDeclarations.kt")
|
||||
public void testInitBlockWithDeclarations() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/initBlockWithDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/nestedClass.kt");
|
||||
|
||||
+5
@@ -116,6 +116,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/genericProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initBlockWithDeclarations.kt")
|
||||
public void testInitBlockWithDeclarations() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/initBlockWithDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/nestedClass.kt");
|
||||
|
||||
+53
-14
@@ -5,14 +5,15 @@
|
||||
|
||||
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.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
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.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -34,29 +35,67 @@ abstract class AbstractPartialRawFirBuilderTestCase : AbstractRawFirBuilderTestC
|
||||
|
||||
private fun testFunctionPartialBuilding(filePath: String, nameToFind: String) {
|
||||
testPartialBuilding(
|
||||
filePath,
|
||||
{ file -> file.findDescendantOfType<KtNamedFunction> { it.name == nameToFind }!! }
|
||||
) { rawFirBuilder, function -> rawFirBuilder.buildFunctionWithBody(function, original = null) }
|
||||
filePath
|
||||
) { file -> file.findDescendantOfType<KtNamedFunction> { it.name == nameToFind }!! }
|
||||
}
|
||||
|
||||
private fun testPropertyPartialBuilding(filePath: String, nameToFind: String) {
|
||||
testPartialBuilding(
|
||||
filePath,
|
||||
{ file -> file.findDescendantOfType<KtProperty> { it.name == nameToFind }!! }
|
||||
) { rawFirBuilder, property -> rawFirBuilder.buildPropertyWithBody(property, original = null) }
|
||||
filePath
|
||||
) { file -> file.findDescendantOfType<KtProperty> { it.name == nameToFind }!! }
|
||||
}
|
||||
|
||||
private class DesignationBuilder(private val elementToBuild: KtDeclaration) : FirVisitorVoid() {
|
||||
val designation = mutableListOf<FirDeclaration>()
|
||||
var originalDeclaration: FirDeclaration? = null
|
||||
var built = false
|
||||
|
||||
override fun visitElement(element: FirElement) {
|
||||
if (built) return
|
||||
when (element) {
|
||||
is FirSimpleFunction, is FirProperty -> {
|
||||
if (element.psi == elementToBuild) {
|
||||
originalDeclaration = element as FirDeclaration
|
||||
built = true
|
||||
} else {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
designation.add(element)
|
||||
element.acceptChildren(this)
|
||||
if (!built) {
|
||||
designation.removeLast()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : KtElement> testPartialBuilding(
|
||||
filePath: String,
|
||||
findPsiElement: (KtFile) -> T,
|
||||
buildFirElement: (RawFirBuilder, T) -> FirElement
|
||||
findPsiElement: (KtFile) -> T
|
||||
) {
|
||||
val file = createKtFile(filePath)
|
||||
val elementToBuild = findPsiElement(file)
|
||||
val elementToBuild = findPsiElement(file) as KtDeclaration
|
||||
|
||||
val session = FirSessionFactory.createEmptySession()
|
||||
val firBuilder = RawFirBuilder(session, StubFirScopeProvider)
|
||||
val original = firBuilder.buildFirFile(file)
|
||||
|
||||
val firElement = buildFirElement(RawFirBuilder(session, StubFirScopeProvider), elementToBuild)
|
||||
val designationBuilder = DesignationBuilder(elementToBuild)
|
||||
original.accept(designationBuilder)
|
||||
TestCase.assertTrue(designationBuilder.built)
|
||||
|
||||
val firElement = RawFirFragmentForLazyBodiesBuilder.build(
|
||||
session,
|
||||
StubFirScopeProvider,
|
||||
designationBuilder.designation,
|
||||
elementToBuild
|
||||
)
|
||||
|
||||
val firDump = firElement.render(FirRenderer.RenderMode.WithFqNames)
|
||||
val expectedPath = filePath.replace(".kt", ".txt")
|
||||
|
||||
+9
-7
@@ -92,9 +92,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
|
||||
inline fun <T> withCapturedTypeParameters(block: () -> T): T {
|
||||
val previous = context.capturedTypeParameters
|
||||
val result = block()
|
||||
context.capturedTypeParameters = previous
|
||||
return result
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
context.capturedTypeParameters = previous
|
||||
}
|
||||
}
|
||||
|
||||
fun addCapturedTypeParameters(typeParameters: List<FirTypeParameterRef>) {
|
||||
@@ -191,17 +193,17 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
}
|
||||
|
||||
fun T?.toDelegatedSelfType(firClass: FirRegularClassBuilder): FirResolvedTypeRef =
|
||||
toDelegatedSelfType(firClass, firClass.symbol)
|
||||
toDelegatedSelfType(firClass.typeParameters, firClass.symbol)
|
||||
|
||||
fun T?.toDelegatedSelfType(firObject: FirAnonymousObjectBuilder): FirResolvedTypeRef =
|
||||
toDelegatedSelfType(firObject, firObject.symbol)
|
||||
toDelegatedSelfType(firObject.typeParameters, firObject.symbol)
|
||||
|
||||
private fun T?.toDelegatedSelfType(firClass: FirClassBuilder, symbol: FirClassLikeSymbol<*>): FirResolvedTypeRef {
|
||||
protected fun T?.toDelegatedSelfType(typeParameters: List<FirTypeParameterRef>, symbol: FirClassLikeSymbol<*>): FirResolvedTypeRef {
|
||||
return buildResolvedTypeRef {
|
||||
source = this@toDelegatedSelfType?.toFirSourceElement(FirFakeSourceElementKind.ClassSelfTypeRef)
|
||||
type = ConeClassLikeTypeImpl(
|
||||
symbol.toLookupTag(),
|
||||
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
+6
@@ -123,6 +123,12 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizerTe
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/genericProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("initBlockWithDeclarations.kt")
|
||||
public void testInitBlockWithDeclarations() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/initBlockWithDeclarations.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
|
||||
+6
@@ -123,6 +123,12 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/genericProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("initBlockWithDeclarations.kt")
|
||||
public void testInitBlockWithDeclarations() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/initBlockWithDeclarations.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user