diff --git a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt index d8410ce9a3a..6fae7563b5d 100644 --- a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt +++ b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt @@ -1312,8 +1312,11 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver } } - private fun FlowContent.generate(functionCall: FirFunctionCall) { - generateReceiver(functionCall) + private fun FlowContent.generate(functionCall: FirFunctionCall, skipReceiver: Boolean = false) { + + if (!skipReceiver) { + generateReceiver(functionCall) + } generate(functionCall.calleeReference) generateTypeProjections(functionCall.typeArguments) @@ -1567,6 +1570,10 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver is FirVarargArgumentsExpression -> generate(expression) is FirResolvedReifiedParameterReference -> generate(expression) is FirComparisonExpression -> generate(expression) + is FirSafeCallExpression -> generate(expression) + is FirCheckedSafeCallSubject -> { + +"\$subj\$" + } else -> inlineUnsupported(expression) } } @@ -1578,6 +1585,30 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver generate(comparisonExpression.right) } + private fun FlowContent.generate(safeCallExpression: FirSafeCallExpression) { + generate(safeCallExpression.receiver) + + +"?." + + val nestedQualifier = safeCallExpression.regularQualifiedAccess + if (nestedQualifier.explicitReceiver == safeCallExpression.checkedSubject.value) { + when (nestedQualifier) { + is FirFunctionCall -> { + return generate(nestedQualifier, skipReceiver = true) + } + is FirQualifiedAccessExpression -> { + return generate(nestedQualifier, skipReceiver = true) + } + } + } + + +"{ " + + generate(nestedQualifier) + + +" }" + } + private fun FlowContent.generate(resolvedReifiedParameterReference: FirResolvedReifiedParameterReference) { val typeParameter = resolvedReifiedParameterReference.symbol.fir +typeParameter.name.identifier @@ -1593,8 +1624,10 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver generate(binaryLogicExpression.rightOperand) } - private fun FlowContent.generate(qualifiedAccessExpression: FirQualifiedAccessExpression) { - generateReceiver(qualifiedAccessExpression) + private fun FlowContent.generate(qualifiedAccessExpression: FirQualifiedAccessExpression, skipReceiver: Boolean = false) { + if (!skipReceiver) { + generateReceiver(qualifiedAccessExpression) + } generate(qualifiedAccessExpression.calleeReference) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index 8e03baacdfc..580eeeb82a2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -510,6 +510,17 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM } } + 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) } diff --git a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt index 13f215e4cfd..b563a2663b1 100644 --- a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt +++ b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt @@ -406,6 +406,17 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { //skip rendering for as/as?/is/!is } + override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: StringBuilder) { + safeCallExpression.receiver.accept(this, data) + data.append("?.{ ") + safeCallExpression.regularQualifiedAccess.accept(this, data) + data.append(" }") + } + + override fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: StringBuilder) { + data.append("\$subj\$") + } + override fun visitFunctionCall(functionCall: FirFunctionCall, data: StringBuilder) { when (val callee = functionCall.calleeReference) { is FirResolvedNamedReference -> {