[NI] Report special error message on constant expression type mismatch.

This commit is contained in:
Dmitry Petrov
2016-10-21 15:09:52 +03:00
committed by Stanislav Erokhin
parent 5afd3e72d6
commit f5c59b1343
2 changed files with 26 additions and 3 deletions
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.*
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
@@ -32,9 +34,13 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstantChecker
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
class DiagnosticReporterByTrackingStrategy(
val constantExpressionEvaluator: ConstantExpressionEvaluator,
val context: BasicCallResolutionContext,
val trace: BindingTrace,
val psiKotlinCall: PSIKotlinCall
@@ -137,6 +143,7 @@ class DiagnosticReporterByTrackingStrategy(
val constraintError = diagnostic as NewConstraintError
(constraintError.position as? ArgumentConstraintPosition)?.let {
val expression = it.argument.psiExpression ?: return
if (reportConstantTypeMismatch(constraintError, expression)) return
trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType))
}
(constraintError.position as? ExplicitTypeParameterConstraintPosition)?.let {
@@ -153,4 +160,16 @@ class DiagnosticReporterByTrackingStrategy(
}
}
}
private fun reportConstantTypeMismatch(constraintError: NewConstraintError, expression: KtExpression): Boolean {
if (expression is KtConstantExpression) {
val builtIns = context.scope.ownerDescriptor.builtIns
val constantValue = constantExpressionEvaluator.evaluateToConstantValue(expression, trace, context.expectedType)
val hasConstantTypeError = CompileTimeConstantChecker(context, builtIns, true)
.checkConstantExpressionType(constantValue, expression, constraintError.upperType)
if (hasConstantTypeError) return true
}
return false
}
}
@@ -25,7 +25,9 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.*
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.DiagnosticReporterByTrackingStrategy
import org.jetbrains.kotlin.resolve.calls.REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
@@ -36,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -49,7 +52,8 @@ class KotlinToResolvedCallTransformer(
private val callCheckers: Iterable<CallChecker>,
private val languageFeatureSettings: LanguageVersionSettings,
private val dataFlowAnalyzer: DataFlowAnalyzer,
private val argumentTypeResolver: ArgumentTypeResolver
private val argumentTypeResolver: ArgumentTypeResolver,
private val constantExpressionEvaluator: ConstantExpressionEvaluator
) {
fun <D : CallableDescriptor> transformAndReport(
@@ -185,7 +189,7 @@ class KotlinToResolvedCallTransformer(
reported = true
}
}
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(context, reportTrackedTrace, completedCall.kotlinCall.psiKotlinCall)
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, context, reportTrackedTrace, completedCall.kotlinCall.psiKotlinCall)
for (diagnostic in completedCall.resolutionStatus.diagnostics) {
reported = false