[Analysis API] Minor, prettify code on KT-71083
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KaFirCompilerFacility.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KaFirCompilerFacility.kt index 88602d8..dfbbc24 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KaFirCompilerFacility.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KaFirCompilerFacility.kt
@@ -155,9 +155,9 @@ // Since the order of dependency files matters, we have to use "List" here. Otherwise, we will meet a case // that it has a missing "inline function" when filling inline functions as a part of the JVM bytecode-gen. val dependencyFiles = buildList { - addAll(compilationPeerData.filesInPostOrder) + addAll(compilationPeerData.filesToCompile) - val filesAsSet = compilationPeerData.filesInPostOrder.toHashSet() + val filesAsSet = compilationPeerData.filesToCompile.toHashSet() codeFragmentMappings?.capturedFiles?.forEach { if (it !in filesAsSet) add(it) } // The main file needs to be the last so caches for the context declarations are populated in FIR-to-IR. @@ -178,22 +178,32 @@ val irGeneratorExtensions = IrGenerationExtension.getInstances(project) - val inlineFuncDependencyByteArray = mutableMapOf<String, ByteArray>() - dependencyFiles.forEach { dependencyFile -> + val inlineFunDependencyBytecode = mutableMapOf<String, ByteArray>() + + for (dependencyFile in dependencyFiles) { var compileResult: KaCompilationResult? = null runFir2IrForDependency( listOf(dependencyFile), configuration, jvmIrDeserializer, diagnosticReporter, irGeneratorExtensions ) { fir2IrResult, ktFiles, dependencyConfiguration -> - val codegenFactory = - createJvmIrCodegenFactory(dependencyConfiguration, dependencyFile is KtCodeFragment, fir2IrResult.irModuleFragment) - val filter = SingleFileGenerateClassFilter(dependencyFile, compilationPeerData.inlinedClasses) - val jvmGeneratorExtensions = JvmFir2IrExtensions(dependencyConfiguration, jvmIrDeserializer) + val codegenFactory = createJvmIrCodegenFactory( + configuration = dependencyConfiguration, + isCodeFragment = dependencyFile is KtCodeFragment, + irModuleFragment = fir2IrResult.irModuleFragment + ) + compileResult = runJvmIrCodeGen( - fir2IrResult, dependencyConfiguration, target, ktFiles, null, codegenFactory, filter, diagnosticReporter, - jvmGeneratorExtensions, - allowedErrorFilter, + fir2IrResult = fir2IrResult, + configuration = dependencyConfiguration, + target = target, + targetFiles = ktFiles, + codeFragmentMappings = null, + codegenFactory = codegenFactory, + generateClassFilter = SingleFileGenerateClassFilter(dependencyFile, compilationPeerData.inlinedClasses), + diagnosticReporter = diagnosticReporter, + jvmGeneratorExtensions = JvmFir2IrExtensions(dependencyConfiguration, jvmIrDeserializer), + allowedErrorFilter = allowedErrorFilter, ) { generationState -> - inlineFuncDependencyByteArray.forEach { (className, compileResult) -> + inlineFunDependencyBytecode.forEach { (className, compileResult) -> generationState.inlineCache.classBytes.put(className, compileResult) } } @@ -201,21 +211,21 @@ when (compileResult) { is KaCompilationResult.Success -> { val artifact = compileResult as KaCompilationResult.Success - artifact.output.forEach { compiledFile -> + for (compiledFile in artifact.output) { val path = compiledFile.path // `GenerationState.inlineCache` uses the path to class file without ".class" as a key. For example, // - The key for `Foo` class in `com.example.foo` package is `com/example/foo/Foo`. // - The key for companion object of `Foo` in `com.example.foo` package is `com/example/foo/Foo$Companion`. // - The key for an inner class `Inner` of `Foo` in `com.example.foo` package is `com/example/foo/Foo$Inner`. - if (!path.endsWith(".class")) return@forEach + if (!path.endsWith(".class")) continue val className = path.substringBeforeLast(".class") - inlineFuncDependencyByteArray[className] = compiledFile.content + inlineFunDependencyBytecode[className] = compiledFile.content } } is KaCompilationResult.Failure -> return compileResult!! - null -> return@forEach + null -> continue } } @@ -264,7 +274,7 @@ jvmGeneratorExtensions, allowedErrorFilter, ) { generationState -> - inlineFuncDependencyByteArray.forEach { (className, compileResult) -> + inlineFunDependencyBytecode.forEach { (className, compileResult) -> generationState.inlineCache.classBytes.put(className, compileResult) } } @@ -359,8 +369,10 @@ irGeneratorExtensions: List<IrGenerationExtension>, handleFir2IrResult: ((Fir2IrActualizedResult, List<KtFile>, CompilerConfiguration) -> Unit)? = null, ) { - dependencyFiles.map { Pair(it, getFullyResolvedFirFile(it)) }.groupBy { it.second.llFirSession } - .map { (dependencySession, dependencyFiles) -> + dependencyFiles + .map { Pair(it, getFullyResolvedFirFile(it)) } + .groupBy { it.second.llFirSession } + .forEach { (dependencySession, dependencyFileMapping) -> val dependencyConfiguration = configuration.copy().apply { put(CommonConfigurationKeys.USE_FIR, true) put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, dependencySession.languageVersionSettings) @@ -369,13 +381,16 @@ val dependencyFir2IrExtensions = JvmFir2IrExtensions(dependencyConfiguration, jvmIrDeserializer) val fir2IrResult = runFir2Ir( dependencySession, - dependencyFiles.map { it.second }, + dependencyFileMapping.map { it.second }, dependencyFir2IrExtensions, diagnosticReporter, dependencyConfiguration, irGeneratorExtensions ) - handleFir2IrResult?.let { it(fir2IrResult, dependencyFiles.map { it.first }, dependencyConfiguration) } + + if (handleFir2IrResult != null) { + handleFir2IrResult(fir2IrResult, dependencyFileMapping.map { it.first }, dependencyConfiguration) + } } }
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CompilationPeerCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CompilationPeerCollector.kt index fd4d7c6..4cd3e4c 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CompilationPeerCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CompilationPeerCollector.kt
@@ -61,14 +61,14 @@ * - A is main source module. A has dependency on source module libraries B and C. * - B contains an inline function. B has dependency on a source module library C. * - C contains an inline function. - * - [filesInPostOrder] returned by [CompilationPeerCollector.process] will be {C, B, A}. + * - [filesToCompile] returned by [CompilationPeerCollector.process] will be {C, B, A}. * - * More formally, i-th element of [filesInPostOrder] will not have inline-dependency on any j-th element of - * [filesInPostOrder], where j > i. + * More formally, i-th element of [filesToCompile] will not have inline-dependency on any j-th element of + * [filesToCompile], where j > i. * * This list does not contain duplicated files. */ - val filesInPostOrder: List<KtFile>, + val filesToCompile: List<KtFile>, /** Local classes inlined as a part of inline functions. */ val inlinedClasses: Set<KtClassOrObject> @@ -97,11 +97,20 @@ if (containingKtFile.isCompiled || containingKtFile in collectedFiles) return if (!processed.add(declaration)) { - throw CyclicInlineDependencyException("Inline functions have a cyclic dependency:\n${ - processed.map { fir -> - "${fir.getContainingFile()?.let { "${it.packageFqName}/${it.name}" } ?: "(no containing file)"}:\n${fir.render()}" + val exceptionMessage = buildString { + appendLine("Inline functions have a cyclic dependency:") + for (problematicFir in processed) { + val problematicFirFile = problematicFir.getContainingFile() + if (problematicFirFile != null) { + appendLine(problematicFirFile.packageFqName.asString()).append('/').append(problematicFirFile.name) + } else { + appendLine("(No containing file)") + } + appendLine(problematicFir.render()) } - }") + } + + throw CyclicInlineDependencyException(exceptionMessage) } val inlineFunctionsUsedByDeclaration = mutableSetOf<FirDeclaration>()
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCompilationPeerAnalysisTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCompilationPeerAnalysisTest.kt index 3262131..1964dd3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCompilationPeerAnalysisTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCompilationPeerAnalysisTest.kt
@@ -26,7 +26,7 @@ val compilationPeerData = CompilationPeerCollector.process(firFile) - val actualItems = compilationPeerData.filesInPostOrder.map { "File " + it.name }.sorted() + + val actualItems = compilationPeerData.filesToCompile.map { "File " + it.name }.sorted() + compilationPeerData.inlinedClasses.map { "Class " + it.name } val actualText = actualItems.joinToString(separator = "\n")