From 3dc49ab1d4d9bfc15232e07ffb7e3d55a1a54bdb Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 15 Oct 2019 16:36:53 +0300 Subject: [PATCH] [FIR] Add resolve phase for resolving inheritors of sealed classes --- .../FirSealedClassInheritorsTransformer.kt | 90 +++++++++++++++++++ .../resolve/transformers/ResolvePhaseUtils.kt | 1 + .../fir/declarations/FirResolvePhase.kt | 1 + 3 files changed, 92 insertions(+) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt new file mode 100644 index 00000000000..f56c0499fdf --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsTransformer.kt @@ -0,0 +1,90 @@ +/* + * 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.resolve.transformers + +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol +import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.name.ClassId + +class FirSealedClassInheritorsTransformer : FirTransformer() { + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + throw IllegalStateException("Should not be there") + } + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + val sealedClassInheritorsMap = mutableMapOf>() + file.accept(InheritorsCollector, sealedClassInheritorsMap) + if (sealedClassInheritorsMap.isEmpty()) return file.compose() + return file.transform(InheritorsTransformer(sealedClassInheritorsMap), null) + } + + private class InheritorsTransformer(private val inheritorsMap: MutableMap>) : FirTransformer() { + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + return element.compose() + } + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + return (file.transformChildren(this, data) as FirFile).compose() + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult { + if (inheritorsMap.isEmpty()) return regularClass.compose() + return (regularClass.transformChildren(this, data) as FirRegularClass).compose() + } + + override fun transformSealedClass(sealedClass: FirSealedClass, data: Nothing?): CompositeTransformResult { + val inheritors = inheritorsMap.remove(sealedClass) + if (inheritors != null) { + sealedClass.replaceInheritors(inheritors) + } + return transformRegularClass(sealedClass, data) + } + } + + private object InheritorsCollector : FirDefaultVisitor>>() { + override fun visitElement(element: FirElement, data: MutableMap>) {} + + override fun visitFile(file: FirFile, data: MutableMap>) { + file.declarations.forEach { it.accept(this, data) } + } + + override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap>) { + regularClass.declarations.forEach { it.accept(this, data) } + + val symbolProvider = regularClass.session.firSymbolProvider + + for (typeRef in regularClass.superTypeRefs) { + val parent = extractClassFromTypeRef(symbolProvider, typeRef).takeIf { it?.modality == Modality.SEALED } ?: continue + val inheritors = data.computeIfAbsent(parent as FirSealedClass) { mutableListOf() } + inheritors += regularClass.symbol.classId + } + } + + private fun extractClassFromTypeRef(symbolProvider: FirSymbolProvider, typeRef: FirTypeRef): FirRegularClass? { + val lookupTag = ((typeRef as FirResolvedTypeRef).type as? ConeLookupTagBasedType)?.lookupTag ?: return null + val classLikeSymbol: FirClassifierSymbol<*> = symbolProvider.getSymbolByLookupTag(lookupTag) ?: return null + return when (classLikeSymbol) { + is FirClassSymbol -> classLikeSymbol.fir + is FirTypeAliasSymbol -> extractClassFromTypeRef(symbolProvider, classLikeSymbol.fir.expandedTypeRef) + else -> null + } + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt index c738a57eb94..812ba867917 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt @@ -15,6 +15,7 @@ fun FirResolvePhase.createTransformerByPhase(): FirTransformer { RAW_FIR -> throw AssertionError("Raw FIR building phase does not have a transformer") IMPORTS -> FirImportResolveTransformer() SUPER_TYPES -> FirSupertypeResolverTransformer() + SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsTransformer() TYPES -> FirTypeResolveTransformer() STATUS -> FirStatusResolveTransformer() IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveTransformerAdapter() diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt index 2a585452ef7..f43c2d8d756 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt @@ -9,6 +9,7 @@ enum class FirResolvePhase { RAW_FIR, IMPORTS, SUPER_TYPES, + SEALED_CLASS_INHERITORS, TYPES, STATUS, IMPLICIT_TYPES_BODY_RESOLVE,