From 3dff232710e2944509a11fcce53f04a311cd6b2d Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 15 Nov 2023 14:08:11 +0200 Subject: [PATCH] [FIR2IR] Generate IR for unbound symbols in `allowNonCachedDeclarations` mode `allowNonCachedDeclarations` mode allows referring source declaration which does not belong to the set of sources passed to fir2ir (e.g. for debugger support). So if code refers to such declaration, fir2ir creates symbol for it but not the IR declaration itself --- ...ceModuleCompilerFacilityTestGenerated.java | 12 +++ ...ceModuleCompilerFacilityTestGenerated.java | 12 +++ .../localDelegatedProperty.capturing.txt | 3 + .../localDelegatedProperty.fragment.kt | 2 + .../capturing/localDelegatedProperty.ir.txt | 16 ++++ .../capturing/localDelegatedProperty.kt | 16 ++++ .../capturing/localDelegatedProperty.txt | 5 + .../capturing/localVariable.capturing.txt | 3 + .../capturing/localVariable.fragment.kt | 2 + .../capturing/localVariable.ir.txt | 16 ++++ .../codeFragments/capturing/localVariable.kt | 4 + .../codeFragments/capturing/localVariable.txt | 5 + .../CodeFragmentCapturingTestGenerated.java | 12 +++ .../kotlin/fir/backend/Fir2IrConverter.kt | 6 ++ .../fir/backend/Fir2IrDeclarationStorage.kt | 92 +++++++++++++++---- .../fir/backend/Fir2IrLocalCallableStorage.kt | 4 + .../kotlin/fir/backend/Fir2IrScopeCache.kt | 3 + .../kotlin/fir/FirVisibilityChecker.kt | 9 -- .../src/org/jetbrains/kotlin/fir/Utils.kt | 13 +++ 19 files changed, 208 insertions(+), 27 deletions(-) create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.capturing.txt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.fragment.kt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.ir.txt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.txt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.capturing.txt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.fragment.kt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.ir.txt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt create mode 100644 analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.txt diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerated.java index 27fc937b452..c600d2265db 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerated.java @@ -208,6 +208,12 @@ public class FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerate runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt"); } + @Test + @TestMetadata("localDelegatedProperty.kt") + public void testLocalDelegatedProperty() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt"); + } + @Test @TestMetadata("localFunction.kt") public void testLocalFunction() throws Exception { @@ -262,6 +268,12 @@ public class FirIdeNormalAnalysisLibrarySourceModuleCompilerFacilityTestGenerate runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt"); } + @Test + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt"); + } + @Test @TestMetadata("multipleClassAndFunctionContextReceivers.kt") public void testMultipleClassAndFunctionContextReceivers() throws Exception { diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java index cb5a00ff30b..efaca46fbc9 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java @@ -208,6 +208,12 @@ public class FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated exten runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt"); } + @Test + @TestMetadata("localDelegatedProperty.kt") + public void testLocalDelegatedProperty() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt"); + } + @Test @TestMetadata("localFunction.kt") public void testLocalFunction() throws Exception { @@ -262,6 +268,12 @@ public class FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated exten runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt"); } + @Test + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt"); + } + @Test @TestMetadata("multipleClassAndFunctionContextReceivers.kt") public void testMultipleClassAndFunctionContextReceivers() throws Exception { diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.capturing.txt new file mode 100644 index 00000000000..97d5637b014 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.capturing.txt @@ -0,0 +1,3 @@ +LocalDelegate[name: x; isMutated: true; displayText: x$delegate] + lvar x: R|kotlin/String| + R|kotlin/String| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.fragment.kt new file mode 100644 index 00000000000..3897e79b34e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.fragment.kt @@ -0,0 +1,2 @@ +x = "O" +x + "K" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.ir.txt new file mode 100644 index 00000000000..a82c87ae5f5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.ir.txt @@ -0,0 +1,16 @@ +MODULE_FRAGMENT + FILE fqName: fileName:fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.String) returnType:kotlin.String + VALUE_PARAMETER SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT name:p0 index:0 type:kotlin.String [assignable] + EXPRESSION_BODY + BLOCK type=kotlin.String origin=null + SET_VAR 'p0: kotlin.String [assignable] declared in .CodeFragment.run' type=kotlin.Unit origin=null + CONST String type=kotlin.String value="O" + CALL 'public final fun plus (other: kotlin.Any?): kotlin.String [operator] declared in kotlin.String' type=kotlin.String origin=PLUS + $this: GET_VAR 'p0: kotlin.String [assignable] declared in .CodeFragment.run' type=kotlin.String origin=null + other: CONST String type=kotlin.String value="K" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt new file mode 100644 index 00000000000..8640d18270e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt @@ -0,0 +1,16 @@ +import kotlin.reflect.KProperty + +class Delegate(private var value: String) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + return value + } + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + this.value = value + } +} + +fun test() { + var x by Delegate("a") + x +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.txt new file mode 100644 index 00000000000..a97a3af64a0 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: java.lang.String): java.lang.String +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.capturing.txt new file mode 100644 index 00000000000..70a86aab236 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.capturing.txt @@ -0,0 +1,3 @@ +Local[name: x; isMutated: true; displayText: x] + lvar x: R|kotlin/String| + R|kotlin/String| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.fragment.kt new file mode 100644 index 00000000000..3897e79b34e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.fragment.kt @@ -0,0 +1,2 @@ +x = "O" +x + "K" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.ir.txt new file mode 100644 index 00000000000..a82c87ae5f5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.ir.txt @@ -0,0 +1,16 @@ +MODULE_FRAGMENT + FILE fqName: fileName:fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.String) returnType:kotlin.String + VALUE_PARAMETER SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT name:p0 index:0 type:kotlin.String [assignable] + EXPRESSION_BODY + BLOCK type=kotlin.String origin=null + SET_VAR 'p0: kotlin.String [assignable] declared in .CodeFragment.run' type=kotlin.Unit origin=null + CONST String type=kotlin.String value="O" + CALL 'public final fun plus (other: kotlin.Any?): kotlin.String [operator] declared in kotlin.String' type=kotlin.String origin=PLUS + $this: GET_VAR 'p0: kotlin.String [assignable] declared in .CodeFragment.run' type=kotlin.String origin=null + other: CONST String type=kotlin.String value="K" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt new file mode 100644 index 00000000000..1612fd40807 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt @@ -0,0 +1,4 @@ +fun test() { + var x = "a" + x +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.txt new file mode 100644 index 00000000000..a97a3af64a0 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: java.lang.String): java.lang.String +} diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java index 42571b63d63..59908069fc4 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java @@ -84,6 +84,12 @@ public class CodeFragmentCapturingTestGenerated extends AbstractCodeFragmentCapt runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt"); } + @Test + @TestMetadata("localDelegatedProperty.kt") + public void testLocalDelegatedProperty() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localDelegatedProperty.kt"); + } + @Test @TestMetadata("localFunction.kt") public void testLocalFunction() throws Exception { @@ -138,6 +144,12 @@ public class CodeFragmentCapturingTestGenerated extends AbstractCodeFragmentCapt runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt"); } + @Test + @TestMetadata("localVariable.kt") + public void testLocalVariable() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localVariable.kt"); + } + @Test @TestMetadata("multipleClassAndFunctionContextReceivers.kt") public void testMultipleClassAndFunctionContextReceivers() throws Exception { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 23e64f09639..e8656ad5ae9 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -122,6 +122,12 @@ class Fir2IrConverter( declarationStorage.generateUnboundFakeOverrides() } + if (configuration.allowNonCachedDeclarations) { + // See the comment to fillUnboundSymbols function itself + @OptIn(LeakedDeclarationCaches::class) + declarationStorage.fillUnboundSymbols() + } + evaluateConstants(irModuleFragment, components) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index eb6bc2fd8c2..46dd4c58189 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -9,14 +9,12 @@ import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.backend.generators.isExternalParent import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty -import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField -import org.jetbrains.kotlin.fir.declarations.utils.isExpect -import org.jetbrains.kotlin.fir.declarations.utils.isStatic -import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol @@ -1177,22 +1175,75 @@ class Fir2IrDeclarationStorage( for ((identifier, symbol) in irForFirSessionDependantDeclarationMap) { if (symbol.isBound) continue val (originalSymbol, dispatchReceiverLookupTag, _) = identifier - val irParent = findIrParent(originalSymbol.fir, dispatchReceiverLookupTag) - when (originalSymbol) { - is FirPropertySymbol -> createAndCacheIrProperty( - originalSymbol.fir, - irParent, - fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag - ) + generateDeclaration(originalSymbol, dispatchReceiverLookupTag) + } + } - is FirNamedFunctionSymbol -> createAndCacheIrFunction( - originalSymbol.fir, - irParent, - fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag - ) + /** + * This function iterates over all non f/o callable symbols created in declaration storage and binds all unbound symbols + * + * Usually all symbols are bound after fir2ir conversion is over, but it's not true for `allowNonCachedDeclarations`, when + * we convert to IR only part of sources from code fragments. + * + * ``` + * // Original code + * fun foo(x: Int) {} // (1) + * + * fun bar() { + * 1.let { // (2) + * + * } + * } + * + * // Code fragment + * foo(this@let) + * + * Here in the body of the code fragment we reference function (1) and lambda (2), which leads to creation of their symbols, + * but not to generation of their IR. And since the original code won't be processed by fir2ir, we need to manually create + * IR for all symbols from it, to avoid publication of unbound symbols after fir2ri conversion is over + * + * Note that in the code fragment we may capture even local functions and lambdas, which are stored not in global caches, + * but in `localStorage`, which is getting cleared after leaving from corresponding scope. So to generate IR for them we need + * to call this function not only after fir2ir conversion, but also after leaving each local scope (see `leaveScope` function) + */ + @LeakedDeclarationCaches + internal fun fillUnboundSymbols() { + fillUnboundSymbols(functionCache) + fillUnboundSymbols(propertyCache) + } - else -> error("Unexpected declaration: $originalSymbol") - } + @LeakedDeclarationCaches + private fun fillUnboundSymbols(cache: Map) { + for ((firDeclaration, irSymbol) in cache) { + if (irSymbol.isBound) continue + generateDeclaration(firDeclaration.symbol, dispatchReceiverLookupTag = null) + } + } + + private fun generateDeclaration( + originalSymbol: FirBasedSymbol<*>, + dispatchReceiverLookupTag: ConeClassLikeLookupTag?, + ) { + val irParent = findIrParent( + originalSymbol.packageFqName(), + dispatchReceiverLookupTag ?: originalSymbol.getContainingClassSymbol(session)?.toLookupTag(), + originalSymbol, + originalSymbol.origin + ) + when (originalSymbol) { + is FirPropertySymbol -> createAndCacheIrProperty( + originalSymbol.fir, + irParent, + fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag + ) + + is FirNamedFunctionSymbol -> createAndCacheIrFunction( + originalSymbol.fir, + irParent, + fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag + ) + + else -> error("Unexpected declaration: $originalSymbol") } } @@ -1240,6 +1291,11 @@ class Fir2IrDeclarationStorage( symbol is IrEnumEntrySymbol || symbol is IrScriptSymbol ) { + if (configuration.allowNonCachedDeclarations) { + // See KDoc to `fillUnboundSymbols` function + @OptIn(LeakedDeclarationCaches::class) + fillUnboundSymbols(localStorage.lastCache.localFunctions) + } localStorage.leaveCallable() } symbolTable.leaveScope(symbol) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrLocalCallableStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrLocalCallableStorage.kt index 54dc5ba17aa..bccecbe27ce 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrLocalCallableStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrLocalCallableStorage.kt @@ -19,6 +19,10 @@ class Fir2IrLocalCallableStorage { cacheStack += Fir2IrScopeCache() } + @LeakedDeclarationCaches + val lastCache: Fir2IrScopeCache + get() = cacheStack.last() + fun leaveCallable() { cacheStack.last().clear() cacheStack.removeAt(cacheStack.size - 1) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrScopeCache.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrScopeCache.kt index e9c1523bcd5..b9c064fec6a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrScopeCache.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrScopeCache.kt @@ -17,6 +17,9 @@ class Fir2IrScopeCache { private val localFunctionCache = mutableMapOf() + val localFunctions: Map + get() = localFunctionCache + private val delegatedPropertyCache = mutableMapOf() fun getParameter(parameter: FirValueParameter): IrValueParameterSymbol? { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt index 7be73961585..70dd10069e8 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/FirVisibilityChecker.kt @@ -464,15 +464,6 @@ abstract class FirVisibilityChecker : FirSessionComponent { return false } - - protected fun FirBasedSymbol<*>.packageFqName(): FqName { - return when (this) { - is FirClassLikeSymbol<*> -> classId.packageFqName - is FirPropertyAccessorSymbol -> propertySymbol.packageFqName() - is FirCallableSymbol<*> -> callableId.packageName - else -> error("No package fq name for $this") - } - } } val FirSession.moduleVisibilityChecker: FirModuleVisibilityChecker? by FirSession.nullableSessionComponentAccessor() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt index 5cd2bbea8f2..73bb6f653a0 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt @@ -20,6 +20,10 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin import org.jetbrains.kotlin.fir.renderer.FirRenderer +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.impl.* @@ -273,3 +277,12 @@ val FirExpression.isStatementLikeExpression: Boolean private val FirExpression.isIndexedAssignment: Boolean get() = this is FirBlock && statements.lastOrNull()?.source?.kind == KtFakeSourceElementKind.ImplicitUnit.IndexedAssignmentCoercion + +fun FirBasedSymbol<*>.packageFqName(): FqName { + return when (this) { + is FirClassLikeSymbol<*> -> classId.packageFqName + is FirPropertyAccessorSymbol -> propertySymbol.packageFqName() + is FirCallableSymbol<*> -> callableId.packageName + else -> error("No package fq name for $this") + } +}