All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.FirRenderer.kt Maven / Gradle / Ivy
/*
* Copyright 2000-2018 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
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.contracts.*
import org.jetbrains.kotlin.fir.contracts.description.ConeContractRenderer
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun FirElement.renderWithType(mode: FirRenderer.RenderMode = FirRenderer.RenderMode.Normal): String = buildString {
append(this@renderWithType)
append(": ")
[email protected] (FirRenderer(this, mode))
}
fun FirElement.render(mode: FirRenderer.RenderMode = FirRenderer.RenderMode.Normal): String =
buildString { [email protected] (FirRenderer(this, mode)) }
class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderMode.Normal) : FirVisitorVoid() {
companion object {
private val visibilitiesToRenderEffectiveSet = setOf(
Visibilities.Private, Visibilities.PrivateToThis, Visibilities.Internal,
Visibilities.Protected, Visibilities.Public, Visibilities.Local
)
}
abstract class RenderMode(
val renderLambdaBodies: Boolean,
val renderCallArguments: Boolean,
val renderCallableFqNames: Boolean
) {
object Normal : RenderMode(renderLambdaBodies = true, renderCallArguments = true, renderCallableFqNames = false)
object WithFqNames: RenderMode(renderLambdaBodies = true, renderCallArguments = true, renderCallableFqNames = true)
}
private val printer = Printer(builder)
private var lineBeginning = true
private fun print(vararg objects: Any) {
if (lineBeginning) {
lineBeginning = false
printer.print(*objects)
} else {
printer.printWithNoIndent(*objects)
}
}
private fun println(vararg objects: Any) {
print(*objects)
printer.printlnWithNoIndent()
lineBeginning = true
}
private fun pushIndent() {
printer.pushIndent()
}
private fun popIndent() {
printer.popIndent()
}
fun newLine() {
println()
}
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
override fun visitFile(file: FirFile) {
println("FILE: ${file.name}")
pushIndent()
visitElement(file)
popIndent()
}
private fun List.renderSeparated() {
for ((index, element) in this.withIndex()) {
if (index > 0) {
print(", ")
}
element.accept(this@FirRenderer)
}
}
private fun List.renderSeparatedWithNewlines() {
for ((index, element) in this.withIndex()) {
if (index > 0) {
print(",")
newLine()
}
element.accept(this@FirRenderer)
}
}
private fun List.renderTypesSeparated() {
for ((index, element) in this.withIndex()) {
if (index > 0) {
print(", ")
}
print(element.render())
}
}
private fun List.renderParameters() {
print("(")
renderSeparated()
print(")")
}
private fun List.renderAnnotations() {
for (annotation in this) {
visitAnnotationCall(annotation)
}
}
private fun Variance.renderVariance() {
label.let {
print(it)
if (it.isNotEmpty()) {
print(" ")
}
}
}
override fun > visitCallableDeclaration(callableDeclaration: FirCallableDeclaration) {
if (callableDeclaration is FirMemberDeclaration) {
visitMemberDeclaration(callableDeclaration)
} else {
callableDeclaration.annotations.renderAnnotations()
visitTypedDeclaration(callableDeclaration)
}
val receiverType = callableDeclaration.receiverTypeRef
print(" ")
if (receiverType != null) {
receiverType.accept(this)
print(".")
}
when (callableDeclaration) {
is FirSimpleFunction -> {
if (!mode.renderCallableFqNames) {
print(callableDeclaration.name)
} else {
print(callableDeclaration.symbol.callableId)
}
}
is FirVariable<*> -> {
if (!mode.renderCallableFqNames) {
print(callableDeclaration.name)
} else {
print(callableDeclaration.symbol.callableId)
}
}
}
if (callableDeclaration is FirFunction<*>) {
callableDeclaration.valueParameters.renderParameters()
}
print(": ")
callableDeclaration.returnTypeRef.accept(this)
callableDeclaration.renderContractDescription()
}
private fun FirDeclaration.renderContractDescription() {
val contractDescription = (this as? FirContractDescriptionOwner)?.contractDescription ?: return
pushIndent()
contractDescription.accept(this@FirRenderer)
popIndent()
}
private fun Visibility.asString(effectiveVisibility: FirEffectiveVisibility? = null): String {
val itself = when (this) {
Visibilities.Unknown -> return "public?"
else -> toString()
}
if (effectiveVisibility == null || effectiveVisibility == FirEffectiveVisibility.Default) return itself
val effectiveAsVisibility = effectiveVisibility.toVisibility()
if (effectiveAsVisibility == this) return itself
if (effectiveAsVisibility == Visibilities.Private && this == Visibilities.PrivateToThis) return itself
if (this !in visibilitiesToRenderEffectiveSet) return itself
return itself + "[${effectiveVisibility.name}]"
}
private fun FirMemberDeclaration.modalityAsString(): String {
return modality?.name?.toLowerCase() ?: run {
if (this is FirCallableMemberDeclaration<*> && this.isOverride) {
"open?"
} else {
"final?"
}
}
}
private fun List.renderTypeParameters() {
if (isNotEmpty()) {
print("<")
renderSeparated()
print(">")
}
}
private fun List.renderTypeArguments() {
if (isNotEmpty()) {
print("<")
renderSeparated()
print(">")
}
}
override fun visitTypeParameterRef(typeParameterRef: FirTypeParameterRef) {
typeParameterRef.symbol.fir.accept(this)
}
override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration) {
memberDeclaration.annotations.renderAnnotations()
if (memberDeclaration !is FirProperty || !memberDeclaration.isLocal) {
// we can't access session.effectiveVisibilityResolver from here!
// print(memberDeclaration.visibility.asString(memberDeclaration.getEffectiveVisibility(...)) + " ")
print(memberDeclaration.visibility.asString() + " ")
print(memberDeclaration.modalityAsString() + " ")
}
if (memberDeclaration.isExpect) {
print("expect ")
}
if (memberDeclaration.isActual) {
print("actual ")
}
if (memberDeclaration is FirCallableMemberDeclaration<*>) {
if (memberDeclaration.isOverride) {
print("override ")
}
if (memberDeclaration.isStatic) {
print("static ")
}
}
if (memberDeclaration is FirRegularClass) {
if (memberDeclaration.isInner) {
print("inner ")
}
if (memberDeclaration.isCompanion) {
print("companion ")
}
if (memberDeclaration.isData) {
print("data ")
}
if (memberDeclaration.isInline) {
print("inline ")
}
} else if (memberDeclaration is FirSimpleFunction) {
if (memberDeclaration.isOperator) {
print("operator ")
}
if (memberDeclaration.isInfix) {
print("infix ")
}
if (memberDeclaration.isInline) {
print("inline ")
}
if (memberDeclaration.isTailRec) {
print("tailrec ")
}
if (memberDeclaration.isExternal) {
print("external ")
}
if (memberDeclaration.isSuspend) {
print("suspend ")
}
} else if (memberDeclaration is FirProperty) {
if (memberDeclaration.isConst) {
print("const ")
}
if (memberDeclaration.isLateInit) {
print("lateinit ")
}
}
visitDeclaration(memberDeclaration)
when (memberDeclaration) {
is FirClassLikeDeclaration<*> -> {
if (memberDeclaration is FirRegularClass) {
print(" " + memberDeclaration.name)
}
if (memberDeclaration is FirTypeAlias) {
print(" " + memberDeclaration.name)
}
memberDeclaration.typeParameters.renderTypeParameters()
}
is FirCallableDeclaration<*> -> {
// Name is handled by visitCallableDeclaration
if (memberDeclaration.typeParameters.isNotEmpty()) {
print(" ")
memberDeclaration.typeParameters.renderTypeParameters()
}
}
}
}
override fun visitDeclaration(declaration: FirDeclaration) {
print(
when (declaration) {
is FirRegularClass -> declaration.classKind.name.toLowerCase().replace("_", " ")
is FirTypeAlias -> "typealias"
is FirSimpleFunction -> "fun"
is FirProperty -> {
val prefix = if (declaration.isLocal) "l" else ""
prefix + if (declaration.isVal) "val" else "var"
}
is FirField -> "field"
is FirEnumEntry -> "enum entry"
else -> "unknown"
}
)
}
private fun List.renderDeclarations() {
renderInBraces {
for (declaration in this) {
declaration.accept(this@FirRenderer)
println()
}
}
}
fun renderInBraces(leftBrace: String = "{", rightBrace: String = "}", f: () -> Unit) {
println(" $leftBrace")
pushIndent()
f()
popIndent()
println(rightBrace)
}
fun renderSupertypes(regularClass: FirRegularClass) {
if (regularClass.superTypeRefs.isNotEmpty()) {
print(" : ")
regularClass.superTypeRefs.renderSeparated()
}
}
override fun visitRegularClass(regularClass: FirRegularClass) {
visitMemberDeclaration(regularClass)
renderSupertypes(regularClass)
regularClass.declarations.renderDeclarations()
}
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
visitCallableDeclaration(enumEntry)
enumEntry.initializer?.let {
print(" = ")
it.accept(this)
}
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
anonymousObject.annotations.renderAnnotations()
print("object : ")
anonymousObject.superTypeRefs.renderSeparated()
anonymousObject.declarations.renderDeclarations()
}
override fun > visitVariable(variable: FirVariable) {
visitCallableDeclaration(variable)
variable.initializer?.let {
print(" = ")
it.accept(this)
}
variable.delegate?.let {
print("by ")
it.accept(this)
}
}
override fun visitField(field: FirField) {
visitVariable(field)
println()
}
override fun visitProperty(property: FirProperty) {
visitVariable(property)
if (property.isLocal) return
println()
pushIndent()
property.getter?.accept(this)
if (property.getter?.body == null) {
println()
}
if (property.isVar) {
property.setter?.accept(this)
if (property.setter?.body == null) {
println()
}
}
popIndent()
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
visitCallableDeclaration(simpleFunction)
simpleFunction.body?.renderBody()
if (simpleFunction.body == null) {
println()
}
}
override fun visitConstructor(constructor: FirConstructor) {
constructor.annotations.renderAnnotations()
// we can't access session.effectiveVisibilityResolver from here!
// print(constructor.visibility.asString(constructor.getEffectiveVisibility(...)) + " ")
print(constructor.visibility.asString() + " ")
if (constructor.isExpect) {
print("expect ")
}
if (constructor.isActual) {
print("actual ")
}
print("constructor")
constructor.typeParameters.renderTypeParameters()
constructor.valueParameters.renderParameters()
print(": ")
constructor.returnTypeRef.accept(this)
val body = constructor.body
val delegatedConstructor = constructor.delegatedConstructor
if (body == null) {
if (delegatedConstructor != null) {
renderInBraces {
delegatedConstructor.accept(this)
println()
}
} else {
println()
}
}
body?.renderBody(listOfNotNull(delegatedConstructor))
}
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
propertyAccessor.annotations.renderAnnotations()
print(propertyAccessor.visibility.asString() + " ")
print(if (propertyAccessor.isGetter) "get" else "set")
propertyAccessor.valueParameters.renderParameters()
print(": ")
propertyAccessor.returnTypeRef.accept(this)
propertyAccessor.renderContractDescription()
propertyAccessor.body?.renderBody()
}
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
anonymousFunction.annotations.renderAnnotations()
val label = anonymousFunction.label
if (label != null) {
print("${label.name}@")
}
print("fun ")
val receiverType = anonymousFunction.receiverTypeRef
if (receiverType != null) {
receiverType.accept(this)
print(".")
}
print("")
anonymousFunction.valueParameters.renderParameters()
print(": ")
anonymousFunction.returnTypeRef.accept(this)
if (anonymousFunction.invocationKind != null) {
print(" ")
}
if (mode.renderLambdaBodies) {
anonymousFunction.body?.renderBody()
}
}
override fun > visitFunction(function: FirFunction) {
function.valueParameters.renderParameters()
visitDeclaration(function)
function.body?.renderBody()
}
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer) {
print("init")
anonymousInitializer.body?.renderBody()
}
private fun FirBlock.renderBody(additionalStatements: List = emptyList()) {
renderInBraces {
for (statement in additionalStatements + statements) {
statement.accept(this@FirRenderer)
println()
}
}
}
override fun visitBlock(block: FirBlock) {
block.renderBody()
}
override fun visitTypeAlias(typeAlias: FirTypeAlias) {
typeAlias.annotations.renderAnnotations()
visitMemberDeclaration(typeAlias)
print(" = ")
typeAlias.expandedTypeRef.accept(this)
println()
}
override fun visitTypeParameter(typeParameter: FirTypeParameter) {
typeParameter.annotations.renderAnnotations()
if (typeParameter.isReified) {
print("reified ")
}
typeParameter.variance.renderVariance()
print(typeParameter.name)
val meaningfulBounds = typeParameter.bounds.filter {
if (it !is FirResolvedTypeRef) return@filter true
if (!it.type.isNullable) return@filter true
val type = it.type as? ConeLookupTagBasedType ?: return@filter true
type.lookupTag.safeAs()?.classId != StandardClassIds.Any
}
if (meaningfulBounds.isNotEmpty()) {
print(" : ")
meaningfulBounds.renderSeparated()
}
}
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) {
safeCallExpression.receiver.accept(this)
print("?.{ ")
safeCallExpression.regularQualifiedAccess.accept(this)
print(" }")
}
override fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject) {
print("\$subj\$")
}
override fun visitTypedDeclaration(typedDeclaration: FirTypedDeclaration) {
visitDeclaration(typedDeclaration)
}
override fun visitValueParameter(valueParameter: FirValueParameter) {
valueParameter.annotations.renderAnnotations()
if (valueParameter.isCrossinline) {
print("crossinline ")
}
if (valueParameter.isNoinline) {
print("noinline ")
}
if (valueParameter.isVararg) {
print("vararg ")
}
if (valueParameter.name != SpecialNames.NO_NAME_PROVIDED) {
print(valueParameter.name.toString() + ": ")
}
valueParameter.returnTypeRef.accept(this)
valueParameter.defaultValue?.let {
print(" = ")
it.accept(this)
}
}
override fun visitImport(import: FirImport) {
visitElement(import)
}
override fun visitStatement(statement: FirStatement) {
if (statement is FirStubStatement) {
print("[StubStatement]")
} else {
visitElement(statement)
}
}
override fun visitReturnExpression(returnExpression: FirReturnExpression) {
returnExpression.annotations.renderAnnotations()
print("^")
val target = returnExpression.target
val labeledElement = target.labeledElement
if (labeledElement is FirSimpleFunction) {
print("${labeledElement.name}")
} else {
val labelName = target.labelName
if (labelName != null) {
print("@$labelName")
}
}
print(" ")
returnExpression.result.accept(this)
}
override fun visitWhenBranch(whenBranch: FirWhenBranch) {
val condition = whenBranch.condition
if (condition is FirElseIfTrueCondition) {
print("else")
} else {
condition.accept(this)
}
print(" -> ")
whenBranch.result.accept(this)
}
override fun visitWhenExpression(whenExpression: FirWhenExpression) {
whenExpression.annotations.renderAnnotations()
print("when (")
val subjectVariable = whenExpression.subjectVariable
if (subjectVariable != null) {
subjectVariable.accept(this)
} else {
whenExpression.subject?.accept(this)
}
println(") {")
pushIndent()
for (branch in whenExpression.branches) {
branch.accept(this)
}
popIndent()
println("}")
}
override fun visitWhenSubjectExpression(whenSubjectExpression: FirWhenSubjectExpression) {
print("\$subj\$")
}
override fun visitTryExpression(tryExpression: FirTryExpression) {
tryExpression.annotations.renderAnnotations()
print("try")
tryExpression.tryBlock.accept(this)
for (catchClause in tryExpression.catches) {
print("catch (")
catchClause.parameter.accept(this)
print(")")
catchClause.block.accept(this)
}
val finallyBlock = tryExpression.finallyBlock ?: return
print("finally")
finallyBlock.accept(this)
}
override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop) {
val label = doWhileLoop.label
if (label != null) {
print("${label.name}@")
}
print("do")
doWhileLoop.block.accept(this)
print("while(")
doWhileLoop.condition.accept(this)
print(")")
}
override fun visitWhileLoop(whileLoop: FirWhileLoop) {
val label = whileLoop.label
if (label != null) {
print("${label.name}@")
}
print("while(")
whileLoop.condition.accept(this)
print(")")
whileLoop.block.accept(this)
}
override fun visitLoopJump(loopJump: FirLoopJump) {
val target = loopJump.target
val labeledElement = target.labeledElement
print("@@@[")
labeledElement.condition.accept(this)
print("] ")
}
override fun visitBreakExpression(breakExpression: FirBreakExpression) {
breakExpression.annotations.renderAnnotations()
print("break")
visitLoopJump(breakExpression)
}
override fun visitContinueExpression(continueExpression: FirContinueExpression) {
continueExpression.annotations.renderAnnotations()
print("continue")
visitLoopJump(continueExpression)
}
override fun visitExpression(expression: FirExpression) {
expression.annotations.renderAnnotations()
print(
when (expression) {
is FirExpressionStub -> "STUB"
is FirUnitExpression -> "Unit"
is FirElseIfTrueCondition -> "else"
is FirNoReceiverExpression -> ""
else -> "??? ${expression.javaClass}"
}
)
}
override fun visitConstExpression(constExpression: FirConstExpression) {
constExpression.annotations.renderAnnotations()
val kind = constExpression.kind
val value = constExpression.value
print("$kind(")
if (value !is Char) {
print(value.toString())
} else {
if (value.toInt() in 32..127) {
print(value)
} else {
print(value.toInt())
}
}
print(")")
}
override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) {
wrappedDelegateExpression.expression.accept(this)
}
override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) {
print(namedArgumentExpression.name)
print(" = ")
if (namedArgumentExpression.isSpread) {
print("*")
}
namedArgumentExpression.expression.accept(this)
}
override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression) {
if (spreadArgumentExpression.isSpread) {
print("*")
}
spreadArgumentExpression.expression.accept(this)
}
override fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression) {
print(" = ")
lambdaArgumentExpression.expression.accept(this)
}
override fun visitVarargArgumentsExpression(varargArgumentsExpression: FirVarargArgumentsExpression) {
print("vararg(")
varargArgumentsExpression.arguments.renderSeparated()
print(")")
}
override fun visitCall(call: FirCall) {
print("(")
if (mode.renderCallArguments) {
call.arguments.renderSeparated()
} else {
if (call.arguments.isNotEmpty()) {
print("...")
}
}
print(")")
}
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall) {
print("")
visitCall(stringConcatenationCall)
}
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall) {
print("(")
typeOperatorCall.argument.accept(this)
print(" ")
print(typeOperatorCall.operation.operator)
print(" ")
typeOperatorCall.conversionTypeRef.accept(this)
print(")")
}
override fun visitAnnotationCall(annotationCall: FirAnnotationCall) {
print("@")
annotationCall.useSiteTarget?.let {
print(it.name)
print(":")
}
annotationCall.annotationTypeRef.accept(this)
visitCall(annotationCall)
if (annotationCall.useSiteTarget == AnnotationUseSiteTarget.FILE) {
println()
} else {
print(" ")
}
}
override fun visitDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall) {
val dispatchReceiver = delegatedConstructorCall.dispatchReceiver
if (dispatchReceiver !is FirNoReceiverExpression) {
dispatchReceiver.accept(this)
print(".")
}
if (delegatedConstructorCall.isSuper) {
print("super<")
} else if (delegatedConstructorCall.isThis) {
print("this<")
}
delegatedConstructorCall.constructedTypeRef.accept(this)
print(">")
visitCall(delegatedConstructorCall)
}
override fun visitTypeRef(typeRef: FirTypeRef) {
typeRef.annotations.renderAnnotations()
visitElement(typeRef)
}
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef) {
visitTypeRef(errorTypeRef)
print("")
}
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef) {
print("")
}
override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability) {
if (typeRefWithNullability.isMarkedNullable) {
print("?")
}
}
override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef) {
dynamicTypeRef.annotations.renderAnnotations()
print("")
visitTypeRefWithNullability(dynamicTypeRef)
}
override fun visitFunctionTypeRef(functionTypeRef: FirFunctionTypeRef) {
print("( ")
functionTypeRef.receiverTypeRef?.let {
it.accept(this)
print(".")
}
functionTypeRef.valueParameters.renderParameters()
print(" -> ")
functionTypeRef.returnTypeRef.accept(this)
print(" )")
visitTypeRefWithNullability(functionTypeRef)
}
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
val kind = resolvedTypeRef.functionTypeKind
val annotations = if (kind.withPrettyRender()) {
resolvedTypeRef.annotations.dropExtensionFunctionAnnotation()
} else {
resolvedTypeRef.annotations
}
annotations.renderAnnotations()
print("R|")
val coneType = resolvedTypeRef.type
print(coneType.renderFunctionType(kind, resolvedTypeRef.annotations.any {
it.isExtensionFunctionAnnotationCall
}))
print("|")
}
private val FirResolvedTypeRef.functionTypeKind: FunctionClassKind?
get() {
val classId = (type as? ConeClassLikeType)?.lookupTag?.classId ?: return null
return FunctionClassKind.getFunctionalClassKind(
classId.shortClassName.asString(), classId.packageFqName
)
}
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) {
userTypeRef.annotations.renderAnnotations()
for ((index, qualifier) in userTypeRef.qualifier.withIndex()) {
if (index != 0) {
print(".")
}
print(qualifier.name)
if (qualifier.typeArgumentList.typeArguments.isNotEmpty()) {
print("<")
qualifier.typeArgumentList.typeArguments.renderSeparated()
print(">")
}
}
visitTypeRefWithNullability(userTypeRef)
}
override fun visitTypeProjection(typeProjection: FirTypeProjection) {
visitElement(typeProjection)
}
override fun visitTypeProjectionWithVariance(typeProjectionWithVariance: FirTypeProjectionWithVariance) {
typeProjectionWithVariance.variance.renderVariance()
typeProjectionWithVariance.typeRef.accept(this)
}
override fun visitStarProjection(starProjection: FirStarProjection) {
print("*")
}
private fun AbstractFirBasedSymbol<*>.render(): String {
return when (this) {
is FirCallableSymbol<*> -> callableId.toString()
is FirClassLikeSymbol<*> -> classId.toString()
else -> "?"
}
}
override fun visitNamedReference(namedReference: FirNamedReference) {
val symbol = namedReference.candidateSymbol
when {
symbol != null -> {
print("R?C|${symbol.render()}|")
}
namedReference is FirErrorNamedReference -> print("<${namedReference.diagnostic.reason}>#")
else -> print("${namedReference.name}#")
}
}
override fun visitBackingFieldReference(backingFieldReference: FirBackingFieldReference) {
print("F|")
print(backingFieldReference.resolvedSymbol.callableId)
print("|")
}
override fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference) {
print("D|")
print(delegateFieldReference.resolvedSymbol.callableId)
print("|")
}
override fun visitResolvedNamedReference(resolvedNamedReference: FirResolvedNamedReference) {
print("R|")
val symbol = resolvedNamedReference.resolvedSymbol
val isFakeOverride = when (symbol) {
is FirNamedFunctionSymbol -> symbol.isFakeOverride
is FirPropertySymbol -> symbol.isFakeOverride
else -> false
}
if (isFakeOverride) {
print("FakeOverride<")
}
print(symbol.render())
if (resolvedNamedReference is FirResolvedCallableReference) {
if (resolvedNamedReference.inferredTypeArguments.isNotEmpty()) {
print("<")
resolvedNamedReference.inferredTypeArguments.renderTypesSeparated()
print(">")
}
}
if (isFakeOverride) {
when (symbol) {
is FirNamedFunctionSymbol -> {
print(": ")
symbol.fir.returnTypeRef.accept(this)
}
is FirPropertySymbol -> {
print(": ")
symbol.fir.returnTypeRef.accept(this)
}
}
print(">")
}
print("|")
}
override fun visitResolvedCallableReference(resolvedCallableReference: FirResolvedCallableReference) {
visitResolvedNamedReference(resolvedCallableReference)
}
override fun visitThisReference(thisReference: FirThisReference) {
print("this")
val labelName = thisReference.labelName
val symbol = thisReference.boundSymbol
when {
symbol != null -> print("@R|${symbol.render()}|")
labelName != null -> print("@$labelName#")
else -> print("#")
}
}
override fun visitSuperReference(superReference: FirSuperReference) {
print("super<")
superReference.superTypeRef.accept(this)
print(">")
superReference.labelName?.let {
print("@$it#")
}
}
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) {
val explicitReceiver = qualifiedAccess.explicitReceiver
val dispatchReceiver = qualifiedAccess.dispatchReceiver
val extensionReceiver = qualifiedAccess.extensionReceiver
var hasSomeReceiver = true
when {
dispatchReceiver !is FirNoReceiverExpression && extensionReceiver !is FirNoReceiverExpression -> {
print("(")
dispatchReceiver.accept(this)
print(", ")
extensionReceiver.accept(this)
print(")")
}
dispatchReceiver !is FirNoReceiverExpression -> {
dispatchReceiver.accept(this)
}
extensionReceiver !is FirNoReceiverExpression -> {
extensionReceiver.accept(this)
}
explicitReceiver != null -> {
explicitReceiver.accept(this)
}
else -> {
hasSomeReceiver = false
}
}
if (hasSomeReceiver) {
print(".")
}
}
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) {
checkNotNullCall.argument.accept(this)
print("!!")
}
override fun visitElvisExpression(elvisExpression: FirElvisExpression) {
elvisExpression.lhs.accept(this)
print(" ?: ")
elvisExpression.rhs.accept(this)
}
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) {
callableReferenceAccess.annotations.renderAnnotations()
callableReferenceAccess.explicitReceiver?.accept(this)
if (callableReferenceAccess.hasQuestionMarkAtLHS && callableReferenceAccess.explicitReceiver !is FirResolvedQualifier) {
print("?")
}
print("::")
callableReferenceAccess.calleeReference.accept(this)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
qualifiedAccessExpression.annotations.renderAnnotations()
visitQualifiedAccess(qualifiedAccessExpression)
qualifiedAccessExpression.calleeReference.accept(this)
qualifiedAccessExpression.typeArguments.renderTypeArguments()
}
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression) {
visitQualifiedAccessExpression(thisReceiverExpression)
}
override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast) {
visitQualifiedAccessExpression(expressionWithSmartcast)
}
private fun visitAssignment(operation: FirOperation, rValue: FirExpression) {
print(operation.operator)
print(" ")
rValue.accept(this)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment) {
variableAssignment.annotations.renderAnnotations()
visitQualifiedAccess(variableAssignment)
variableAssignment.lValue.accept(this)
print(" ")
visitAssignment(FirOperation.ASSIGN, variableAssignment.rValue)
}
override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall) {
augmentedArraySetCall.annotations.renderAnnotations()
print("ArraySet:[")
augmentedArraySetCall.assignCall.accept(this)
print("]")
}
override fun visitFunctionCall(functionCall: FirFunctionCall) {
functionCall.annotations.renderAnnotations()
visitQualifiedAccess(functionCall)
functionCall.calleeReference.accept(this)
functionCall.typeArguments.renderTypeArguments()
visitCall(functionCall)
}
override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression) {
print("CMP(${comparisonExpression.operation.operator}, ")
comparisonExpression.compareToCall.accept(this)
print(")")
}
override fun visitAssignmentOperatorStatement(assignmentOperatorStatement: FirAssignmentOperatorStatement) {
assignmentOperatorStatement.annotations.renderAnnotations()
print(assignmentOperatorStatement.operation.operator)
print("(")
assignmentOperatorStatement.leftArgument.accept(this@FirRenderer)
print(", ")
assignmentOperatorStatement.rightArgument.accept(this@FirRenderer)
print(")")
}
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall) {
equalityOperatorCall.annotations.renderAnnotations()
print(equalityOperatorCall.operation.operator)
visitCall(equalityOperatorCall)
}
override fun visitComponentCall(componentCall: FirComponentCall) {
visitFunctionCall(componentCall)
}
override fun visitGetClassCall(getClassCall: FirGetClassCall) {
getClassCall.annotations.renderAnnotations()
print("")
visitCall(getClassCall)
}
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
classReferenceExpression.annotations.renderAnnotations()
print("")
print("(")
classReferenceExpression.classTypeRef.accept(this)
print(")")
}
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
arrayOfCall.annotations.renderAnnotations()
print("")
visitCall(arrayOfCall)
}
override fun visitThrowExpression(throwExpression: FirThrowExpression) {
throwExpression.annotations.renderAnnotations()
print("throw ")
throwExpression.exception.accept(this)
}
override fun visitErrorExpression(errorExpression: FirErrorExpression) {
print("ERROR_EXPR(${errorExpression.diagnostic.reason})")
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) {
print("Q|")
val classId = resolvedQualifier.classId
if (classId != null) {
print(classId.asString())
} else {
print(resolvedQualifier.packageFqName.asString().replace(".", "/"))
}
if (resolvedQualifier.isNullableLHSForCallableReference) {
print("?")
}
print("|")
}
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression) {
binaryLogicExpression.leftOperand.accept(this)
print(" ${binaryLogicExpression.kind.token} ")
binaryLogicExpression.rightOperand.accept(this)
}
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference) {
visitNamedReference(errorNamedReference)
}
override fun visitLegacyRawContractDescription(legacyRawContractDescription: FirLegacyRawContractDescription) {
newLine()
print("[Contract description]")
renderInBraces("<", ">") {
legacyRawContractDescription.contractCall.accept(this)
newLine()
}
}
override fun visitRawContractDescription(rawContractDescription: FirRawContractDescription) {
newLine()
print("[Contract description]")
renderInBraces("<", ">") {
rawContractDescription.rawEffects.renderSeparatedWithNewlines()
newLine()
}
}
override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration) {
newLine()
print("[Effect declaration]")
renderInBraces("<", ">") {
println(buildString { effectDeclaration.effect.accept(ConeContractRenderer(this), null) })
}
}
override fun visitResolvedContractDescription(resolvedContractDescription: FirResolvedContractDescription) {
newLine()
println("[R|Contract description]")
renderInBraces("<", ">") {
resolvedContractDescription.effects
.map { it.effect }
.forEach {
println(buildString { it.accept(ConeContractRenderer(this), null) })
}
}
}
override fun visitContractDescription(contractDescription: FirContractDescription) {
require(contractDescription is FirEmptyContractDescription)
}
}