Added 'isExternal' to ValueArgument
'subject' is external for 'in(contains)' resolve in 'when' condition:
when (subject) {
in range -> ...
}
This commit is contained in:
@@ -61,4 +61,9 @@ public class JetValueArgument extends JetElementImpl implements ValueArgument {
|
|||||||
ASTNode node = getNode().findChildByType(JetTokens.MUL);
|
ASTNode node = getNode().findChildByType(JetTokens.MUL);
|
||||||
return node == null ? null : (LeafPsiElement) node.getPsi();
|
return node == null ? null : (LeafPsiElement) node.getPsi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExternal() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,4 +36,7 @@ public interface ValueArgument {
|
|||||||
/* The '*' in something like foo(*arr) i.e. pass an array as a number of vararg arguments */
|
/* The '*' in something like foo(*arr) i.e. pass an array as a number of vararg arguments */
|
||||||
@Nullable
|
@Nullable
|
||||||
LeafPsiElement getSpreadElement();
|
LeafPsiElement getSpreadElement();
|
||||||
|
|
||||||
|
/* The argument is placed externally to call element, e.g. in 'when' condition with subject: 'when (a) { in c -> }' */
|
||||||
|
boolean isExternal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,14 +226,11 @@ public class CallCompleter(
|
|||||||
valueArgument: ValueArgument,
|
valueArgument: ValueArgument,
|
||||||
context: BasicCallResolutionContext
|
context: BasicCallResolutionContext
|
||||||
) {
|
) {
|
||||||
|
if (valueArgument.isExternal()) return
|
||||||
|
|
||||||
val expression = valueArgument.getArgumentExpression()
|
val expression = valueArgument.getArgumentExpression()
|
||||||
if (expression == null) return
|
if (expression == null) return
|
||||||
|
|
||||||
// for the 'in' call 'when (b) { in 1..10 -> true }' 'b' is an argument, but an error shouldn't be generated on it
|
|
||||||
// todo add special call type for such a case, and check this call type instead
|
|
||||||
val parent = expression.getParent()
|
|
||||||
if (parent is JetWhenExpression && expression == parent.getSubjectExpression()) return
|
|
||||||
|
|
||||||
val recordedType = context.trace[BindingContext.EXPRESSION_TYPE, expression]
|
val recordedType = context.trace[BindingContext.EXPRESSION_TYPE, expression]
|
||||||
var updatedType: JetType? = recordedType
|
var updatedType: JetType? = recordedType
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,21 @@ public class CallMaker {
|
|||||||
|
|
||||||
private final JetElement reportErrorsOn;
|
private final JetElement reportErrorsOn;
|
||||||
|
|
||||||
private ExpressionValueArgument(@Nullable JetExpression expression, @NotNull JetElement reportErrorsOn) {
|
private final boolean isExternal;
|
||||||
|
|
||||||
|
private ExpressionValueArgument(
|
||||||
|
@Nullable JetExpression expression,
|
||||||
|
@NotNull JetElement reportErrorsOn,
|
||||||
|
boolean isExternal
|
||||||
|
) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.reportErrorsOn = expression == null ? reportErrorsOn : expression;
|
this.reportErrorsOn = expression == null ? reportErrorsOn : expression;
|
||||||
|
this.isExternal = isExternal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExternal() {
|
||||||
|
return isExternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -236,7 +248,12 @@ public class CallMaker {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static ValueArgument makeValueArgument(@Nullable JetExpression expression, @NotNull JetElement reportErrorsOn) {
|
public static ValueArgument makeValueArgument(@Nullable JetExpression expression, @NotNull JetElement reportErrorsOn) {
|
||||||
return new ExpressionValueArgument(expression, reportErrorsOn);
|
return new ExpressionValueArgument(expression, reportErrorsOn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ValueArgument makeExternalValueArgument(@NotNull JetExpression expression) {
|
||||||
|
return new ExpressionValueArgument(expression, expression, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+6
-7
@@ -40,10 +40,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
|
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
|
import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
|
||||||
@@ -908,7 +905,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
|
result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
||||||
result = checkInExpression(expression, operationSign, left, right, context);
|
ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
|
||||||
|
result = checkInExpression(expression, operationSign, leftArgument, right, context);
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
|
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
|
||||||
result = visitBooleanOperationExpression(operationType, left, right, context);
|
result = visitBooleanOperationExpression(operationType, left, right, context);
|
||||||
@@ -1076,10 +1074,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
public JetTypeInfo checkInExpression(
|
public JetTypeInfo checkInExpression(
|
||||||
@NotNull JetElement callElement,
|
@NotNull JetElement callElement,
|
||||||
@NotNull JetSimpleNameExpression operationSign,
|
@NotNull JetSimpleNameExpression operationSign,
|
||||||
@Nullable JetExpression left,
|
@NotNull ValueArgument leftArgument,
|
||||||
@Nullable JetExpression right,
|
@Nullable JetExpression right,
|
||||||
@NotNull ExpressionTypingContext context
|
@NotNull ExpressionTypingContext context
|
||||||
) {
|
) {
|
||||||
|
JetExpression left = leftArgument.getArgumentExpression();
|
||||||
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
|
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||||
if (right == null) {
|
if (right == null) {
|
||||||
if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
|
if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
|
||||||
@@ -1093,7 +1092,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
|
OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
|
||||||
contextWithDataFlow,
|
contextWithDataFlow,
|
||||||
CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
|
CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
|
||||||
operationSign,
|
operationSign,
|
||||||
OperatorConventions.CONTAINS);
|
OperatorConventions.CONTAINS);
|
||||||
JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
|
JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
|
||||||
|
|||||||
+8
-4
@@ -18,14 +18,18 @@ package org.jetbrains.jet.lang.types.expressions;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
|
||||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||||
|
|
||||||
/*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade {
|
/*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade {
|
||||||
@NotNull
|
@NotNull
|
||||||
JetTypeInfo checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
|
JetTypeInfo checkInExpression(
|
||||||
|
@NotNull JetElement callElement,
|
||||||
|
@NotNull JetSimpleNameExpression operationSign,
|
||||||
|
@NotNull ValueArgument leftArgument,
|
||||||
|
@Nullable JetExpression right,
|
||||||
|
@NotNull ExpressionTypingContext context
|
||||||
|
);
|
||||||
|
|
||||||
void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -74,8 +74,14 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JetTypeInfo checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
|
public JetTypeInfo checkInExpression(
|
||||||
return basic.checkInExpression(callElement, operationSign, left, right, context);
|
@NotNull JetElement callElement,
|
||||||
|
@NotNull JetSimpleNameExpression operationSign,
|
||||||
|
@NotNull ValueArgument leftArgument,
|
||||||
|
@Nullable JetExpression right,
|
||||||
|
@NotNull ExpressionTypingContext context
|
||||||
|
) {
|
||||||
|
return basic.checkInExpression(callElement, operationSign, leftArgument, right, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+6
-5
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.TypeResolutionContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
@@ -148,7 +149,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
DataFlowInfos infos = null;
|
DataFlowInfos infos = null;
|
||||||
for (JetWhenCondition condition : whenEntry.getConditions()) {
|
for (JetWhenCondition condition : whenEntry.getConditions()) {
|
||||||
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
|
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectType, condition,
|
||||||
context, subjectDataFlowValue);
|
context, subjectDataFlowValue);
|
||||||
if (infos != null) {
|
if (infos != null) {
|
||||||
infos = new DataFlowInfos(infos.thenInfo.or(conditionInfos.thenInfo), infos.elseInfo.and(conditionInfos.elseInfo));
|
infos = new DataFlowInfos(infos.thenInfo.or(conditionInfos.thenInfo), infos.elseInfo.and(conditionInfos.elseInfo));
|
||||||
@@ -162,7 +163,6 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
private DataFlowInfos checkWhenCondition(
|
private DataFlowInfos checkWhenCondition(
|
||||||
@Nullable final JetExpression subjectExpression,
|
@Nullable final JetExpression subjectExpression,
|
||||||
final boolean expectedCondition,
|
|
||||||
final JetType subjectType,
|
final JetType subjectType,
|
||||||
JetWhenCondition condition,
|
JetWhenCondition condition,
|
||||||
final ExpressionTypingContext context,
|
final ExpressionTypingContext context,
|
||||||
@@ -174,14 +174,15 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) {
|
public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) {
|
||||||
JetExpression rangeExpression = condition.getRangeExpression();
|
JetExpression rangeExpression = condition.getRangeExpression();
|
||||||
if (rangeExpression == null) return;
|
if (rangeExpression == null) return;
|
||||||
if (expectedCondition) {
|
if (subjectExpression == null) {
|
||||||
context.trace.report(EXPECTED_CONDITION.on(condition));
|
context.trace.report(EXPECTED_CONDITION.on(condition));
|
||||||
DataFlowInfo dataFlowInfo = facade.getTypeInfo(rangeExpression, context).getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = facade.getTypeInfo(rangeExpression, context).getDataFlowInfo();
|
||||||
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
|
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ValueArgument argumentForSubject = CallMaker.makeExternalValueArgument(subjectExpression);
|
||||||
JetTypeInfo typeInfo = facade.checkInExpression(condition, condition.getOperationReference(),
|
JetTypeInfo typeInfo = facade.checkInExpression(condition, condition.getOperationReference(),
|
||||||
subjectExpression, rangeExpression, context);
|
argumentForSubject, rangeExpression, context);
|
||||||
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||||
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
|
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
|
||||||
if (!KotlinBuiltIns.getInstance().getBooleanType().equals(typeInfo.getType())) {
|
if (!KotlinBuiltIns.getInstance().getBooleanType().equals(typeInfo.getType())) {
|
||||||
@@ -191,7 +192,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) {
|
public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) {
|
||||||
if (expectedCondition) {
|
if (subjectExpression == null) {
|
||||||
context.trace.report(EXPECTED_CONDITION.on(condition));
|
context.trace.report(EXPECTED_CONDITION.on(condition));
|
||||||
}
|
}
|
||||||
if (condition.getTypeRef() != null) {
|
if (condition.getTypeRef() != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user