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.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
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.inference.ConstraintSystem;
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 static final Name PROPERTY_DELEGATED_FUNCTION_NAME = Name.identifier("propertyDelegated");
private final ExpressionTypingServices expressionTypingServices;
private final FakeCallResolver fakeCallResolver;
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;
public DelegatedPropertyResolver(
@NotNull Iterable<SymbolUsageValidator> symbolUsageValidators,
@NotNull KotlinBuiltIns builtIns,
@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.fakeCallResolver = fakeCallResolver;
this.expressionTypingServices = expressionTypingServices;
this.languageFeatureSettings = languageFeatureSettings;
this.callCheckers = callCheckers;
this.symbolUsageValidators = symbolUsageValidators;
}
public void resolvePropertyDelegate(
@@ -274,6 +283,11 @@ public class DelegatedPropertyResolver {
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) {
validator.validateCall(resultingCall, trace, byKeyword);
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.config.LanguageFeatureSettings
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.Name
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.LocalVariableResolver
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.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@@ -37,6 +40,8 @@ class DestructuringDeclarationResolver(
private val fakeCallResolver: FakeCallResolver,
private val localVariableResolver: LocalVariableResolver,
private val typeResolver: TypeResolver,
private val languageFeatureSettings: LanguageFeatureSettings,
private val callCheckers: Iterable<CallChecker>,
private val symbolUsageValidators: Iterable<SymbolUsageValidator>
) {
fun defineLocalVariablesFromMultiDeclaration(
@@ -81,6 +86,10 @@ class DestructuringDeclarationResolver(
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) {
validator.validateCall(results.resultingCall, context.trace, entry)
}
@@ -20,6 +20,7 @@ import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
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.psi.Call;
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.model.ResolvedCall;
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.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
import java.util.Collections;
@@ -45,16 +49,22 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*;
public class ForLoopConventionsChecker {
private final KotlinBuiltIns builtIns;
private final Iterable<SymbolUsageValidator> symbolUsageValidators;
private final FakeCallResolver fakeCallResolver;
private final LanguageFeatureSettings languageFeatureSettings;
private final Iterable<CallChecker> callCheckers;
private final Iterable<SymbolUsageValidator> symbolUsageValidators;
public ForLoopConventionsChecker(
@NotNull KotlinBuiltIns builtIns,
@NotNull FakeCallResolver fakeCallResolver,
@NotNull LanguageFeatureSettings languageFeatureSettings,
@NotNull Iterable<CallChecker> callCheckers,
@NotNull Iterable<SymbolUsageValidator> symbolUsageValidators
) {
this.builtIns = builtIns;
this.fakeCallResolver = fakeCallResolver;
this.languageFeatureSettings = languageFeatureSettings;
this.callCheckers = callCheckers;
this.symbolUsageValidators = symbolUsageValidators;
}
@@ -63,10 +73,10 @@ public class ForLoopConventionsChecker {
KtExpression loopRangeExpression = loopRange.getExpression();
// Make a fake call loopRange.iterator(), and try to resolve it
Name iterator = Name.identifier("iterator");
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls =
fakeCallResolver.makeAndResolveFakeCall(loopRange, context, Collections.<KtExpression>emptyList(), iterator,
loopRangeExpression, FakeCallKind.ITERATOR, loopRangeExpression);
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = fakeCallResolver.makeAndResolveFakeCall(
loopRange, context, Collections.<KtExpression>emptyList(), OperatorNameConventions.ITERATOR, loopRangeExpression,
FakeCallKind.ITERATOR, loopRangeExpression
);
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
if (iteratorResolutionResults.isSuccess()) {
@@ -76,20 +86,27 @@ public class ForLoopConventionsChecker {
checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace);
CallCheckerContext callCheckerContext = new CallCheckerContext(context, languageFeatureSettings);
for (CallChecker checker : callCheckers) {
checker.check(iteratorResolvedCall, loopRangeExpression, callCheckerContext);
}
for (SymbolUsageValidator validator : symbolUsageValidators) {
validator.validateCall(iteratorResolvedCall, context.trace, loopRangeExpression);
}
KotlinType iteratorType = iteratorFunction.getReturnType();
KotlinType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext",
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE,
LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
//noinspection ConstantConditions
KotlinType hasNextType = checkConventionForIterator(
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)) {
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
}
return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next",
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE,
LOOP_RANGE_NEXT_RESOLVED_CALL);
return checkConventionForIterator(
context, loopRangeExpression, iteratorType, OperatorNameConventions.NEXT,
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL
);
}
return null;
}
@@ -109,14 +126,15 @@ public class ForLoopConventionsChecker {
@NotNull ExpressionTypingContext context,
@NotNull KtExpression loopRangeExpression,
@NotNull KotlinType iteratorType,
@NotNull String name,
@NotNull Name name,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> ambiguity,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> missing,
@NotNull DiagnosticFactory1<KtExpression, KotlinType> noneApplicable,
@NotNull WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
) {
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = fakeCallResolver.resolveFakeCall(
context, new TransientReceiver(iteratorType), Name.identifier(name), loopRangeExpression);
context, new TransientReceiver(iteratorType), name, loopRangeExpression
);
if (nextResolutionResults.isAmbiguity()) {
context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
}
@@ -131,6 +149,11 @@ public class ForLoopConventionsChecker {
ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
CallCheckerContext callCheckerContext = new CallCheckerContext(context, languageFeatureSettings);
for (CallChecker checker : callCheckers) {
checker.check(resolvedCall, loopRangeExpression, callCheckerContext);
}
for (SymbolUsageValidator validator : symbolUsageValidators) {
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
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 (d2, e2) = <!USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>ext<!>
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, USAGE_IS_NOT_INLINABLE, USAGE_IS_NOT_INLINABLE!>ext<!>
}