diff --git a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt index 82b01068a9a..439a6106186 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/frontend/di/injection.kt @@ -43,9 +43,13 @@ public fun StorageComponentContainer.configureModule( useInstance(moduleContext.platformToKotlinClassMap) useInstance(additionalCheckerProvider) useInstance(additionalCheckerProvider.symbolUsageValidator) + additionalCheckerProvider.declarationCheckers.forEach { useInstance(it) } + additionalCheckerProvider.typeCheckers.forEach { + useInstance(it) + } } public fun StorageComponentContainer.configureModule( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt index e66791d2c5e..a690cbf0226 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AdditionalCheckerProvider.kt @@ -34,7 +34,7 @@ public abstract class AdditionalCheckerProvider( public val declarationCheckers: List = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers public val callChecker: CallChecker = CompositeChecker(DEFAULT_CALL_CHECKERS + additionalCallCheckers) - public val typeChecker: AdditionalTypeChecker = AdditionalTypeChecker.Composite(DEFAULT_TYPE_CHECKERS + additionalTypeCheckers) + public val typeCheckers: List = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers public val symbolUsageValidator: SymbolUsageValidator = SymbolUsageValidator.Composite(DEFAULT_VALIDATORS + additionalSymbolUsageValidators) public object DefaultProvider : AdditionalCheckerProvider(listOf(), listOf(), listOf(), listOf()) {} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 952f299a05e..739357e7e26 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -264,8 +264,8 @@ public class CallResolver { return resolveFunctionCall( BasicCallResolutionContext.create( trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, - additionalCheckerProvider.getCallChecker(), - additionalCheckerProvider.getTypeChecker(), isAnnotationContext) + additionalCheckerProvider.getCallChecker(), isAnnotationContext + ) ); } @@ -345,7 +345,7 @@ public class CallResolver { CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, - callChecker, additionalCheckerProvider.getTypeChecker(), false); + callChecker, false); if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index e72cb37e6e8..849d4ae0c27 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedT import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getErasedReceiverType import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnExpressionWithBothReceivers import org.jetbrains.kotlin.resolve.calls.callUtil.isExplicitSafeCall +import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker import org.jetbrains.kotlin.resolve.calls.context.* import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall @@ -64,7 +65,8 @@ public class CandidateResolver( private val argumentTypeResolver: ArgumentTypeResolver, private val genericCandidateResolver: GenericCandidateResolver, private val reflectionTypes: ReflectionTypes, - private val modifiersChecker: ModifiersChecker + private val modifiersChecker: ModifiersChecker, + private val additionalTypeCheckers: Iterable ){ public fun performResolutionForCandidateCall( @@ -463,7 +465,7 @@ public class CandidateResolver( tracing.unnecessarySafeCall(trace, receiverArgumentType) } - additionalTypeChecker.checkReceiver(receiverParameter, receiverArgument, safeAccess, this) + additionalTypeCheckers.forEach { it.checkReceiver(receiverParameter, receiverArgument, safeAccess, this) } return SUCCESS } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AdditionalTypeChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AdditionalTypeChecker.kt index 8809c6cab38..e7887564604 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AdditionalTypeChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/AdditionalTypeChecker.kt @@ -16,38 +16,18 @@ package org.jetbrains.kotlin.resolve.calls.checkers -import org.jetbrains.kotlin.psi.JetExpression -import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext +import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.types.JetType public interface AdditionalTypeChecker { - - public class Composite(val checkers: List): AdditionalTypeChecker { - override fun checkType(expression: JetExpression, expressionType: JetType, c: ResolutionContext<*>) { - for (checker in checkers) { - checker.checkType(expression, expressionType, c) - } - } - - override fun checkReceiver( - receiverParameter: ReceiverParameterDescriptor, - receiverArgument: ReceiverValue, - safeAccess: Boolean, - c: CallResolutionContext<*> - ) { - for (checker in checkers) { - checker.checkReceiver(receiverParameter, receiverArgument, safeAccess, c) - } - } - } - fun checkType(expression: JetExpression, expressionType: JetType, c: ResolutionContext<*>) fun checkReceiver( - receiverParameter: ReceiverParameterDescriptor, - receiverArgument: ReceiverValue, + receiverParameter: ReceiverParameterDescriptor, + receiverArgument: ReceiverValue, safeAccess: Boolean, c: CallResolutionContext<*> ) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java index 09f8a76c8a3..7592bb7daf0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/BasicCallResolutionContext.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.StatementFilter; -import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker; import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; @@ -40,14 +39,13 @@ public class BasicCallResolutionContext extends CallResolutionContext @NotNull ResolutionResultsCache resolutionResultsCache, @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments, @NotNull CallChecker callChecker, - @NotNull AdditionalTypeChecker additionalTypeChecker, @NotNull StatementFilter statementFilter, @NotNull ReceiverValue explicitExtensionReceiverForInvoke, @NotNull CandidateResolveMode candidateResolveMode, @@ -64,7 +62,7 @@ public final class CallCandidateResolutionContext boolean insideSafeCallChain ) { super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache, - dataFlowInfoForArguments, callChecker, additionalTypeChecker, statementFilter, isAnnotationContext, + dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, insideSafeCallChain); this.candidateCall = candidateCall; this.tracing = tracing; @@ -82,7 +80,7 @@ public final class CallCandidateResolutionContext candidateCall, tracing, trace, context.scope, call, context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache, context.dataFlowInfoForArguments, - context.callChecker, context.additionalTypeChecker, context.statementFilter, explicitExtensionReceiverForInvoke, + context.callChecker, context.statementFilter, explicitExtensionReceiverForInvoke, candidateResolveMode, context.isAnnotationContext, context.collectAllCandidates, context.insideCallChain); } @@ -93,7 +91,7 @@ public final class CallCandidateResolutionContext return new CallCandidateResolutionContext( candidateCall, tracing, context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache, - context.dataFlowInfoForArguments, context.callChecker, context.additionalTypeChecker, context.statementFilter, + context.dataFlowInfoForArguments, context.callChecker, context.statementFilter, ReceiverValue.NO_RECEIVER, CandidateResolveMode.FULLY, context.isAnnotationContext, context.collectAllCandidates, context.insideCallChain); } @@ -111,7 +109,7 @@ public final class CallCandidateResolutionContext ) { return new CallCandidateResolutionContext( candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, - resolutionResultsCache, dataFlowInfoForArguments, callChecker, additionalTypeChecker, statementFilter, + resolutionResultsCache, dataFlowInfoForArguments, callChecker, statementFilter, explicitExtensionReceiverForInvoke, candidateResolveMode, isAnnotationContext, collectAllCandidates, insideSafeCallChain); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java index 75bbcb6a28e..79661288b6a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/context/CallResolutionContext.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.StatementFilter; -import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker; import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl; import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments; @@ -49,14 +48,12 @@ public abstract class CallResolutionContext extends C @NotNull ResolutionResultsCache resolutionResultsCache, @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments, @NotNull CallChecker callChecker, - @NotNull AdditionalTypeChecker additionalTypeChecker, @NotNull StatementFilter statementFilter, @NotNull Collection> resolvedCalls, boolean isAnnotationContext, @@ -64,7 +62,7 @@ public class ResolutionTask extends C boolean insideSafeCallChain ) { super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache, - dataFlowInfoForArguments, callChecker, additionalTypeChecker, statementFilter, isAnnotationContext, collectAllCandidates, insideSafeCallChain); + dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, insideSafeCallChain); this.lazyCandidates = lazyCandidates; this.resolvedCalls = resolvedCalls; this.tracing = tracing; @@ -79,7 +77,7 @@ public class ResolutionTask extends C context.trace, context.scope, context.call, context.expectedType, context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache, context.dataFlowInfoForArguments, - context.callChecker, context.additionalTypeChecker, + context.callChecker, context.statementFilter, new SmartList>(), context.isAnnotationContext, context.collectAllCandidates, context.insideCallChain); } @@ -113,7 +111,7 @@ public class ResolutionTask extends C return new ResolutionTask( lazyCandidates, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache, dataFlowInfoForArguments, - callChecker, additionalTypeChecker, + callChecker, statementFilter, resolvedCalls, isAnnotationContext, collectAllCandidates, insideSafeCallChain); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index d59205ff35c..9b27e50a892 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; +import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker; import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue; @@ -48,6 +49,12 @@ import static org.jetbrains.kotlin.types.TypeUtils.*; public class DataFlowAnalyzer { + private final Iterable additionalTypeCheckers; + + public DataFlowAnalyzer(@NotNull Iterable additionalTypeCheckers) { + this.additionalTypeCheckers = additionalTypeCheckers; + } + @NotNull public DataFlowInfo extractDataFlowInfoFromCondition( @Nullable JetExpression condition, @@ -164,7 +171,9 @@ public class DataFlowAnalyzer { if (expressionType == null) return null; - c.additionalTypeChecker.checkType(expression, expressionType, c); + for (AdditionalTypeChecker checker : additionalTypeCheckers) { + checker.checkType(expression, expressionType, c); + } if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() || JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, c.expectedType)) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java index c600003d75c..32bb12fa987 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingContext.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.resolve.AdditionalCheckerProvider; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.StatementFilter; -import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker; import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; import org.jetbrains.kotlin.resolve.calls.context.ContextDependency; import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext; @@ -57,7 +56,6 @@ public class ExpressionTypingContext extends ResolutionContext = callResolver.resolveFunctionCall(callResolutionContext)