From 233b9f12429977c4e408dff9bab2bd7bf54b6f92 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 1 Oct 2021 15:11:06 +0300 Subject: [PATCH] [FIR] Generate IR for generated FIR declarations --- .../kotlin/fir/backend/ConversionUtils.kt | 29 ++++++++ .../kotlin/fir/backend/Fir2IrConverter.kt | 74 ++++++++++++++++--- .../generators/ClassMemberGenerator.kt | 17 ++++- .../extensions/generatedDeclarationsUtils.kt | 48 ++++++++++++ .../handlers/IrPrettyKotlinDumpHandler.kt | 4 +- .../backend/handlers/IrTextDumpHandler.kt | 12 ++- .../backend/handlers/IrTreeVerifierHandler.kt | 3 +- .../frontend/fir/handlers/FirDumpHandler.kt | 50 ++----------- .../fir/plugin/generators/generationUtils.kt | 6 ++ ...hGeneratedMembersAndNestedClass.fir.ir.txt | 22 +++++- ...WithGeneratedMembersAndNestedClass.fir.txt | 2 + ...lassWithMembersAndNestedClasses.fir.ir.txt | 56 +++++++++++++- ...edClassWithMembersAndNestedClasses.fir.txt | 8 +- .../memberGen/topLevelCallables.fir.ir.txt | 3 + .../memberGen/topLevelCallables.fir.txt | 2 +- 15 files changed, 265 insertions(+), 71 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/generatedDeclarationsUtils.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index a5b5e74d4c9..27aafd5b71d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -13,7 +13,9 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator +import org.jetbrains.kotlin.fir.builder.buildPackageDirective import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.builder.buildFile import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isJava @@ -21,6 +23,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess +import org.jetbrains.kotlin.fir.extensions.declarationGenerators +import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference @@ -569,3 +573,28 @@ fun FirRegularClass.getIrSymbolsForSealedSubclasses(components: Fir2IrComponents symbolProvider.getClassLikeSymbolByClassId(it)?.toSymbol(session, components.classifierStorage) }.filterIsInstance() } + +fun FirSession.createFilesWithGeneratedDeclarations(): List { + val symbolProvider = symbolProvider + val declarationGenerators = extensionService.declarationGenerators + val topLevelClasses = declarationGenerators.flatMap { it.getTopLevelClassIds() }.groupBy { it.packageFqName } + val topLevelCallables = declarationGenerators.flatMap { it.getTopLevelCallableIds() }.groupBy { it.packageName } + + return buildList { + for (packageFqName in (topLevelClasses.keys + topLevelCallables.keys)) { + this += buildFile { + origin = FirDeclarationOrigin.Synthetic + moduleData = this@createFilesWithGeneratedDeclarations.moduleData + packageDirective = buildPackageDirective { + this.packageFqName = packageFqName + } + name = "__GENERATED DECLARATIONS__.kt" + declarations += topLevelCallables.getOrDefault(packageFqName, emptyList()) + .flatMap { symbolProvider.getTopLevelCallableSymbols(packageFqName, it.callableName) } + .map { it.fir } + declarations += topLevelClasses.getOrDefault(packageFqName, emptyList()) + .mapNotNull { symbolProvider.getClassLikeSymbolByClassId(it)?.fir } + } + } + } +} 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 e78e9ba9274..279e69c1ee1 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 @@ -15,13 +15,16 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor +import org.jetbrains.kotlin.fir.extensions.declarationGenerators +import org.jetbrains.kotlin.fir.extensions.extensionService +import org.jetbrains.kotlin.fir.extensions.generatedMembers +import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers import org.jetbrains.kotlin.fir.packageFqName import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.fir.signaturer.FirMangler -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -import org.jetbrains.kotlin.ir.PsiIrFileEntry +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl @@ -40,6 +43,8 @@ class Fir2IrConverter( private val components: Fir2IrComponents ) : Fir2IrComponents by components { + private val generatorExtensions = session.extensionService.declarationGenerators + fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent) { val irClass = registerClassAndNestedClasses(regularClass, parent) processClassAndNestedClassHeaders(regularClass) @@ -57,8 +62,30 @@ class Fir2IrConverter( } fun registerFileAndClasses(file: FirFile, moduleFragment: IrModuleFragment) { + val fileEntry = when (file.origin) { + FirDeclarationOrigin.Source -> PsiIrFileEntry(file.psi as KtFile) + FirDeclarationOrigin.Synthetic -> object : IrFileEntry { + override val name = file.name + override val maxOffset = UNDEFINED_OFFSET + + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo = + SourceRangeInfo( + "", + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET + ) + + override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET + override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET + } + else -> error("Unsupported file origin: ${file.origin}") + } val irFile = IrFileImpl( - PsiIrFileEntry(file.psi as KtFile), + fileEntry, moduleDescriptor.getPackage(file.packageFqName).fragments.first(), moduleFragment ) @@ -130,14 +157,20 @@ class Fir2IrConverter( regularClass: FirRegularClass, irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!! ): IrClass { - val irConstructor = regularClass.primaryConstructor?.let { - declarationStorage.getOrCreateIrConstructor(it, irClass, isLocal = regularClass.isLocal) + val allDeclarations = mutableListOf().apply { + addAll(regularClass.declarations.toMutableList()) + if (generatorExtensions.isNotEmpty()) { + addAll(regularClass.generatedMembers(session)) + addAll(regularClass.generatedNestedClassifiers(session)) + } + } + val irConstructor = (allDeclarations.firstOrNull { it is FirConstructor && it.isPrimary })?.let { + declarationStorage.getOrCreateIrConstructor(it as FirConstructor, irClass, isLocal = regularClass.isLocal) } if (irConstructor != null) { irClass.declarations += irConstructor } - val allDeclarations = regularClass.declarations.toMutableList() - for (declaration in syntheticPropertiesLast(regularClass.declarations)) { + for (declaration in syntheticPropertiesLast(allDeclarations)) { val irDeclaration = processMemberDeclaration(declaration, regularClass, irClass) ?: continue irClass.declarations += irDeclaration } @@ -186,6 +219,13 @@ class Fir2IrConverter( registerClassAndNestedClasses(it, irClass) } } + if (generatorExtensions.isNotEmpty()) { + regularClass.generatedNestedClassifiers(session).forEach { + if (it is FirRegularClass) { + registerClassAndNestedClasses(it, irClass) + } + } + } return irClass } @@ -196,6 +236,13 @@ class Fir2IrConverter( processClassAndNestedClassHeaders(it) } } + if (generatorExtensions.isNotEmpty()) { + regularClass.generatedNestedClassifiers(session).forEach { + if (it is FirRegularClass) { + processClassAndNestedClassHeaders(it) + } + } + } } private fun processMemberDeclaration( @@ -294,7 +341,12 @@ class Fir2IrConverter( components.callGenerator = callGenerator val irModuleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns) - for (firFile in firFiles) { + + val allFirFiles = buildList { + addAll(firFiles) + addAll(session.createFilesWithGeneratedDeclarations()) + } + for (firFile in allFirFiles) { converter.registerFileAndClasses(firFile, irModuleFragment) } val irProviders = @@ -306,14 +358,14 @@ class Fir2IrConverter( // Necessary call to generate built-in IR classes externalDependenciesGenerator.generateUnboundSymbolsAsDependencies() classifierStorage.preCacheBuiltinClasses() - for (firFile in firFiles) { + for (firFile in allFirFiles) { converter.processClassHeaders(firFile) } - for (firFile in firFiles) { + for (firFile in allFirFiles) { converter.processFileAndClassMembers(firFile) } - for (firFile in firFiles) { + for (firFile in allFirFiles) { firFile.accept(fir2irVisitor, null) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index b163890b51b..d167c209d90 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -12,12 +12,15 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isFromEnumClass -import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression +import org.jetbrains.kotlin.fir.extensions.declarationGenerators +import org.jetbrains.kotlin.fir.extensions.extensionService +import org.jetbrains.kotlin.fir.extensions.generatedMembers +import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -48,7 +51,15 @@ internal class ClassMemberGenerator( fun convertClassContent(irClass: IrClass, klass: FirClass) { declarationStorage.enterScope(irClass) conversionScope.withClass(irClass) { - val primaryConstructor = klass.primaryConstructor + val allDeclarations = buildList { + addAll(klass.declarations) + if (session.extensionService.declarationGenerators.isNotEmpty()) { + addAll(klass.generatedMembers(session)) + addAll(klass.generatedNestedClassifiers(session)) + } + } + + val primaryConstructor = allDeclarations.firstOrNull { it is FirConstructor && it.isPrimary } as FirConstructor? val irPrimaryConstructor = primaryConstructor?.let { declarationStorage.getCachedIrConstructor(it)!! } if (irPrimaryConstructor != null) { with(declarationStorage) { @@ -60,7 +71,7 @@ internal class ClassMemberGenerator( fakeOverrideGenerator.bindOverriddenSymbols(irClass.declarations) components.delegatedMemberGenerator.bindDelegatedMembersOverriddenSymbols(irClass) - klass.declarations.forEach { declaration -> + allDeclarations.forEach { declaration -> when { declaration is FirTypeAlias -> { } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/generatedDeclarationsUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/generatedDeclarationsUtils.kt new file mode 100644 index 00000000000..9dacd84a47e --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/generatedDeclarationsUtils.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.extensions + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope +import org.jetbrains.kotlin.fir.scopes.processClassifiersByName + +fun FirClass.generatedNestedClassifiers(session: FirSession): List { + val scope = session.declaredMemberScope(this) + val result = mutableListOf() + for (name in scope.getClassifierNames()) { + scope.processClassifiersByName(name) { + if (it.fir.origin.generated) { + result += it.fir + } + } + } + return result +} + +fun FirClass.generatedMembers(session: FirSession): List { + val scope = session.declaredMemberScope(this) + val result = mutableListOf() + for (name in scope.getCallableNames()) { + scope.processFunctionsByName(name) { + if (it.fir.origin.generated) { + result += it.fir + } + } + scope.processPropertiesByName(name) { + if (it.fir.origin.generated) { + result += it.fir + } + } + } + scope.processDeclaredConstructors { + if (it.fir.origin.generated) { + result += it.fir + } + } + return result +} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt index 392d13f8b72..408238f12a0 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrPrettyKotlinDumpHandler.kt @@ -38,8 +38,8 @@ class IrPrettyKotlinDumpHandler(testServices: TestServices) : AbstractIrHandler( val irFiles = info.backendInput.irModuleFragment.files val builder = dumper.builderForModule(module) - val filteredIrFiles = irFiles.groupWithTestFiles(module).filter { - EXTERNAL_FILE !in it.first.directives + val filteredIrFiles = irFiles.groupWithTestFiles(module).filterNot { + it.first?.directives?.contains(EXTERNAL_FILE) == true }.map { it.second } val printFileName = filteredIrFiles.size > 1 || testServices.moduleStructure.modules.size > 1 for (irFile in filteredIrFiles) { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt index 96b0aa34404..6ceb4527542 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTextDumpHandler.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.backend.handlers import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFile @@ -46,9 +47,9 @@ class IrTextDumpHandler(testServices: TestServices) : AbstractIrHandler(testServ defaultExtension else "fir.$defaultExtension" } - fun List.groupWithTestFiles(module: TestModule): List> = mapNotNull { irFile -> + fun List.groupWithTestFiles(module: TestModule): List> = mapNotNull { irFile -> val name = irFile.fileEntry.name.removePrefix("/") - val testFile = module.files.firstOrNull { it.name == name } ?: return@mapNotNull null + val testFile = module.files.firstOrNull { it.name == name } testFile to irFile } } @@ -66,8 +67,11 @@ class IrTextDumpHandler(testServices: TestServices) : AbstractIrHandler(testServ val testFileToIrFile = irFiles.groupWithTestFiles(module) val builder = baseDumper.builderForModule(module) for ((testFile, irFile) in testFileToIrFile) { - if (EXTERNAL_FILE in testFile.directives) continue - val actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue + var actualDump = irFile.dumpTreesFromLineNumber(lineNumber = 0, normalizeNames = true) + if (actualDump.isEmpty()) { + actualDump = irFile.dumpTreesFromLineNumber(lineNumber = UNDEFINED_OFFSET, normalizeNames = true) + } builder.append(actualDump) } compareDumpsOfExternalClasses(module, info) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt index fb8225b0bb7..acff06595ce 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrTreeVerifierHandler.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.util.dumpTreesFromLineNumber import org.jetbrains.kotlin.test.backend.handlers.IrTextDumpHandler.Companion.groupWithTestFiles import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.directives.CodegenTestDirectives +import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.EXTERNAL_FILE import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestServices @@ -24,7 +25,7 @@ class IrTreeVerifierHandler(testServices: TestServices) : AbstractIrHandler(test val irFiles = info.backendInput.irModuleFragment.files val testFileToIrFile = irFiles.groupWithTestFiles(module) for ((testFile, irFile) in testFileToIrFile) { - if (CodegenTestDirectives.EXTERNAL_FILE in testFile.directives) continue + if (testFile?.directives?.contains(EXTERNAL_FILE) == true) continue IrVerifier(assertions).verifyWithAssert(irFile) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt index caffadf8b15..ff277150f50 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt @@ -7,12 +7,15 @@ package org.jetbrains.kotlin.test.frontend.fir.handlers import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.createFilesWithGeneratedDeclarations import org.jetbrains.kotlin.fir.builder.buildPackageDirective import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.builder.buildFile import org.jetbrains.kotlin.fir.extensions.declarationGenerators import org.jetbrains.kotlin.fir.extensions.extensionService +import org.jetbrains.kotlin.fir.extensions.generatedMembers +import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope @@ -42,28 +45,9 @@ class FirDumpHandler( val builderForModule = dumper.builderForModule(module) val firFiles = info.firFiles - val symbolProvider = info.session.symbolProvider - val declarationGenerators = info.session.extensionService.declarationGenerators - val topLevelClasses = declarationGenerators.flatMap { it.getTopLevelClassIds() }.groupBy { it.packageFqName } - val topLevelCallables = declarationGenerators.flatMap { it.getTopLevelCallableIds() }.groupBy { it.packageName } - val allFiles = buildList { addAll(firFiles.values) - for (packageFqName in (topLevelClasses.keys + topLevelCallables.keys)) { - this += buildFile { - origin = FirDeclarationOrigin.Synthetic - moduleData = info.session.moduleData - packageDirective = buildPackageDirective { - this.packageFqName = packageFqName - } - name = "### GENERATED DECLARATIONS ###" - declarations += topLevelCallables.getOrDefault(packageFqName, emptyList()) - .flatMap { symbolProvider.getTopLevelCallableSymbols(packageFqName, it.callableName) } - .map { it.fir } - declarations += topLevelClasses.getOrDefault(packageFqName, emptyList()) - .mapNotNull { symbolProvider.getClassLikeSymbolByClassId(it)?.fir } - } - } + addAll(info.session.createFilesWithGeneratedDeclarations()) } val renderer = FirRendererWithGeneratedDeclarations(info.session, builderForModule) @@ -92,30 +76,8 @@ class FirDumpHandler( override fun renderClassDeclarations(regularClass: FirRegularClass) { val allDeclarations = buildList { addAll(regularClass.declarations) - - @OptIn(SymbolInternals::class) - fun addGeneratedDeclaration(symbol: FirBasedSymbol<*>) { - val declaration = symbol.fir - if (declaration.origin.generated) { - add(declaration) - } - } - - val scope = session.declaredMemberScope(regularClass) - for (callableName in scope.getCallableNames()) { - scope.processFunctionsByName(callableName) { - addGeneratedDeclaration(it) - } - scope.processPropertiesByName(callableName) { - addGeneratedDeclaration(it) - } - } - - for (classifierName in scope.getClassifierNames()) { - scope.processClassifiersByName(classifierName) { - addGeneratedDeclaration(it) - } - } + addAll(regularClass.generatedMembers(session)) + addAll(regularClass.generatedNestedClassifiers(session)) } allDeclarations.renderDeclarations() } diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/generationUtils.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/generationUtils.kt index c6638023c75..d77cdd772e4 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/generationUtils.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/generationUtils.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.containingClassForStaticMemberAttr import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.buildPrimaryConstructor @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.ClassId +@OptIn(SymbolInternals::class) fun FirDeclarationGenerationExtension.buildMaterializeFunction( matchedClassSymbol: FirClassLikeSymbol<*>, callableId: CallableId @@ -50,6 +52,10 @@ fun FirDeclarationGenerationExtension.buildMaterializeFunction( } name = callableId.callableName symbol = FirNamedFunctionSymbol(callableId) + dispatchReceiverType = callableId.classId?.let { + val firClass = session.symbolProvider.getClassLikeSymbolByClassId(it)?.fir as? FirClass + firClass?.defaultType() + } } } diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.ir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.ir.txt index a728526ca76..d1f18d9b274 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.ir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.ir.txt @@ -26,7 +26,24 @@ FILE fqName: fileName:/classWithGeneratedMembersAndNestedClass.kt overridden: public open fun toString (): kotlin.String declared in kotlin.Any $this: VALUE_PARAMETER name: type:kotlin.Any - FUN FAKE_OVERRIDE name:materialize visibility:public modality:FINAL <> () returnType:.Foo [fake_override] + FUN name:materialize visibility:public modality:FINAL <> ($this:.Foo) returnType:.Foo + $this: VALUE_PARAMETER name: type:.Foo + CLASS CLASS name:Nested modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Foo.Nested + CONSTRUCTOR visibility:public <> () returnType:.Foo.Nested [primary] + 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: 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: 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: type: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 @@ -63,6 +80,7 @@ FILE fqName: fileName:/classWithGeneratedMembersAndNestedClass.kt VALUE_PARAMETER name:foo index:0 type:.Foo BLOCK_BODY VAR name:foo2 type:.Foo [val] - CALL 'public final fun materialize (): .Foo declared in ' type=.Foo origin=null + CALL 'public final fun materialize (): .Foo declared in .Foo' type=.Foo origin=null + $this: GET_VAR 'foo: .Foo declared in .test_1' type=.Foo origin=null VAR name:nested type:.Foo.Nested [val] CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Foo.Nested' type=.Foo.Nested origin=null diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.txt index cbf88da1cfc..37d9d790e5a 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/classWithGeneratedMembersAndNestedClass.fir.txt @@ -14,6 +14,8 @@ FILE: classWithGeneratedMembersAndNestedClass.kt public final fun materialize(): R|Foo| public final class Nested : R|kotlin/Any| { + public constructor(): R|Foo.Nested| + } } diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.ir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.ir.txt index 339e2cd6c92..350d90ebd92 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.ir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.ir.txt @@ -56,8 +56,60 @@ FILE fqName:bar fileName:/generatedClassWithMembersAndNestedClasses.kt VAR name:nestedFoo type:foo.AllOpenGenerated.NestedFoo [val] CONSTRUCTOR_CALL 'public constructor () [primary] declared in foo.AllOpenGenerated.NestedFoo' type=foo.AllOpenGenerated.NestedFoo origin=null CALL 'public final fun foo (): kotlin.Unit declared in bar.Foo' type=kotlin.Unit origin=null - $this: CALL 'public final fun materialize (): bar.Foo declared in foo' type=bar.Foo origin=null + $this: CALL 'public final fun materialize (): bar.Foo declared in foo.AllOpenGenerated.NestedFoo' type=bar.Foo origin=null + $this: GET_VAR 'val nestedFoo: foo.AllOpenGenerated.NestedFoo [val] declared in bar.testNestedClasses' type=foo.AllOpenGenerated.NestedFoo origin=null VAR name:nestedBar type:foo.AllOpenGenerated.NestedBar [val] CONSTRUCTOR_CALL 'public constructor () [primary] declared in foo.AllOpenGenerated.NestedBar' type=foo.AllOpenGenerated.NestedBar origin=null CALL 'public final fun bar (): kotlin.Unit declared in bar.Bar' type=kotlin.Unit origin=null - $this: CALL 'public final fun materialize (): bar.Foo declared in foo' type=bar.Bar origin=null + $this: CALL 'public final fun materialize (): bar.Bar declared in foo.AllOpenGenerated.NestedBar' type=bar.Bar origin=null + $this: GET_VAR 'val nestedBar: foo.AllOpenGenerated.NestedBar [val] declared in bar.testNestedClasses' type=foo.AllOpenGenerated.NestedBar origin=null +FILE fqName:foo fileName:__GENERATED DECLARATIONS__.kt + CLASS CLASS name:AllOpenGenerated modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.AllOpenGenerated + CLASS CLASS name:NestedFoo modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.AllOpenGenerated.NestedFoo + FUN name:materialize visibility:public modality:FINAL <> ($this:foo.AllOpenGenerated.NestedFoo) returnType:bar.Foo + $this: VALUE_PARAMETER name: type:foo.AllOpenGenerated.NestedFoo + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:NestedBar modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:foo.AllOpenGenerated.NestedBar + FUN name:materialize visibility:public modality:FINAL <> ($this:foo.AllOpenGenerated.NestedBar) returnType:bar.Bar + $this: VALUE_PARAMETER name: type:foo.AllOpenGenerated.NestedBar + 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: 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: 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: type: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: 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: 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: type:kotlin.Any diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.txt index 39cda0f2c06..4c1dca0ee5a 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/generatedClassWithMembersAndNestedClasses.fir.txt @@ -28,18 +28,24 @@ FILE: generatedClassWithMembersAndNestedClasses.kt lval nestedBar: R|foo/AllOpenGenerated.NestedBar| = Q|foo/AllOpenGenerated|.R|foo/AllOpenGenerated.NestedBar|() R|/nestedBar|.R|foo/AllOpenGenerated.NestedBar.materialize|().R|bar/Bar.bar|() } -FILE: ### GENERATED DECLARATIONS ### +FILE: __GENERATED DECLARATIONS__.kt package foo public final class AllOpenGenerated : R|kotlin/Any| { + public constructor(): R|foo/AllOpenGenerated| + public final class NestedFoo : R|kotlin/Any| { public final fun materialize(): R|bar/Foo| + public constructor(): R|foo/AllOpenGenerated.NestedFoo| + } public final class NestedBar : R|kotlin/Any| { public final fun materialize(): R|bar/Bar| + public constructor(): R|foo/AllOpenGenerated.NestedBar| + } } diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.ir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.ir.txt index 0e16cf0ff85..8ece258c6a1 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.ir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.ir.txt @@ -31,3 +31,6 @@ FILE fqName:foo fileName:/topLevelCallables.kt FUN name:takeString visibility:public modality:FINAL <> (s:kotlin.String) returnType:kotlin.Unit VALUE_PARAMETER name:s index:0 type:kotlin.String BLOCK_BODY +FILE fqName:foo fileName:__GENERATED DECLARATIONS__.kt + FUN name:dummyMySuperClass visibility:public modality:FINAL <> (value:foo.MySuperClass) returnType:kotlin.String + VALUE_PARAMETER name:value index:0 type:foo.MySuperClass diff --git a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.txt b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.txt index b3cddfe51ba..e4cc92bf4ec 100644 --- a/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/fir2ir/memberGen/topLevelCallables.fir.txt @@ -14,7 +14,7 @@ FILE: topLevelCallables.kt } public final fun takeString(s: R|kotlin/String|): R|kotlin/Unit| { } -FILE: ### GENERATED DECLARATIONS ### +FILE: __GENERATED DECLARATIONS__.kt package foo public final fun dummyMySuperClass(value: R|foo/MySuperClass|): R|kotlin/String|