FIR renderer: extract separate ConeTypeRenderer
This commit is contained in:
+1
-1
@@ -161,7 +161,7 @@ internal class KtFirTypeProvider(
|
||||
|
||||
require(typeParameterSymbols.size == argumentTypes.size) {
|
||||
"'${symbol.fir.render(FirRenderer.RenderMode.NoBodies)}' expects '${typeParameterSymbols.size}' type arguments " +
|
||||
"but type '${this.render()}' has ${argumentTypes.size} type arguments."
|
||||
"but type '${this.renderForDebugging()}' has ${argumentTypes.size} type arguments."
|
||||
}
|
||||
|
||||
val substitutor = substitutorByMap(typeParameterSymbols.zip(argumentTypes).toMap(), session)
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ internal class ConeTypeIdeRenderer(
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
renderAnnotationList(type)
|
||||
append(type.render())
|
||||
append(type.renderReadableWithFqNames())
|
||||
renderNullability(type.type)
|
||||
}
|
||||
is ConeDefinitelyNotNullType -> {
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtCapturedType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeCapturedType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirCapturedType(
|
||||
override val coneType: ConeCapturedType,
|
||||
@@ -27,7 +27,7 @@ internal class KtFirCapturedType(
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
|
||||
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirClassErrorType(
|
||||
override val coneType: ConeErrorType,
|
||||
@@ -37,7 +37,7 @@ internal class KtFirClassErrorType(
|
||||
symbols.map { builder.classifierBuilder.buildClassLikeSymbol(it) }
|
||||
}
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtDefinitelyNotNullType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.fir.types.ConeDefinitelyNotNullType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirDefinitelyNotNullType(
|
||||
override val coneType: ConeDefinitelyNotNullType,
|
||||
@@ -26,7 +26,7 @@ internal class KtFirDefinitelyNotNullType(
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtDynamicType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeDynamicType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirDynamicType(
|
||||
override val coneType: ConeDynamicType,
|
||||
@@ -26,7 +26,7 @@ internal class KtFirDynamicType(
|
||||
}
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtFlexibleType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeFlexibleType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirFlexibleType(
|
||||
override val coneType: ConeFlexibleType,
|
||||
@@ -30,7 +30,7 @@ internal class KtFirFlexibleType(
|
||||
}
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.types.receiverType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
internal class KtFirFunctionalType(
|
||||
@@ -73,7 +73,7 @@ internal class KtFirFunctionalType(
|
||||
override val returnType: KtType
|
||||
get() = withValidityAssertion { (typeArguments.last() as KtTypeArgumentWithVariance).type }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtClassType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtIntegerLiteralType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralConstantType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirIntegerLiteralType(
|
||||
override val coneType: ConeIntegerLiteralConstantType,
|
||||
@@ -38,7 +38,7 @@ internal class KtFirIntegerLiteralType(
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtIntersectionType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntersectionType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirIntersectionType(
|
||||
override val coneType: ConeIntersectionType,
|
||||
@@ -30,7 +30,7 @@ internal class KtFirIntersectionType(
|
||||
}
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeParameterType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class KtFirTypeParameterType(
|
||||
@@ -35,7 +35,7 @@ internal class KtFirTypeParameterType(
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtUsualClassType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
internal class KtFirUsualClassType(
|
||||
@@ -40,7 +40,7 @@ internal class KtFirUsualClassType(
|
||||
}
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
+2
-2
@@ -52,8 +52,8 @@ abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFi
|
||||
bodyBuildingMode = BodyBuildingMode.NORMAL
|
||||
).buildFirFile(ktFile)
|
||||
|
||||
val laziedFirFileDump = StringBuilder().also { FirRenderer(it).visitFile(laziedFirFile) }.toString()
|
||||
val fullFirFileDump = StringBuilder().also { FirRenderer(it).visitFile(fullFirFile) }.toString()
|
||||
val laziedFirFileDump = StringBuilder().also { FirRenderer(it).Visitor().visitFile(laziedFirFile) }.toString()
|
||||
val fullFirFileDump = StringBuilder().also { FirRenderer(it).Visitor().visitFile(fullFirFile) }.toString()
|
||||
|
||||
TestCase.assertEquals(laziedFirFileDump, fullFirFileDump)
|
||||
}
|
||||
|
||||
+2
-2
@@ -37,14 +37,14 @@ abstract class AbstractFirLoadBinariesTest : AbstractFirResolveWithSessionTestCa
|
||||
|
||||
for (name in declarationNames) {
|
||||
for (symbol in provider.getTopLevelCallableSymbols(packageFqName, name)) {
|
||||
symbol.fir.accept(firRenderer)
|
||||
symbol.fir.accept(firRenderer.Visitor())
|
||||
builder.appendLine()
|
||||
}
|
||||
}
|
||||
|
||||
for (name in declarationNames) {
|
||||
val classLikeSymbol = provider.getClassLikeSymbolByClassId(ClassId.topLevel(packageFqName.child(name))) ?: continue
|
||||
classLikeSymbol.fir.accept(firRenderer)
|
||||
classLikeSymbol.fir.accept(firRenderer.Visitor())
|
||||
builder.appendLine()
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -24,9 +24,10 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir
|
||||
val memberScope = javaClass.unsubstitutedScope(session, ScopeSession(), withForcedTypeCalculator = true)
|
||||
|
||||
val staticScope = javaClass.scopeProvider.getStaticScope(javaClass, session, ScopeSession())
|
||||
val visitor = renderer.Visitor()
|
||||
|
||||
renderer.renderAnnotations(javaClass)
|
||||
renderer.visitMemberDeclaration(javaClass)
|
||||
visitor.visitMemberDeclaration(javaClass)
|
||||
renderer.renderSupertypes(javaClass)
|
||||
renderer.renderInBraces {
|
||||
val renderedDeclarations = mutableListOf<FirDeclaration>()
|
||||
@@ -34,7 +35,7 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir
|
||||
fun renderAndCache(symbol: FirCallableSymbol<*>) {
|
||||
val enhanced = symbol.fir
|
||||
if (enhanced !in renderedDeclarations) {
|
||||
enhanced.accept(renderer, null)
|
||||
enhanced.accept(visitor, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += enhanced
|
||||
}
|
||||
@@ -55,7 +56,7 @@ fun renderJavaClass(renderer: FirRenderer, javaClass: FirJavaClass, session: Fir
|
||||
is FirJavaField -> scopeToUse!!.processPropertiesByName(declaration.name, ::renderAndCache)
|
||||
is FirEnumEntry -> scopeToUse!!.processPropertiesByName(declaration.name, ::renderAndCache)
|
||||
else -> {
|
||||
declaration.accept(renderer, null)
|
||||
declaration.accept(visitor, null)
|
||||
renderer.newLine()
|
||||
renderedDeclarations += declaration
|
||||
}
|
||||
|
||||
+2
-5
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateErr
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableWrongReceiver
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
@@ -72,7 +69,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() {
|
||||
val errorNamedReference = functionCall.calleeReference as? FirErrorNamedReference ?: return false
|
||||
if (errorNamedReference.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false
|
||||
val expectedFunctionSignature =
|
||||
(if (isGet) "getValue" else "setValue") + "(${functionCall.arguments.joinToString(", ") { it.typeRef.coneType.render() }})"
|
||||
(if (isGet) "getValue" else "setValue") + "(${functionCall.arguments.joinToString(", ") { it.typeRef.coneType.renderReadable() }})"
|
||||
val delegateDescription = if (isGet) "delegate" else "delegate for var (read-write property)"
|
||||
|
||||
fun reportInapplicableDiagnostics(candidates: Collection<FirBasedSymbol<*>>) {
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
class ErrorNodeDiagnosticCollectorComponent(
|
||||
session: FirSession,
|
||||
@@ -42,7 +42,7 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) {
|
||||
assert(resolvedTypeRef.type !is ConeErrorType) {
|
||||
"Instead use FirErrorTypeRef for ${resolvedTypeRef.type.render()}"
|
||||
"Instead use FirErrorTypeRef for ${resolvedTypeRef.type.renderForDebugging()}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
import org.jetbrains.kotlin.fir.types.renderReadableWithFqNames
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
|
||||
object FirDiagnosticRenderers {
|
||||
@@ -89,7 +89,7 @@ object FirDiagnosticRenderers {
|
||||
|
||||
val RENDER_TYPE = Renderer { t: ConeKotlinType ->
|
||||
// TODO: need a way to tune granuality, e.g., without parameter names in functional types.
|
||||
t.render()
|
||||
t.renderReadableWithFqNames()
|
||||
}
|
||||
|
||||
val FQ_NAMES_IN_TYPES = Renderer { symbol: FirBasedSymbol<*> ->
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
open class ConeTypeRenderer(protected val builder: StringBuilder) {
|
||||
|
||||
open fun renderAsPossibleFunctionType(
|
||||
type: ConeKotlinType, renderType: ConeTypeProjection.() -> Unit = { render() }
|
||||
) {
|
||||
val kind = type.functionTypeKind
|
||||
if (!kind.withPrettyRender()) {
|
||||
type.renderType()
|
||||
return
|
||||
}
|
||||
|
||||
if (type.isMarkedNullable) {
|
||||
builder.append("(")
|
||||
}
|
||||
if (kind == FunctionClassKind.SuspendFunction) {
|
||||
builder.append("suspend ")
|
||||
}
|
||||
val typeArguments = type.typeArguments
|
||||
val isExtension = type.isExtensionFunctionType
|
||||
val (receiver, otherTypeArguments) = if (isExtension && typeArguments.first() != ConeStarProjection) {
|
||||
typeArguments.first() to typeArguments.drop(1)
|
||||
} else {
|
||||
null to typeArguments.toList()
|
||||
}
|
||||
val arguments = otherTypeArguments.subList(0, otherTypeArguments.size - 1)
|
||||
val returnType = otherTypeArguments.last()
|
||||
if (receiver != null) {
|
||||
receiver.render()
|
||||
builder.append(".")
|
||||
}
|
||||
builder.append("(")
|
||||
for ((index, argument) in arguments.withIndex()) {
|
||||
if (index != 0) {
|
||||
builder.append(", ")
|
||||
}
|
||||
argument.render()
|
||||
}
|
||||
builder.append(") -> ")
|
||||
returnType.render()
|
||||
if (type.isMarkedNullable) {
|
||||
builder.append(")?")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
private fun FunctionClassKind?.withPrettyRender(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@withPrettyRender != null)
|
||||
}
|
||||
return this != null && this != FunctionClassKind.KSuspendFunction && this != FunctionClassKind.KFunction
|
||||
}
|
||||
|
||||
fun render(type: ConeKotlinType) {
|
||||
if (type !is ConeFlexibleType && type !is ConeDefinitelyNotNullType) {
|
||||
// We don't render attributes for flexible/definitely not null types here,
|
||||
// because bounds duplicate these attributes often
|
||||
type.renderAttributes()
|
||||
}
|
||||
when (type) {
|
||||
is ConeTypeVariableType -> {
|
||||
builder.append("TypeVariable(")
|
||||
builder.append(type.lookupTag.name)
|
||||
builder.append(")")
|
||||
}
|
||||
is ConeDefinitelyNotNullType -> {
|
||||
render(type.original)
|
||||
builder.append(" & Any")
|
||||
}
|
||||
is ConeErrorType -> {
|
||||
builder.append("ERROR CLASS: ${type.diagnostic.reason}")
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
builder.append("CapturedType(")
|
||||
type.constructor.projection.render()
|
||||
builder.append(")")
|
||||
}
|
||||
is ConeClassLikeType -> {
|
||||
type.render()
|
||||
}
|
||||
is ConeLookupTagBasedType -> {
|
||||
builder.append(type.lookupTag.name.asString())
|
||||
}
|
||||
is ConeDynamicType -> {
|
||||
builder.append("dynamic")
|
||||
}
|
||||
is ConeFlexibleType -> {
|
||||
type.render()
|
||||
}
|
||||
is ConeIntersectionType -> {
|
||||
builder.append("it(")
|
||||
for ((index, intersected) in type.intersectedTypes.withIndex()) {
|
||||
if (index > 0) {
|
||||
builder.append(" & ")
|
||||
}
|
||||
render(intersected)
|
||||
}
|
||||
builder.append(")")
|
||||
}
|
||||
is ConeStubTypeForSyntheticFixation -> {
|
||||
builder.append("Stub (fixation): ${type.constructor.variable}")
|
||||
}
|
||||
is ConeStubTypeForChainInference -> {
|
||||
builder.append("Stub (chain inference): ${type.constructor.variable}")
|
||||
}
|
||||
is ConeStubType -> {
|
||||
builder.append("Stub (subtyping): ${type.constructor.variable}")
|
||||
}
|
||||
is ConeIntegerLiteralConstantType -> {
|
||||
builder.append("ILT: ${type.value}")
|
||||
}
|
||||
is ConeIntegerConstantOperatorType -> {
|
||||
builder.append("IOT")
|
||||
}
|
||||
}
|
||||
if (type !is ConeFlexibleType && type !is ConeErrorType) {
|
||||
builder.append(type.nullability.suffix)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeClassLikeType.render() {
|
||||
lookupTag.classId.render()
|
||||
if (typeArguments.isEmpty()) return
|
||||
builder.append("<")
|
||||
for ((index, typeArgument) in typeArguments.withIndex()) {
|
||||
if (index > 0) {
|
||||
builder.append(", ")
|
||||
}
|
||||
typeArgument.render()
|
||||
}
|
||||
builder.append(">")
|
||||
}
|
||||
|
||||
protected open fun ClassId.render() {
|
||||
builder.append(relativeClassName.asString())
|
||||
}
|
||||
|
||||
private fun ConeFlexibleType.render() {
|
||||
val lowerBound = lowerBound
|
||||
val upperBound = upperBound
|
||||
if (lowerBound is ConeLookupTagBasedType && upperBound is ConeLookupTagBasedType &&
|
||||
lowerBound.lookupTag == upperBound.lookupTag &&
|
||||
lowerBound.nullability == ConeNullability.NOT_NULL && upperBound.nullability == ConeNullability.NULLABLE
|
||||
) {
|
||||
if (lowerBound !is ConeClassLikeType || lowerBound.typeArguments.isEmpty()) {
|
||||
if (upperBound !is ConeClassLikeType || upperBound.typeArguments.isEmpty()) {
|
||||
render(lowerBound)
|
||||
builder.append("!")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.append("ft<")
|
||||
render(lowerBound)
|
||||
builder.append(", ")
|
||||
render(upperBound)
|
||||
builder.append(">")
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.renderAttributes() {
|
||||
if (!attributes.any()) return
|
||||
builder.append(attributes.joinToString(" ", postfix = " ") { it.toString() })
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.render() {
|
||||
when (this) {
|
||||
ConeStarProjection -> {
|
||||
builder.append("*")
|
||||
}
|
||||
is ConeKotlinTypeConflictingProjection -> {
|
||||
builder.append("CONFLICTING-PROJECTION ")
|
||||
render(type)
|
||||
}
|
||||
is ConeKotlinTypeProjectionIn -> {
|
||||
builder.append("in ")
|
||||
render(type)
|
||||
}
|
||||
is ConeKotlinTypeProjectionOut -> {
|
||||
builder.append("out ")
|
||||
render(type)
|
||||
}
|
||||
is ConeKotlinType -> {
|
||||
render(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeProjection
|
||||
|
||||
class ConeTypeRendererForDebugging(builder: StringBuilder) : ConeTypeRendererWithFqNames(builder) {
|
||||
override fun renderAsPossibleFunctionType(type: ConeKotlinType, renderType: ConeTypeProjection.() -> Unit) {
|
||||
builder.append("R|")
|
||||
super.renderAsPossibleFunctionType(type, renderType)
|
||||
builder.append("|")
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.name.ClassId
|
||||
|
||||
open class ConeTypeRendererWithFqNames(builder: StringBuilder) : ConeTypeRenderer(builder) {
|
||||
override fun ClassId.render() {
|
||||
builder.append(asString())
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRenderer
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererForDebugging
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererWithFqNames
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -107,3 +111,30 @@ fun ConeClassLikeType.replaceArgumentsWithStarProjections(): ConeClassLikeType {
|
||||
val newArguments = Array(typeArguments.size) { ConeStarProjection }
|
||||
return withArguments(newArguments)
|
||||
}
|
||||
|
||||
val ConeKotlinType?.functionTypeKind: FunctionClassKind?
|
||||
get() {
|
||||
val classId = (this as? ConeClassLikeType)?.lookupTag?.classId ?: return null
|
||||
return FunctionClassKind.getFunctionalClassKind(
|
||||
classId.shortClassName.asString(), classId.packageFqName
|
||||
)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.renderForDebugging(): String {
|
||||
val builder = StringBuilder()
|
||||
ConeTypeRendererForDebugging(builder).render(this)
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun ConeKotlinType.renderReadable(): String {
|
||||
val builder = StringBuilder()
|
||||
ConeTypeRenderer(builder).render(this)
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun ConeKotlinType.renderReadableWithFqNames(): String {
|
||||
val builder = StringBuilder()
|
||||
ConeTypeRendererWithFqNames(builder).render(this)
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ sealed class ConeKotlinType : ConeKotlinTypeProjection(), KotlinTypeMarker, Type
|
||||
abstract val attributes: ConeAttributes
|
||||
|
||||
final override fun toString(): String {
|
||||
return render()
|
||||
return renderForDebugging()
|
||||
}
|
||||
|
||||
abstract override fun equals(other: Any?): Boolean
|
||||
@@ -160,7 +160,7 @@ data class ConeCapturedType(
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 0
|
||||
var result = 7
|
||||
result = 31 * result + (lowerType?.hashCode() ?: 0)
|
||||
result = 31 * result + constructor.projection.hashCode()
|
||||
result = 31 * result + constructor.typeParameterMarker.hashCode()
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
fun ConeKotlinType.render(renderFqNames: Boolean = true): String {
|
||||
val nullabilitySuffix = if (this !is ConeFlexibleType && this !is ConeErrorType) nullability.suffix else ""
|
||||
return when (this) {
|
||||
is ConeTypeVariableType -> "${renderAttributes()}TypeVariable(${this.lookupTag.name})"
|
||||
is ConeDefinitelyNotNullType -> "${original.render(renderFqNames)} & Any"
|
||||
is ConeErrorType -> "${renderAttributes()}ERROR CLASS: ${diagnostic.reason}"
|
||||
is ConeCapturedType -> "${renderAttributes()}CapturedType(${constructor.projection.render(renderFqNames)})"
|
||||
is ConeClassLikeType -> {
|
||||
buildString {
|
||||
append(renderAttributes())
|
||||
if (renderFqNames) {
|
||||
append(lookupTag.classId.asString())
|
||||
} else {
|
||||
append(lookupTag.classId.relativeClassName.asString())
|
||||
}
|
||||
if (typeArguments.isNotEmpty()) {
|
||||
append(typeArguments.joinToString(prefix = "<", postfix = ">") {
|
||||
it.render(renderFqNames)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
is ConeLookupTagBasedType -> {
|
||||
"${renderAttributes()}${lookupTag.name.asString()}"
|
||||
}
|
||||
is ConeDynamicType -> "dynamic"
|
||||
is ConeFlexibleType -> this.render(renderFqNames)
|
||||
is ConeIntersectionType -> {
|
||||
intersectedTypes.joinToString(
|
||||
separator = " & ",
|
||||
prefix = "${renderAttributes()}it(",
|
||||
postfix = ")"
|
||||
) {
|
||||
it.render(renderFqNames)
|
||||
}
|
||||
}
|
||||
is ConeStubTypeForSyntheticFixation -> "${renderAttributes()}Stub (fixation): ${constructor.variable}"
|
||||
is ConeStubTypeForChainInference -> "${renderAttributes()}Stub (chain inference): ${constructor.variable}"
|
||||
is ConeStubType -> "${renderAttributes()}Stub (subtyping): ${constructor.variable}"
|
||||
is ConeIntegerLiteralConstantType -> "${renderAttributes()}ILT: $value"
|
||||
is ConeIntegerConstantOperatorType -> "${renderAttributes()}IOT"
|
||||
} + nullabilitySuffix
|
||||
}
|
||||
|
||||
private fun ConeFlexibleType.render(renderFqNames: Boolean): String {
|
||||
if (lowerBound is ConeLookupTagBasedType && upperBound is ConeLookupTagBasedType &&
|
||||
lowerBound.lookupTag == upperBound.lookupTag &&
|
||||
lowerBound.nullability == ConeNullability.NOT_NULL && upperBound.nullability == ConeNullability.NULLABLE
|
||||
) {
|
||||
if (lowerBound !is ConeClassLikeType || lowerBound.typeArguments.isEmpty()) {
|
||||
if (upperBound !is ConeClassLikeType || upperBound.typeArguments.isEmpty()) {
|
||||
return buildString {
|
||||
append(lowerBound.render(renderFqNames))
|
||||
append("!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return buildString {
|
||||
append("ft<")
|
||||
append(lowerBound.render(renderFqNames))
|
||||
append(", ")
|
||||
append(upperBound.render(renderFqNames))
|
||||
append(">")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.renderAttributes(): String {
|
||||
if (!attributes.any()) return ""
|
||||
return attributes.joinToString(" ", postfix = " ") { it.toString() }
|
||||
}
|
||||
|
||||
fun ConeTypeProjection.render(renderFqNames: Boolean): String {
|
||||
return when (this) {
|
||||
ConeStarProjection -> "*"
|
||||
is ConeKotlinTypeConflictingProjection -> "CONFLICTING-PROJECTION ${type.render(renderFqNames)}"
|
||||
is ConeKotlinTypeProjectionIn -> "in ${type.render(renderFqNames)}"
|
||||
is ConeKotlinTypeProjectionOut -> "out ${type.render(renderFqNames)}"
|
||||
is ConeKotlinType -> render(renderFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.renderFunctionType(
|
||||
kind: FunctionClassKind?, renderFqNames: Boolean, renderType: ConeTypeProjection.() -> String = { render(renderFqNames) }
|
||||
): String {
|
||||
if (!kind.withPrettyRender()) return renderType()
|
||||
|
||||
val isExtension = isExtensionFunctionType
|
||||
|
||||
val renderedType = buildString {
|
||||
if (kind == FunctionClassKind.SuspendFunction) {
|
||||
append("suspend ")
|
||||
}
|
||||
val (receiver, otherTypeArguments) = if (isExtension && typeArguments.first() != ConeStarProjection) {
|
||||
typeArguments.first() to typeArguments.drop(1)
|
||||
} else {
|
||||
null to typeArguments.toList()
|
||||
}
|
||||
val arguments = otherTypeArguments.subList(0, otherTypeArguments.size - 1)
|
||||
val returnType = otherTypeArguments.last()
|
||||
if (receiver != null) {
|
||||
append(receiver.renderType())
|
||||
append(".")
|
||||
}
|
||||
append(arguments.joinToString(", ", "(", ")") { it.renderType() })
|
||||
append(" -> ")
|
||||
append(returnType.renderType())
|
||||
}
|
||||
return if (isMarkedNullable) "($renderedType)?" else renderedType
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun FunctionClassKind?.withPrettyRender(): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@withPrettyRender != null)
|
||||
}
|
||||
return this != null && this != FunctionClassKind.KSuspendFunction && this != FunctionClassKind.KFunction
|
||||
}
|
||||
+3
-3
@@ -685,15 +685,15 @@ class FirElementSerializer private constructor(
|
||||
typeApproximator.approximateToSubType(type, TypeApproximatorConfiguration.PublicDeclaration)
|
||||
}
|
||||
assert(approximatedType != type && approximatedType is ConeKotlinType) {
|
||||
"Approximation failed: ${type.render()}"
|
||||
"Approximation failed: ${type.renderForDebugging()}"
|
||||
}
|
||||
return typeProto(approximatedType as ConeKotlinType)
|
||||
}
|
||||
is ConeIntegerLiteralType -> {
|
||||
throw IllegalStateException("Integer literal types should not persist up to the serializer: ${type.render()}")
|
||||
throw IllegalStateException("Integer literal types should not persist up to the serializer: ${type.renderForDebugging()}")
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
throw IllegalStateException("Captured types should not persist up to the serializer: ${type.render()}")
|
||||
throw IllegalStateException("Captured types should not persist up to the serializer: ${type.renderForDebugging()}")
|
||||
}
|
||||
else -> {
|
||||
throw AssertionError("Should not be here: ${type::class.java}")
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext<JvmSignatur
|
||||
val toIndex = firClass.typeParameters.count { it is FirTypeParameter } + index
|
||||
if (!firClass.isInner) {
|
||||
assert(toIndex == typeArguments.size || firClass.isLocal) {
|
||||
"${typeArguments.size - toIndex} trailing arguments were found in this type: ${render()}"
|
||||
"${typeArguments.size - toIndex} trailing arguments were found in this type: ${renderForDebugging()}"
|
||||
}
|
||||
return PossiblyInnerConeType(classifier, typeArguments.toList().subList(index, typeArguments.size), null)
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
override fun KotlinTypeMarker.getFunctionalTypeFromSupertypes(): KotlinTypeMarker {
|
||||
require(this is ConeKotlinType)
|
||||
assert(this.isBuiltinFunctionalTypeOrSubtype()) {
|
||||
"Not a function type or subtype: ${this.render()}"
|
||||
"Not a function type or subtype: ${this.renderForDebugging()}"
|
||||
}
|
||||
|
||||
return fullyExpandedType(session).let {
|
||||
|
||||
@@ -122,7 +122,7 @@ fun <T : ConeKotlinType> T.withArguments(arguments: Array<out ConeTypeProjection
|
||||
is ConeErrorType -> this
|
||||
is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, arguments, nullability.isNullable) as T
|
||||
is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withArguments(arguments)) as T
|
||||
else -> error("Not supported: $this: ${this.render()}")
|
||||
else -> error("Not supported: $this: ${this.renderForDebugging()}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ fun <T : ConeKotlinType> T.withAttributes(attributes: ConeAttributes): T {
|
||||
// Attributes for stub types are not supported, and it's not obvious if it should
|
||||
is ConeStubType -> this
|
||||
is ConeIntegerLiteralType -> this
|
||||
else -> error("Not supported: $this: ${this.render()}")
|
||||
else -> error("Not supported: $this: ${this.renderForDebugging()}")
|
||||
} as T
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ class TotalKotlinTest : AbstractRawFirBuilderTestCase() {
|
||||
DebugUtil.psiTreeToString(ktFile, false)
|
||||
} else {
|
||||
val firFile = ktFile.toFirFile()
|
||||
StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
||||
StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFile) }.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class TotalKotlinTest : AbstractRawFirBuilderTestCase() {
|
||||
DebugUtil.lightTreeToString(lightTree, false)
|
||||
} else {
|
||||
val firFile = converter.buildFirFile(text, sourceFile, linesMapping)
|
||||
StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
||||
StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFile) }.toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -72,12 +72,12 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
|
||||
//psi
|
||||
val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text.toString().trim()) as KtFile
|
||||
val firFileFromPsi = ktFile.toFirFile()
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).visitFile(firFileFromPsi) }.toString()
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFileFromPsi) }.toString()
|
||||
.replace("<ERROR TYPE REF:.*?>".toRegex(), "<ERROR TYPE REF>")
|
||||
|
||||
//light tree
|
||||
val firFileFromLightTree = lightTreeConverter.buildFirFile(text, KtIoFileSourceFile(file), linesMapping)
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).visitFile(firFileFromLightTree) }.toString()
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFileFromLightTree) }.toString()
|
||||
.replace("<ERROR TYPE REF:.*?>".toRegex(), "<ERROR TYPE REF>")
|
||||
|
||||
return@compareBase treeFromLightTree == treeFromPsi
|
||||
@@ -104,7 +104,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
|
||||
//psi
|
||||
val ktFile = createPsiFile(FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.path)), text) as KtFile
|
||||
val firFileFromPsi = ktFile.toFirFile()
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).visitFile(firFileFromPsi) }.toString()
|
||||
val treeFromPsi = StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFileFromPsi) }.toString()
|
||||
.replace("<Unsupported LValue.*?>".toRegex(), "<Unsupported LValue>")
|
||||
.replace("<ERROR TYPE REF:.*?>".toRegex(), "<ERROR TYPE REF>")
|
||||
|
||||
@@ -115,7 +115,7 @@ class TreesCompareTest : AbstractRawFirBuilderTestCase() {
|
||||
KtInMemoryTextSourceFile(file.name, file.path, text),
|
||||
text.toSourceLinesMapping()
|
||||
)
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).visitFile(firFileFromLightTree) }.toString()
|
||||
val treeFromLightTree = StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFileFromLightTree) }.toString()
|
||||
.replace("<Unsupported LValue.*?>".toRegex(), "<Unsupported LValue>")
|
||||
.replace("<ERROR TYPE REF:.*?>".toRegex(), "<ERROR TYPE REF>")
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ abstract class AbstractRawFirBuilderLazyBodiesTestCase : AbstractRawFirBuilderTe
|
||||
override fun doRawFirTest(filePath: String) {
|
||||
val file = createKtFile(filePath)
|
||||
val firFile = file.toFirFile(BodyBuildingMode.LAZY_BODIES)
|
||||
val firFileDump = StringBuilder().also { FirRenderer(it).visitFile(firFile) }.toString()
|
||||
val firFileDump = StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFile) }.toString()
|
||||
val expectedPath = filePath.replace(".kt", ".lazyBodies.txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
}
|
||||
|
||||
+4
-2
@@ -65,7 +65,9 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
||||
protected open fun doRawFirTest(filePath: String) {
|
||||
val file = createKtFile(filePath)
|
||||
val firFile = file.toFirFile(BodyBuildingMode.NORMAL)
|
||||
val firFileDump = StringBuilder().also { FirRenderer(it, mode = FirRenderer.RenderMode.WithDeclarationAttributes).visitFile(firFile) }.toString()
|
||||
val firFileDump = StringBuilder().also {
|
||||
FirRenderer(it, mode = FirRenderer.RenderMode.WithDeclarationAttributes).Visitor().visitFile(firFile)
|
||||
}.toString()
|
||||
val expectedPath = filePath.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
|
||||
}
|
||||
@@ -191,7 +193,7 @@ private fun throwTwiceVisitingError(element: FirElement) {
|
||||
if (psiParent is KtPropertyDelegate || psiParent?.parent is KtPropertyDelegate) return
|
||||
}
|
||||
|
||||
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
|
||||
val elementDump = StringBuilder().also { element.accept(FirRenderer(it).Visitor()) }.toString()
|
||||
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
time += measureNanoTime {
|
||||
firFile = ktFile.toFirFile()
|
||||
}
|
||||
totalLength += StringBuilder().also { FirRenderer(it).visitFile(firFile) }.length
|
||||
totalLength += StringBuilder().also { FirRenderer(it).Visitor().visitFile(firFile) }.length
|
||||
counter++
|
||||
firFile.accept(object : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
|
||||
@@ -20,7 +20,7 @@ abstract class FirLookupTrackerComponent : FirSessionComponent {
|
||||
|
||||
fun FirLookupTrackerComponent.recordCallLookup(callInfo: AbstractCallInfo, inType: ConeKotlinType) {
|
||||
if (inType.classId?.isLocal == true) return
|
||||
val scopes = SmartList(inType.render().replace('/', '.'))
|
||||
val scopes = SmartList(inType.renderForDebugging().replace('/', '.'))
|
||||
if (inType.classId?.shortClassName?.asString() == "Companion") {
|
||||
scopes.add(inType.classId!!.outerClassId!!.asString().replace('/', '.'))
|
||||
}
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
|
||||
+3
-1
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.contracts.description
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
class ConeContractRenderer(private val builder: StringBuilder) : ConeContractDescriptionVisitor<Unit, Nothing?>() {
|
||||
override fun visitConditionalEffectDeclaration(conditionalEffect: ConeConditionalEffectDeclaration, data: Nothing?) {
|
||||
conditionalEffect.effect.accept(this, data)
|
||||
@@ -37,7 +39,7 @@ class ConeContractRenderer(private val builder: StringBuilder) : ConeContractDes
|
||||
|
||||
override fun visitIsInstancePredicate(isInstancePredicate: ConeIsInstancePredicate, data: Nothing?) {
|
||||
isInstancePredicate.arg.accept(this, data)
|
||||
builder.append(" ${if (isInstancePredicate.isNegated) "!" else ""}is ${isInstancePredicate.type}")
|
||||
builder.append(" ${if (isInstancePredicate.isNegated) "!" else ""}is ${isInstancePredicate.type.renderForDebugging()}")
|
||||
}
|
||||
|
||||
override fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: Nothing?) {
|
||||
|
||||
@@ -23,7 +23,7 @@ open class FirAnnotationRenderer internal constructor(components: FirRendererCom
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderAnnotation(annotation: FirAnnotation) {
|
||||
internal fun renderAnnotation(annotation: FirAnnotation) {
|
||||
printer.print("@")
|
||||
annotation.useSiteTarget?.let {
|
||||
printer.print(it.name)
|
||||
|
||||
@@ -20,7 +20,7 @@ class FirBodyRenderer internal constructor(components: FirRendererComponents) :
|
||||
if (block == null) return
|
||||
when (block) {
|
||||
is FirLazyBlock -> {
|
||||
println(" { LAZY_BLOCK }")
|
||||
printer.println(" { LAZY_BLOCK }")
|
||||
}
|
||||
else -> {
|
||||
annotationRenderer?.render(block)
|
||||
|
||||
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.renderer
|
||||
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
abstract class FirPrinter internal constructor(builder: StringBuilder) {
|
||||
open class FirPrinter(builder: StringBuilder) {
|
||||
private val printer = Printer(builder)
|
||||
|
||||
private var lineBeginning = true
|
||||
|
||||
@@ -47,6 +47,8 @@ open class FirRenderer private constructor(
|
||||
|
||||
override var bodyRenderer: FirBodyRenderer? = null
|
||||
|
||||
override lateinit var typeRenderer: ConeTypeRenderer
|
||||
|
||||
override lateinit var visitor: Visitor
|
||||
|
||||
override lateinit var printer: FirPrinter
|
||||
@@ -154,12 +156,18 @@ open class FirRenderer private constructor(
|
||||
else ->
|
||||
null
|
||||
}
|
||||
private val bodyRenderer = if (mode.renderBodies) FirBodyRenderer(components) else null
|
||||
private val bodyRenderer =
|
||||
if (mode.renderBodies) FirBodyRenderer(components) else null
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
private val typeRenderer =
|
||||
if (mode.renderDetailedTypeReferences) ConeTypeRendererForDebugging(builder) else ConeTypeRenderer(builder)
|
||||
|
||||
init {
|
||||
components.visitor = visitor
|
||||
components.annotationRenderer = annotationRenderer
|
||||
components.bodyRenderer = bodyRenderer
|
||||
components.typeRenderer = typeRenderer
|
||||
@Suppress("LeakingThis")
|
||||
components.printer = this
|
||||
}
|
||||
@@ -188,7 +196,7 @@ open class FirRenderer private constructor(
|
||||
if (index > 0) {
|
||||
print(", ")
|
||||
}
|
||||
print(element.render())
|
||||
print(element.renderForDebugging())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +326,10 @@ open class FirRenderer private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun renderAnnotations(annotationContainer: FirAnnotationContainer) {
|
||||
annotationRenderer?.render(annotationContainer)
|
||||
}
|
||||
|
||||
protected open fun renderClassDeclarations(regularClass: FirRegularClass) {
|
||||
if (mode.renderNestedDeclarations) {
|
||||
regularClass.declarations.renderDeclarations()
|
||||
@@ -346,6 +358,14 @@ open class FirRenderer private constructor(
|
||||
popIndent()
|
||||
}
|
||||
|
||||
override fun visitAnnotation(annotation: FirAnnotation) {
|
||||
annotationRenderer?.renderAnnotation(annotation)
|
||||
}
|
||||
|
||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall) {
|
||||
annotationRenderer?.renderAnnotation(annotationCall)
|
||||
}
|
||||
|
||||
override fun visitCallableDeclaration(callableDeclaration: FirCallableDeclaration) {
|
||||
renderContexts(callableDeclaration.contextReceivers)
|
||||
annotationRenderer?.render(callableDeclaration)
|
||||
@@ -603,7 +623,7 @@ open class FirRenderer private constructor(
|
||||
constructor.renderDeclarationData()
|
||||
|
||||
constructor.dispatchReceiverType?.let {
|
||||
print(it.render())
|
||||
typeRenderer.render(it)
|
||||
print(".")
|
||||
}
|
||||
print("constructor")
|
||||
@@ -1051,15 +1071,7 @@ open class FirRenderer private constructor(
|
||||
}
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
||||
val kind = resolvedTypeRef.functionTypeKind
|
||||
if (mode.renderDetailedTypeReferences) {
|
||||
print("R|")
|
||||
}
|
||||
val coneType = resolvedTypeRef.type
|
||||
print(coneType.renderFunctionType(kind, renderFqNames = mode.renderDetailedTypeReferences))
|
||||
if (mode.renderDetailedTypeReferences) {
|
||||
print("|")
|
||||
}
|
||||
typeRenderer.renderAsPossibleFunctionType(resolvedTypeRef.type)
|
||||
}
|
||||
|
||||
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef) {
|
||||
|
||||
@@ -10,4 +10,5 @@ internal interface FirRendererComponents {
|
||||
val printer: FirPrinter
|
||||
val annotationRenderer: FirAnnotationRenderer?
|
||||
val bodyRenderer: FirBodyRenderer?
|
||||
val typeRenderer: ConeTypeRenderer
|
||||
}
|
||||
@@ -75,13 +75,13 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
when (a) {
|
||||
is ConeErrorType -> {
|
||||
require(b is ConeErrorType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
return a.hashCode() - b.hashCode()
|
||||
}
|
||||
is ConeLookupTagBasedType -> {
|
||||
require(b is ConeLookupTagBasedType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val nameDiff = a.lookupTag.name.compareTo(b.lookupTag.name)
|
||||
if (nameDiff != 0) {
|
||||
@@ -95,7 +95,7 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
}
|
||||
is ConeFlexibleType -> {
|
||||
require(b is ConeFlexibleType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val lowerBoundDiff = compare(a.lowerBound, b.lowerBound)
|
||||
if (lowerBoundDiff != 0) {
|
||||
@@ -105,7 +105,7 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
require(b is ConeCapturedType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val aHasLowerType = if (a.lowerType != null) 1 else 0
|
||||
val bHasLowerType = if (b.lowerType != null) 1 else 0
|
||||
@@ -127,13 +127,13 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
}
|
||||
is ConeDefinitelyNotNullType -> {
|
||||
require(b is ConeDefinitelyNotNullType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
return compare(a.original, b.original)
|
||||
}
|
||||
is ConeIntersectionType -> {
|
||||
require(b is ConeIntersectionType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val sizeDiff = a.intersectedTypes.size - b.intersectedTypes.size
|
||||
if (sizeDiff != 0) {
|
||||
@@ -144,7 +144,7 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
}
|
||||
is ConeStubType -> {
|
||||
require(b is ConeStubType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val nameDiff = a.constructor.variable.typeConstructor.name.compareTo(b.constructor.variable.typeConstructor.name)
|
||||
if (nameDiff != 0) {
|
||||
@@ -154,7 +154,7 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
}
|
||||
is ConeIntegerLiteralConstantType -> {
|
||||
require(b is ConeIntegerLiteralConstantType) {
|
||||
"priority is inconsistent: ${a.render()} v.s. ${b.render()}"
|
||||
"priority is inconsistent: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}"
|
||||
}
|
||||
val valueDiff = a.value - b.value
|
||||
if (valueDiff != 0L) {
|
||||
@@ -171,7 +171,7 @@ object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
return compare(a.nullability, b.nullability)
|
||||
}
|
||||
else ->
|
||||
error("Unsupported type comparison: ${a.render()} v.s. ${b.render()}")
|
||||
error("Unsupported type comparison: ${a.renderForDebugging()} v.s. ${b.renderForDebugging()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
@@ -15,6 +14,8 @@ import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.extensions.typeAttributeExtensions
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRenderer
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererForDebugging
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
@@ -195,13 +196,3 @@ val ConeKotlinType.canBeNull: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
val ConeKotlinType?.functionTypeKind: FunctionClassKind?
|
||||
get() {
|
||||
val classId = (this as? ConeClassLikeType)?.lookupTag?.classId ?: return null
|
||||
return FunctionClassKind.getFunctionalClassKind(
|
||||
classId.shortClassName.asString(), classId.packageFqName
|
||||
)
|
||||
}
|
||||
|
||||
val FirResolvedTypeRef.functionTypeKind: FunctionClassKind?
|
||||
get() = type.functionTypeKind
|
||||
|
||||
@@ -103,7 +103,7 @@ abstract class AbstractKtDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
||||
}
|
||||
|
||||
fun checkFir(testDataFile: File, firFiles: List<FirFile>) {
|
||||
val firFileDump = StringBuilder().apply { firFiles.forEach { it.accept(FirRenderer(this), null) } }.toString()
|
||||
val firFileDump = StringBuilder().apply { firFiles.forEach { it.accept(FirRenderer(this).Visitor(), null) } }.toString()
|
||||
val expectedPath = testDataFile.absolutePath.replace(".kt", ".txt")
|
||||
KotlinTestUtils.assertEqualsToFile(
|
||||
File(expectedPath),
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.CharsetToolkit
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtIoFileSourceFile
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
@@ -339,7 +337,7 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? =
|
||||
return
|
||||
}
|
||||
val psi = resolvedTypeRef.psi ?: return
|
||||
val problem = "${resolvedTypeRef::class.simpleName} -> ${type::class.simpleName}: ${type.render()}"
|
||||
val problem = "${resolvedTypeRef::class.simpleName} -> ${type::class.simpleName}: ${type.renderForDebugging()}"
|
||||
reportProblem(problem, psi)
|
||||
}
|
||||
}
|
||||
|
||||
+74
-39
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererForDebugging
|
||||
import org.jetbrains.kotlin.fir.renderer.FirPrinter
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
@@ -322,10 +324,22 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
private val filePackage = firFile.packageFqName.toString()
|
||||
private val filePackageWithSlash = filePackage.replace(".", "/")
|
||||
|
||||
private fun ConeTypeProjection.tryToRenderConeAsFunctionType(): String {
|
||||
if (this !is ConeKotlinType) return localTypeRenderer()
|
||||
val functionType = renderFunctionType(functionTypeKind, renderFqNames = true) { localTypeRenderer() }
|
||||
return functionType.removeCurrentFilePackage()
|
||||
private fun ConeTypeProjection.tryToRenderConeAsFunctionTypeString(): String {
|
||||
return buildString {
|
||||
tryToRenderConeAsFunctionType(this@buildString)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.tryToRenderConeAsFunctionType(builder: StringBuilder) {
|
||||
if (this !is ConeKotlinType) {
|
||||
localTypeProjectionRenderer(builder)
|
||||
return
|
||||
}
|
||||
val projectionBuilder = StringBuilder()
|
||||
ConeTypeRendererForDebugging(projectionBuilder).renderAsPossibleFunctionType(this) {
|
||||
localTypeProjectionRenderer(projectionBuilder)
|
||||
}
|
||||
builder.append(projectionBuilder.toString().removeCurrentFilePackage())
|
||||
}
|
||||
|
||||
// TODO rewrite or extract in common utils
|
||||
@@ -384,33 +398,49 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.localTypeRenderer(): String {
|
||||
private fun ConeTypeProjection.localTypeProjectionRenderer(builder: StringBuilder) {
|
||||
val nullabilitySuffix = when {
|
||||
this is ConeKotlinType && this !is ConeErrorType && this !is ConeErrorType -> nullability.suffix
|
||||
this is ConeKotlinType && this !is ConeErrorType -> nullability.suffix
|
||||
else -> ""
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
is ConeKotlinTypeProjectionIn -> "in ${type.tryToRenderConeAsFunctionType()}"
|
||||
is ConeKotlinTypeProjectionOut -> "out ${type.tryToRenderConeAsFunctionType()}"
|
||||
when (this) {
|
||||
is ConeKotlinTypeProjectionIn -> {
|
||||
builder.append("in ")
|
||||
type.tryToRenderConeAsFunctionType(builder)
|
||||
}
|
||||
is ConeKotlinTypeProjectionOut -> {
|
||||
builder.append("out ")
|
||||
type.tryToRenderConeAsFunctionType(builder)
|
||||
}
|
||||
is ConeStarProjection -> builder.append("*")
|
||||
is ConeClassLikeType -> {
|
||||
val type = this.fullyExpandedType(session)
|
||||
if (type != this) return type.tryToRenderConeAsFunctionType()
|
||||
val classId = type.lookupTag.classId
|
||||
buildString {
|
||||
when {
|
||||
classId.isLocal -> append(classId.shortClassName.asString().let { stack.getPathByName(it) + it })
|
||||
else -> append(classId.asString())
|
||||
}
|
||||
if (type.typeArguments.isNotEmpty()) {
|
||||
append(type.typeArguments.joinToString(prefix = "<", postfix = ">") { it.tryToRenderConeAsFunctionType() })
|
||||
}
|
||||
append(nullabilitySuffix)
|
||||
if (type != this) {
|
||||
type.tryToRenderConeAsFunctionType(builder)
|
||||
return
|
||||
}
|
||||
val classId = type.lookupTag.classId
|
||||
when {
|
||||
classId.isLocal -> builder.append(classId.shortClassName.asString().let { stack.getPathByName(it) + it })
|
||||
else -> builder.append(classId.asString())
|
||||
}
|
||||
if (type.typeArguments.isNotEmpty()) {
|
||||
builder.append("<")
|
||||
for ((index, typeArgument) in type.typeArguments.withIndex()) {
|
||||
if (index != 0) {
|
||||
builder.append(", ")
|
||||
}
|
||||
typeArgument.tryToRenderConeAsFunctionType(builder)
|
||||
}
|
||||
builder.append(">")
|
||||
}
|
||||
builder.append(nullabilitySuffix)
|
||||
}
|
||||
is ConeLookupTagBasedType -> lookupTag.name.asString() + nullabilitySuffix
|
||||
is ConeLookupTagBasedType -> builder.append(lookupTag.name.asString() + nullabilitySuffix)
|
||||
is ConeFlexibleType -> {
|
||||
val lowerRendered = lowerBound.tryToRenderConeAsFunctionType()
|
||||
val lowerBuilder = StringBuilder()
|
||||
lowerBound.tryToRenderConeAsFunctionType(lowerBuilder)
|
||||
if (lowerBound.nullability == ConeNullability.NOT_NULL && upperBound.nullability == ConeNullability.NULLABLE &&
|
||||
AbstractStrictEqualityTypeChecker
|
||||
.strictEqualTypes(
|
||||
@@ -419,17 +449,20 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
upperBound.withNullability(ConeNullability.NOT_NULL, session.typeContext)
|
||||
)
|
||||
) {
|
||||
"$lowerRendered!"
|
||||
builder.append(lowerBuilder)
|
||||
} else {
|
||||
val upperRendered = upperBound.tryToRenderConeAsFunctionType()
|
||||
tryToSquashFlexibleType(lowerRendered, upperRendered) ?: "$lowerRendered..$upperRendered"
|
||||
val upperBuilder = StringBuilder()
|
||||
upperBound.tryToRenderConeAsFunctionType(upperBuilder)
|
||||
builder.append(
|
||||
tryToSquashFlexibleType(lowerBuilder.toString(), upperBuilder.toString()) ?: "$lowerBuilder..$upperBuilder"
|
||||
)
|
||||
}
|
||||
}
|
||||
is ConeIntersectionType -> {
|
||||
intersectedTypes.map { it.render().replace("/", ".").replace("kotlin.", "") }.sorted()
|
||||
intersectedTypes.map { it.renderForDebugging().replace("/", ".").replace("kotlin.", "") }.sorted()
|
||||
.joinToString(separator = " & ", prefix = "{", postfix = "}")
|
||||
}
|
||||
else -> this.render(renderFqNames = true)
|
||||
else -> builder.append((this as ConeKotlinType).renderForDebugging())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,11 +518,11 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
if (original.isVal) data.append("val ") else if (original.isVar) data.append("var ")
|
||||
|
||||
data.append("(")
|
||||
.append(original.dispatchReceiverType?.tryToRenderConeAsFunctionType())
|
||||
.append(").")
|
||||
original.dispatchReceiverType?.tryToRenderConeAsFunctionType(data)
|
||||
data.append(").")
|
||||
.append(original.name)
|
||||
.append(": ")
|
||||
.append(original.returnTypeRef.coneType.tryToRenderConeAsFunctionType())
|
||||
original.returnTypeRef.coneType.tryToRenderConeAsFunctionType(data)
|
||||
}
|
||||
|
||||
private fun renderVariable(variable: FirVariable, data: StringBuilder) {
|
||||
@@ -513,15 +546,15 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
}
|
||||
|
||||
val receiver = when (variable) {
|
||||
is FirField -> variable.dispatchReceiverType?.tryToRenderConeAsFunctionType()
|
||||
is FirField -> variable.dispatchReceiverType?.tryToRenderConeAsFunctionTypeString()
|
||||
else -> getSymbolId(variable.symbol)
|
||||
}
|
||||
|
||||
data.append(receiver)
|
||||
.append(variable.symbol.callableId.callableName)
|
||||
.append(": ")
|
||||
.append(returnType?.tryToRenderConeAsFunctionType())
|
||||
.append((variable as? FirValueParameter)?.defaultValue?.let { " = ..." } ?: "")
|
||||
returnType?.tryToRenderConeAsFunctionType(data)
|
||||
data.append((variable as? FirValueParameter)?.defaultValue?.let { " = ..." } ?: "")
|
||||
}
|
||||
|
||||
private fun renderPropertySymbol(symbol: FirPropertySymbol, data: StringBuilder) {
|
||||
@@ -533,7 +566,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
when {
|
||||
receiver != null -> data.append(receiver).append(".").append(symbol.callableId.callableName)
|
||||
fir.dispatchReceiverType != null -> {
|
||||
val dispatchReceiver = fir.dispatchReceiverType?.tryToRenderConeAsFunctionType()
|
||||
val dispatchReceiver = fir.dispatchReceiverType?.tryToRenderConeAsFunctionTypeString()
|
||||
data.append("($dispatchReceiver)").append(".").append(symbol.callableId.callableName)
|
||||
}
|
||||
else -> {
|
||||
@@ -578,7 +611,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
}
|
||||
call.dispatchReceiver !is FirNoReceiverExpression -> {
|
||||
data.append("(")
|
||||
val dispatch = fir.dispatchReceiverType!!.tryToRenderConeAsFunctionType()
|
||||
val dispatch = fir.dispatchReceiverType!!.tryToRenderConeAsFunctionTypeString()
|
||||
.let { if (it.endsWith("!")) it.dropLast(1) else it } // this hack drop flexible annotation for receiver
|
||||
data.append(dispatch).append(").").append(callableName)
|
||||
}
|
||||
@@ -654,7 +687,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
override fun visitValueParameter(valueParameter: FirValueParameter, data: StringBuilder) {
|
||||
if (valueParameter.isVararg) {
|
||||
data.append("vararg ")
|
||||
valueParameter.returnTypeRef.coneType.arrayElementType()?.let { data.append(it.localTypeRenderer()) }
|
||||
valueParameter.returnTypeRef.coneType.arrayElementType()?.localTypeProjectionRenderer(data)
|
||||
} else {
|
||||
valueParameter.returnTypeRef.accept(this, data)
|
||||
}
|
||||
@@ -683,7 +716,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
data.append(stack.getPathByName(resolvedNamedReference.name.asString()))
|
||||
.append(resolvedNamedReference.name)
|
||||
.append(": ")
|
||||
.append(fir.dispatchReceiverType?.tryToRenderConeAsFunctionType())
|
||||
fir.dispatchReceiverType?.tryToRenderConeAsFunctionType(data)
|
||||
}
|
||||
symbol is FirFieldSymbol -> renderField(symbol.fir, data)
|
||||
else -> (symbol.fir as? FirVariable)?.let { renderVariable(it, data) }
|
||||
@@ -813,7 +846,7 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
}
|
||||
|
||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: StringBuilder) {
|
||||
data.append(resolvedTypeRef.type.tryToRenderConeAsFunctionType())
|
||||
resolvedTypeRef.type.tryToRenderConeAsFunctionType(data)
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: StringBuilder) {
|
||||
@@ -836,7 +869,9 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() {
|
||||
val typeParameters = if (typeArguments.isEmpty()) "" else " <T>"
|
||||
data.append("fun$typeParameters ${name.replaceFirstChar(Char::lowercaseChar)}Of")
|
||||
typeArguments.firstOrNull()?.let {
|
||||
data.append("<").append(it.tryToRenderConeAsFunctionType()).append(">")
|
||||
data.append("<")
|
||||
it.tryToRenderConeAsFunctionType(data)
|
||||
data.append(">")
|
||||
}
|
||||
val valueParameter = name.replace("Array", "").takeIf { it.isNotEmpty() } ?: "T"
|
||||
data.append("(vararg $valueParameter): $name${typeParameters.trim()}") // TODO change "T" to concrete type is array is primitive
|
||||
|
||||
Reference in New Issue
Block a user