diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/MissingSupertypesResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/MissingSupertypesResolver.kt new file mode 100644 index 00000000000..9d5ff5d8963 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/MissingSupertypesResolver.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.types.typeUtil.supertypes + +class MissingSupertypesResolver( + storageManager: StorageManager, + private val moduleDescriptor: ModuleDescriptor +) { + fun getMissingSuperClassifiers(descriptor: ClassifierDescriptor) = missingClassifiers(descriptor) + + private val missingClassifiers = storageManager.createMemoizedFunction { classifier: ClassifierDescriptor -> + doGetMissingClassifiers(classifier) + } + + private fun doGetMissingClassifiers(descriptor: ClassifierDescriptor): Set { + val missingSuperClassifiers = mutableSetOf() + val type = descriptor.defaultType + + for (supertype in type.supertypes()) { + val supertypeDeclaration = supertype.constructor.declarationDescriptor + + /* + * TODO: expects are not checked, because findClassAcrossModuleDependencies does not work with actualization via type alias + * Type parameters are skipped here in favor to explicit checks for bounds, local declarations are ignored for optimization + */ + if (supertypeDeclaration !is ClassDescriptor || supertypeDeclaration.isExpect) continue + if (supertypeDeclaration.visibility == Visibilities.LOCAL) continue + + val superTypeClassId = supertypeDeclaration.classId ?: continue + val dependency = moduleDescriptor.findClassAcrossModuleDependencies(superTypeClassId) + + if (dependency == null || dependency is NotFoundClasses.MockClassDescriptor) { + missingSuperClassifiers.add(supertypeDeclaration) + } + } + + return missingSuperClassifiers.toSet() + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index 99dabe061a8..a41070940fd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -266,7 +266,8 @@ public class ModifiersChecker { public void runDeclarationCheckers(@NotNull KtDeclaration declaration, @NotNull DeclarationDescriptor descriptor) { DeclarationCheckerContext context = new DeclarationCheckerContext( - trace, languageVersionSettings, deprecationResolver, moduleDescriptor, expectActualTracker + trace, languageVersionSettings, deprecationResolver, moduleDescriptor, expectActualTracker, + missingSupertypesResolver ); for (DeclarationChecker checker : declarationCheckers) { checker.check(declaration, descriptor, context); @@ -291,6 +292,7 @@ public class ModifiersChecker { private final ExpectActualTracker expectActualTracker; private final DeprecationResolver deprecationResolver; private final ModuleDescriptor moduleDescriptor; + private final MissingSupertypesResolver missingSupertypesResolver; public ModifiersChecker( @NotNull AnnotationChecker annotationChecker, @@ -298,7 +300,8 @@ public class ModifiersChecker { @NotNull LanguageVersionSettings languageVersionSettings, @NotNull ExpectActualTracker expectActualTracker, @NotNull DeprecationResolver deprecationResolver, - @NotNull ModuleDescriptor moduleDescriptor + @NotNull ModuleDescriptor moduleDescriptor, + @NotNull MissingSupertypesResolver missingSupertypesResolver ) { this.annotationChecker = annotationChecker; this.declarationCheckers = declarationCheckers; @@ -306,6 +309,7 @@ public class ModifiersChecker { this.expectActualTracker = expectActualTracker; this.deprecationResolver = deprecationResolver; this.moduleDescriptor = moduleDescriptor; + this.missingSupertypesResolver = missingSupertypesResolver; } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index ccf38c91ac7..554759a6af7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -59,7 +59,8 @@ class CallCompleter( private val moduleDescriptor: ModuleDescriptor, private val deprecationResolver: DeprecationResolver, private val effectSystem: EffectSystem, - private val dataFlowValueFactory: DataFlowValueFactory + private val dataFlowValueFactory: DataFlowValueFactory, + private val missingSupertypesResolver: MissingSupertypesResolver ) { fun completeCall( context: BasicCallResolutionContext, @@ -78,7 +79,7 @@ class CallCompleter( if (context.trace.wantsDiagnostics()) { if (resolvedCall == null) { - checkMissingSupertypes(context, moduleDescriptor) + checkMissingSupertypes(context, missingSupertypesResolver) } else { val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.variableCall.call.calleeExpression @@ -88,7 +89,7 @@ class CallCompleter( if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression else resolvedCall.call.callElement - val callCheckerContext = CallCheckerContext(context, deprecationResolver, moduleDescriptor) + val callCheckerContext = CallCheckerContext(context, deprecationResolver, moduleDescriptor, missingSupertypesResolver) for (callChecker in callCheckers) { callChecker.check(resolvedCall, reportOn, callCheckerContext) @@ -105,12 +106,15 @@ class CallCompleter( return results } - private fun checkMissingSupertypes(context: BasicCallResolutionContext, moduleDescriptor: ModuleDescriptor) { + private fun checkMissingSupertypes( + context: BasicCallResolutionContext, + missingSupertypesResolver: MissingSupertypesResolver + ) { val call = context.call - val explicitReceiver = call.explicitReceiver.safeAs() - ?: return + val explicitReceiver = call.explicitReceiver.safeAs() ?: return + MissingDependencySupertypeChecker.checkSupertypes( - explicitReceiver.type, call.callElement, context.trace, moduleDescriptor + explicitReceiver.type, call.callElement, context.trace, missingSupertypesResolver ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt index 90cbbd98ed9..60875e30575 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallChecker.kt @@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo @@ -42,6 +43,7 @@ class CallCheckerContext @JvmOverloads constructor( val resolutionContext: ResolutionContext<*>, override val deprecationResolver: DeprecationResolver, override val moduleDescriptor: ModuleDescriptor, + val missingSupertypesResolver: MissingSupertypesResolver, override val trace: BindingTrace = resolutionContext.trace ) : CheckerContext { val scope: LexicalScope diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt index 0c2f4ddce05..0602c5faf68 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/CoroutineInferenceSession.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.components.CompletedCallInfo @@ -49,7 +50,8 @@ class CoroutineInferenceSession( private val doubleColonExpressionResolver: DoubleColonExpressionResolver, private val deprecationResolver: DeprecationResolver, private val moduleDescriptor: ModuleDescriptor, - private val typeApproximator: TypeApproximator + private val typeApproximator: TypeApproximator, + private val missingSupertypesResolver: MissingSupertypesResolver ) : ManyCandidatesResolver( psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns ) { @@ -222,7 +224,7 @@ class CoroutineInferenceSession( return ResolvedAtomCompleter( resultSubstitutor, context, kotlinToResolvedCallTransformer, expressionTypingServices, argumentTypeResolver, doubleColonExpressionResolver, builtIns, - deprecationResolver, moduleDescriptor, context.dataFlowValueFactory, typeApproximator + deprecationResolver, moduleDescriptor, context.dataFlowValueFactory, typeApproximator, missingSupertypesResolver ) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index 6a1a8e42afa..253633c44b8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -38,8 +38,6 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices @@ -75,7 +73,8 @@ class KotlinResolutionCallbacksImpl( val doubleColonExpressionResolver: DoubleColonExpressionResolver, val deprecationResolver: DeprecationResolver, val moduleDescriptor: ModuleDescriptor, - val topLevelCallContext: BasicCallResolutionContext? + val topLevelCallContext: BasicCallResolutionContext?, + val missingSupertypesResolver: MissingSupertypesResolver ) : KotlinResolutionCallbacks { class LambdaInfo(val expectedType: UnwrappedType, val contextDependency: ContextDependency) { val returnStatements = ArrayList>() @@ -161,7 +160,8 @@ class KotlinResolutionCallbacksImpl( psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns, topLevelCallContext, stubsForPostponedVariables, trace, kotlinToResolvedCallTransformer, expressionTypingServices, argumentTypeResolver, - doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, typeApproximator + doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, typeApproximator, + missingSupertypesResolver ) } else { null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index f483415e3f5..cb93c7805ff 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -72,7 +72,8 @@ class KotlinToResolvedCallTransformer( private val builtIns: KotlinBuiltIns, private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate, private val smartCastManager: SmartCastManager, - private val typeApproximator: TypeApproximator + private val typeApproximator: TypeApproximator, + private val missingSupertypesResolver: MissingSupertypesResolver ) { companion object { private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC @@ -134,7 +135,7 @@ class KotlinToResolvedCallTransformer( val ktPrimitiveCompleter = ResolvedAtomCompleter( resultSubstitutor, context, this, expressionTypingServices, argumentTypeResolver, doubleColonExpressionResolver, builtIns, deprecationResolver, moduleDescriptor, dataFlowValueFactory, - typeApproximator + typeApproximator, missingSupertypesResolver ) if (!ErrorUtils.isError(candidate.candidateDescriptor)) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 330b52282d7..f47863dc005 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -69,7 +69,8 @@ class PSICallResolver( private val deprecationResolver: DeprecationResolver, private val moduleDescriptor: ModuleDescriptor, private val callableReferenceResolver: CallableReferenceResolver, - private val candidateInterceptor: CandidateInterceptor + private val candidateInterceptor: CandidateInterceptor, + private val missingSupertypesResolver: MissingSupertypesResolver ) { private val givenCandidatesName = Name.special("") @@ -182,7 +183,7 @@ class PSICallResolver( argumentTypeResolver, languageVersionSettings, kotlinToResolvedCallTransformer, dataFlowValueFactory, inferenceSession, constantExpressionEvaluator, typeResolver, this, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, - doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context + doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, context, missingSupertypesResolver ) private fun calculateExpectedType(context: BasicCallResolutionContext): UnwrappedType? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 6078e5b7922..9a61285badb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator @@ -49,9 +50,12 @@ class ResolvedAtomCompleter( private val deprecationResolver: DeprecationResolver, private val moduleDescriptor: ModuleDescriptor, private val dataFlowValueFactory: DataFlowValueFactory, - private val typeApproximator: TypeApproximator + private val typeApproximator: TypeApproximator, + private val missingSupertypesResolver: MissingSupertypesResolver ) { - private val topLevelCallCheckerContext = CallCheckerContext(topLevelCallContext, deprecationResolver, moduleDescriptor) + private val topLevelCallCheckerContext = CallCheckerContext( + topLevelCallContext, deprecationResolver, moduleDescriptor, missingSupertypesResolver + ) private val topLevelTrace = topLevelCallCheckerContext.trace private fun complete(resolvedAtom: ResolvedAtom) { @@ -90,7 +94,7 @@ class ResolvedAtomCompleter( val lastCall = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.functionCall else resolvedCall if (ErrorUtils.isError(resolvedCall.candidateDescriptor)) { kotlinToResolvedCallTransformer.runArgumentsChecks(topLevelCallContext, topLevelTrace, lastCall as NewResolvedCallImpl<*>) - checkMissingReceiverSupertypes(resolvedCall, moduleDescriptor, topLevelTrace) + checkMissingReceiverSupertypes(resolvedCall, missingSupertypesResolver, topLevelTrace) return resolvedCall } @@ -101,7 +105,8 @@ class ResolvedAtomCompleter( CallCheckerContext( resolutionContextForPartialCall.replaceBindingTrace(topLevelTrace), deprecationResolver, - moduleDescriptor + moduleDescriptor, + missingSupertypesResolver ) else topLevelCallCheckerContext @@ -119,7 +124,7 @@ class ResolvedAtomCompleter( private fun checkMissingReceiverSupertypes( resolvedCall: ResolvedCall, - moduleDescriptor: ModuleDescriptor, + missingSupertypesResolver: MissingSupertypesResolver, trace: BindingTrace ) { val receiverValue = resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver @@ -128,7 +133,7 @@ class ResolvedAtomCompleter( receiverType, resolvedCall.call.callElement, trace, - moduleDescriptor + missingSupertypesResolver ) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeclarationChecker.kt index b0790dda1ee..8426b205c5c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/DeclarationChecker.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver interface DeclarationChecker { @@ -33,5 +34,6 @@ class DeclarationCheckerContext( override val languageVersionSettings: LanguageVersionSettings, override val deprecationResolver: DeprecationResolver, override val moduleDescriptor: ModuleDescriptor, - val expectActualTracker: ExpectActualTracker + val expectActualTracker: ExpectActualTracker, + val missingSupertypesResolver: MissingSupertypesResolver ) : CheckerContext diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt index 03c35b38ad3..c85695a0ac5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencySupertypeChecker.kt @@ -12,29 +12,27 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtTypeParameterListOwner import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.MissingSupertypesResolver import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.supertypes object MissingDependencySupertypeChecker { object ForDeclarations : DeclarationChecker { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { val trace = context.trace - val module = context.moduleDescriptor if (descriptor is ClassDescriptor) { - checkSupertypes(descriptor.defaultType, declaration, trace, module) + checkSupertypes(descriptor, declaration, trace, context.missingSupertypesResolver) } if (declaration is KtTypeParameterListOwner) { for (ktTypeParameter in declaration.typeParameters) { val typeParameterDescriptor = trace.bindingContext.get(BindingContext.TYPE_PARAMETER, ktTypeParameter) ?: continue for (upperBound in typeParameterDescriptor.upperBounds) { - checkSupertypes(upperBound, ktTypeParameter, trace, module) + checkSupertypes(upperBound, ktTypeParameter, trace, context.missingSupertypesResolver) } } } @@ -45,57 +43,54 @@ object MissingDependencySupertypeChecker { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.resultingDescriptor - // Constructor call leads to resolution of supertypes of enclosing class if it's an inner class constructor - checkHierarchy(descriptor.dispatchReceiverParameter?.declaration, reportOn, context) - // The constructed class' own supertypes are not resolved after constructor call, - // so its containing declaration should not be checked. - if (descriptor !is ConstructorDescriptor) { - checkHierarchy(descriptor.containingDeclaration, reportOn, context) - checkHierarchy(descriptor.extensionReceiverParameter?.declaration, reportOn, context) + val errorReported = checkSupertypes( + descriptor.dispatchReceiverParameter?.declaration, reportOn, + context.trace, context.missingSupertypesResolver + ) + if (descriptor !is ConstructorDescriptor && !errorReported) { + // The constructed class' own supertypes are not resolved after constructor call, + // so its containing declaration should not be checked. + // Dispatch receiver is checked before for case of inner class constructor call. + checkSupertypes(descriptor.containingDeclaration, reportOn, context.trace, context.missingSupertypesResolver) + checkSupertypes( + descriptor.extensionReceiverParameter?.declaration, reportOn, + context.trace, context.missingSupertypesResolver + ) } } private val ReceiverParameterDescriptor.declaration get() = value.type.constructor.declarationDescriptor - - private fun checkHierarchy(declaration: DeclarationDescriptor?, reportOn: PsiElement, context: CallCheckerContext) { - if (declaration !is ClassifierDescriptor) return - - checkSupertypes(declaration.defaultType, reportOn, context.trace, context.moduleDescriptor) - } } + // true for reported error fun checkSupertypes( classifierType: KotlinType, reportOn: PsiElement, trace: BindingTrace, - moduleDescriptor: ModuleDescriptor - ) { - val classifierDescriptor = classifierType.constructor.declarationDescriptor ?: return + missingSupertypesResolver: MissingSupertypesResolver + ) = checkSupertypes(classifierType.constructor.declarationDescriptor, reportOn, trace, missingSupertypesResolver) - for (supertype in classifierType.supertypes()) { - val supertypeDeclaration = supertype.constructor.declarationDescriptor + // true for reported error + fun checkSupertypes( + declaration: DeclarationDescriptor?, + reportOn: PsiElement, + trace: BindingTrace, + missingSupertypesResolver: MissingSupertypesResolver + ): Boolean { + if (declaration !is ClassifierDescriptor) + return false - /* - * TODO: expects are not checked, because findClassAcrossModuleDependencies does not work with actualization via type alias - * Type parameters are skipped here, bounds of type parameters are checked in declaration checker separately - * Local declarations are ignored for optimization - */ - if (supertypeDeclaration !is ClassDescriptor || supertypeDeclaration.isExpect) continue - if (supertypeDeclaration.visibility == Visibilities.LOCAL) continue - - val superTypeClassId = supertypeDeclaration.classId ?: continue - val dependency = moduleDescriptor.findClassAcrossModuleDependencies(superTypeClassId) - - if (dependency == null || dependency is NotFoundClasses.MockClassDescriptor) { - trace.report( - Errors.MISSING_DEPENDENCY_SUPERCLASS.on( - reportOn, - supertypeDeclaration.fqNameSafe, - classifierDescriptor.fqNameSafe - ) + val missingSupertypes = missingSupertypesResolver.getMissingSuperClassifiers(declaration) + for (missingClassifier in missingSupertypes) { + trace.report( + Errors.MISSING_DEPENDENCY_SUPERCLASS.on( + reportOn, + missingClassifier.fqNameSafe, + declaration.fqNameSafe ) - } + ) } + return missingSupertypes.isNotEmpty() } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 4d9a156e249..b59ec9ca5ac 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -961,7 +961,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { // Call must be validated with the actual, not temporary trace in order to report operator diagnostic // Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace CallCheckerContext callCheckerContext = - new CallCheckerContext(context, components.deprecationResolver, components.moduleDescriptor, trace); + new CallCheckerContext( + context, + components.deprecationResolver, + components.moduleDescriptor, + components.missingSupertypesResolver, + trace + ); for (CallChecker checker : components.callCheckers) { checker.check(resolvedCall, expression, callCheckerContext); } @@ -1038,7 +1044,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @NotNull private CallCheckerContext createCallCheckerContext(@NotNull ExpressionTypingContext context) { - return new CallCheckerContext(context, components.deprecationResolver, components.moduleDescriptor); + return new CallCheckerContext( + context, + components.deprecationResolver, + components.moduleDescriptor, + components.missingSupertypesResolver + ); } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index 208513313de..77e4303401a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -66,6 +66,7 @@ public class ExpressionTypingComponents { /*package*/ DataFlowValueFactory dataFlowValueFactory; /*package*/ NewKotlinTypeChecker kotlinTypeChecker; /*package*/ TypeResolutionInterceptor typeResolutionInterceptor; + /*package*/ MissingSupertypesResolver missingSupertypesResolver; @Inject @@ -252,4 +253,9 @@ public class ExpressionTypingComponents { public void setTypeResolutionInterceptor(@NotNull TypeResolutionInterceptor typeResolutionInterceptor) { this.typeResolutionInterceptor = typeResolutionInterceptor; } + + @Inject + public void setMissingSupertypesResolver(@NotNull MissingSupertypesResolver missingSupertypesResolver) { + this.missingSupertypesResolver = missingSupertypesResolver; + } }