[LL][KMP] Don't create JVM container source in non-JVM symbol providers
Multiple .knm parts of the same KMP library were considered part of the
same JVM file facade. Because of that, an incorrect overload could
be selected, depending on the order of dependencies.
KT-69395
(cherry picked from commit 70b108608599450739867174e7e2a3dc29607275)
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/DeserializedContainerSourceProviders.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/DeserializedContainerSourceProviders.kt
new file mode 100644
index 0000000..780fb45
--- /dev/null
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/DeserializedContainerSourceProviders.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2010-2024 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.analysis.low.level.api.fir.stubBased.deserialization
+
+import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.stubs.impl.KotlinStubOrigin
+import org.jetbrains.kotlin.resolve.jvm.JvmClassName
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
+
+internal interface DeserializedContainerSourceProvider {
+ fun getFacadeContainerSource(
+ file: KtFile,
+ stubOrigin: KotlinStubOrigin?,
+ declarationOrigin: FirDeclarationOrigin,
+ ): DeserializedContainerSource?
+
+ fun getClassContainerSource(classId: ClassId): DeserializedContainerSource?
+}
+
+// Currently, `null` is returned for KLIBs to avoid incorrect application of JVM file facade logic and overload filtering.
+// We might want to provide non-`null` container source for all types of binaries in the future.
+internal object NullDeserializedContainerSourceProvider : DeserializedContainerSourceProvider {
+ override fun getFacadeContainerSource(
+ file: KtFile,
+ stubOrigin: KotlinStubOrigin?,
+ declarationOrigin: FirDeclarationOrigin,
+ ): DeserializedContainerSource? = null
+
+ override fun getClassContainerSource(classId: ClassId): DeserializedContainerSource? = null
+}
+
+internal object JvmDeserializedContainerSourceProvider : DeserializedContainerSourceProvider {
+ override fun getFacadeContainerSource(
+ file: KtFile,
+ stubOrigin: KotlinStubOrigin?,
+ declarationOrigin: FirDeclarationOrigin,
+ ): DeserializedContainerSource {
+ return when (stubOrigin) {
+ is KotlinStubOrigin.Facade -> {
+ val className = JvmClassName.byInternalName(stubOrigin.className)
+ JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null)
+ }
+ is KotlinStubOrigin.MultiFileFacade -> {
+ val className = JvmClassName.byInternalName(stubOrigin.className)
+ val facadeClassName = JvmClassName.byInternalName(stubOrigin.facadeClassName)
+ JvmStubDeserializedFacadeContainerSource(className, facadeClassName)
+ }
+ else -> {
+ val virtualFile = file.virtualFile
+ val classId = ClassId(file.packageFqName, Name.identifier(virtualFile.nameWithoutExtension))
+ val className = JvmClassName.byClassId(classId)
+ JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null)
+ }
+ }
+ }
+
+ override fun getClassContainerSource(classId: ClassId): DeserializedContainerSource? {
+ return JvmStubDeserializedContainerSource(classId)
+ }
+}
+
+internal object BuiltinsDeserializedContainerSourceProvider : DeserializedContainerSourceProvider {
+ override fun getFacadeContainerSource(
+ file: KtFile,
+ stubOrigin: KotlinStubOrigin?,
+ declarationOrigin: FirDeclarationOrigin,
+ ): DeserializedContainerSource {
+ require(stubOrigin is KotlinStubOrigin.Facade) {
+ "Expected builtins file to have Facade origin, got origin=$stubOrigin instead"
+ }
+
+ return JvmStubDeserializedBuiltInsContainerSource(
+ facadeClassName = JvmClassName.byInternalName(stubOrigin.className)
+ )
+ }
+
+ override fun getClassContainerSource(classId: ClassId): DeserializedContainerSource? {
+ return JvmStubDeserializedContainerSource(classId)
+ }
+}
+
+internal object JvmAndBuiltinsDeserializedContainerSourceProvider : DeserializedContainerSourceProvider {
+ override fun getFacadeContainerSource(
+ file: KtFile,
+ stubOrigin: KotlinStubOrigin?,
+ declarationOrigin: FirDeclarationOrigin
+ ): DeserializedContainerSource? {
+ if (declarationOrigin is FirDeclarationOrigin.BuiltIns) {
+ return BuiltinsDeserializedContainerSourceProvider.getFacadeContainerSource(file, stubOrigin, declarationOrigin)
+ }
+
+ return JvmDeserializedContainerSourceProvider.getFacadeContainerSource(file, stubOrigin, declarationOrigin)
+ }
+
+ override fun getClassContainerSource(classId: ClassId): DeserializedContainerSource? {
+ return JvmStubDeserializedContainerSource(classId)
+ }
+}
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/LLStubBasedLibrarySymbolProviderFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/LLStubBasedLibrarySymbolProviderFactory.kt
index 65b7006..725bca3 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/LLStubBasedLibrarySymbolProviderFactory.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/LLStubBasedLibrarySymbolProviderFactory.kt
@@ -142,6 +142,7 @@
session,
SingleModuleDataProvider(moduleData),
kotlinScopeProvider,
+ BuiltinsDeserializedContainerSourceProvider,
project,
BuiltinsVirtualFileProvider.getInstance().createBuiltinsScope(project),
isFallbackDependenciesProvider = false,
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirDeserializedSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirDeserializedSymbolProvider.kt
index d4d3795..6720798 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirDeserializedSymbolProvider.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirDeserializedSymbolProvider.kt
@@ -30,9 +30,7 @@
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getTopmostParentOfType
import org.jetbrains.kotlin.psi.stubs.impl.*
-import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
-import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
typealias DeserializedTypeAliasPostProcessor = (FirTypeAliasSymbol) -> Unit
@@ -53,6 +51,7 @@
session: FirSession,
moduleDataProvider: SingleModuleDataProvider,
private val kotlinScopeProvider: FirKotlinScopeProvider,
+ private val deserializedContainerSourceProvider: DeserializedContainerSourceProvider,
project: Project,
scope: GlobalSearchScope,
@@ -153,7 +152,7 @@
StubBasedAnnotationDeserializer(session),
kotlinScopeProvider,
parentContext = parentContext,
- containerSource = JvmStubDeserializedContainerSource(classId),
+ containerSource = deserializedContainerSourceProvider.getClassContainerSource(classId),
deserializeNestedClass = this::getClass,
initialOrigin = parentContext?.initialOrigin ?: getDeclarationOriginFor(classLikeDeclaration.containingKtFile)
)
@@ -173,8 +172,9 @@
for (function in topLevelFunctions) {
val functionStub = function.stub as? KotlinFunctionStubImpl ?: loadStubByElement(function)
val functionFile = function.containingKtFile
- val containerSource = getContainerSource(functionFile, functionStub?.origin)
val functionOrigin = getDeclarationOriginFor(functionFile)
+ val containerSource =
+ deserializedContainerSourceProvider.getFacadeContainerSource(functionFile, functionStub?.origin, functionOrigin)
if (functionOrigin != FirDeclarationOrigin.BuiltIns &&
containerSource is FacadeClassSource &&
@@ -199,8 +199,12 @@
for (property in topLevelProperties) {
val propertyStub = property.stub as? KotlinPropertyStubImpl ?: loadStubByElement(property)
val propertyFile = property.containingKtFile
- val containerSource = getContainerSource(propertyFile, propertyStub?.origin)
val propertyOrigin = getDeclarationOriginFor(propertyFile)
+ val containerSource = deserializedContainerSourceProvider.getFacadeContainerSource(
+ propertyFile,
+ propertyStub?.origin,
+ propertyOrigin,
+ )
val symbol = FirPropertySymbol(callableId)
val rootContext = StubBasedFirDeserializationContext
@@ -211,36 +215,6 @@
}
}
- private fun getContainerSource(file: KtFile, origin: KotlinStubOrigin?): DeserializedContainerSource {
- if (getDeclarationOriginFor(file) == FirDeclarationOrigin.BuiltIns) {
- require(origin is KotlinStubOrigin.Facade) {
- "Expected builtins file to have Facade origin, got origin=$origin instead"
- }
-
- return JvmStubDeserializedBuiltInsContainerSource(
- facadeClassName = JvmClassName.byInternalName(origin.className)
- )
- }
-
- return when (origin) {
- is KotlinStubOrigin.Facade -> {
- val className = JvmClassName.byInternalName(origin.className)
- JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null)
- }
- is KotlinStubOrigin.MultiFileFacade -> {
- val className = JvmClassName.byInternalName(origin.className)
- val facadeClassName = JvmClassName.byInternalName(origin.facadeClassName)
- JvmStubDeserializedFacadeContainerSource(className, facadeClassName)
- }
- else -> {
- val virtualFile = file.virtualFile
- val classId = ClassId(file.packageFqName, Name.identifier(virtualFile.nameWithoutExtension))
- val className = JvmClassName.byClassId(classId)
- JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null)
- }
- }
- }
-
private fun getClass(classId: ClassId, parentContext: StubBasedFirDeserializationContext? = null): FirRegularClassSymbol? =
if (parentContext?.classLikeDeclaration != null) {
classCache.getNotNullValueForNotNullContext(classId, parentContext)
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt
index 18b3c41..744138b 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt
@@ -165,7 +165,7 @@
parameterListOwner: KtTypeParameterListOwner,
symbol: FirBasedSymbol<*>,
initialOrigin: FirDeclarationOrigin,
- containerSource: DeserializedContainerSource
+ containerSource: DeserializedContainerSource?,
): StubBasedFirDeserializationContext {
return createRootContext(
moduleData,
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirSymbolProviderFactories.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirSymbolProviderFactories.kt
index 1039594..0d554c7 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirSymbolProviderFactories.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirSymbolProviderFactories.kt
@@ -31,6 +31,7 @@
session,
moduleDataProvider,
kotlinScopeProvider,
+ JvmAndBuiltinsDeserializedContainerSourceProvider,
isFallbackDependenciesProvider,
fileFilter = { file ->
val extension = file.extension
@@ -51,6 +52,7 @@
session,
moduleDataProvider,
kotlinScopeProvider,
+ NullDeserializedContainerSourceProvider,
isFallbackDependenciesProvider,
fileFilter = { file ->
val extension = file.extension
@@ -74,6 +76,7 @@
session,
moduleDataProvider,
kotlinScopeProvider,
+ NullDeserializedContainerSourceProvider,
isFallbackDependenciesProvider,
fileFilter = { file -> file.extension == KLIB_METADATA_FILE_EXTENSION },
)
@@ -84,6 +87,7 @@
session: FirSession,
moduleDataProvider: SingleModuleDataProvider,
kotlinScopeProvider: FirKotlinScopeProvider,
+ deserializedContainerSourceProvider: DeserializedContainerSourceProvider,
isFallbackDependenciesProvider: Boolean,
fileFilter: (VirtualFile) -> Boolean,
): StubBasedFirDeserializedSymbolProvider {
@@ -94,6 +98,7 @@
session,
moduleDataProvider,
kotlinScopeProvider,
+ deserializedContainerSourceProvider,
project,
reducedScope,
isFallbackDependenciesProvider,
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.kt
new file mode 100644
index 0000000..3153390
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+class MyClass {
+ fun fn() = Unit
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.txt
new file mode 100644
index 0000000..d2856ea
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public final fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.kt
new file mode 100644
index 0000000..1708c30
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+class MyClass {
+ val prop: String = ""
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.txt
new file mode 100644
index 0000000..c5c7318
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public final val prop: kotlin.String /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/String|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.kt
new file mode 100644
index 0000000..ffacda8
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass()
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.txt
new file mode 100644
index 0000000..ac0c648
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtPrimaryConstructor
+KT element text:
+public constructor()
+FIR element: FirPrimaryConstructor
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor(): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.kt
new file mode 100644
index 0000000..76e68b7
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass {
+ constructor(a: Int)
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.txt
new file mode 100644
index 0000000..54ef104
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtSecondaryConstructor
+KT element text:
+public constructor(a: kotlin.Int) { /* compiled code */ }
+FIR element: FirConstructorImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Int|): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.kt
new file mode 100644
index 0000000..c257c7c
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+fun fn() = Unit
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.txt
new file mode 100644
index 0000000..3c08ec6
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.kt
new file mode 100644
index 0000000..9fc2afd
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+val prop: Int = 37
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.txt
new file mode 100644
index 0000000..f1b049d
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public val prop: kotlin.Int /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/Int|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.kt
new file mode 100644
index 0000000..3153390
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+class MyClass {
+ fun fn() = Unit
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.txt
new file mode 100644
index 0000000..1dece5a
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public final fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedContainerSource test/MyClass
+File name: MyClass.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.kt
new file mode 100644
index 0000000..1708c30
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+class MyClass {
+ val prop: String = ""
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.txt
new file mode 100644
index 0000000..50c6fb5
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public final val prop: kotlin.String /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedContainerSource test/MyClass
+File name: MyClass.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/String|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.kt
new file mode 100644
index 0000000..ffacda8
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass()
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.txt
new file mode 100644
index 0000000..acc85f6
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtPrimaryConstructor
+KT element text:
+public constructor()
+FIR element: FirPrimaryConstructor
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedContainerSource test/MyClass
+File name: MyClass.class
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor(): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.kt
new file mode 100644
index 0000000..76e68b7
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass {
+ constructor(a: Int)
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.txt
new file mode 100644
index 0000000..b9f9838
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtSecondaryConstructor
+KT element text:
+public constructor(a: kotlin.Int) { /* compiled code */ }
+FIR element: FirConstructorImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedContainerSource test/MyClass
+File name: MyClass.class
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Int|): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.kt
new file mode 100644
index 0000000..c257c7c
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+fun fn() = Unit
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.txt
new file mode 100644
index 0000000..c7fb6e1
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedFacadeContainerSource test/TopLevelFunctionKt
+File name: TopLevelFunctionKt.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.kt
new file mode 100644
index 0000000..5467990
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+@file:JvmName("ChangedFileName")
+
+package test
+
+fun fn() = Unit
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.txt
new file mode 100644
index 0000000..68b7b7d
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedFacadeContainerSource test/ChangedFileName
+File name: ChangedFileName.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.kt
new file mode 100644
index 0000000..9fc2afd
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+val prop: Int = 37
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.txt
new file mode 100644
index 0000000..a325c60
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public val prop: kotlin.Int /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedFacadeContainerSource test/TopLevelPropertyKt
+File name: TopLevelPropertyKt.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/Int|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.kt
new file mode 100644
index 0000000..0a0e6d1
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+@file:JvmName("ChangedFileName")
+
+package test
+
+val prop: Int = 37
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.txt
new file mode 100644
index 0000000..c0ba8ab
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public val prop: kotlin.Int /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: JvmStubDeserializedFacadeContainerSource test/ChangedFileName
+File name: ChangedFileName.class
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/Int|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.kt
new file mode 100644
index 0000000..3153390
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+class MyClass {
+ fun fn() = Unit
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.txt
new file mode 100644
index 0000000..d2856ea
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public final fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.kt
new file mode 100644
index 0000000..1708c30
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+class MyClass {
+ val prop: String = ""
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.txt
new file mode 100644
index 0000000..c5c7318
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public final val prop: kotlin.String /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/String|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.kt
new file mode 100644
index 0000000..ffacda8
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass()
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.txt
new file mode 100644
index 0000000..ac0c648
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtPrimaryConstructor
+KT element text:
+public constructor()
+FIR element: FirPrimaryConstructor
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor(): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.kt
new file mode 100644
index 0000000..76e68b7
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.kt
@@ -0,0 +1,7 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtConstructor
+
+package test
+
+class MyClass {
+ constructor(a: Int)
+}
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.txt
new file mode 100644
index 0000000..54ef104
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.txt
@@ -0,0 +1,10 @@
+KT element: KtSecondaryConstructor
+KT element text:
+public constructor(a: kotlin.Int) { /* compiled code */ }
+FIR element: FirConstructorImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Int|): R|test/MyClass|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.kt
new file mode 100644
index 0000000..c257c7c
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtFunction
+
+package test
+
+fun fn() = Unit
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.txt
new file mode 100644
index 0000000..3c08ec6
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.txt
@@ -0,0 +1,10 @@
+KT element: KtNamedFunction
+KT element text:
+public fun fn(): kotlin.Unit { /* compiled code */ }
+FIR element: FirSimpleFunctionImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] fun fn(): R|kotlin/Unit|
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.kt
new file mode 100644
index 0000000..9fc2afd
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.kt
@@ -0,0 +1,5 @@
+// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtProperty
+
+package test
+
+val prop: Int = 37
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.txt
new file mode 100644
index 0000000..f1b049d
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.txt
@@ -0,0 +1,11 @@
+KT element: KtProperty
+KT element text:
+public val prop: kotlin.Int /* compiled code */
+FIR element: FirPropertyImpl
+FIR source kind: KtRealSourceElementKind
+FIR container source: null
+File name: 0_test.knm
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] val prop: R|kotlin/Int|
+ public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractGetOrBuildFirTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractGetOrBuildFirTest.kt
index 9456f3f..8f9fbd7 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractGetOrBuildFirTest.kt
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractGetOrBuildFirTest.kt
@@ -7,6 +7,8 @@
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
+import org.jetbrains.kotlin.analysis.low.level.api.fir.services.FirRenderingOptions
+import org.jetbrains.kotlin.analysis.low.level.api.fir.services.firRenderingOptions
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirOutOfContentRootTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirScriptTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
@@ -14,11 +16,13 @@
import org.jetbrains.kotlin.analysis.test.framework.projectStructure.KtTestModule
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
import org.jetbrains.kotlin.fir.FirElement
+import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.renderer.*
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
@@ -30,6 +34,7 @@
renderActualFir(
fir = selectedElement.getOrBuildFir(session),
ktElement = selectedElement,
+ renderingOptions = testServices.firRenderingOptions,
firFile = mainFile.getOrBuildFirFile(session),
)
}
@@ -38,18 +43,30 @@
}
}
-fun renderActualFir(
+internal fun renderActualFir(
fir: FirElement?,
ktElement: KtElement,
- renderKtText: Boolean = false,
+ renderingOptions: FirRenderingOptions,
firFile: FirFile? = null,
-): String = """
- |KT element: ${ktElement::class.simpleName}${if (renderKtText) "\nKT element text:\n" + ktElement.text else ""}
- |FIR element: ${fir?.let { it::class.simpleName }}
- |FIR source kind: ${fir?.source?.kind?.let { it::class.simpleName }}
- |
- |FIR element rendered:
- |${render(fir).trimEnd()}${if (firFile != null) "\n\nFIR FILE:\n${render(firFile).trimEnd()}" else ""}""".trimMargin()
+): String = buildString {
+ appendLine("KT element: ${ktElement::class.simpleName}")
+ if (renderingOptions.renderKtText) {
+ appendLine("KT element text:")
+ appendLine(ktElement.text)
+ }
+ appendLine("FIR element: ${fir?.let { it::class.simpleName }}")
+ appendLine("FIR source kind: ${fir?.source?.kind?.let { it::class.simpleName }}")
+ if (renderingOptions.renderContainerSource)
+ appendLine("FIR container source: ${fir.renderContainerSource()}")
+ if (renderingOptions.renderKtFileName)
+ appendLine("File name: ${ktElement.containingKtFile.name}")
+ appendLine("\nFIR element rendered:")
+ appendLine(render(fir).trimEnd())
+ if (firFile != null) {
+ appendLine("\nFIR FILE:")
+ append(render(firFile).trimEnd())
+ }
+}
private fun render(firElement: FirElement?): String = when (firElement) {
null -> "null"
@@ -61,6 +78,9 @@
).renderElementAsString(firElement)
}
+private fun FirElement?.renderContainerSource(): String =
+ (this as? FirCallableDeclaration)?.containerSource?.let { "${it::class.simpleName} ${it.presentableString}" } ?: "null"
+
abstract class AbstractSourceGetOrBuildFirTest : AbstractGetOrBuildFirTest() {
override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
}
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLibraryGetOrBuildFirTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLibraryGetOrBuildFirTest.kt
index a833403..cde95f0 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLibraryGetOrBuildFirTest.kt
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLibraryGetOrBuildFirTest.kt
@@ -6,13 +6,19 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir
import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analysis.low.level.api.fir.services.FirRenderingOptions
+import org.jetbrains.kotlin.analysis.low.level.api.fir.services.firRenderingOptions
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirLibraryBinaryDecompiledTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
import org.jetbrains.kotlin.analysis.test.framework.projectStructure.KtTestModule
import org.jetbrains.kotlin.analysis.test.framework.services.libraries.CompiledLibraryProvider
+import org.jetbrains.kotlin.analysis.test.framework.services.libraries.TestModuleDecompiler
+import org.jetbrains.kotlin.analysis.test.framework.services.libraries.TestModuleDecompilerDirectory
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
+import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.js.JsPlatforms
+import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
@@ -26,13 +32,29 @@
override val configurator get() = AnalysisApiFirLibraryBinaryDecompiledTestConfigurator
override fun configureTest(builder: TestConfigurationBuilder) {
- builder.forTestsMatching("analysis/low-level-api-fir/testData/getOrBuildFirBinary/js/*") {
+ val renderingOptionsBuilder = FirRenderingOptions.Builder().apply { renderKtText = true }
+
+ builder.forTestsMatching("*/js/*") {
this.defaultsProviderBuilder.targetPlatform = JsPlatforms.defaultJsPlatform
}
+ builder.forTestsMatching("*/jvm/*") {
+ this.defaultsProviderBuilder.targetPlatform = JvmPlatforms.defaultJvmPlatform
+ }
+ builder.forTestsMatching("*/metadata/*") {
+ this.defaultsProviderBuilder.targetPlatform = CommonPlatforms.defaultCommonPlatform
+ this.useAdditionalService<TestModuleDecompiler> { TestModuleDecompilerDirectory() }
+ }
+ builder.forTestsMatching("*/containerSource/*") {
+ renderingOptionsBuilder.renderKtFileName = true
+ renderingOptionsBuilder.renderContainerSource = true
+ }
super.configureTest(builder)
with(builder) {
useDirectives(Directives)
- useAdditionalServices(service(::CompiledLibraryProvider))
+ useAdditionalServices(
+ service(::CompiledLibraryProvider),
+ service<FirRenderingOptions> { renderingOptionsBuilder.build() }
+ )
}
}
@@ -44,7 +66,7 @@
val symbolProvider = resolveSession.getSessionFor(ktModule).symbolProvider
val fir = FirDeclarationForCompiledElementSearcher(symbolProvider).findNonLocalDeclaration(declaration)
- testServices.assertions.assertEqualsToTestDataFileSibling(renderActualFir(fir, declaration, true))
+ testServices.assertions.assertEqualsToTestDataFileSibling(renderActualFir(fir, declaration, testServices.firRenderingOptions))
}
private fun getElementToSearch(ktFile: KtFile, moduleStructure: TestModuleStructure): KtDeclaration? {
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractStdLibBasedGetOrBuildFirTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractStdLibBasedGetOrBuildFirTest.kt
index fd2253c..c6f5d49 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractStdLibBasedGetOrBuildFirTest.kt
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractStdLibBasedGetOrBuildFirTest.kt
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
+import org.jetbrains.kotlin.analysis.low.level.api.fir.services.firRenderingOptions
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
import org.jetbrains.kotlin.analysis.test.framework.projectStructure.KtTestModule
@@ -34,6 +35,6 @@
val resolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSession(mainModule.ktModule)
val fir = declaration.resolveToFirSymbol(resolveSession).fir
- testServices.assertions.assertEqualsToTestDataFileSibling(renderActualFir(fir, declaration))
+ testServices.assertions.assertEqualsToTestDataFileSibling(renderActualFir(fir, declaration, testServices.firRenderingOptions))
}
}
\ No newline at end of file
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/LibraryGetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/LibraryGetOrBuildFirTestGenerated.java
index c7179f3..cbeb9c7 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/LibraryGetOrBuildFirTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/LibraryGetOrBuildFirTestGenerated.java
@@ -97,6 +97,166 @@
}
@Nested
+ @TestMetadata("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource")
+ @TestDataPath("$PROJECT_ROOT")
+ public class ContainerSource {
+ @Test
+ public void testAllFilesPresentInContainerSource() {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Nested
+ @TestMetadata("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Js {
+ @Test
+ public void testAllFilesPresentInJs() {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Test
+ @TestMetadata("memberFunction.kt")
+ public void testMemberFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("memberProperty.kt")
+ public void testMemberProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/memberProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("primaryConstructor.kt")
+ public void testPrimaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/primaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("secondaryConstructor.kt")
+ public void testSecondaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/secondaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelFunction.kt")
+ public void testTopLevelFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelProperty.kt")
+ public void testTopLevelProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/js/topLevelProperty.kt");
+ }
+ }
+
+ @Nested
+ @TestMetadata("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Jvm {
+ @Test
+ public void testAllFilesPresentInJvm() {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Test
+ @TestMetadata("memberFunction.kt")
+ public void testMemberFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("memberProperty.kt")
+ public void testMemberProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/memberProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("primaryConstructor.kt")
+ public void testPrimaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/primaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("secondaryConstructor.kt")
+ public void testSecondaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/secondaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelFunction.kt")
+ public void testTopLevelFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelFunctionWithJvmName.kt")
+ public void testTopLevelFunctionWithJvmName() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelFunctionWithJvmName.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelProperty.kt")
+ public void testTopLevelProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelPropertyWithJvmName.kt")
+ public void testTopLevelPropertyWithJvmName() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/jvm/topLevelPropertyWithJvmName.kt");
+ }
+ }
+
+ @Nested
+ @TestMetadata("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata")
+ @TestDataPath("$PROJECT_ROOT")
+ public class Metadata {
+ @Test
+ public void testAllFilesPresentInMetadata() {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Test
+ @TestMetadata("memberFunction.kt")
+ public void testMemberFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("memberProperty.kt")
+ public void testMemberProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/memberProperty.kt");
+ }
+
+ @Test
+ @TestMetadata("primaryConstructor.kt")
+ public void testPrimaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/primaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("secondaryConstructor.kt")
+ public void testSecondaryConstructor() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/secondaryConstructor.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelFunction.kt")
+ public void testTopLevelFunction() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelFunction.kt");
+ }
+
+ @Test
+ @TestMetadata("topLevelProperty.kt")
+ public void testTopLevelProperty() {
+ runTest("analysis/low-level-api-fir/testData/getOrBuildFirBinary/containerSource/metadata/topLevelProperty.kt");
+ }
+ }
+ }
+
+ @Nested
@TestMetadata("analysis/low-level-api-fir/testData/getOrBuildFirBinary/js")
@TestDataPath("$PROJECT_ROOT")
public class Js {
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt
index c6185d8..32f0734 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir
-import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
-import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider
import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibraryModule
import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibrarySourceModule
-import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider
+import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
+import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/FirRenderingOptions.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/FirRenderingOptions.kt
new file mode 100644
index 0000000..d3dbeaa
--- /dev/null
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/FirRenderingOptions.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2024 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.analysis.low.level.api.fir.services
+
+import org.jetbrains.kotlin.test.services.TestService
+import org.jetbrains.kotlin.test.services.TestServices
+
+internal class FirRenderingOptions(
+ val renderKtText: Boolean = false,
+ val renderKtFileName: Boolean = false,
+ val renderContainerSource: Boolean = false,
+) : TestService {
+ companion object {
+ val DEFAULT = FirRenderingOptions()
+ }
+
+ class Builder {
+ var renderKtText: Boolean = false
+ var renderKtFileName: Boolean = false
+ var renderContainerSource: Boolean = false
+
+ fun build(): FirRenderingOptions = FirRenderingOptions(
+ renderKtText,
+ renderKtFileName,
+ renderContainerSource,
+ )
+ }
+}
+
+internal val TestServices.firRenderingOptionsIfRegistered: FirRenderingOptions? by TestServices.nullableTestServiceAccessor()
+internal val TestServices.firRenderingOptions: FirRenderingOptions
+ get() = firRenderingOptionsIfRegistered ?: FirRenderingOptions.DEFAULT