Added 'isExternal' to ValueArgument

'subject' is external for 'in(contains)' resolve in 'when' condition:
when (subject) {
  in range -> ...
}
This commit is contained in:
Svetlana Isakova
2014-07-01 15:45:10 +04:00
parent ae8757f6b8
commit e1fb5a9a04
8 changed files with 57 additions and 25 deletions
@@ -61,4 +61,9 @@ public class JetValueArgument extends JetElementImpl implements ValueArgument {
ASTNode node = getNode().findChildByType(JetTokens.MUL);
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 */
@Nullable
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,
context: BasicCallResolutionContext
) {
if (valueArgument.isExternal()) return
val expression = valueArgument.getArgumentExpression()
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]
var updatedType: JetType? = recordedType
@@ -37,9 +37,21 @@ public class CallMaker {
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.reportErrorsOn = expression == null ? reportErrorsOn : expression;
this.isExternal = isExternal;
}
@Override
public boolean isExternal() {
return isExternal;
}
@Override
@@ -236,7 +248,12 @@ public class CallMaker {
@NotNull
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
@@ -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.CheckValueArgumentsMode;
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.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.model.*;
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.OverloadResolutionResultsUtil;
@@ -908,7 +905,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
result = JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), context.dataFlowInfo);
}
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)) {
result = visitBooleanOperationExpression(operationType, left, right, context);
@@ -1076,10 +1074,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public JetTypeInfo checkInExpression(
@NotNull JetElement callElement,
@NotNull JetSimpleNameExpression operationSign,
@Nullable JetExpression left,
@NotNull ValueArgument leftArgument,
@Nullable JetExpression right,
@NotNull ExpressionTypingContext context
) {
JetExpression left = leftArgument.getArgumentExpression();
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
if (right == null) {
if (left != null) facade.getTypeInfo(left, contextWithNoExpectedType);
@@ -1093,7 +1092,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
OverloadResolutionResults<FunctionDescriptor> resolutionResult = components.callResolver.resolveCallWithGivenName(
contextWithDataFlow,
CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)),
operationSign,
OperatorConventions.CONTAINS);
JetType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context.contextDependency);
@@ -18,14 +18,18 @@ package org.jetbrains.jet.lang.types.expressions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetTypeInfo;
/*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade {
@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);
@@ -74,8 +74,14 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
@NotNull
@Override
public JetTypeInfo checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
return basic.checkInExpression(callElement, operationSign, left, right, context);
public JetTypeInfo checkInExpression(
@NotNull JetElement callElement,
@NotNull JetSimpleNameExpression operationSign,
@NotNull ValueArgument leftArgument,
@Nullable JetExpression right,
@NotNull ExpressionTypingContext context
) {
return basic.checkInExpression(callElement, operationSign, leftArgument, right, context);
}
@Override
@@ -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.DataFlowValue;
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.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -148,7 +149,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowInfos infos = null;
for (JetWhenCondition condition : whenEntry.getConditions()) {
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectType, condition,
context, subjectDataFlowValue);
if (infos != null) {
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(
@Nullable final JetExpression subjectExpression,
final boolean expectedCondition,
final JetType subjectType,
JetWhenCondition condition,
final ExpressionTypingContext context,
@@ -174,14 +174,15 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) {
JetExpression rangeExpression = condition.getRangeExpression();
if (rangeExpression == null) return;
if (expectedCondition) {
if (subjectExpression == null) {
context.trace.report(EXPECTED_CONDITION.on(condition));
DataFlowInfo dataFlowInfo = facade.getTypeInfo(rangeExpression, context).getDataFlowInfo();
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
return;
}
ValueArgument argumentForSubject = CallMaker.makeExternalValueArgument(subjectExpression);
JetTypeInfo typeInfo = facade.checkInExpression(condition, condition.getOperationReference(),
subjectExpression, rangeExpression, context);
argumentForSubject, rangeExpression, context);
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
newDataFlowInfo.set(new DataFlowInfos(dataFlowInfo, dataFlowInfo));
if (!KotlinBuiltIns.getInstance().getBooleanType().equals(typeInfo.getType())) {
@@ -191,7 +192,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
@Override
public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) {
if (expectedCondition) {
if (subjectExpression == null) {
context.trace.report(EXPECTED_CONDITION.on(condition));
}
if (condition.getTypeRef() != null) {