org.jetbrains.kotlin.fir.renderer.FirRenderer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2024 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.renderer
import org.jetbrains.kotlin.builtins.functions.AllowedToUsedOnlyInK1
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKindExtractor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirPackageDirective
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
import org.jetbrains.kotlin.fir.contracts.description.ConeContractRenderer
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.isCatchParameter
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
import java.util.*
class FirRenderer(
builder: StringBuilder = StringBuilder(),
override val annotationRenderer: FirAnnotationRenderer? = FirAnnotationRenderer(),
override val bodyRenderer: FirBodyRenderer? = FirBodyRenderer(),
override val callArgumentsRenderer: FirCallArgumentsRenderer? = FirCallArgumentsRenderer(),
override val classMemberRenderer: FirClassMemberRenderer? = FirClassMemberRenderer(),
override val contractRenderer: ConeContractRenderer? = ConeContractRenderer(),
override val declarationRenderer: FirDeclarationRenderer? = FirDeclarationRenderer(),
override val idRenderer: ConeIdRenderer = ConeIdRendererForDebugging(),
override val modifierRenderer: FirModifierRenderer? = FirAllModifierRenderer(),
override val packageDirectiveRenderer: FirPackageDirectiveRenderer? = null,
override val propertyAccessorRenderer: FirPropertyAccessorRenderer? = FirPropertyAccessorRenderer(),
override val resolvePhaseRenderer: FirResolvePhaseRenderer? = null,
override val typeRenderer: ConeTypeRenderer = ConeTypeRendererForDebugging(),
override val referencedSymbolRenderer: FirSymbolRenderer = FirSymbolRenderer(),
override val valueParameterRenderer: FirValueParameterRenderer? = FirValueParameterRenderer(),
override val errorExpressionRenderer: FirErrorExpressionRenderer? = FirErrorExpressionOnlyErrorRenderer(),
override val resolvedNamedReferenceRenderer: FirResolvedNamedReferenceRenderer = FirResolvedNamedReferenceRendererWithLabel(),
override val resolvedQualifierRenderer: FirResolvedQualifierRenderer = FirResolvedQualifierRendererWithLabel(),
private val lineBreakAfterContextReceivers: Boolean = true,
private val renderFieldAnnotationSeparately: Boolean = true,
override val getClassCallRenderer: FirGetClassCallRenderer = FirGetClassCallRendererForDebugging(),
) : FirRendererComponents {
override val visitor: Visitor = Visitor()
override val printer: FirPrinter = FirPrinter(builder)
companion object {
fun noAnnotationBodiesAccessorAndArguments(): FirRenderer = FirRenderer(
annotationRenderer = null,
bodyRenderer = null,
propertyAccessorRenderer = null,
callArgumentsRenderer = FirCallNoArgumentsRenderer(),
)
fun withResolvePhase(): FirRenderer = FirRenderer(
resolvePhaseRenderer = FirResolvePhaseRenderer(),
)
fun withDeclarationAttributes(): FirRenderer = FirRenderer(
declarationRenderer = FirDeclarationRendererWithAttributes(),
)
fun forReadability(): FirRenderer = FirRenderer(
typeRenderer = ConeTypeRenderer(),
idRenderer = ConeIdShortRenderer(),
classMemberRenderer = FirNoClassMemberRenderer(),
bodyRenderer = null,
propertyAccessorRenderer = null,
callArgumentsRenderer = FirCallNoArgumentsRenderer(),
modifierRenderer = FirPartialModifierRenderer(),
valueParameterRenderer = FirValueParameterRendererForReadability(),
declarationRenderer = FirDeclarationRenderer("local "),
)
}
init {
annotationRenderer?.components = this
bodyRenderer?.components = this
callArgumentsRenderer?.components = this
classMemberRenderer?.components = this
contractRenderer?.components = this
declarationRenderer?.components = this
idRenderer.builder = builder
modifierRenderer?.components = this
packageDirectiveRenderer?.components = this
propertyAccessorRenderer?.components = this
resolvePhaseRenderer?.components = this
typeRenderer.builder = builder
typeRenderer.idRenderer = idRenderer
referencedSymbolRenderer.components = this
valueParameterRenderer?.components = this
errorExpressionRenderer?.components = this
resolvedNamedReferenceRenderer.components = this
resolvedQualifierRenderer.components = this
getClassCallRenderer.components = this
}
fun renderElementAsString(element: FirElement, trim: Boolean = false): String {
element.accept(visitor)
return printer.toString().applyIf(trim, String::trim)
}
fun renderElementWithTypeAsString(element: FirElement): String {
print(element)
print(": ")
return renderElementAsString(element)
}
fun renderAsCallableDeclarationString(callableDeclaration: FirCallableDeclaration): String {
visitor.visitCallableDeclaration(callableDeclaration)
return printer.toString()
}
fun renderMemberDeclarationClass(firClass: FirClass) {
visitor.visitMemberDeclaration(firClass)
}
fun renderAnnotations(annotationContainer: FirAnnotationContainer) {
annotationRenderer?.render(annotationContainer)
}
fun renderSupertypes(regularClass: FirRegularClass) {
if (regularClass.superTypeRefs.isNotEmpty()) {
print(" : ")
renderSeparated(regularClass.superTypeRefs, visitor)
}
}
private fun Variance.renderVariance() {
label.let {
print(it)
if (it.isNotEmpty()) {
print(" ")
}
}
}
private fun renderContexts(contextReceivers: List) {
if (contextReceivers.isEmpty()) return
print("context(")
renderSeparated(contextReceivers, visitor)
print(")")
if (lineBreakAfterContextReceivers) {
printer.newLine()
} else {
print(" ")
}
}
private fun List.renderTypeParameters() {
if (isNotEmpty()) {
print("<")
renderSeparated(this, visitor)
print(">")
}
}
private fun List.renderTypeArguments() {
if (isNotEmpty()) {
print("<")
renderSeparated(this, visitor)
print(">")
}
}
private fun print(s: Any) {
printer.print(s)
}
private fun renderSeparated(elements: List, visitor: Visitor) {
printer.renderSeparated(elements, visitor)
}
private fun renderType(type: ConeKotlinType?) {
if (type == null) return
print("R|")
typeRenderer.render(type)
print("|")
}
inner class Visitor internal constructor() : FirVisitorVoid() {
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
override fun visitFile(file: FirFile) {
printer.print("FILE: ")
resolvePhaseRenderer?.render(file)
printer.println(file.name)
printer.pushIndent()
annotationRenderer?.render(file)
visitPackageDirective(file.packageDirective)
file.imports.forEach { it.accept(this) }
file.declarations.forEach { it.accept(this) }
printer.popIndent()
}
override fun visitScript(script: FirScript) {
annotationRenderer?.render(script)
printer.print("SCRIPT: ")
declarationRenderer?.renderPhaseAndAttributes(script) ?: resolvePhaseRenderer?.render(script)
printer.println(script.name)
printer.pushIndent()
// following the function convention, although in a compiled script parameters are passed before receivers
script.receivers.forEach {
it.accept(this)
printer.newLine()
}
script.parameters.forEach {
it.accept(this)
printer.newLine()
}
printer.newLine()
script.declarations.forEach {
it.accept(this)
printer.newLine()
}
printer.popIndent()
}
override fun visitScriptReceiverParameter(scriptReceiverParameter: FirScriptReceiverParameter) {
print("