From a82baf87cbb4120b392e419cbadf113ece006740 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 5 Jul 2022 11:56:50 +0200 Subject: [PATCH] FIR renderer: extract separate ConeTypeRenderer --- .../api/fir/components/KtFirTypeProvider.kt | 2 +- .../api/fir/renderer/ConeTypeIdeRenderer.kt | 2 +- .../api/fir/types/KtFirCapturedType.kt | 4 +- .../api/fir/types/KtFirClassErrorType.kt | 4 +- .../fir/types/KtFirDefinitelyNotNullType.kt | 4 +- .../api/fir/types/KtFirDynamicType.kt | 4 +- .../api/fir/types/KtFirFlexibleType.kt | 4 +- .../api/fir/types/KtFirFunctionalType.kt | 4 +- .../api/fir/types/KtFirIntegerLiteralType.kt | 4 +- .../api/fir/types/KtFirIntersectionType.kt | 4 +- .../api/fir/types/KtFirTypeParameterType.kt | 4 +- .../api/fir/types/KtFirUsualClassType.kt | 4 +- .../AbstractFirLazyBodiesCalculatorTest.kt | 4 +- .../kotlin/fir/AbstractFirLoadBinariesTest.kt | 4 +- .../kotlin/fir/java/JavaClassRendering.kt | 7 +- .../FirDelegatedPropertyChecker.kt | 7 +- .../ErrorNodeDiagnosticCollectorComponent.kt | 4 +- .../diagnostics/FirDiagnosticRenderers.kt | 4 +- .../kotlin/fir/renderer/ConeTypeRenderer.kt | 199 ++++++++++++++++++ .../renderer/ConeTypeRendererForDebugging.kt | 17 ++ .../renderer/ConeTypeRendererWithFqNames.kt | 14 ++ .../kotlin/fir/types/ConeTypeUtils.kt | 31 +++ .../jetbrains/kotlin/fir/types/ConeTypes.kt | 4 +- .../kotlin/fir/types/TypeRenderer.kt | 129 ------------ .../fir/serialization/FirElementSerializer.kt | 6 +- .../fir/backend/jvm/FirJvmTypeMapper.kt | 2 +- .../kotlin/fir/types/ConeInferenceContext.kt | 2 +- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 4 +- .../kotlin/fir/lightTree/TotalKotlinTest.kt | 4 +- .../fir/lightTree/compare/TreesCompareTest.kt | 8 +- ...AbstractRawFirBuilderLazyBodiesTestCase.kt | 2 +- .../builder/AbstractRawFirBuilderTestCase.kt | 6 +- .../RawFirBuilderTotalKotlinTestCase.kt | 2 +- .../kotlin/fir/FirLookupTrackerComponent.kt | 2 +- .../resolve/diagnostics/ConeDiagnostics.kt | 1 + .../description/ConeContractRenderer.kt | 4 +- .../fir/renderer/FirAnnotationRenderer.kt | 2 +- .../kotlin/fir/renderer/FirBodyRenderer.kt | 2 +- .../kotlin/fir/renderer/FirPrinter.kt | 2 +- .../kotlin/fir/renderer/FirRenderer.kt | 36 ++-- .../fir/renderer/FirRendererComponents.kt | 1 + .../fir/types/ConeKotlinTypeComparator.kt | 18 +- .../kotlin/fir/types/FirTypeUtils.kt | 13 +- .../kotlin/fir/AbstractFirDiagnosticTest.kt | 2 +- .../jetbrains/kotlin/fir/FirResolveBench.kt | 4 +- .../compiler/visualizer/FirVisualizer.kt | 113 ++++++---- 46 files changed, 438 insertions(+), 266 deletions(-) create mode 100644 compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRenderer.kt create mode 100644 compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererForDebugging.kt create mode 100644 compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererWithFqNames.kt delete mode 100644 compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt index dfa9ae80466..93d251ccf96 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirTypeProvider.kt @@ -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) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/ConeTypeIdeRenderer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/ConeTypeIdeRenderer.kt index e647a97901f..da2a6b916d1 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/ConeTypeIdeRenderer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/renderer/ConeTypeIdeRenderer.kt @@ -77,7 +77,7 @@ internal class ConeTypeIdeRenderer( } is ConeCapturedType -> { renderAnnotationList(type) - append(type.render()) + append(type.renderReadableWithFqNames()) renderNullability(type.type) } is ConeDefinitelyNotNullType -> { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt index 3c4f206d5a9..92a9c482dc1 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirCapturedType.kt @@ -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) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt index e4888819f19..f7e5f4e24ac 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirClassErrorType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt index 903da23e9fb..665cbecb32e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDefinitelyNotNullType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDynamicType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDynamicType.kt index 8a9e772f860..b76d9f5b27a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDynamicType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirDynamicType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt index 79db272a9cd..133f8193ac7 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFlexibleType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt index 4026ec2f1b9..dcd79a398d4 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirFunctionalType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt index 2faf80bb0d2..53f04539b3d 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntegerLiteralType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt index abc8fc9f669..cbe012cde66 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirIntersectionType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt index 69568748322..3b72d304705 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirTypeParameterType.kt @@ -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() } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt index 7acbff6e21a..2033362d5da 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirUsualClassType.kt @@ -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() } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyBodiesCalculatorTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyBodiesCalculatorTest.kt index b50399841f5..648f74303ef 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyBodiesCalculatorTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyBodiesCalculatorTest.kt @@ -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) } diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt index dbe776cc675..0ef61f6f044 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadBinariesTest.kt @@ -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() } diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt index 8226256dac8..19b0693aee1 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/JavaClassRendering.kt @@ -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() @@ -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 } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt index f986dfe51f8..36c5a83dfd2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt @@ -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>) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index a77c37b7ca4..a5927ca1187 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -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()}" } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index 4893baafd8a..970e796d9a4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -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<*> -> diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRenderer.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRenderer.kt new file mode 100644 index 00000000000..b0d5da0ce5b --- /dev/null +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRenderer.kt @@ -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) + } + } + } +} \ No newline at end of file diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererForDebugging.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererForDebugging.kt new file mode 100644 index 00000000000..45340d2d04b --- /dev/null +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererForDebugging.kt @@ -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("|") + } +} \ No newline at end of file diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererWithFqNames.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererWithFqNames.kt new file mode 100644 index 00000000000..756db8f3e9d --- /dev/null +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/renderer/ConeTypeRendererWithFqNames.kt @@ -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()) + } +} \ No newline at end of file diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index 250941f8890..23a77b615a0 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -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() +} + diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index f45d08f4678..1dc13fb15b2 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -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() diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt deleted file mode 100644 index 8a238c0815e..00000000000 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt +++ /dev/null @@ -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 -} diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index 4e4f4466193..2dd27bf9048 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -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}") diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt index 3b57e57861f..891c38ca8ef 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -121,7 +121,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext T.withArguments(arguments: Array 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.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 } diff --git a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt index 596847a5ffe..dab5adf9b49 100644 --- a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt +++ b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/TotalKotlinTest.kt @@ -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() } } diff --git a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt index ff8c79e45cb..479f589a289 100644 --- a/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt +++ b/compiler/fir/raw-fir/light-tree2fir/tests/org/jetbrains/kotlin/fir/lightTree/compare/TreesCompareTest.kt @@ -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("".toRegex(), "") //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("".toRegex(), "") 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("".toRegex(), "") .replace("".toRegex(), "") @@ -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("".toRegex(), "") .replace("".toRegex(), "") diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderLazyBodiesTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderLazyBodiesTestCase.kt index 2c7e3f3fce8..f2046e4be72 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderLazyBodiesTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderLazyBodiesTestCase.kt @@ -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) } diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt index c961695cfcb..01b6821292f 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilderTestCase.kt @@ -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") } diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index 023e4b5e17b..5d0eced06e5 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -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) { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirLookupTrackerComponent.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirLookupTrackerComponent.kt index ea55bf9cbf8..4dedbe600f2 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirLookupTrackerComponent.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirLookupTrackerComponent.kt @@ -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('/', '.')) } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt index 5767d47c4a5..d4aca7c4517 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt @@ -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 diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeContractRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeContractRenderer.kt index 05b9eabfbb3..11a8fc63692 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeContractRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/contracts/description/ConeContractRenderer.kt @@ -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() { 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?) { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirAnnotationRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirAnnotationRenderer.kt index e438c1cd457..c3746ed332c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirAnnotationRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirAnnotationRenderer.kt @@ -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) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirBodyRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirBodyRenderer.kt index 96a3efbeceb..d0be2c62e94 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirBodyRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirBodyRenderer.kt @@ -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) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirPrinter.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirPrinter.kt index f8b5a990920..d12bc2e5d3f 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirPrinter.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirPrinter.kt @@ -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 diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index 752006bb942..f29e78f2cc4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -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) { diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRendererComponents.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRendererComponents.kt index 46140fd5103..d9ade492f2d 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRendererComponents.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRendererComponents.kt @@ -10,4 +10,5 @@ internal interface FirRendererComponents { val printer: FirPrinter val annotationRenderer: FirAnnotationRenderer? val bodyRenderer: FirBodyRenderer? + val typeRenderer: ConeTypeRenderer } \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt index df7c4369160..5735dd5d528 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt @@ -75,13 +75,13 @@ object ConeKotlinTypeComparator : Comparator { 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 { } 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 { } 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 { } 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 { } 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 { } 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 { 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()}") } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt index 094f4cab2ae..f4242947981 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt @@ -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 diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index c9bc82b90e3..92531bb0217 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -103,7 +103,7 @@ abstract class AbstractKtDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { } fun checkFir(testDataFile: File, firFiles: List) { - 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), diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt index 790006c8e4f..95685cad9d3 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt @@ -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) } } 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 17609b3dcbe..e4111496b9a 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 @@ -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 " " 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