[FIR] Properly set type of constants for java declarations

This commit is contained in:
Dmitriy Novozhilov
2020-10-16 11:57:28 +03:00
parent 5f641a2552
commit 0e47d32587
3 changed files with 55 additions and 41 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredCallableSymbols
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.expectedConeType
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
@@ -519,6 +520,9 @@ private fun <T> List<T>.createArrayOfCall(session: FirSession, @Suppress("UNUSED
arguments += element.createConstantOrError(session)
}
}
typeRef = buildResolvedTypeRef {
type = kind.expectedConeType(session).createArrayType()
}
}
}
@@ -530,15 +534,15 @@ internal fun Any?.createConstantOrError(session: FirSession): FirExpression {
internal fun Any?.createConstantIfAny(session: FirSession): FirExpression? {
return when (this) {
is Byte -> buildConstExpression(null, FirConstKind.Byte, this)
is Short -> buildConstExpression(null, FirConstKind.Short, this)
is Int -> buildConstExpression(null, FirConstKind.Int, this)
is Long -> buildConstExpression(null, FirConstKind.Long, this)
is Char -> buildConstExpression(null, FirConstKind.Char, this)
is Float -> buildConstExpression(null, FirConstKind.Float, this)
is Double -> buildConstExpression(null, FirConstKind.Double, this)
is Boolean -> buildConstExpression(null, FirConstKind.Boolean, this)
is String -> buildConstExpression(null, FirConstKind.String, this)
is Byte -> buildConstExpression(null, FirConstKind.Byte, this).setProperType(session)
is Short -> buildConstExpression(null, FirConstKind.Short, this).setProperType(session)
is Int -> buildConstExpression(null, FirConstKind.Int, this).setProperType(session)
is Long -> buildConstExpression(null, FirConstKind.Long, this).setProperType(session)
is Char -> buildConstExpression(null, FirConstKind.Char, this).setProperType(session)
is Float -> buildConstExpression(null, FirConstKind.Float, this).setProperType(session)
is Double -> buildConstExpression(null, FirConstKind.Double, this).setProperType(session)
is Boolean -> buildConstExpression(null, FirConstKind.Boolean, this).setProperType(session)
is String -> buildConstExpression(null, FirConstKind.String, this).setProperType(session)
is ByteArray -> toList().createArrayOfCall(session, FirConstKind.Byte)
is ShortArray -> toList().createArrayOfCall(session, FirConstKind.Short)
is IntArray -> toList().createArrayOfCall(session, FirConstKind.Int)
@@ -547,12 +551,20 @@ internal fun Any?.createConstantIfAny(session: FirSession): FirExpression? {
is FloatArray -> toList().createArrayOfCall(session, FirConstKind.Float)
is DoubleArray -> toList().createArrayOfCall(session, FirConstKind.Double)
is BooleanArray -> toList().createArrayOfCall(session, FirConstKind.Boolean)
null -> buildConstExpression(null, FirConstKind.Null, null)
null -> buildConstExpression(null, FirConstKind.Null, null).setProperType(session)
else -> null
}
}
private fun FirConstExpression<*>.setProperType(session: FirSession): FirConstExpression<*> {
val typeRef = buildResolvedTypeRef {
type = kind.expectedConeType(session)
}
replaceTypeRef(typeRef)
return this
}
private fun JavaType.toFirResolvedTypeRef(
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack
): FirResolvedTypeRef {
@@ -11,11 +11,13 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import kotlin.math.min
import org.jetbrains.kotlin.name.ClassId
inline fun <reified T : FirElement> FirBasedSymbol<*>.firUnsafe(): T {
val fir = this.fir
@@ -98,3 +100,31 @@ fun FirBlock.writeResultType(session: FirSession) {
}
}
}
fun FirConstKind<*>.expectedConeType(session: FirSession): ConeKotlinType {
fun constructLiteralType(classId: ClassId, isNullable: Boolean = false): ConeKotlinType {
val symbol = session.firSymbolProvider.getClassLikeSymbolByFqName(classId)
?: return ConeClassErrorType(ConeSimpleDiagnostic("Missing stdlib class: $classId", DiagnosticKind.MissingStdlibClass))
return symbol.toLookupTag().constructClassType(emptyArray(), isNullable)
}
return when (this) {
FirConstKind.Null -> session.builtinTypes.nullableNothingType.type
FirConstKind.Boolean -> session.builtinTypes.booleanType.type
FirConstKind.Char -> constructLiteralType(StandardClassIds.Char)
FirConstKind.Byte -> constructLiteralType(StandardClassIds.Byte)
FirConstKind.Short -> constructLiteralType(StandardClassIds.Short)
FirConstKind.Int -> constructLiteralType(StandardClassIds.Int)
FirConstKind.Long -> constructLiteralType(StandardClassIds.Long)
FirConstKind.String -> constructLiteralType(StandardClassIds.String)
FirConstKind.Float -> constructLiteralType(StandardClassIds.Float)
FirConstKind.Double -> constructLiteralType(StandardClassIds.Double)
FirConstKind.UnsignedByte -> constructLiteralType(StandardClassIds.UByte)
FirConstKind.UnsignedShort -> constructLiteralType(StandardClassIds.UShort)
FirConstKind.UnsignedInt -> constructLiteralType(StandardClassIds.UInt)
FirConstKind.UnsignedLong -> constructLiteralType(StandardClassIds.ULong)
FirConstKind.IntegerLiteral -> constructLiteralType(StandardClassIds.Int)
FirConstKind.UnsignedIntegerLiteral -> constructLiteralType(StandardClassIds.UInt)
}
}
@@ -627,7 +627,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
override fun transformGetClassCall(getClassCall: FirGetClassCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
val arg = getClassCall.argument
val dataWithExpectedType = if (arg is FirConstExpression<*>) {
withExpectedType(arg.typeRef.resolvedTypeFromPrototype(arg.kind.expectedConeType()))
withExpectedType(arg.typeRef.resolvedTypeFromPrototype(arg.kind.expectedConeType(session)))
} else {
data
}
@@ -670,34 +670,6 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
return transformedGetClassCall.compose()
}
private fun FirConstKind<*>.expectedConeType(): ConeKotlinType {
fun constructLiteralType(classId: ClassId, isNullable: Boolean = false): ConeKotlinType {
val symbol = symbolProvider.getClassLikeSymbolByFqName(classId)
?: return ConeClassErrorType(ConeSimpleDiagnostic("Missing stdlib class: $classId", DiagnosticKind.MissingStdlibClass))
return symbol.toLookupTag().constructClassType(emptyArray(), isNullable)
}
return when (this) {
FirConstKind.Null -> session.builtinTypes.nullableNothingType.type
FirConstKind.Boolean -> session.builtinTypes.booleanType.type
FirConstKind.Char -> constructLiteralType(StandardClassIds.Char)
FirConstKind.Byte -> constructLiteralType(StandardClassIds.Byte)
FirConstKind.Short -> constructLiteralType(StandardClassIds.Short)
FirConstKind.Int -> constructLiteralType(StandardClassIds.Int)
FirConstKind.Long -> constructLiteralType(StandardClassIds.Long)
FirConstKind.String -> constructLiteralType(StandardClassIds.String)
FirConstKind.Float -> constructLiteralType(StandardClassIds.Float)
FirConstKind.Double -> constructLiteralType(StandardClassIds.Double)
FirConstKind.UnsignedByte -> constructLiteralType(StandardClassIds.UByte)
FirConstKind.UnsignedShort -> constructLiteralType(StandardClassIds.UShort)
FirConstKind.UnsignedInt -> constructLiteralType(StandardClassIds.UInt)
FirConstKind.UnsignedLong -> constructLiteralType(StandardClassIds.ULong)
FirConstKind.IntegerLiteral -> constructLiteralType(StandardClassIds.Int)
FirConstKind.UnsignedIntegerLiteral -> constructLiteralType(StandardClassIds.UInt)
}
}
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ResolutionMode,
@@ -718,7 +690,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
integerLiteralType
}
}
else -> kind.expectedConeType()
else -> kind.expectedConeType(session)
}
dataFlowAnalyzer.exitConstExpression(constExpression as FirConstExpression<*>)