[FIR IDE] Move and rename RawFirFragmentForLazyBodiesBuilder into Fir Ide module
This commit is contained in:
committed by
TeamCityServer
parent
0569f810cf
commit
c5372be267
-147
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* 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.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
data class RawFirReplacement<T : KtElement>(val from: T, val to: T)
|
||||
|
||||
class RawFirFragmentForLazyBodiesBuilder<T : KtElement> private constructor(
|
||||
session: FirSession,
|
||||
baseScopeProvider: FirScopeProvider,
|
||||
private val declarationToBuild: KtDeclaration,
|
||||
private val replacement: RawFirReplacement<T>? = null
|
||||
) : RawFirBuilder(session, baseScopeProvider, RawFirBuilderMode.NORMAL) {
|
||||
|
||||
private var replacementApplied = false
|
||||
|
||||
companion object {
|
||||
fun elementIsApplicable(element: KtElement) = when (element) {
|
||||
is KtFile, is KtClassInitializer, is KtClassOrObject, is KtObjectLiteralExpression, is KtTypeAlias,
|
||||
is KtNamedFunction, is KtLambdaExpression, is KtAnonymousInitializer, is KtProperty, is KtTypeReference,
|
||||
is KtAnnotationEntry, is KtTypeParameter, is KtTypeProjection, is KtParameter, is KtBlockExpression,
|
||||
is KtSimpleNameExpression, is KtConstantExpression, is KtStringTemplateExpression, is KtReturnExpression,
|
||||
is KtTryExpression, is KtIfExpression, is KtWhenExpression, is KtDoWhileExpression, is KtWhileExpression,
|
||||
is KtForExpression, is KtBreakExpression, is KtContinueExpression, is KtBinaryExpression, is KtBinaryExpressionWithTypeRHS,
|
||||
is KtIsExpression, is KtUnaryExpression, is KtCallExpression, is KtArrayAccessExpression, is KtQualifiedExpression,
|
||||
is KtThisExpression, is KtSuperExpression, is KtParenthesizedExpression, is KtLabeledExpression, is KtAnnotatedExpression,
|
||||
is KtThrowExpression, is KtDestructuringDeclaration, is KtClassLiteralExpression, is KtCallableReferenceExpression,
|
||||
is KtCollectionLiteralExpression -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun <T : KtElement> buildWithReplacement(
|
||||
session: FirSession,
|
||||
baseScopeProvider: FirScopeProvider,
|
||||
designation: List<FirDeclaration>,
|
||||
declarationToBuild: KtDeclaration,
|
||||
replacement: RawFirReplacement<T>? = null
|
||||
): FirDeclaration {
|
||||
if (replacement != null) {
|
||||
require(elementIsApplicable(replacement.from)) {
|
||||
"Build with replacement is possible for applicable type but given ${replacement.from::class.simpleName}"
|
||||
}
|
||||
require(replacement.from::class == replacement.to::class) {
|
||||
"Build with replacement is possible for same type in replacements but given\n${replacement.from::class.simpleName} and ${replacement.to::class.simpleName}"
|
||||
}
|
||||
}
|
||||
|
||||
val builder = RawFirFragmentForLazyBodiesBuilder(session, baseScopeProvider, declarationToBuild, replacement)
|
||||
builder.context.packageFqName = declarationToBuild.containingKtFile.packageFqName
|
||||
|
||||
val result = builder.moveNext(designation.iterator(), containingClass = null)
|
||||
check(replacement == null || builder.replacementApplied) {
|
||||
"Replacement requested but was not applied for ${replacement!!.from::class.simpleName}"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun build(
|
||||
session: FirSession,
|
||||
baseScopeProvider: FirScopeProvider,
|
||||
designation: List<FirDeclaration>,
|
||||
rootNonLocalDeclaration: KtDeclaration
|
||||
): FirDeclaration {
|
||||
val builder = RawFirFragmentForLazyBodiesBuilder<KtElement>(session, baseScopeProvider, rootNonLocalDeclaration)
|
||||
builder.context.packageFqName = rootNonLocalDeclaration.containingKtFile.packageFqName
|
||||
return builder.moveNext(designation.iterator(), containingClass = null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtElement.replaced(): KtElement {
|
||||
if (replacement == null || replacement.from != this) return this
|
||||
replacementApplied = true
|
||||
return replacement.to
|
||||
}
|
||||
|
||||
private inner class VisitorWithReplacement : Visitor() {
|
||||
override fun convertElement(element: KtElement): FirElement? =
|
||||
super.convertElement(element.replaced())
|
||||
|
||||
override fun convertProperty(
|
||||
property: KtProperty,
|
||||
ownerRegularOrAnonymousObjectSymbol: FirClassSymbol<*>?,
|
||||
ownerRegularClassTypeParametersCount: Int?
|
||||
): FirProperty {
|
||||
val replacementProperty = property.replaced()
|
||||
check(replacementProperty is KtProperty)
|
||||
return super.convertProperty(
|
||||
property = replacementProperty,
|
||||
ownerRegularOrAnonymousObjectSymbol = ownerRegularOrAnonymousObjectSymbol,
|
||||
ownerRegularClassTypeParametersCount = ownerRegularClassTypeParametersCount
|
||||
)
|
||||
}
|
||||
|
||||
override fun convertValueParameter(valueParameter: KtParameter, defaultTypeRef: FirTypeRef?): FirValueParameter {
|
||||
val replacementParameter = valueParameter.replaced()
|
||||
check(replacementParameter is KtParameter)
|
||||
return super.convertValueParameter(
|
||||
valueParameter = replacementParameter,
|
||||
defaultTypeRef = defaultTypeRef
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveNext(iterator: Iterator<FirDeclaration>, containingClass: FirRegularClass?): FirDeclaration {
|
||||
if (!iterator.hasNext()) {
|
||||
val visitor = VisitorWithReplacement()
|
||||
return when (declarationToBuild) {
|
||||
is KtProperty -> {
|
||||
val ownerSymbol = containingClass?.symbol
|
||||
val ownerTypeArgumentsCount = containingClass?.typeParameters?.size
|
||||
visitor.convertProperty(declarationToBuild, ownerSymbol, ownerTypeArgumentsCount)
|
||||
}
|
||||
else -> visitor.convertElement(declarationToBuild)
|
||||
} as FirDeclaration
|
||||
}
|
||||
|
||||
val parent = iterator.next()
|
||||
if (parent !is FirRegularClass) return moveNext(iterator, containingClass = null)
|
||||
|
||||
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, parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement?.toDelegatedSelfType(firClass: FirRegularClass): FirResolvedTypeRef =
|
||||
toDelegatedSelfType(firClass.typeParameters, firClass.symbol)
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// 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) {}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
local final? fun <local>/bar(): R|kotlin/Unit| {
|
||||
baz#(i#, x#)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// FUNCTION: foo
|
||||
|
||||
package test.classes
|
||||
|
||||
class Outer {
|
||||
inner class Inner {
|
||||
fun bar()
|
||||
|
||||
fun foo() {
|
||||
val outer = Outer()
|
||||
val inner = outer.Inner()
|
||||
inner.bar()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
public? final? fun test/classes/Outer.Inner.foo(): R|kotlin/Unit| {
|
||||
lval <local>/outer: <implicit> = Outer#()
|
||||
lval <local>/inner: <implicit> = outer#.Inner#()
|
||||
inner#.bar#()
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
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#()
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
// FUNCTION: foo
|
||||
|
||||
package test.classes
|
||||
|
||||
class Outer<X> {
|
||||
fun foo() {
|
||||
val z = object { }
|
||||
}
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
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|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// FUNCTION: foo
|
||||
|
||||
package test
|
||||
|
||||
fun bar(): Int {
|
||||
return -1
|
||||
}
|
||||
|
||||
fun foo(): Int {
|
||||
return 0
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
public? final? fun test/foo(): Int {
|
||||
^foo IntegerLiteral(0)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// PROPERTY: foo
|
||||
|
||||
package test
|
||||
|
||||
val bar: Int = 10
|
||||
|
||||
val foo: Int = 0
|
||||
@@ -1,2 +0,0 @@
|
||||
public? final? val test/foo: Int = IntegerLiteral(0)
|
||||
public? get(): Int
|
||||
@@ -1,7 +0,0 @@
|
||||
// PROPERTY: foo
|
||||
|
||||
package test
|
||||
|
||||
val bar: Int = 10
|
||||
|
||||
var foo: Int = 0
|
||||
@@ -1,3 +0,0 @@
|
||||
public? final? var test/foo: Int = IntegerLiteral(0)
|
||||
public? get(): Int
|
||||
public? set(value: Int): R|kotlin/Unit|
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
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 {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("localFunction.kt")
|
||||
public void testLocalFunction() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/localFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("memberFunction.kt")
|
||||
public void testMemberFunction() throws Exception {
|
||||
runTest("compiler/fir/raw-fir/psi2fir/testData/partialRawBuilder/memberFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("memberProperty.kt")
|
||||
public void testMemberProperty() throws Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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 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.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
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractPartialRawFirBuilderTestCase : AbstractRawFirBuilderTestCase() {
|
||||
override fun doRawFirTest(filePath: String) {
|
||||
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 }!! }
|
||||
}
|
||||
|
||||
private fun testPropertyPartialBuilding(filePath: String, nameToFind: String) {
|
||||
testPartialBuilding(
|
||||
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
|
||||
) {
|
||||
val file = createKtFile(filePath)
|
||||
val elementToBuild = findPsiElement(file) as KtDeclaration
|
||||
|
||||
val session = FirSessionFactory.createEmptySession()
|
||||
val firBuilder = RawFirBuilder(session, StubFirScopeProvider)
|
||||
val original = firBuilder.buildFirFile(file)
|
||||
|
||||
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")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firDump)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FUNCTION_DIRECTIVE = "// FUNCTION: "
|
||||
private const val PROPERTY_DIRECTIVE = "// PROPERTY: "
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user