Refactor and prettify checkCompileTimeConstant method
This commit is contained in:
+53
-68
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
*
|
* that can be found in the license/LICENSE.txt file.
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.constants.evaluate
|
package org.jetbrains.kotlin.resolve.constants.evaluate
|
||||||
@@ -120,72 +109,63 @@ class ConstantExpressionEvaluator(
|
|||||||
|
|
||||||
private fun checkCompileTimeConstant(
|
private fun checkCompileTimeConstant(
|
||||||
argumentExpression: KtExpression,
|
argumentExpression: KtExpression,
|
||||||
expectedType: KotlinType,
|
expressionType: KotlinType,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
) {
|
) {
|
||||||
val expressionType = trace.getType(argumentExpression)
|
|
||||||
|
|
||||||
if (expressionType == null || !KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
|
|
||||||
// TYPE_MISMATCH should be reported otherwise
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// array(1, <!>null<!>, 3) - error should be reported on inner expression
|
|
||||||
if (argumentExpression is KtCallExpression) {
|
|
||||||
getArgumentExpressionsForArrayCall(argumentExpression, trace)?.let { checkArgumentsAreCompileTimeConstants(it, trace) }
|
|
||||||
}
|
|
||||||
if (argumentExpression is KtCollectionLiteralExpression) {
|
|
||||||
getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)?.let {
|
|
||||||
checkArgumentsAreCompileTimeConstants(
|
|
||||||
it,
|
|
||||||
trace
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
|
val constant = ConstantExpressionEvaluator.getConstant(argumentExpression, trace.bindingContext)
|
||||||
if (constant != null && constant.canBeUsedInAnnotations) {
|
if (constant != null && constant.canBeUsedInAnnotations) {
|
||||||
if (constant.usesNonConstValAsConstant) {
|
checkInnerPartsOfCompileTimeConstant(constant, trace, argumentExpression)
|
||||||
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentExpression is KtClassLiteralExpression) {
|
|
||||||
val lhsExpression = argumentExpression.receiverExpression
|
|
||||||
if (lhsExpression != null) {
|
|
||||||
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
|
||||||
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
|
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val descriptor = expressionType.constructor.declarationDescriptor
|
val descriptor = expressionType.constructor.declarationDescriptor
|
||||||
if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) {
|
val diagnosticFactory = when {
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression))
|
DescriptorUtils.isEnumClass(descriptor) -> Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST
|
||||||
} else if (descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor)) {
|
descriptor is ClassDescriptor && KotlinBuiltIns.isKClass(descriptor) -> Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
else -> Errors.ANNOTATION_PARAMETER_MUST_BE_CONST
|
||||||
} else {
|
|
||||||
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace.report(diagnosticFactory.on(argumentExpression))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkArgumentsAreCompileTimeConstants(
|
private fun checkInnerPartsOfCompileTimeConstant(
|
||||||
argumentsWithComponentType: Pair<List<KtExpression>, KotlinType?>,
|
constant: CompileTimeConstant<*>,
|
||||||
trace: BindingTrace
|
trace: BindingTrace,
|
||||||
|
argumentExpression: KtExpression
|
||||||
) {
|
) {
|
||||||
val (arguments, componentType) = argumentsWithComponentType
|
// array(1, <!>null<!>, 3) - error should be reported on inner expression
|
||||||
for (expression in arguments) {
|
val callArguments = when (argumentExpression) {
|
||||||
checkCompileTimeConstant(expression, componentType!!, trace)
|
is KtCallExpression -> getArgumentExpressionsForArrayCall(argumentExpression, trace)
|
||||||
|
is KtCollectionLiteralExpression -> getArgumentExpressionsForCollectionLiteralCall(argumentExpression, trace)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callArguments != null) {
|
||||||
|
for (argument in callArguments) {
|
||||||
|
val type = trace.getType(argument) ?: continue
|
||||||
|
checkCompileTimeConstant(argument, type, trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constant.usesNonConstValAsConstant) {
|
||||||
|
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(argumentExpression))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentExpression is KtClassLiteralExpression) {
|
||||||
|
val lhsExpression = argumentExpression.receiverExpression
|
||||||
|
if (lhsExpression != null) {
|
||||||
|
val doubleColonLhs = trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, lhsExpression)
|
||||||
|
if (doubleColonLhs is DoubleColonLHS.Expression && !doubleColonLhs.isObjectQualifier) {
|
||||||
|
trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_KCLASS_LITERAL.on(argumentExpression))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getArgumentExpressionsForArrayCall(
|
private fun getArgumentExpressionsForArrayCall(
|
||||||
expression: KtCallExpression,
|
expression: KtCallExpression,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
): Pair<List<KtExpression>, KotlinType?>? {
|
): List<KtExpression>? {
|
||||||
val resolvedCall = expression.getResolvedCall(trace.bindingContext) ?: return null
|
val resolvedCall = expression.getResolvedCall(trace.bindingContext) ?: return null
|
||||||
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
||||||
}
|
}
|
||||||
@@ -193,19 +173,16 @@ class ConstantExpressionEvaluator(
|
|||||||
private fun getArgumentExpressionsForCollectionLiteralCall(
|
private fun getArgumentExpressionsForCollectionLiteralCall(
|
||||||
expression: KtCollectionLiteralExpression,
|
expression: KtCollectionLiteralExpression,
|
||||||
trace: BindingTrace
|
trace: BindingTrace
|
||||||
): Pair<List<KtExpression>, KotlinType?>? {
|
): List<KtExpression>? {
|
||||||
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
|
val resolvedCall = trace[COLLECTION_LITERAL_CALL, expression] ?: return null
|
||||||
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
return getArgumentExpressionsForArrayLikeCall(resolvedCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): Pair<List<KtExpression>, KotlinType>? {
|
private fun getArgumentExpressionsForArrayLikeCall(resolvedCall: ResolvedCall<*>): List<KtExpression>? {
|
||||||
if (!CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
if (!CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnType = resolvedCall.resultingDescriptor.returnType ?: return null
|
|
||||||
val componentType = module.builtIns.getArrayElementType(returnType)
|
|
||||||
|
|
||||||
val result = arrayListOf<KtExpression>()
|
val result = arrayListOf<KtExpression>()
|
||||||
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
for ((_, resolvedValueArgument) in resolvedCall.valueArguments) {
|
||||||
for (valueArgument in resolvedValueArgument.arguments) {
|
for (valueArgument in resolvedValueArgument.arguments) {
|
||||||
@@ -216,7 +193,7 @@ class ConstantExpressionEvaluator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair<List<KtExpression>, KotlinType>(result, componentType)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
|
private fun hasSpread(argument: ResolvedValueArgument): Boolean {
|
||||||
@@ -240,7 +217,15 @@ class ConstantExpressionEvaluator(
|
|||||||
if (constant != null) {
|
if (constant != null) {
|
||||||
constants.add(constant)
|
constants.add(constant)
|
||||||
}
|
}
|
||||||
checkCompileTimeConstant(argumentExpression, expectedType, trace)
|
|
||||||
|
val expressionType = trace.getType(argumentExpression) ?: continue
|
||||||
|
|
||||||
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
|
||||||
|
// TYPE_MISMATCH should be reported otherwise
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCompileTimeConstant(argumentExpression, expressionType, trace)
|
||||||
}
|
}
|
||||||
return constants
|
return constants
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user