[LL API] Correct used IR symbols in code fragments

As 'FirCodeFragments' are converted to IR independently of its context,
in some cases duplicate (and not quite correct) symbols for local
classes and functions are created.

Until properly fixed in fir2ir, here we replace such duplicates with
original symbols.
This commit is contained in:
Yan Zhulanow
2023-08-08 02:51:53 +09:00
committed by Space Team
parent ee7e6b0fce
commit 5a67b0d7dc
39 changed files with 611 additions and 9 deletions
@@ -41,23 +41,28 @@ import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.jvm.*
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.pipeline.applyIrGenerationExtensions
import org.jetbrains.kotlin.fir.pipeline.signatureComposerForJvmFir2Ir
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.toResolvedSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.PsiIrFileEntry
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.load.kotlin.toSourceElement
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -67,6 +72,7 @@ import org.jetbrains.kotlin.psi2ir.generators.fragments.EvaluatorFragmentInfo
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import java.util.Collections
internal class KtFirCompilerFacility(
override val analysisSession: KtFirAnalysisSession
@@ -147,6 +153,8 @@ internal class KtFirCompilerFacility(
initializedIrBuiltIns = null
)
patchCodeFragmentIr(fir2IrResult)
ProgressManager.checkCanceled()
val irGeneratorExtensions = IrGenerationExtension.getInstances(project)
@@ -200,6 +208,22 @@ internal class KtFirCompilerFacility(
}
}
private fun patchCodeFragmentIr(fir2IrResult: Fir2IrResult) {
fun isCodeFragmentFile(irFile: IrFile): Boolean {
val firFiles = (irFile.metadata as? FirMetadataSource.File)?.files ?: return false
return firFiles.any { it.psi is KtCodeFragment }
}
val (irCodeFragmentFiles, irOrdinaryFiles) = fir2IrResult.irModuleFragment.files.partition(::isCodeFragmentFile)
// Collect original declarations from the context files
val collectingVisitor = IrDeclarationMappingCollectingVisitor()
irOrdinaryFiles.forEach { it.acceptVoid(collectingVisitor) }
// Replace duplicate symbols with the original ones
val patchingVisitor = IrDeclarationPatchingVisitor(collectingVisitor.mappings)
irCodeFragmentFiles.forEach { it.acceptVoid(patchingVisitor) }
}
private fun getFullyResolvedFirFile(file: KtFile): FirFile {
val firFile = file.getOrBuildFirFile(firResolveSession)
LLFirWholeFileResolveTarget(firFile).resolve(FirResolvePhase.BODY_RESOLVE)
@@ -368,4 +392,96 @@ internal class KtFirCompilerFacility(
ideCodegenSettings = ideCodegenSettings,
)
}
}
private class IrDeclarationMappingCollectingVisitor : IrElementVisitorVoid {
private val collectedMappings = HashMap<FirDeclaration, IrDeclaration>()
val mappings: Map<FirDeclaration, IrDeclaration>
get() = Collections.unmodifiableMap(collectedMappings)
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitDeclaration(declaration: IrDeclarationBase) {
dumpDeclaration(declaration)
super.visitDeclaration(declaration)
}
private fun dumpDeclaration(declaration: IrDeclaration) {
if (declaration is IrMetadataSourceOwner) {
val fir = (declaration.metadata as? FirMetadataSource)?.fir
if (fir != null) {
collectedMappings.putIfAbsent(fir, declaration)
}
}
}
}
private class IrDeclarationPatchingVisitor(private val mapping: Map<FirDeclaration, IrDeclaration>) : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFieldAccess(expression: IrFieldAccessExpression) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
patchIfNeeded(expression.superQualifierSymbol) { expression.superQualifierSymbol = it }
super.visitFieldAccess(expression)
}
override fun visitValueAccess(expression: IrValueAccessExpression) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
super.visitValueAccess(expression)
}
override fun visitGetEnumValue(expression: IrGetEnumValue) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
super.visitGetEnumValue(expression)
}
override fun visitGetObjectValue(expression: IrGetObjectValue) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
super.visitGetObjectValue(expression)
}
override fun visitCall(expression: IrCall) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
patchIfNeeded(expression.superQualifierSymbol) { expression.superQualifierSymbol = it }
super.visitCall(expression)
}
override fun visitConstructorCall(expression: IrConstructorCall) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
super.visitConstructorCall(expression)
}
override fun visitPropertyReference(expression: IrPropertyReference) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
patchIfNeeded(expression.getter) { expression.getter = it }
patchIfNeeded(expression.setter) { expression.setter = it }
super.visitPropertyReference(expression)
}
override fun visitFunctionReference(expression: IrFunctionReference) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
patchIfNeeded(expression.reflectionTarget) { expression.reflectionTarget = it }
super.visitFunctionReference(expression)
}
override fun visitClassReference(expression: IrClassReference) {
patchIfNeeded(expression.symbol) { expression.symbol = it }
super.visitClassReference(expression)
}
private inline fun <reified T : IrSymbol> patchIfNeeded(irSymbol: T?, patcher: (T) -> Unit) {
if (irSymbol != null) {
val irDeclaration = irSymbol.owner as? IrMetadataSourceOwner ?: return
val firDeclaration = (irDeclaration.metadata as? FirMetadataSource)?.fir ?: return
val correctedIrSymbol = mapping[firDeclaration]?.symbol as? T ?: return
if (correctedIrSymbol != irSymbol) {
patcher(correctedIrSymbol)
}
}
}
}
@@ -172,6 +172,48 @@ public class FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated exten
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt");
}
@Test
@TestMetadata("localFunctionContainingClassClosure.kt")
public void testLocalFunctionContainingClassClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionContainingClassClosure.kt");
}
@Test
@TestMetadata("localFunctionExtensionReceiverClosure.kt")
public void testLocalFunctionExtensionReceiverClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionExtensionReceiverClosure.kt");
}
@Test
@TestMetadata("localFunctionLambdaParameterClosure.kt")
public void testLocalFunctionLambdaParameterClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLambdaParameterClosure.kt");
}
@Test
@TestMetadata("localFunctionLocalClosure.kt")
public void testLocalFunctionLocalClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLocalClosure.kt");
}
@Test
@TestMetadata("localFunctionLocalClosureMutating.kt")
public void testLocalFunctionLocalClosureMutating() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLocalClosureMutating.kt");
}
@Test
@TestMetadata("localFunctionMultipleCapturing.kt")
public void testLocalFunctionMultipleCapturing() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionMultipleCapturing.kt");
}
@Test
@TestMetadata("localFunctionParameterClosure.kt")
public void testLocalFunctionParameterClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionParameterClosure.kt");
}
@Test
@TestMetadata("localMutated.kt")
public void testLocalMutated() throws Exception {
@@ -26,10 +26,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.ConfigurationDirectives
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
@@ -181,7 +178,7 @@ internal fun createCodeFragment(ktFile: KtFile, module: TestModule, testServices
return null
}
val contextElement = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtDeclaration>(ktFile)
val contextElement = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtElement>(ktFile)
val fragmentText = ioFragmentFile.readText()
val isBlockFragment = fragmentText.any { it == '\n' }
@@ -0,0 +1,42 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionContainingClassClosure.kt
CLASS CLASS name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Foo
CONSTRUCTOR visibility:public <> () returnType:<root>.Foo [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> ($this:<root>.Foo) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Foo
BLOCK_BODY
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun consume (obj: <root>.Foo): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
obj: GET_VAR '<this>: <root>.Foo declared in <root>.Foo.test' type=<root>.Foo origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.Foo.test' type=kotlin.Unit origin=null
FUN name:consume visibility:public modality:FINAL <> (obj:<root>.Foo) returnType:kotlin.Unit
VALUE_PARAMETER name:obj index:0 type:<root>.Foo
BLOCK_BODY
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.Foo.test' type=kotlin.Unit origin=null
@@ -0,0 +1,11 @@
class Foo {
fun test() {
fun call() {
consume(this@Foo)
}
<caret>call()
}
}
fun consume(obj: Foo) {}
@@ -0,0 +1,14 @@
public final class CodeFragment {
// source: 'fragment.kt'
public method <init>(): void
public final static method run(p0: Foo): void
}
public final class Foo {
// source: 'localFunctionContainingClassClosure.kt'
public method <init>(): void
private final static method test$call(p0: Foo): void
public final method test(): void
}
public final class LocalFunctionContainingClassClosureKt
@@ -0,0 +1,37 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionExtensionReceiverClosure.kt
FUN name:block visibility:public modality:FINAL <T> (obj:T of <root>.block, block:@[ExtensionFunctionType] kotlin.Function1<T of <root>.block, kotlin.Unit>) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
VALUE_PARAMETER name:obj index:0 type:T of <root>.block
VALUE_PARAMETER name:block index:1 type:@[ExtensionFunctionType] kotlin.Function1<T of <root>.block, kotlin.Unit>
BLOCK_BODY
CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=INVOKE
$this: GET_VAR 'block: @[ExtensionFunctionType] kotlin.Function1<T of <root>.block, kotlin.Unit> declared in <root>.block' type=@[ExtensionFunctionType] kotlin.Function1<T of <root>.block, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
p1: GET_VAR 'obj: T of <root>.block declared in <root>.block' type=T of <root>.block origin=null
FUN name:consume visibility:public modality:FINAL <> (text:kotlin.String) returnType:kotlin.Unit
VALUE_PARAMETER name:text index:0 type:kotlin.String
BLOCK_BODY
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun block <T> (obj: T of <root>.block, block: @[ExtensionFunctionType] kotlin.Function1<T of <root>.block, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: kotlin.String
obj: CONST String type=kotlin.String value="foo"
block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1<kotlin.String, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:kotlin.String) returnType:kotlin.Unit
$receiver: VALUE_PARAMETER name:$this$block type:kotlin.String
BLOCK_BODY
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun consume (text: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
text: GET_VAR '$this$block: kotlin.String declared in <root>.test.<anonymous>' type=kotlin.String origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test.<anonymous>' type=kotlin.Unit origin=null
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test.<anonymous>' type=kotlin.Unit origin=null
@@ -0,0 +1,15 @@
fun test() {
block("foo") {
fun call() {
consume(this@block)
}
<caret>call()
}
}
fun <T> block(obj: T, block: T.() -> Unit) {
obj.block()
}
fun consume(text: String) {}
@@ -0,0 +1,8 @@
public final class CodeFragment {
// source: 'fragment.kt'
inner (anonymous) class LocalFunctionExtensionReceiverClosureKt$test$1
public method <init>(): void
public final static method run(p0: java.lang.String): void
}
public final class LocalFunctionExtensionReceiverClosureKt
@@ -0,0 +1,37 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionLambdaParameterClosure.kt
FUN name:block visibility:public modality:FINAL <T> (obj:T of <root>.block, block:kotlin.Function1<T of <root>.block, kotlin.Unit>) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
VALUE_PARAMETER name:obj index:0 type:T of <root>.block
VALUE_PARAMETER name:block index:1 type:kotlin.Function1<T of <root>.block, kotlin.Unit>
BLOCK_BODY
CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Unit origin=INVOKE
$this: GET_VAR 'block: kotlin.Function1<T of <root>.block, kotlin.Unit> declared in <root>.block' type=kotlin.Function1<T of <root>.block, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
p1: GET_VAR 'obj: T of <root>.block declared in <root>.block' type=T of <root>.block origin=null
FUN name:consume visibility:public modality:FINAL <> (text:kotlin.String) returnType:kotlin.Unit
VALUE_PARAMETER name:text index:0 type:kotlin.String
BLOCK_BODY
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun block <T> (obj: T of <root>.block, block: kotlin.Function1<T of <root>.block, kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
<T>: kotlin.String
obj: CONST String type=kotlin.String value="foo"
block: FUN_EXPR type=kotlin.Function1<kotlin.String, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (foo:kotlin.String) returnType:kotlin.Unit
VALUE_PARAMETER name:foo index:0 type:kotlin.String
BLOCK_BODY
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun consume (text: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
text: GET_VAR 'foo: kotlin.String declared in <root>.test.<anonymous>' type=kotlin.String origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test.<anonymous>' type=kotlin.Unit origin=null
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test.<anonymous>' type=kotlin.Unit origin=null
@@ -0,0 +1,15 @@
fun test() {
block("foo") { foo ->
fun call() {
consume(foo)
}
<caret>call()
}
}
fun <T> block(obj: T, block: (T) -> Unit) {
block(obj)
}
fun consume(text: String) {}
@@ -0,0 +1,8 @@
public final class CodeFragment {
// source: 'fragment.kt'
inner (anonymous) class LocalFunctionLambdaParameterClosureKt$test$1
public method <init>(): void
public final static method run(p0: java.lang.String): void
}
public final class LocalFunctionLambdaParameterClosureKt
@@ -0,0 +1,24 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionLocalClosure.kt
FUN name:consume visibility:public modality:FINAL <> (n:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER name:n index:0 type:kotlin.Int
BLOCK_BODY
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:x type:kotlin.Int [val]
CONST Int type=kotlin.Int value=0
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun consume (n: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
n: GET_VAR 'val x: kotlin.Int [val] declared in <root>.test' type=kotlin.Int origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
@@ -0,0 +1,11 @@
fun test() {
val x = 0
fun call() {
consume(x)
}
<caret>call()
}
fun consume(n: Int) {}
@@ -0,0 +1,7 @@
public final class CodeFragment {
// source: 'fragment.kt'
public method <init>(): void
public final static method run(p0: int): void
}
public final class LocalFunctionLocalClosureKt
@@ -0,0 +1,21 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionLocalClosureMutating.kt
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:x type:kotlin.Int [var]
CONST Int type=kotlin.Int value=0
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
SET_VAR 'var x: kotlin.Int [var] declared in <root>.test' type=kotlin.Unit origin=EQ
CONST Int type=kotlin.Int value=1
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
@@ -0,0 +1,9 @@
fun test() {
var x = 0
fun call() {
x = 1
}
<caret>call()
}
@@ -0,0 +1,8 @@
public final class CodeFragment {
// source: 'fragment.kt'
public method <init>(): void
public final static method run(p0: kotlin.jvm.internal.Ref$IntRef): void
public final inner class kotlin/jvm/internal/Ref$IntRef
}
public final class LocalFunctionLocalClosureMutatingKt
@@ -0,0 +1,53 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionMultipleCapturing.kt
CLASS CLASS name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Foo
CONSTRUCTOR visibility:public <> () returnType:<root>.Foo [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:test visibility:public modality:FINAL <> ($this:<root>.Foo, $receiver:kotlin.String) returnType:kotlin.Unit
$this: VALUE_PARAMETER name:<this> type:<root>.Foo
$receiver: VALUE_PARAMETER name:<this> type:kotlin.String
BLOCK_BODY
VAR name:x type:kotlin.Int [var]
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> (a:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER name:a index:0 type:kotlin.Int
BLOCK_BODY
CALL 'public final fun consume (obj: kotlin.Any): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
obj: GET_VAR 'a: kotlin.Int declared in <root>.Foo.test.call' type=kotlin.Int origin=null
CALL 'public final fun consume (obj: kotlin.Any): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
obj: GET_VAR '<this>: <root>.Foo declared in <root>.Foo.test' type=<root>.Foo origin=null
CALL 'public final fun consume (obj: kotlin.Any): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
obj: GET_VAR '<this>: kotlin.String declared in <root>.Foo.test' type=kotlin.String origin=null
SET_VAR 'var x: kotlin.Int [var] declared in <root>.Foo.test' type=kotlin.Unit origin=EQ
CONST Int type=kotlin.Int value=42
CALL 'local final fun call (a: kotlin.Int): kotlin.Unit declared in <root>.Foo.test' type=kotlin.Unit origin=null
a: CONST Int type=kotlin.Int value=1
FUN name:consume visibility:public modality:FINAL <> (obj:kotlin.Any) returnType:kotlin.Unit
VALUE_PARAMETER name:obj index:0 type:kotlin.Any
BLOCK_BODY
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (a: kotlin.Int): kotlin.Unit declared in <root>.Foo.test' type=kotlin.Unit origin=null
a: CONST Int type=kotlin.Int value=0
@@ -0,0 +1,16 @@
class Foo {
fun String.test() {
var x: Int
fun call(a: Int) {
consume(a)
consume(this@Foo)
consume(this@test)
x = 42
}
<caret>call(1)
}
}
fun consume(obj: Any) {}
@@ -0,0 +1,16 @@
public final class CodeFragment {
// source: 'fragment.kt'
public method <init>(): void
public final static method run(p0: Foo, p1: java.lang.String, p2: kotlin.jvm.internal.Ref$IntRef): void
public final inner class kotlin/jvm/internal/Ref$IntRef
}
public final class Foo {
// source: 'localFunctionMultipleCapturing.kt'
public method <init>(): void
private final static method test$call(p0: Foo, p1: java.lang.String, p2: kotlin.jvm.internal.Ref$IntRef, p3: int): void
public final method test(p0: java.lang.String): void
public final inner class kotlin/jvm/internal/Ref$IntRef
}
public final class LocalFunctionMultipleCapturingKt
@@ -0,0 +1,23 @@
MODULE_FRAGMENT name:<Sources of main>
FILE fqName:<root> fileName:/localFunctionParameterClosure.kt
FUN name:consume visibility:public modality:FINAL <> (n:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER name:n index:0 type:kotlin.Int
BLOCK_BODY
FUN name:test visibility:public modality:FINAL <> (x:kotlin.Int) returnType:kotlin.Unit
VALUE_PARAMETER name:x index:0 type:kotlin.Int
BLOCK_BODY
FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun consume (n: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
n: GET_VAR 'x: kotlin.Int declared in <root>.test' type=kotlin.Int origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
FILE fqName:<root> fileName:/fragment.kt
CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.CodeFragment
CONSTRUCTOR visibility:public <> () returnType:<root>.CodeFragment [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit
EXPRESSION_BODY
BLOCK type=kotlin.Unit origin=null
CALL 'local final fun call (): kotlin.Unit declared in <root>.test' type=kotlin.Unit origin=null
@@ -0,0 +1,9 @@
fun test(x: Int) {
fun call() {
consume(x)
}
<caret>call()
}
fun consume(n: Int) {}
@@ -0,0 +1,7 @@
public final class CodeFragment {
// source: 'fragment.kt'
public method <init>(): void
public final static method run(p0: int): void
}
public final class LocalFunctionParameterClosureKt
@@ -72,6 +72,48 @@ public class CodeFragmentCapturingTestGenerated extends AbstractCodeFragmentCapt
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt");
}
@Test
@TestMetadata("localFunctionContainingClassClosure.kt")
public void testLocalFunctionContainingClassClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionContainingClassClosure.kt");
}
@Test
@TestMetadata("localFunctionExtensionReceiverClosure.kt")
public void testLocalFunctionExtensionReceiverClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionExtensionReceiverClosure.kt");
}
@Test
@TestMetadata("localFunctionLambdaParameterClosure.kt")
public void testLocalFunctionLambdaParameterClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLambdaParameterClosure.kt");
}
@Test
@TestMetadata("localFunctionLocalClosure.kt")
public void testLocalFunctionLocalClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLocalClosure.kt");
}
@Test
@TestMetadata("localFunctionLocalClosureMutating.kt")
public void testLocalFunctionLocalClosureMutating() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionLocalClosureMutating.kt");
}
@Test
@TestMetadata("localFunctionMultipleCapturing.kt")
public void testLocalFunctionMultipleCapturing() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionMultipleCapturing.kt");
}
@Test
@TestMetadata("localFunctionParameterClosure.kt")
public void testLocalFunctionParameterClosure() throws Exception {
runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunctionParameterClosure.kt");
}
@Test
@TestMetadata("localMutated.kt")
public void testLocalMutated() throws Exception {