FirRenderer: add renderAllModifiers and renderDetailedTypeReferences

Related to KT-52020
This commit is contained in:
Mikhail Glukhikh
2022-06-24 10:21:21 +02:00
committed by Space
parent b2a9ad079d
commit 31ec10142b
16 changed files with 83 additions and 66 deletions
@@ -82,4 +82,4 @@ KtErrorCallInfo:
callableIdIfNonLocal = null) callableIdIfNonLocal = null)
} }
] ]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [public final fun function(a: R|kotlin/Char|): R|kotlin/Unit|, public final fun function(b: R|kotlin/Boolean|): R|kotlin/Unit|, public final fun function(c: R|kotlin/String|): R|kotlin/Unit|]> diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [fun function(a: Char): Unit, fun function(b: Boolean): Unit, fun function(c: String): Unit]>
@@ -47,4 +47,4 @@ KtErrorCallInfo:
typeArgumentsMapping = {} typeArgumentsMapping = {}
argumentMapping = {} argumentMapping = {}
] ]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [local final operator fun R|kotlin/Int|.invoke(a: R|kotlin/String|): R|kotlin/Unit|, local final operator fun R|kotlin/Int|.invoke(b: R|kotlin/Boolean|): R|kotlin/Unit|]> diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [fun Int.invoke(a: String): Unit, fun Int.invoke(b: Boolean): Unit]>
@@ -106,4 +106,4 @@ KtErrorCallInfo:
callableIdIfNonLocal = null) callableIdIfNonLocal = null)
} }
] ]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [public final fun <T> function(t: R|T|, a: R|kotlin/Char|): R|kotlin/Unit|, public final fun <U> function(u: R|U|, b: R|kotlin/Boolean|): R|kotlin/Unit|, public final fun <V> function(v: R|V|, c: R|kotlin/String|): R|kotlin/Unit|]> diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [fun <T> function(t: T, a: Char): Unit, fun <U> function(u: U, b: Boolean): Unit, fun <V> function(v: V, c: String): Unit]>
@@ -100,4 +100,4 @@ KtErrorCallInfo:
callableIdIfNonLocal = null) callableIdIfNonLocal = null)
} }
] ]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [public final fun <T> function(t: R|T|, a: R|kotlin/Char|): R|kotlin/Unit|, public final fun <U> function(u: R|U|, b: R|kotlin/Boolean|): R|kotlin/Unit|, public final fun <V> function(v: R|V|, c: R|kotlin/String|): R|kotlin/Unit|]> diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [fun <T> function(t: T, a: Char): Unit, fun <U> function(u: U, b: Boolean): Unit, fun <V> function(v: V, c: String): Unit]>
@@ -47,4 +47,4 @@ KtErrorCallInfo:
typeArgumentsMapping = {} typeArgumentsMapping = {}
argumentMapping = {} argumentMapping = {}
] ]
diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [public constructor(p: R|kotlin/Int|): R|Sub|, public constructor(i: R|kotlin/Int|, j: R|kotlin/Int|): R|Sub|]> diagnostic = ERROR<NONE_APPLICABLE: None of the following functions are applicable: [public constructor(p: Int): Sub, public constructor(i: Int, j: Int): Sub]>
@@ -14,4 +14,4 @@ KtErrorCallInfo:
typeArgumentsMapping = {} typeArgumentsMapping = {}
argumentMapping = {} argumentMapping = {}
] ]
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private constructor(): R|Obj| is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private constructor(): Obj is invisible>
@@ -17,4 +17,4 @@ KtErrorCallInfo:
typeArgumentsMapping = {} typeArgumentsMapping = {}
argumentMapping = {} argumentMapping = {}
] ]
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private final fun foo(): R|kotlin/Unit| is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol fun foo(): Unit is invisible>
@@ -1,5 +1,5 @@
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Double|.invoke(): R|kotlin/Unit|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Double.invoke(): Unit]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -38,7 +38,7 @@ KtApplicableCallCandidateInfo:
isInBestCandidates = true isInBestCandidates = true
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Long|.invoke(): R|kotlin/Double|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Long.invoke(): Double]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -1,5 +1,5 @@
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Double|.invoke(): R|kotlin/Unit|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Double.invoke(): Unit]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -19,7 +19,7 @@ KtInapplicableCallCandidateInfo:
isInBestCandidates = false isInBestCandidates = false
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Int|.invoke(): R|kotlin/Long|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Int.invoke(): Long]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -18,7 +18,7 @@ KtApplicableCallCandidateInfo:
isInBestCandidates = true isInBestCandidates = true
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Int|.invoke(): R|kotlin/Long|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Int.invoke(): Long]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -38,7 +38,7 @@ KtInapplicableCallCandidateInfo:
isInBestCandidates = false isInBestCandidates = false
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [public final operator fun R|kotlin/Long|.invoke(): R|kotlin/Double|]> diagnostic = ERROR<UNRESOLVED_REFERENCE_WRONG_RECEIVER: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: [fun Long.invoke(): Double]>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = true isImplicitInvoke = true
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -1,5 +1,5 @@
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private constructor(): R|Obj| is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private constructor(): Obj is invisible>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = false isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -1,5 +1,5 @@
KtInapplicableCallCandidateInfo: KtInapplicableCallCandidateInfo:
diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol private final fun foo(): R|kotlin/Unit| is invisible> diagnostic = ERROR<INVISIBLE_REFERENCE: Symbol fun foo(): Unit is invisible>
candidate = KtSimpleFunctionCall: candidate = KtSimpleFunctionCall:
isImplicitInvoke = false isImplicitInvoke = false
partiallyAppliedSymbol = KtPartiallyAppliedSymbol: partiallyAppliedSymbol = KtPartiallyAppliedSymbol:
@@ -9,20 +9,24 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
fun ConeKotlinType.render(): String { fun ConeKotlinType.render(renderFqNames: Boolean = true): String {
val nullabilitySuffix = if (this !is ConeFlexibleType && this !is ConeErrorType) nullability.suffix else "" val nullabilitySuffix = if (this !is ConeFlexibleType && this !is ConeErrorType) nullability.suffix else ""
return when (this) { return when (this) {
is ConeTypeVariableType -> "${renderAttributes()}TypeVariable(${this.lookupTag.name})" is ConeTypeVariableType -> "${renderAttributes()}TypeVariable(${this.lookupTag.name})"
is ConeDefinitelyNotNullType -> "${original.render()} & Any" is ConeDefinitelyNotNullType -> "${original.render(renderFqNames)} & Any"
is ConeErrorType -> "${renderAttributes()}ERROR CLASS: ${diagnostic.reason}" is ConeErrorType -> "${renderAttributes()}ERROR CLASS: ${diagnostic.reason}"
is ConeCapturedType -> "${renderAttributes()}CapturedType(${constructor.projection.render()})" is ConeCapturedType -> "${renderAttributes()}CapturedType(${constructor.projection.render(renderFqNames)})"
is ConeClassLikeType -> { is ConeClassLikeType -> {
buildString { buildString {
append(renderAttributes()) append(renderAttributes())
append(lookupTag.classId.asString()) if (renderFqNames) {
append(lookupTag.classId.asString())
} else {
append(lookupTag.classId.relativeClassName.asString())
}
if (typeArguments.isNotEmpty()) { if (typeArguments.isNotEmpty()) {
append(typeArguments.joinToString(prefix = "<", postfix = ">") { append(typeArguments.joinToString(prefix = "<", postfix = ">") {
it.render() it.render(renderFqNames)
}) })
} }
} }
@@ -31,13 +35,15 @@ fun ConeKotlinType.render(): String {
"${renderAttributes()}${lookupTag.name.asString()}" "${renderAttributes()}${lookupTag.name.asString()}"
} }
is ConeDynamicType -> "dynamic" is ConeDynamicType -> "dynamic"
is ConeFlexibleType -> this.render() is ConeFlexibleType -> this.render(renderFqNames)
is ConeIntersectionType -> { is ConeIntersectionType -> {
intersectedTypes.joinToString( intersectedTypes.joinToString(
separator = " & ", separator = " & ",
prefix = "${renderAttributes()}it(", prefix = "${renderAttributes()}it(",
postfix = ")" postfix = ")"
) ) {
it.render(renderFqNames)
}
} }
is ConeStubTypeForSyntheticFixation -> "${renderAttributes()}Stub (fixation): ${constructor.variable}" is ConeStubTypeForSyntheticFixation -> "${renderAttributes()}Stub (fixation): ${constructor.variable}"
is ConeStubTypeForChainInference -> "${renderAttributes()}Stub (chain inference): ${constructor.variable}" is ConeStubTypeForChainInference -> "${renderAttributes()}Stub (chain inference): ${constructor.variable}"
@@ -47,12 +53,12 @@ fun ConeKotlinType.render(): String {
} + nullabilitySuffix } + nullabilitySuffix
} }
private fun ConeFlexibleType.render(): String = private fun ConeFlexibleType.render(renderFqNames: Boolean): String =
buildString { buildString {
append("ft<") append("ft<")
append(lowerBound.render()) append(lowerBound.render(renderFqNames))
append(", ") append(", ")
append(upperBound.render()) append(upperBound.render(renderFqNames))
append(">") append(">")
} }
@@ -61,18 +67,18 @@ private fun ConeKotlinType.renderAttributes(): String {
return attributes.joinToString(" ", postfix = " ") { it.toString() } return attributes.joinToString(" ", postfix = " ") { it.toString() }
} }
fun ConeTypeProjection.render(): String { fun ConeTypeProjection.render(renderFqNames: Boolean): String {
return when (this) { return when (this) {
ConeStarProjection -> "*" ConeStarProjection -> "*"
is ConeKotlinTypeConflictingProjection -> "CONFLICTING-PROJECTION ${type.render()}" is ConeKotlinTypeConflictingProjection -> "CONFLICTING-PROJECTION ${type.render(renderFqNames)}"
is ConeKotlinTypeProjectionIn -> "in ${type.render()}" is ConeKotlinTypeProjectionIn -> "in ${type.render(renderFqNames)}"
is ConeKotlinTypeProjectionOut -> "out ${type.render()}" is ConeKotlinTypeProjectionOut -> "out ${type.render(renderFqNames)}"
is ConeKotlinType -> render() is ConeKotlinType -> render(renderFqNames)
} }
} }
fun ConeKotlinType.renderFunctionType( fun ConeKotlinType.renderFunctionType(
kind: FunctionClassKind?, renderType: ConeTypeProjection.() -> String = { render() } kind: FunctionClassKind?, renderFqNames: Boolean, renderType: ConeTypeProjection.() -> String = { render(renderFqNames) }
): String { ): String {
if (!kind.withPrettyRender()) return renderType() if (!kind.withPrettyRender()) return renderType()
@@ -66,6 +66,8 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
val renderPackageDirective: Boolean = false, val renderPackageDirective: Boolean = false,
val renderNestedDeclarations: Boolean = true, val renderNestedDeclarations: Boolean = true,
val renderDefaultParameterValues: Boolean = true, val renderDefaultParameterValues: Boolean = true,
val renderDetailedTypeReferences: Boolean = true,
val renderAllModifiers: Boolean = true,
) { ) {
companion object { companion object {
val Normal = RenderMode( val Normal = RenderMode(
@@ -124,6 +126,8 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
renderPackageDirective = false, renderPackageDirective = false,
renderNestedDeclarations = false, renderNestedDeclarations = false,
renderDefaultParameterValues = false, renderDefaultParameterValues = false,
renderDetailedTypeReferences = false,
renderAllModifiers = false,
) )
val WithDeclarationAttributes = RenderMode( val WithDeclarationAttributes = RenderMode(
@@ -236,7 +240,6 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
override fun visitCallableDeclaration(callableDeclaration: FirCallableDeclaration) { override fun visitCallableDeclaration(callableDeclaration: FirCallableDeclaration) {
renderContexts(callableDeclaration.contextReceivers) renderContexts(callableDeclaration.contextReceivers)
callableDeclaration.contextReceivers
callableDeclaration.annotations.renderAnnotations() callableDeclaration.annotations.renderAnnotations()
visitMemberDeclaration(callableDeclaration) visitMemberDeclaration(callableDeclaration)
val receiverType = callableDeclaration.receiverTypeRef val receiverType = callableDeclaration.receiverTypeRef
@@ -338,7 +341,7 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
} }
override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration) { override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration) {
if (memberDeclaration !is FirProperty || !memberDeclaration.isLocal) { if (mode.renderAllModifiers && (memberDeclaration !is FirProperty || !memberDeclaration.isLocal)) {
// we can't access session.effectiveVisibilityResolver from here! // we can't access session.effectiveVisibilityResolver from here!
// print(memberDeclaration.visibility.asString(memberDeclaration.getEffectiveVisibility(...)) + " ") // print(memberDeclaration.visibility.asString(memberDeclaration.getEffectiveVisibility(...)) + " ")
print(memberDeclaration.visibility.asString() + " ") print(memberDeclaration.visibility.asString() + " ")
@@ -350,11 +353,13 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
if (memberDeclaration.isActual) { if (memberDeclaration.isActual) {
print("actual ") print("actual ")
} }
if (memberDeclaration.isExternal) { if (mode.renderAllModifiers) {
print("external ") if (memberDeclaration.isExternal) {
} print("external ")
if (memberDeclaration.isOverride) { }
print("override ") if (memberDeclaration.isOverride) {
print("override ")
}
} }
if (memberDeclaration.isStatic) { if (memberDeclaration.isStatic) {
print("static ") print("static ")
@@ -379,26 +384,28 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
print("fun ") print("fun ")
} }
if (memberDeclaration.isInline) { if (mode.renderAllModifiers) {
print("inline ") if (memberDeclaration.isInline) {
} print("inline ")
if (memberDeclaration.isOperator) { }
print("operator ") if (memberDeclaration.isOperator) {
} print("operator ")
if (memberDeclaration.isInfix) { }
print("infix ") if (memberDeclaration.isInfix) {
} print("infix ")
if (memberDeclaration.isTailRec) { }
print("tailrec ") if (memberDeclaration.isTailRec) {
} print("tailrec ")
if (memberDeclaration.isSuspend) { }
print("suspend ") if (memberDeclaration.isSuspend) {
} print("suspend ")
if (memberDeclaration.isConst) { }
print("const ") if (memberDeclaration.isConst) {
} print("const ")
if (memberDeclaration.isLateInit) { }
print("lateinit ") if (memberDeclaration.isLateInit) {
print("lateinit ")
}
} }
visitDeclaration(memberDeclaration as FirDeclaration) visitDeclaration(memberDeclaration as FirDeclaration)
@@ -1128,10 +1135,14 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) { override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
val kind = resolvedTypeRef.functionTypeKind val kind = resolvedTypeRef.functionTypeKind
print("R|") if (mode.renderDetailedTypeReferences) {
print("R|")
}
val coneType = resolvedTypeRef.type val coneType = resolvedTypeRef.type
print(coneType.renderFunctionType(kind)) print(coneType.renderFunctionType(kind, renderFqNames = mode.renderDetailedTypeReferences))
print("|") if (mode.renderDetailedTypeReferences) {
print("|")
}
} }
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) { override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) {
+3 -3
View File
@@ -1,15 +1,15 @@
warning: ATTENTION! warning: ATTENTION!
This build uses experimental K2 compiler: This build uses experimental K2 compiler:
-Xuse-k2 -Xuse-k2
compiler/testData/cli/jvm/firDeprecationJava.kt:3:12: warning: '@R|kotlin/Deprecated|(...) public final fun stop(): R|kotlin/Unit| compiler/testData/cli/jvm/firDeprecationJava.kt:3:12: warning: '@Deprecated(...) fun stop(): Unit
' is deprecated. Deprecated in Java ' is deprecated. Deprecated in Java
thread.stop() thread.stop()
^ ^
compiler/testData/cli/jvm/firDeprecationJava.kt:4:17: warning: '@R|kotlin/Deprecated|(...) public open fun bar(a: R|ft<kotlin/String, kotlin/String?>|, b: R|kotlin/Int|, c: R|kotlin/Double|): R|ft<kotlin/String, kotlin/String?>| compiler/testData/cli/jvm/firDeprecationJava.kt:4:17: warning: '@Deprecated(...) fun bar(a: ft<String, String?>, b: Int, c: Double): ft<String, String?>
' is deprecated. Deprecated in Java ' is deprecated. Deprecated in Java
JavaClass().bar("", 1, 2.0) JavaClass().bar("", 1, 2.0)
^ ^
compiler/testData/cli/jvm/firDeprecationJava.kt:5:27: warning: '@R|kotlin/Deprecated|(...) public open field baz: R|ft<List, List?>| compiler/testData/cli/jvm/firDeprecationJava.kt:5:27: warning: '@Deprecated(...) field baz: ft<List, List?>
' is deprecated. Deprecated in Java ' is deprecated. Deprecated in Java
val baz = JavaClass().baz val baz = JavaClass().baz
^ ^
@@ -324,7 +324,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
private fun ConeTypeProjection.tryToRenderConeAsFunctionType(): String { private fun ConeTypeProjection.tryToRenderConeAsFunctionType(): String {
if (this !is ConeKotlinType) return localTypeRenderer() if (this !is ConeKotlinType) return localTypeRenderer()
val functionType = renderFunctionType(functionTypeKind) { localTypeRenderer() } val functionType = renderFunctionType(functionTypeKind, renderFqNames = true) { localTypeRenderer() }
return functionType.removeCurrentFilePackage() return functionType.removeCurrentFilePackage()
} }
@@ -429,7 +429,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
intersectedTypes.map { it.render().replace("/", ".").replace("kotlin.", "") }.sorted() intersectedTypes.map { it.render().replace("/", ".").replace("kotlin.", "") }.sorted()
.joinToString(separator = " & ", prefix = "{", postfix = "}") .joinToString(separator = " & ", prefix = "{", postfix = "}")
} }
else -> this.render() else -> this.render(renderFqNames = true)
} }
} }