[FIR] Include generated declarations into FIR dump in tests

Also include non root package directive of FirFile to dump
This commit is contained in:
Dmitriy Novozhilov
2021-10-01 11:15:42 +03:00
committed by TeamCityServer
parent ea93d23dca
commit c60ba51f8f
33 changed files with 189 additions and 5 deletions
@@ -1,4 +1,6 @@
FILE: NestedSuperType.kt
package p
public abstract class My : R|kotlin/Any| {
public constructor(): R|p/My| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: TwoDeclarationsInSameFile.kt
package p
public open class A : R|kotlin/Any| {
public constructor(): R|p/A| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: A.kt
package foo
public final class A : R|kotlin/Any| {
public constructor(): R|foo/A| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: companion.kt
package test
public abstract class Some : R|kotlin/Any| {
public constructor(): R|test/Some| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: LinkedList.kt
package foo
public final class LinkedList<T> : R|java/util/LinkedList<T>| {
public constructor<T>(): R|foo/LinkedList<T>| {
super<R|java/util/LinkedList<T>|>()
@@ -6,6 +8,8 @@ FILE: LinkedList.kt
}
FILE: HashSet.kt
package util
public final class HashSet<T> : R|java/util/HashSet<T>| {
public constructor<T>(): R|util/HashSet<T>| {
super<R|java/util/HashSet<T>|>()
@@ -13,6 +17,8 @@ FILE: HashSet.kt
}
FILE: main.kt
package foo
public final class LinkedHashMap<K, V> : R|java/util/LinkedHashMap<K, V>| {
public constructor<K, V>(): R|foo/LinkedHashMap<K, V>| {
super<R|java/util/LinkedHashMap<K, V>|>()
@@ -1,4 +1,6 @@
FILE: multipleBounds.kt
package Jet87
public open class A : R|kotlin/Any| {
public constructor(): R|Jet87/A| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: KotlinImporterComponent.kt
package simulation
@R|simulation/State|(name = String(AutoImportedSourceRoots)) public final class KotlinImporterComponent : R|kotlin/Any| {
public constructor(): R|simulation/KotlinImporterComponent| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: typeArgumentsNotAllowed.kt
package rest
public abstract class Foo<T> : R|kotlin/Any| {
public constructor<T>(): R|rest/Foo<T>| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: CallBasedInExpressionGenerator.kt
package org.jetbrains.kotlin.codegen.range.inExpression
public abstract interface ExpressionCodegen : R|kotlin/Any| {
}
public abstract interface KtSimpleNameExpression : R|kotlin/Any| {
@@ -1,4 +1,6 @@
FILE: qualifiedExpressions.kt
package a.b
public final class C : R|kotlin/Any| {
public constructor(): R|a/b/C| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: complexTypes.kt
package a.b
public final class C<T, out S> : R|kotlin/Any| {
public constructor<T, out S>(): R|a/b/C<T, S>| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: annotations.kt
package annotations
@R|kotlin/annotation/Target|(allowedTargets = vararg(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FILE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FUNCTION|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.TYPE|, Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY_GETTER|)) public final annotation class Simple : R|kotlin/Annotation| {
public constructor(): R|annotations/Simple| {
super<R|kotlin/Any|>()
@@ -58,6 +60,8 @@ FILE: annotations.kt
}
FILE: main.kt
@FILE:R|annotations/Simple|()
package test
@R|annotations/WithInt|(value = Int(42)) public abstract class First : R|kotlin/Any| {
public constructor(): R|test/First| {
super<R|kotlin/Any|>()
@@ -1,10 +1,14 @@
FILE: byteArray.kt
package Test
public abstract interface ByteArray : R|kotlin/Any| {
public abstract val array: R|Test/ByteArray|
public get(): R|Test/ByteArray|
}
FILE: main.kt
package use
public abstract interface My : R|kotlin/Any| {
public abstract val array: R|kotlin/ByteArray|
public get(): R|kotlin/ByteArray|
@@ -1,4 +1,6 @@
FILE: C.kt
package c
public open class C : R|kotlin/Any| {
public constructor(): R|c/C| {
super<R|kotlin/Any|>()
@@ -13,6 +15,8 @@ FILE: C.kt
}
FILE: B.kt
package b
public open class B : R|c/C| {
public constructor(): R|b/B| {
super<R|c/C|>()
@@ -27,6 +31,8 @@ FILE: B.kt
}
FILE: A.kt
package a
public final class A : R|b/B| {
public constructor(): R|a/A| {
super<R|b/B|>()
@@ -1,4 +1,6 @@
FILE: B.kt
package b
public final class A : R|kotlin/Any| {
public constructor(): R|b/A| {
super<R|kotlin/Any|>()
@@ -7,6 +9,8 @@ FILE: B.kt
}
public final typealias TA = R|b/A|
FILE: A.kt
package a
public final class MyClass : R|b/TA| {
public constructor(): R|a/MyClass| {
super<R|b/TA|>()
@@ -1,4 +1,6 @@
FILE: a.kt
package a
public final object A : R|kotlin/Any| {
private constructor(): R|a/A| {
super<R|kotlin/Any|>()
@@ -9,6 +11,8 @@ FILE: a.kt
}
FILE: b.kt
package b
public final fun bar(): R|kotlin/Unit| {
Q|a/A|.R|a/A.foo|()
}
@@ -1,4 +1,6 @@
FILE: test.kt
package test
public sealed class Test : R|kotlin/Any| {
protected constructor(): R|test/Test| {
super<R|kotlin/Any|>()
@@ -23,6 +25,8 @@ FILE: test.kt
}
FILE: main.kt
package other
public abstract class Factory : R|kotlin/Any| {
public constructor(): R|other/Factory| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: B.kt
package b
public abstract class MyClass : R|kotlin/Any| {
public constructor(): R|b/MyClass| {
super<R|kotlin/Any|>()
@@ -12,6 +14,8 @@ FILE: B.kt
public abstract interface I : R|kotlin/Any| {
}
FILE: A.kt
package a
public final class YourClass : R|b/MyClass| {
public constructor(): R|a/YourClass| {
super<R|b/MyClass|>()
@@ -1,4 +1,6 @@
FILE: B.kt
package b
public abstract class MyClass : R|kotlin/Any| {
public constructor(): R|b/MyClass| {
super<R|kotlin/Any|>()
@@ -12,6 +14,8 @@ FILE: B.kt
public abstract interface I : R|kotlin/Any| {
}
FILE: A.kt
package a
public final class YourClass : R|b/MyClass| {
public constructor(): R|a/YourClass| {
super<R|b/MyClass|>()
@@ -1,4 +1,6 @@
FILE: A.kt
package a
public final class MyClass : R|kotlin/Any| {
public constructor(): R|a/MyClass| {
super<R|kotlin/Any|>()
@@ -13,6 +15,8 @@ FILE: A.kt
}
FILE: B.kt
package b
public final class YourClass : R|a/MyClass.MyNested| {
public constructor(): R|b/YourClass| {
super<R|a/MyClass.MyNested|>()
@@ -1,4 +1,6 @@
FILE: A.kt
package a
public final class Outer : R|kotlin/Any| {
public constructor(): R|a/Outer| {
super<R|kotlin/Any|>()
@@ -13,6 +15,8 @@ FILE: A.kt
}
FILE: B.kt
package b
public final class My : R|a/Outer.Nested| {
public constructor(): R|b/My| {
super<R|a/Outer.Nested|>()
@@ -1,4 +1,6 @@
FILE: B.kt
package b.d
public abstract expect interface Other : R|kotlin/Any| {
}
public final expect class Another : R|kotlin/Any| {
@@ -6,6 +8,8 @@ FILE: B.kt
public final fun baz(): R|kotlin/Unit| {
}
FILE: A.kt
package a.d
public final fun foo(arg: R|b/d/Other|): R|b/d/Another|
public final fun bar(): R|kotlin/Unit| {
R|b/d/baz|()
@@ -1,4 +1,6 @@
FILE: main.kt
package foo
public final fun test(): R|kotlin/Unit| {
lval some: R|foo/Some| = R|foo/Some.Some|()
lval another: <ERROR TYPE REF: Unresolved name: Another> = <Unresolved name: Another>#()
@@ -1,4 +1,6 @@
FILE: qualifierWithCompanion.kt
package my
public final class A : R|kotlin/Any| {
public constructor(): R|my/A| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: typeParameterVsNested.kt
package test
public abstract interface Some : R|kotlin/Any| {
public open fun test(): R|kotlin/Int| {
^test Int(10)
@@ -1,4 +1,6 @@
FILE: TestCase1.kt
package testsCase1
public final class Case : R|kotlin/Any| {
public constructor(): R|testsCase1/Case| {
super<R|kotlin/Any|>()
@@ -1,4 +1,6 @@
FILE: User.kt
package test
public final class User : R|BaseClass| {
public constructor(): R|test/User| {
super<R|BaseClass|>()
@@ -1,4 +1,6 @@
FILE: test.kt
package some
public final fun test(jc: R|JavaClass|): R|kotlin/Unit| {
R|<local>/jc|.R|/JavaClass.field|
}
@@ -1,4 +1,6 @@
FILE: test.kt
package jvm
public final fun <K> select(x: R|K|, y: R|K|): R|K| {
^select R|<local>/x|
}
@@ -1,4 +1,6 @@
FILE: k.kt
package k
public final class A : R|kotlin/Any| {
public constructor(): R|k/A| {
super<R|kotlin/Any|>()
@@ -40,6 +42,8 @@ FILE: k.kt
}
FILE: j.kt
package j
public final class C : R|kotlin/Any| {
public constructor(): R|j/C| {
super<R|kotlin/Any|>()
@@ -1,5 +1,7 @@
Module: m1
FILE: base.kt
package hello
public final class Hello : R|kotlin/Any| {
public constructor(msg: R|kotlin/String|): R|hello/Hello| {
super<R|kotlin/Any|>()
@@ -20,6 +22,8 @@ FILE: base.kt
}
Module: m2
FILE: user.kt
package test
public final fun foo(hello: R|hello/Hello|): R|kotlin/String| {
^foo R|<local>/hello|.R|hello/Hello.msg|
}
@@ -42,7 +42,7 @@ fun FirElement.renderWithType(mode: FirRenderer.RenderMode = FirRenderer.RenderM
fun FirElement.render(mode: FirRenderer.RenderMode = FirRenderer.RenderMode.Normal): String =
buildString { this@render.accept(FirRenderer(this, mode)) }
class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderMode.Normal) : FirVisitorVoid() {
open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode = RenderMode.Normal) : FirVisitorVoid() {
companion object {
private val visibilitiesToRenderEffectiveSet = setOf(
Visibilities.Private, Visibilities.PrivateToThis, Visibilities.Internal,
@@ -442,7 +442,7 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
}
private fun List<FirDeclaration>.renderDeclarations() {
protected fun List<FirDeclaration>.renderDeclarations() {
renderInBraces {
for (declaration in this) {
declaration.accept(this@FirRenderer)
@@ -470,6 +470,10 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
regularClass.annotations.renderAnnotations()
visitMemberDeclaration(regularClass)
renderSupertypes(regularClass)
renderClassDeclarations(regularClass)
}
protected open fun renderClassDeclarations(regularClass: FirRegularClass) {
regularClass.declarations.renderDeclarations()
}
@@ -1432,7 +1436,10 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
override fun visitPackageDirective(packageDirective: FirPackageDirective) {
if (mode.renderPackageDirective) {
println("package ${packageDirective.packageFqName.asString()}")
if (!packageDirective.packageFqName.isRoot) {
println("package ${packageDirective.packageFqName.asString()}")
println()
}
}
}
}
@@ -5,7 +5,20 @@
package org.jetbrains.kotlin.test.frontend.fir.handlers
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.FirSession
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.moduleData
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.scopes.processClassifiersByName
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
@@ -13,6 +26,7 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
import java.lang.StringBuilder
class FirDumpHandler(
testServices: TestServices
@@ -22,11 +36,40 @@ class FirDumpHandler(
override val directiveContainers: List<DirectivesContainer>
get() = listOf(FirDiagnosticsDirectives)
@OptIn(SymbolInternals::class)
override fun processModule(module: TestModule, info: FirOutputArtifact) {
if (FirDiagnosticsDirectives.FIR_DUMP !in module.directives) return
val builderForModule = dumper.builderForModule(module)
val firFiles = info.firFiles
firFiles.values.forEach { builderForModule.append(it.render()) }
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 }
}
}
}
val renderer = FirRendererWithGeneratedDeclarations(info.session, builderForModule)
allFiles.forEach {
it.accept(renderer)
}
}
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
@@ -37,4 +80,44 @@ class FirDumpHandler(
val actualText = dumper.generateResultingDump()
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
}
private class FirRendererWithGeneratedDeclarations(
val session: FirSession,
builder: StringBuilder,
) : FirRenderer(builder, modeWithPackageDirective) {
companion object {
val modeWithPackageDirective = RenderMode.Normal.copy(renderPackageDirective = true)
}
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)
}
}
}
allDeclarations.renderDeclarations()
}
}
}