[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.*
import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.* import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.*
import org.jetbrains.kotlin.psi.Call 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.psi.KtPsiUtil
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace 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.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tower.* 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 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
class DiagnosticReporterByTrackingStrategy( class DiagnosticReporterByTrackingStrategy(
val constantExpressionEvaluator: ConstantExpressionEvaluator,
val context: BasicCallResolutionContext, val context: BasicCallResolutionContext,
val trace: BindingTrace, val trace: BindingTrace,
val psiKotlinCall: PSIKotlinCall val psiKotlinCall: PSIKotlinCall
@@ -137,6 +143,7 @@ class DiagnosticReporterByTrackingStrategy(
val constraintError = diagnostic as NewConstraintError val constraintError = diagnostic as NewConstraintError
(constraintError.position as? ArgumentConstraintPosition)?.let { (constraintError.position as? ArgumentConstraintPosition)?.let {
val expression = it.argument.psiExpression ?: return val expression = it.argument.psiExpression ?: return
if (reportConstantTypeMismatch(constraintError, expression)) return
trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType)) trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType))
} }
(constraintError.position as? ExplicitTypeParameterConstraintPosition)?.let { (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.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace 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.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker 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.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind 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.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
@@ -49,7 +52,8 @@ class KotlinToResolvedCallTransformer(
private val callCheckers: Iterable<CallChecker>, private val callCheckers: Iterable<CallChecker>,
private val languageFeatureSettings: LanguageVersionSettings, private val languageFeatureSettings: LanguageVersionSettings,
private val dataFlowAnalyzer: DataFlowAnalyzer, private val dataFlowAnalyzer: DataFlowAnalyzer,
private val argumentTypeResolver: ArgumentTypeResolver private val argumentTypeResolver: ArgumentTypeResolver,
private val constantExpressionEvaluator: ConstantExpressionEvaluator
) { ) {
fun <D : CallableDescriptor> transformAndReport( fun <D : CallableDescriptor> transformAndReport(
@@ -185,7 +189,7 @@ class KotlinToResolvedCallTransformer(
reported = true 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) { for (diagnostic in completedCall.resolutionStatus.diagnostics) {
reported = false reported = false