Invoke call checkers where symbol usage validators are called

The change in componentAccess.kt is a minor regression that should be addressed
later
This commit is contained in:
Alexander Udalov
2016-06-27 18:55:56 +03:00
parent 4a05c749b5
commit 260689eb8c
4 changed files with 66 additions and 20 deletions
@@ -24,11 +24,14 @@ import kotlin.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext;
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker; import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
@@ -62,21 +65,27 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.creat
public class DelegatedPropertyResolver { public class DelegatedPropertyResolver {
public static final Name PROPERTY_DELEGATED_FUNCTION_NAME = Name.identifier("propertyDelegated"); public static final Name PROPERTY_DELEGATED_FUNCTION_NAME = Name.identifier("propertyDelegated");
private final ExpressionTypingServices expressionTypingServices;
private final FakeCallResolver fakeCallResolver;
private final KotlinBuiltIns builtIns; private final KotlinBuiltIns builtIns;
private final FakeCallResolver fakeCallResolver;
private final ExpressionTypingServices expressionTypingServices;
private final LanguageFeatureSettings languageFeatureSettings;
private final Iterable<CallChecker> callCheckers;
private final Iterable<SymbolUsageValidator> symbolUsageValidators; private final Iterable<SymbolUsageValidator> symbolUsageValidators;
public DelegatedPropertyResolver( public DelegatedPropertyResolver(
@NotNull Iterable<SymbolUsageValidator> symbolUsageValidators,
@NotNull KotlinBuiltIns builtIns, @NotNull KotlinBuiltIns builtIns,
@NotNull FakeCallResolver fakeCallResolver, @NotNull FakeCallResolver fakeCallResolver,
@NotNull ExpressionTypingServices expressionTypingServices @NotNull ExpressionTypingServices expressionTypingServices,
@NotNull LanguageFeatureSettings languageFeatureSettings,
@NotNull Iterable<CallChecker> callCheckers,
@NotNull Iterable<SymbolUsageValidator> symbolUsageValidators
) { ) {
this.symbolUsageValidators = symbolUsageValidators;
this.builtIns = builtIns; this.builtIns = builtIns;
this.fakeCallResolver = fakeCallResolver; this.fakeCallResolver = fakeCallResolver;
this.expressionTypingServices = expressionTypingServices; this.expressionTypingServices = expressionTypingServices;
this.languageFeatureSettings = languageFeatureSettings;
this.callCheckers = callCheckers;
this.symbolUsageValidators = symbolUsageValidators;
} }
public void resolvePropertyDelegate( public void resolvePropertyDelegate(
@@ -274,6 +283,11 @@ public class DelegatedPropertyResolver {
OperatorCallChecker.Companion.report(byKeyword, resultingDescriptor, trace); OperatorCallChecker.Companion.report(byKeyword, resultingDescriptor, trace);
} }
CallCheckerContext callCheckerContext =
new CallCheckerContext(trace, delegateFunctionsScope, languageFeatureSettings, dataFlowInfo);
for (CallChecker checker : callCheckers) {
checker.check(resultingCall, byKeyword, callCheckerContext);
}
for (SymbolUsageValidator validator : symbolUsageValidators) { for (SymbolUsageValidator validator : symbolUsageValidators) {
validator.validateCall(resultingCall, trace, byKeyword); validator.validateCall(resultingCall, trace, byKeyword);
} }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.types.expressions package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.config.LanguageFeatureSettings
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
@@ -24,6 +25,8 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.LocalVariableResolver import org.jetbrains.kotlin.resolve.LocalVariableResolver
import org.jetbrains.kotlin.resolve.TypeResolver import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.dataClassUtils.createComponentName import org.jetbrains.kotlin.resolve.dataClassUtils.createComponentName
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -37,6 +40,8 @@ class DestructuringDeclarationResolver(
private val fakeCallResolver: FakeCallResolver, private val fakeCallResolver: FakeCallResolver,
private val localVariableResolver: LocalVariableResolver, private val localVariableResolver: LocalVariableResolver,
private val typeResolver: TypeResolver, private val typeResolver: TypeResolver,
private val languageFeatureSettings: LanguageFeatureSettings,
private val callCheckers: Iterable<CallChecker>,
private val symbolUsageValidators: Iterable<SymbolUsageValidator> private val symbolUsageValidators: Iterable<SymbolUsageValidator>
) { ) {
fun defineLocalVariablesFromMultiDeclaration( fun defineLocalVariablesFromMultiDeclaration(
@@ -81,6 +86,10 @@ class DestructuringDeclarationResolver(
context.trace.record(BindingContext.COMPONENT_RESOLVED_CALL, entry, results.resultingCall) context.trace.record(BindingContext.COMPONENT_RESOLVED_CALL, entry, results.resultingCall)
val callCheckerContext = CallCheckerContext(context, languageFeatureSettings)
for (checker in callCheckers) {
checker.check(results.resultingCall, entry, callCheckerContext)
}
for (validator in symbolUsageValidators) { for (validator in symbolUsageValidators) {
validator.validateCall(results.resultingCall, context.trace, entry) validator.validateCall(results.resultingCall, context.trace, entry)
} }
@@ -20,6 +20,7 @@ import kotlin.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
@@ -27,6 +28,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.psi.Call;
import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext;
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker; import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
@@ -36,6 +39,7 @@ import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator;
import org.jetbrains.kotlin.types.DynamicTypesKt; import org.jetbrains.kotlin.types.DynamicTypesKt;
import org.jetbrains.kotlin.types.ErrorUtils; import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice; import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
import java.util.Collections; import java.util.Collections;
@@ -45,16 +49,22 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*;
public class ForLoopConventionsChecker { public class ForLoopConventionsChecker {
private final KotlinBuiltIns builtIns; private final KotlinBuiltIns builtIns;
private final Iterable<SymbolUsageValidator> symbolUsageValidators;
private final FakeCallResolver fakeCallResolver; private final FakeCallResolver fakeCallResolver;
private final LanguageFeatureSettings languageFeatureSettings;
private final Iterable<CallChecker> callCheckers;
private final Iterable<SymbolUsageValidator> symbolUsageValidators;
public ForLoopConventionsChecker( public ForLoopConventionsChecker(
@NotNull KotlinBuiltIns builtIns, @NotNull KotlinBuiltIns builtIns,
@NotNull FakeCallResolver fakeCallResolver, @NotNull FakeCallResolver fakeCallResolver,
@NotNull LanguageFeatureSettings languageFeatureSettings,
@NotNull Iterable<CallChecker> callCheckers,
@NotNull Iterable<SymbolUsageValidator> symbolUsageValidators @NotNull Iterable<SymbolUsageValidator> symbolUsageValidators
) { ) {
this.builtIns = builtIns; this.builtIns = builtIns;
this.fakeCallResolver = fakeCallResolver; this.fakeCallResolver = fakeCallResolver;
this.languageFeatureSettings = languageFeatureSettings;
this.callCheckers = callCheckers;
this.symbolUsageValidators = symbolUsageValidators; this.symbolUsageValidators = symbolUsageValidators;
} }
@@ -63,10 +73,10 @@ public class ForLoopConventionsChecker {
KtExpression loopRangeExpression = loopRange.getExpression(); KtExpression loopRangeExpression = loopRange.getExpression();
// Make a fake call loopRange.iterator(), and try to resolve it // Make a fake call loopRange.iterator(), and try to resolve it
Name iterator = Name.identifier("iterator"); Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = fakeCallResolver.makeAndResolveFakeCall(
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = loopRange, context, Collections.<KtExpression>emptyList(), OperatorNameConventions.ITERATOR, loopRangeExpression,
fakeCallResolver.makeAndResolveFakeCall(loopRange, context, Collections.<KtExpression>emptyList(), iterator, FakeCallKind.ITERATOR, loopRangeExpression
loopRangeExpression, FakeCallKind.ITERATOR, loopRangeExpression); );
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond(); OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
if (iteratorResolutionResults.isSuccess()) { if (iteratorResolutionResults.isSuccess()) {
@@ -76,20 +86,27 @@ public class ForLoopConventionsChecker {
checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace); checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace);
CallCheckerContext callCheckerContext = new CallCheckerContext(context, languageFeatureSettings);
for (CallChecker checker : callCheckers) {
checker.check(iteratorResolvedCall, loopRangeExpression, callCheckerContext);
}
for (SymbolUsageValidator validator : symbolUsageValidators) { for (SymbolUsageValidator validator : symbolUsageValidators) {
validator.validateCall(iteratorResolvedCall, context.trace, loopRangeExpression); validator.validateCall(iteratorResolvedCall, context.trace, loopRangeExpression);
} }
KotlinType iteratorType = iteratorFunction.getReturnType(); KotlinType iteratorType = iteratorFunction.getReturnType();
KotlinType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext", //noinspection ConstantConditions
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, KotlinType hasNextType = checkConventionForIterator(
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL); context, loopRangeExpression, iteratorType, OperatorNameConventions.HAS_NEXT,
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
);
if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) { if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) {
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType)); context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
} }
return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next", return checkConventionForIterator(
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, context, loopRangeExpression, iteratorType, OperatorNameConventions.NEXT,
LOOP_RANGE_NEXT_RESOLVED_CALL); NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL
);
} }
return null; return null;
} }
@@ -109,14 +126,15 @@ public class ForLoopConventionsChecker {
@NotNull ExpressionTypingContext context, @NotNull ExpressionTypingContext context,
@NotNull KtExpression loopRangeExpression, @NotNull KtExpression loopRangeExpression,
@NotNull KotlinType iteratorType, @NotNull KotlinType iteratorType,
@NotNull String name, @NotNull Name name,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> ambiguity, @NotNull DiagnosticFactory1<KtExpression, KotlinType> ambiguity,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> missing, @NotNull DiagnosticFactory1<KtExpression, KotlinType> missing,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> noneApplicable, @NotNull DiagnosticFactory1<KtExpression, KotlinType> noneApplicable,
@NotNull WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey @NotNull WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
) { ) {
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = fakeCallResolver.resolveFakeCall( OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = fakeCallResolver.resolveFakeCall(
context, new TransientReceiver(iteratorType), Name.identifier(name), loopRangeExpression); context, new TransientReceiver(iteratorType), name, loopRangeExpression
);
if (nextResolutionResults.isAmbiguity()) { if (nextResolutionResults.isAmbiguity()) {
context.trace.report(ambiguity.on(loopRangeExpression, iteratorType)); context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
} }
@@ -131,6 +149,11 @@ public class ForLoopConventionsChecker {
ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall(); ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall); context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor(); FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
CallCheckerContext callCheckerContext = new CallCheckerContext(context, languageFeatureSettings);
for (CallChecker checker : callCheckers) {
checker.check(resolvedCall, loopRangeExpression, callCheckerContext);
}
for (SymbolUsageValidator validator : symbolUsageValidators) { for (SymbolUsageValidator validator : symbolUsageValidators) {
validator.validateCall(resolvedCall, context.trace, loopRangeExpression); validator.validateCall(resolvedCall, context.trace, loopRangeExpression);
} }
@@ -13,6 +13,6 @@ operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.component
operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.component2() = 2 operator fun <T, U, V, W> @ExtensionFunctionType Function3<T, U, V, W>.component2() = 2
inline fun <T, U, V, W> inlineFunWithInvoke(s: (p: T, l: U) -> V, ext: T.(p: U, l: V) -> W) { inline fun <T, U, V, W> inlineFunWithInvoke(s: (p: T, l: U) -> V, ext: T.(p: U, l: V) -> W) {
val (d1, e1) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>s<!> val (d1, e1) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>s<!>
val (d2, e2) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>ext<!> val (d2, e2) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>ext<!>
} }