org.jetbrains.kotlin.fir.resolve.transformers.FirSpecificTypeResolverTransformer.kt Maven / Gradle / Ivy
/*
* 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.fir.*
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
import org.jetbrains.kotlin.fir.resolve.typeResolver
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedFunctionTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FirSpecificTypeResolverTransformer(
override val session: FirSession,
private val errorTypeAsResolved: Boolean = true
) : FirAbstractTreeTransformer(phase = FirResolvePhase.SUPER_TYPES) {
private val typeResolver = session.typeResolver
@set:PrivateForInline
var areBareTypesAllowed: Boolean = false
@OptIn(PrivateForInline::class)
inline fun withAllowedBareTypes(block: () -> R): R {
val oldValue = areBareTypesAllowed
areBareTypesAllowed = true
return try {
block()
} finally {
areBareTypesAllowed = oldValue
}
}
override fun transformTypeRef(typeRef: FirTypeRef, data: FirScope): CompositeTransformResult {
typeRef.transformChildren(this, data)
return transformType(typeRef, typeResolver.resolveType(typeRef, data, areBareTypesAllowed))
}
override fun transformFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: FirScope): CompositeTransformResult {
functionTypeRef.transformChildren(this, data)
return buildResolvedFunctionTypeRef {
source = functionTypeRef.source
type = typeResolver.resolveType(functionTypeRef, data, areBareTypesAllowed).takeIfAcceptable() ?: return functionTypeRef.compose()
isMarkedNullable = functionTypeRef.isMarkedNullable
isSuspend = functionTypeRef.isSuspend
receiverTypeRef = functionTypeRef.receiverTypeRef
returnTypeRef = functionTypeRef.returnTypeRef
annotations += functionTypeRef.annotations
valueParameters += functionTypeRef.valueParameters
}.compose()
}
private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): CompositeTransformResult {
return if (resolvedType !is ConeClassErrorType) {
buildResolvedTypeRef {
source = typeRef.source
type = resolvedType.takeIfAcceptable() ?: return typeRef.compose()
annotations += typeRef.annotations
delegatedTypeRef = typeRef
}
} else {
buildErrorTypeRef {
val typeRefSourceKind = typeRef.source?.kind
val diagnosticSource = resolvedType.diagnostic.safeAs()
?.source.safeAs()
source = if (diagnosticSource != null) {
if (typeRefSourceKind is FirFakeSourceElementKind) {
diagnosticSource.fakeElement(typeRefSourceKind)
} else {
diagnosticSource
}
} else {
typeRef.source
}
diagnostic = resolvedType.diagnostic
}
}.compose()
}
private fun ConeKotlinType.takeIfAcceptable(): ConeKotlinType? = this.takeUnless {
!errorTypeAsResolved && it is ConeClassErrorType
}
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: FirScope): CompositeTransformResult {
return resolvedTypeRef.compose()
}
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: FirScope): CompositeTransformResult {
return implicitTypeRef.compose()
}
}