FIR: transform resolved arrayOf call inside annotation to FirArrayOfCall
This commit is contained in:
committed by
Mikhail Glukhikh
parent
265d066878
commit
18953c4717
@@ -767,6 +767,7 @@ class Fir2IrVisitor(
|
||||
return arrayOfCall.convertWithOffsets { startOffset, endOffset ->
|
||||
lateinit var elementType: IrType
|
||||
lateinit var arrayType: IrType
|
||||
// Resolved arrayOf call will have resolved type. FirArrayOfCall from collection literal won't.
|
||||
if (arrayOfCall.typeRef is FirResolvedTypeRef) {
|
||||
arrayType = arrayOfCall.typeRef.toIrType()
|
||||
elementType = arrayType.getArrayElementType(irBuiltIns)
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.body.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArrayOfCall
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.getOriginalFunction
|
||||
import org.jetbrains.kotlin.fir.types.isArrayType
|
||||
|
||||
/**
|
||||
* A transformer that converts resolved arrayOf() call to [FirArrayOfCall].
|
||||
*
|
||||
* Note that arrayOf() calls only in [FirAnnotationCall] or the default value of annotation constructor are transformed.
|
||||
*/
|
||||
internal class FirArrayOfCallTransformer {
|
||||
private val FirFunctionCall.isArrayOfCall: Boolean
|
||||
get() {
|
||||
val function: FirCallableDeclaration<*> = getOriginalFunction() ?: return false
|
||||
return function is FirSimpleFunction &&
|
||||
// TODO: extend it to other variants, like emptyArray, intArrayOf, floatArrayOf, etc.
|
||||
function.name.asString() == "arrayOf" &&
|
||||
function.returnTypeRef.isArrayType &&
|
||||
function.valueParameters.size == 1 && function.valueParameters[0].isVararg &&
|
||||
arguments.size == 1 &&
|
||||
function.receiverTypeRef == null
|
||||
}
|
||||
|
||||
internal fun toArrayOfCall(functionCall: FirFunctionCall): FirArrayOfCall? {
|
||||
if (!functionCall.isArrayOfCall) {
|
||||
return null
|
||||
}
|
||||
val typeRef = functionCall.typeRef
|
||||
return buildArrayOfCall {
|
||||
source = functionCall.source
|
||||
annotations += functionCall.annotations
|
||||
// Note that the signature is: arrayOf(vararg element). Hence, unwrapping the original argument list here.
|
||||
argumentList = buildArgumentList {
|
||||
if (functionCall.arguments.isNotEmpty()) {
|
||||
(functionCall.argument as FirVarargArgumentsExpression).arguments.forEach {
|
||||
arguments += it
|
||||
}
|
||||
}
|
||||
}
|
||||
}.apply {
|
||||
replaceTypeRef(typeRef)
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirFunctionTarget
|
||||
import org.jetbrains.kotlin.fir.copy
|
||||
@@ -41,6 +42,15 @@ import org.jetbrains.kotlin.name.Name
|
||||
open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
||||
private var containingClass: FirRegularClass? = null
|
||||
|
||||
private inline fun <T> withFirArrayOfCallTransformer(block: () -> T): T {
|
||||
transformer.expressionsTransformer.enableArrayOfCallTransformation = true
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
transformer.expressionsTransformer.enableArrayOfCallTransformation = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformDeclarationContent(
|
||||
declaration: FirDeclaration, data: ResolutionMode
|
||||
): CompositeTransformResult<FirDeclaration> {
|
||||
@@ -506,6 +516,12 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
|
||||
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): CompositeTransformResult<FirDeclaration> {
|
||||
if (implicitTypeOnly) return constructor.compose()
|
||||
if (constructor.isPrimary && containingClass?.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
return withFirArrayOfCallTransformer {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
transformFunction(constructor, data) as CompositeTransformResult<FirDeclaration>
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return transformFunction(constructor, data) as CompositeTransformResult<FirDeclaration>
|
||||
}
|
||||
|
||||
+27
-9
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference
|
||||
@@ -41,11 +39,22 @@ import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
|
||||
private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes
|
||||
private val arrayOfCallTransformer = FirArrayOfCallTransformer()
|
||||
var enableArrayOfCallTransformation = false
|
||||
|
||||
init {
|
||||
components.callResolver.initTransformer(this)
|
||||
}
|
||||
|
||||
private inline fun <T> withFirArrayOfCallTransformer(block: () -> T): T {
|
||||
enableArrayOfCallTransformation = true
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
enableArrayOfCallTransformation = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformExpression(expression: FirExpression, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
||||
if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedExpression) {
|
||||
val type = buildErrorTypeRef {
|
||||
@@ -187,6 +196,13 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
|
||||
}
|
||||
|
||||
dataFlowAnalyzer.exitFunctionCall(completeInference, callCompleted)
|
||||
if (callCompleted) {
|
||||
if (enableArrayOfCallTransformation) {
|
||||
arrayOfCallTransformer.toArrayOfCall(completeInference)?.let {
|
||||
return it.compose()
|
||||
}
|
||||
}
|
||||
}
|
||||
return completeInference.compose()
|
||||
}
|
||||
|
||||
@@ -584,12 +600,14 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
|
||||
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): CompositeTransformResult<FirStatement> {
|
||||
if (annotationCall.resolved) return annotationCall.compose()
|
||||
dataFlowAnalyzer.enterAnnotationCall(annotationCall)
|
||||
return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also {
|
||||
// TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
|
||||
it.argumentList.transformArguments(integerLiteralTypeApproximator, null)
|
||||
it.replaceResolved(true)
|
||||
dataFlowAnalyzer.exitAnnotationCall(it)
|
||||
}.compose()
|
||||
return withFirArrayOfCallTransformer {
|
||||
(annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also {
|
||||
// TODO: it's temporary incorrect solution until we design resolve and completion for annotation calls
|
||||
it.argumentList.transformArguments(integerLiteralTypeApproximator, null)
|
||||
it.replaceResolved(true)
|
||||
dataFlowAnalyzer.exitAnnotationCall(it)
|
||||
}.compose()
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.toFirTypeProjection(): FirTypeProjection = when (this) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
@@ -22,6 +21,10 @@ val FirTypeRef.isNullableNothing: Boolean get() = isBuiltinType(StandardClassIds
|
||||
val FirTypeRef.isUnit: Boolean get() = isBuiltinType(StandardClassIds.Unit, false)
|
||||
val FirTypeRef.isBoolean: Boolean get() = isBuiltinType(StandardClassIds.Boolean, false)
|
||||
val FirTypeRef.isEnum: Boolean get() = isBuiltinType(StandardClassIds.Enum, false)
|
||||
val FirTypeRef.isArrayType: Boolean
|
||||
get() =
|
||||
isBuiltinType(StandardClassIds.Array, false) ||
|
||||
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
|
||||
|
||||
private fun FirTypeRef.isBuiltinType(classId: ClassId, isNullable: Boolean): Boolean {
|
||||
val type = when (this) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ FILE fqName:<root> fileName:/arrayInAnnotationArguments.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
annotations:
|
||||
TestAnnWithIntArray(x = CALL 'public final fun intArrayOf (vararg elements: kotlin.Int): kotlin.IntArray declared in kotlin' type=kotlin.IntArray origin=null)
|
||||
TestAnnWithStringArray(x = CALL 'public final fun arrayOf <T> (vararg elements: T of kotlin.arrayOf): kotlin.Array<T of kotlin.arrayOf> [inline] declared in kotlin' type=kotlin.Array<kotlin.String> origin=null)
|
||||
TestAnnWithStringArray(x = ['a', 'b', 'c'])
|
||||
BLOCK_BODY
|
||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
annotations:
|
||||
|
||||
Reference in New Issue
Block a user