FirAnnotationArgumentChecker: handle conversion calls properly

This commit is contained in:
Mikhail Glukhikh
2020-10-05 15:14:22 +03:00
parent 6f432ea5dd
commit f6b49a2c9a
2 changed files with 25 additions and 7 deletions
@@ -19,5 +19,5 @@ val depth: Int = 42
annotation class KotlinMagicConstant(val intValues: LongArray)
@KotlinMagicConstant(intValues = <!NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION!>[StepRequest.STEP_INTO.<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>toLong()<!>, StepRequest.STEP_OVER.<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>toLong()<!>, StepRequest.STEP_OUT.<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>toLong()<!>]<!>)
@KotlinMagicConstant(intValues = [StepRequest.STEP_INTO.toLong(), StepRequest.STEP_OVER.toLong(), StepRequest.STEP_OUT.toLong()])
val kotlinDepth: Int = 42
@@ -19,7 +19,10 @@ import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.util.OperatorNameConventions.BINARY_OPERATION_NAMES
import org.jetbrains.kotlin.util.OperatorNameConventions.PLUS
@@ -140,18 +143,19 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
}
expression is FirFunctionCall -> {
val calleeReference = expression.calleeReference
if (calleeReference is FirErrorNamedReference)
if (calleeReference is FirErrorNamedReference) {
return null
if (expression.typeRef.coneType.classId == StandardClassIds.KClass)
}
if (expression.typeRef.coneType.classId == StandardClassIds.KClass) {
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
}
//TODO: UNRESOLVED REFERENCE
if (expression.dispatchReceiver is FirThisReceiverExpression)
if (expression.dispatchReceiver is FirThisReceiverExpression) {
return null
}
when (calleeReference.name) {
TO_STRING ->
return checkAnnotationArgument(expression.dispatchReceiver, session)
in BINARY_OPERATION_NAMES, in UNARY_OPERATION_NAMES -> {
val receiverClassId = expression.dispatchReceiver.typeRef.coneType.classId
@@ -167,8 +171,18 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
checkAnnotationArgument(exp, session)?.let { return it }
}
}
else ->
else -> {
if (expression.arguments.isNotEmpty() || calleeReference !is FirResolvedNamedReference) {
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
}
val symbol = calleeReference.resolvedSymbol as? FirCallableSymbol
if (calleeReference.name == TO_STRING ||
calleeReference.name in CONVERSION_NAMES && symbol?.callableId?.packageName?.asString() == "kotlin"
) {
return checkAnnotationArgument(expression.dispatchReceiver, session)
}
return FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
}
}
}
expression is FirQualifiedAccessExpression -> {
@@ -242,4 +256,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
) {
source?.let { report(factory.on(it)) }
}
private val CONVERSION_NAMES = listOf(
"toInt", "toLong", "toShort", "toByte", "toFloat", "toDouble", "toChar", "toBoolean"
).mapTo(hashSetOf()) { Name.identifier(it) }
}