From 5afd3e72d64e6c9db979256b21ece7c524520376 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 20 Oct 2016 17:44:12 +0300 Subject: [PATCH] [NI] Report diagnostic on abstract class instantiation. --- .../kotlin/resolve/calls/CallResolverUtil.kt | 3 +++ .../DiagnosticReporterByTrackingStrategy.kt | 1 + .../resolve/calls/tower/PSIKotlinCalls.kt | 4 ++++ .../calls/components/ResolutionParts.kt | 21 +++++++++++++++---- .../components/SimpleConstraintSystemImpl.kt | 1 + .../kotlin/resolve/calls/model/KotlinCall.kt | 1 + .../calls/model/KotlinResolverContext.kt | 1 + 7 files changed, 28 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 8d2b7003ed2..b5fca756c91 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -157,6 +157,9 @@ fun isInfixCall(call: Call): Boolean { return binaryExpression.operationReference === operationRefExpression && operationRefExpression.operationSignTokenType == null } +fun isSupertypeConstructorCall(call: Call): Boolean = + call.calleeExpression is KtConstructorCalleeExpression + fun isInvokeCallOnVariable(call: Call): Boolean { if (call.callType !== Call.CallType.INVOKE) return false val dispatchReceiver = call.dispatchReceiver diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 3b9b33fabea..00a8c2f6739 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -50,6 +50,7 @@ class DiagnosticReporterByTrackingStrategy( when (diagnostic.javaClass) { VisibilityError::class.java -> tracingStrategy.invisibleMember(trace, (diagnostic as VisibilityError).invisibleMember) NoValueForParameter::class.java -> tracingStrategy.noValueForParameter(trace, (diagnostic as NoValueForParameter).parameterDescriptor) + InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt index 8a453d08e38..3e8b39bfcfa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallKind import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isSupertypeConstructorCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy @@ -59,6 +60,7 @@ class PSIKotlinCallImpl( ) : PSIKotlinCall() { override val isInfixCall: Boolean get() = isInfixCall(psiCall) override val isOperatorCall: Boolean get() = isConventionCall(psiCall) + override val isSupertypeConstructorCall: Boolean get() = isSupertypeConstructorCall(psiCall) } class PSIKotlinCallForVariable( @@ -81,6 +83,7 @@ class PSIKotlinCallForVariable( override val isInfixCall: Boolean get() = false override val isOperatorCall: Boolean get() = false + override val isSupertypeConstructorCall: Boolean get() = false } class PSIKotlinCallForInvoke( @@ -101,6 +104,7 @@ class PSIKotlinCallForInvoke( override val isInfixCall: Boolean get() = false override val isOperatorCall: Boolean get() = true + override val isSupertypeConstructorCall: Boolean get() = false init { val variableReceiver = dispatchReceiverForInvokeExtension ?: explicitReceiver diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index bb6cf6c9c6d..6b40eee78b7 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.resolve.calls.components -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ExplicitTypeParameterConstraintPosition @@ -29,6 +26,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCa import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.* import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.IMPOSSIBLE_TO_GENERATE +import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.RUNTIME_ERROR import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError import org.jetbrains.kotlin.types.IndexedParametersSubstitution import org.jetbrains.kotlin.types.TypeSubstitutor @@ -36,6 +34,17 @@ import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +internal object CheckInstantiationOfAbstractClass : ResolutionPart { + override fun SimpleKotlinResolutionCandidate.process(): List { + if (candidateDescriptor is ConstructorDescriptor && !kotlinCall.isSupertypeConstructorCall) { + if (candidateDescriptor.constructedClass.modality == Modality.ABSTRACT) { + return listOf(InstantiationOfAbstractClass) + } + } + + return emptyList() + } +} internal object CheckVisibility : ResolutionPart { override fun SimpleKotlinResolutionCandidate.process(): List { @@ -213,6 +222,10 @@ fun D.safeSubstitute(substitutor: TypeSubstitutor): D = fun UnwrappedType.substitute(substitutor: TypeSubstitutor): UnwrappedType = substitutor.substitute(this, Variance.INVARIANT)!!.unwrap() +object InstantiationOfAbstractClass : KotlinCallDiagnostic(RUNTIME_ERROR) { + override fun report(reporter: DiagnosticReporter) = reporter.onCall(this) +} + class UnstableSmartCast(val expressionArgument: ExpressionKotlinCallArgument, val targetType: UnwrappedType) : KotlinCallDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR) { override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(expressionArgument, this) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt index 04b24089e0d..08f5afdd7a1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/SimpleConstraintSystemImpl.kt @@ -63,5 +63,6 @@ class SimpleConstraintSystemImpl(constraintInjector: ConstraintInjector, resultT override val externalArgument: KotlinCallArgument? get() = throw UnsupportedOperationException() override val isInfixCall: Boolean get() = throw UnsupportedOperationException() override val isOperatorCall: Boolean get() = throw UnsupportedOperationException() + override val isSupertypeConstructorCall: Boolean get() = throw UnsupportedOperationException() } } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt index 967d05af3f0..4ccab65f950 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt @@ -37,6 +37,7 @@ interface KotlinCall { val isInfixCall: Boolean val isOperatorCall: Boolean + val isSupertypeConstructorCall: Boolean } private fun SimpleKotlinCallArgument.checkReceiverInvariants() { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt index 9f480f25fdc..2bf6533b845 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinResolverContext.kt @@ -81,6 +81,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) { CheckReceivers ), FUNCTION( + CheckInstantiationOfAbstractClass, CheckVisibility, MapTypeArguments, MapArguments,