diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 713f2a0abb6..3ee9f72acef 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -641,6 +641,8 @@ public class JetControlFlowProcessor { JetWhenCondition condition = whenEntry.getCondition(); if (condition != null) { condition.accept(new JetVisitor() { + private final JetVisitor conditionVisitor = this; + @Override public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) { value(condition.getExpression(), false, inCondition); // TODO : inCondition? @@ -689,6 +691,14 @@ public class JetControlFlowProcessor { pattern.getArgumentList().accept(this); } + @Override + public void visitBindingPattern(JetBindingPattern pattern) { + JetWhenCondition condition = pattern.getCondition(); + if (condition != null) { + condition.accept(conditionVisitor); + } + } + @Override public void visitJetElement(JetElement element) { throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index ee7ac511559..ba114905a93 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -886,22 +886,37 @@ public class JetExpressionParsing extends AbstractJetParsing { private void parseBindingPattern() { assert _at(VAL_KEYWORD); + PsiBuilder.Marker declaration = mark(); + advance(); // VAL_KEYWORD expect(IDENTIFIER, "Expecting an identifier"); - if (at(IS_KEYWORD) || at(NOT_IS)) { - advance(); // IS_KEYWORD or NOT_IS - - parsePattern(); - } else if (at(IN_KEYWORD) || at(NOT_IN)) { - advance(); // IN_KEYWORD ot NOT_IN - - parseExpression(); - } else if (at(COLON)) { + if (at(COLON)) { advance(); // EQ myJetParsing.parseTypeRef(); + declaration.done(PROPERTY); + } + else { + declaration.done(PROPERTY); + PsiBuilder.Marker subCondition = mark(); + if (at(IS_KEYWORD) || at(NOT_IS)) { + + advance(); // IS_KEYWORD or NOT_IS + + parsePattern(); + subCondition.done(WHEN_CONDITION_IS_PATTERN); + } else if (at(IN_KEYWORD) || at(NOT_IN)) { + PsiBuilder.Marker mark = mark(); + advance(); // IN_KEYWORD ot NOT_IN + mark.done(OPERATION_REFERENCE); + + parseExpression(); + subCondition.done(WHEN_CONDITION_IN_RANGE); + } else { + subCondition.drop(); + } } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java index e7343798308..4b133263183 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java @@ -2,7 +2,8 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.JetNodeTypes; /** * @author abreslav @@ -12,10 +13,18 @@ public class JetBindingPattern extends JetPattern { super(node); } - public boolean isVar() { - return findChildByType(JetTokens.VAR_KEYWORD) != null; + @NotNull + public JetProperty getVariableDeclaration() { + return (JetProperty) findChildByType(JetNodeTypes.PROPERTY); } + @Nullable + public JetWhenCondition getCondition() { + return findChildByClass(JetWhenCondition.class); + } - + @Override + public void accept(@NotNull JetVisitor visitor) { + visitor.visitBindingPattern(this); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java index 1a1d2d8c695..382b1dda657 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java @@ -397,4 +397,8 @@ public class JetVisitor extends PsiElementVisitor { public void visitObjectDeclaration(JetObjectDeclaration declaration) { visitNamedDeclaration(declaration); } + + public void visitBindingPattern(JetBindingPattern pattern) { + visitPattern(pattern); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 6651734596c..f31d877cf4e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -413,9 +413,14 @@ public class ClassDescriptorResolver { } @NotNull - public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, WritableScope scope, JetProperty property) { + public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, JetScope scope, JetProperty property) { JetType type = getVariableType(scope, property, false); // For a local variable the type must not be deferred + return resolveLocalVariableDescriptorWithType(containingDeclaration, property, type); + } + + @NotNull + public VariableDescriptor resolveLocalVariableDescriptorWithType(DeclarationDescriptor containingDeclaration, JetProperty property, JetType type) { VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor( containingDeclaration, AnnotationResolver.INSTANCE.resolveAnnotations(property.getModifierList()), diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index d5a4f37cc9f..d9d282d1a2f 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -160,7 +160,7 @@ public class ErrorUtils { } private static JetType createErrorType(String debugMessage, JetScope memberScope) { - return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.emptyList(), Collections.emptyList()), memberScope); + return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope); } public static JetType createWrongVarianceErrorType(TypeProjection value) { diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index dc6358d55c7..001995b5d32 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -104,7 +104,7 @@ public class JetTypeChecker { } commonSupertypes = computeCommonRawSupertypes(merge); } - assert !commonSupertypes.isEmpty() : types; + assert !commonSupertypes.isEmpty() : commonSupertypes + " <- " + types; Map.Entry> entry = commonSupertypes.entrySet().iterator().next(); JetType result = computeSupertypeProjections(entry.getKey(), entry.getValue()); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 15aeb87316e..c8a44bd90b5 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -378,23 +378,6 @@ public class JetTypeInferrer { return result; } - private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List result) { - for (JetWhenEntry entry : whenExpression.getEntries()) { - JetWhenExpression subWhen = entry.getSubWhen(); - if (subWhen != null) { - collectAllReturnTypes(subWhen, scope, result); - } else { - JetExpression resultExpression = entry.getExpression(); - if (resultExpression != null) { - JetType type = getType(scope, resultExpression, true); - if (type != null) { - result.add(type); - } - } - } - } - } - @Nullable private JetType resolveCall( @NotNull JetScope scope, @@ -1105,77 +1088,91 @@ public class JetTypeInferrer { // TODO :change scope according to the bound value in the when header final JetExpression subjectExpression = expression.getSubjectExpression(); - JetType subjectType = null; - if (subjectExpression != null) { - subjectType = getType(scope, subjectExpression, false); - } + final JetType subjectType = subjectExpression != null ? safeGetType(scope, subjectExpression, false) : ErrorUtils.createErrorType("Unknown type"); + final VariableDescriptor variableDescriptor = subjectExpression != null ? getVariableDescriptorFromSimpleName(subjectExpression) : null; // TODO : exhaustive patterns + Set expressionTypes = Sets.newHashSet(); for (JetWhenEntry whenEntry : expression.getEntries()) { - final JetType finalSubjectType = subjectType != null ? subjectType : ErrorUtils.createErrorType("Unknown type"); JetWhenCondition condition = whenEntry.getCondition(); + WritableScope scopeToExtend = new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler()); + DataFlowInfo newDataFlowInfo = dataFlowInfo; if (condition != null) { - condition.accept(new JetVisitor() { - @Override - public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) { - JetExpression conditionExpression = condition.getExpression(); - if (conditionExpression != null) { - JetType type = getType(scope, conditionExpression, false); - if (type != null && finalSubjectType != null) { - if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(finalSubjectType, type)) == null) { - trace.getErrorHandler().genericError(conditionExpression.getNode(), "This condition can never hold"); - } - } - } - } - - @Override - public void visitWhenConditionCall(JetWhenConditionCall condition) { - JetExpression callSuffixExpression = condition.getCallSuffixExpression(); - JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker()); - if (callSuffixExpression != null) { - JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false); - ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression"); - checkNullSafety(finalSubjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression)); - } - } - - @Override - public void visitWhenConditionInRange(JetWhenConditionInRange condition) { - JetExpression rangeExpression = condition.getRangeExpression(); - if (rangeExpression != null) { - checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression); - } - } - - @Override - public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { - JetPattern pattern = condition.getPattern(); - if (pattern != null) { - checkPatternType(pattern, finalSubjectType); - } - } - - @Override - public void visitJetElement(JetElement element) { - trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer] : " + element); - } - }); + newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, variableDescriptor, condition, scopeToExtend); + } + JetWhenExpression subWhen = whenEntry.getSubWhen(); + JetExpression bodyExpression = subWhen == null ? whenEntry.getExpression() : subWhen; + if (bodyExpression != null) { + JetType type = getType(scopeToExtend, bodyExpression, false, newDataFlowInfo); + if (type != null) { + expressionTypes.add(type); + } } } - List expressionTypes = new ArrayList(); - collectAllReturnTypes(expression, scope, expressionTypes); if (!expressionTypes.isEmpty()) { result = semanticServices.getTypeChecker().commonSupertype(expressionTypes); } - else { + else if (expression.getEntries().isEmpty()) { trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression"); // TODO : Scope, and maybe this should not an error } } - private void checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType) { + private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final JetType subjectType, final VariableDescriptor variableDescriptor, JetWhenCondition condition, final WritableScope scopeToExtend) { + final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{dataFlowInfo}; + condition.accept(new JetVisitor() { + @Override + public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) { + JetExpression conditionExpression = condition.getExpression(); + if (conditionExpression != null) { + JetType type = getType(scope, conditionExpression, false); + if (type != null && subjectType != null) { + if (TypeUtils.intersect(semanticServices.getTypeChecker(), Sets.newHashSet(subjectType, type)) == null) { + trace.getErrorHandler().genericError(conditionExpression.getNode(), "This condition can never hold"); + } + } + } + } + + @Override + public void visitWhenConditionCall(JetWhenConditionCall condition) { + JetExpression callSuffixExpression = condition.getCallSuffixExpression(); + JetScope compositeScope = new ScopeWithReceiver(scope, subjectType, semanticServices.getTypeChecker()); + if (callSuffixExpression != null) { + JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false); + ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression"); + checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression)); + } + } + + @Override + public void visitWhenConditionInRange(JetWhenConditionInRange condition) { + JetExpression rangeExpression = condition.getRangeExpression(); + if (rangeExpression != null) { + assert subjectExpression != null; + checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression); + } + } + + @Override + public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { + JetPattern pattern = condition.getPattern(); + if (pattern != null) { + newDataFlowInfo[0] = checkPatternType(variableDescriptor, pattern, subjectType, scopeToExtend); + } + } + + @Override + public void visitJetElement(JetElement element) { + trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer] : " + element); + } + }); + return newDataFlowInfo[0]; + } + + private DataFlowInfo checkPatternType(@Nullable final VariableDescriptor subjectVariable, @NotNull JetPattern pattern, @NotNull final JetType subjectType, @NotNull final WritableScope scopeToExtend) { + final DataFlowInfo[] result = new DataFlowInfo[] {dataFlowInfo}; pattern.accept(new JetVisitor() { @Override public void visitTypePattern(JetTypePattern typePattern) { @@ -1183,26 +1180,18 @@ public class JetTypeInferrer { if (typeReference != null) { JetType type = typeResolver.resolveType(scope, typeReference); checkTypeCompatibility(type, subjectType, typePattern); + if (subjectVariable != null) { + result[0] = dataFlowInfo.isInstanceOf(subjectVariable, type); + } } } - @Override - public void visitWildcardPattern(JetWildcardPattern pattern) { - // Nothing - } - - @Override - public void visitExpressionPattern(JetExpressionPattern pattern) { - JetType type = getType(scope, pattern.getExpression(), false); - checkTypeCompatibility(type, subjectType, pattern); - } - @Override public void visitTuplePattern(JetTuplePattern pattern) { List entries = pattern.getEntries(); TypeConstructor typeConstructor = subjectType.getConstructor(); if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor) - || typeConstructor.getParameters().size() != entries.size()) { + || typeConstructor.getParameters().size() != entries.size()) { trace.getErrorHandler().genericError(pattern.getNode(), "Type mismatch: subject is of type " + subjectType + " but the pattern is of type Tuple" + entries.size()); // TODO : message } else { @@ -1218,7 +1207,7 @@ public class JetTypeInferrer { JetPattern entryPattern = entry.getPattern(); if (entryPattern != null) { - checkPatternType(entryPattern, type); + result[0] = checkPatternType(null, entryPattern, type, scopeToExtend); } } } @@ -1228,10 +1217,41 @@ public class JetTypeInferrer { public void visitDecomposerPattern(JetDecomposerPattern pattern) { JetType selectorReturnType = getSelectorReturnType(subjectType, pattern.getDecomposerExpression()); - checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType); + result[0] = checkPatternType(null, pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend); + } + + @Override + public void visitWildcardPattern(JetWildcardPattern pattern) { + // Nothing + } + + @Override + public void visitExpressionPattern(JetExpressionPattern pattern) { + JetType type = getType(scope, pattern.getExpression(), false); + checkTypeCompatibility(type, subjectType, pattern); + } + + @Override + public void visitBindingPattern(JetBindingPattern pattern) { + JetProperty variableDeclaration = pattern.getVariableDeclaration(); + JetTypeReference propertyTypeRef = variableDeclaration.getPropertyTypeRef(); + JetType type = propertyTypeRef == null ? subjectType : typeResolver.resolveType(scope, propertyTypeRef); + VariableDescriptor variableDescriptor = classDescriptorResolver.resolveLocalVariableDescriptorWithType(scope.getContainingDeclaration(), variableDeclaration, type); + scopeToExtend.addVariableDescriptor(variableDescriptor); + if (propertyTypeRef != null) { + if (!semanticServices.getTypeChecker().isSubtypeOf(subjectType, type)) { + trace.getErrorHandler().genericError(propertyTypeRef.getNode(), type + " must be a supertype of " + subjectType + ". Use 'is' to match against " + type); + } + } + + JetWhenCondition condition = pattern.getCondition(); + if (condition != null) { + result[0] = checkWhenCondition(null, subjectType, variableDescriptor, condition, scopeToExtend); + } } private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) { + // TODO : Take auto casts into account? if (type == null) { return; } @@ -1245,6 +1265,7 @@ public class JetTypeInferrer { trace.getErrorHandler().genericError(element.getNode(), "Unsupported [JetTypeInferrer]"); } }); + return result[0]; } @Override @@ -1667,6 +1688,9 @@ public class JetTypeInferrer { trace.recordAutoCast(receiverExpression, possibleType); break; } + else { + errorHandler.closeAndReturnCurrentRegion(); + } } } @@ -1789,6 +1813,7 @@ public class JetTypeInferrer { @Override public void visitIsExpression(JetIsExpression expression) { // TODO : patterns and everything + // TODO : Unify with WhenExpression JetType knownType = getType(scope, expression.getLeftHandSide(), false); JetPattern pattern = expression.getPattern(); if (pattern instanceof JetTypePattern) { diff --git a/idea/testData/checker/infos/Autocasts.jet b/idea/testData/checker/infos/Autocasts.jet index 83f21da42ee..54a4aaa47a7 100644 --- a/idea/testData/checker/infos/Autocasts.jet +++ b/idea/testData/checker/infos/Autocasts.jet @@ -53,3 +53,25 @@ fun f10(a : A?) { } } } + +fun f11(a : A?) { + when (a) { + is B => a.bar() + is A => a.foo() + is Any => a.foo() + is Any? => a.bar() + else => a?.foo() + } +} + +fun f12(a : A?) { + when (a) { + is B => a.bar() + is A => a.foo() + is Any => a.foo(); + is Any? => a.bar() + is val c : B => c.foo() + is val c is C => c.foo() + else => a?.foo() + } +} diff --git a/idea/testData/psi/AttributesOnPatterns.txt b/idea/testData/psi/AttributesOnPatterns.txt index beeaa74ce4b..1a17a6c4b98 100644 --- a/idea/testData/psi/AttributesOnPatterns.txt +++ b/idea/testData/psi/AttributesOnPatterns.txt @@ -35,9 +35,10 @@ JetFile: AttributesOnPatterns.jet PsiElement(IDENTIFIER)('a') PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') - PsiElement(val)('val') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') @@ -58,17 +59,19 @@ JetFile: AttributesOnPatterns.jet PsiElement(IDENTIFIER)('a') PsiElement(RBRACKET)(']') PsiWhiteSpace(' ') - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('foo') + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') diff --git a/idea/testData/psi/When.txt b/idea/testData/psi/When.txt index 3c76d08e1ad..3779b04add3 100644 --- a/idea/testData/psi/When.txt +++ b/idea/testData/psi/When.txt @@ -327,17 +327,19 @@ JetFile: When.jet PsiElement(is)('is') PsiWhiteSpace(' ') BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Foo') + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Foo') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') @@ -352,17 +354,19 @@ JetFile: When.jet PsiElement(LPAR)('(') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Foo') + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Foo') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY @@ -473,9 +477,10 @@ JetFile: When.jet PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('r') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('r') PsiElement(RPAR)(')') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') @@ -686,17 +691,19 @@ JetFile: When.jet PsiElement(LPAR)('(') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('T') + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY @@ -833,17 +840,19 @@ JetFile: When.jet PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Foo') + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Foo') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY @@ -888,19 +897,22 @@ JetFile: When.jet PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(in)('in') - PsiWhiteSpace(' ') - BINARY_EXPRESSION - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('1') + WHEN_CONDITION_IN_RANGE OPERATION_REFERENCE - PsiElement(RANGE)('..') - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('2') + PsiElement(in)('in') + PsiWhiteSpace(' ') + BINARY_EXPRESSION + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + OPERATION_REFERENCE + PsiElement(RANGE)('..') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY @@ -910,55 +922,59 @@ JetFile: When.jet PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('_') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('_') - PsiWhiteSpace(' ') - PsiElement(NOT_IS)('!is') - PsiWhiteSpace(' ') - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Foo') + WHEN_CONDITION_IS_PATTERN + PsiElement(NOT_IS)('!is') + PsiWhiteSpace(' ') + TYPE_PATTERN + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Foo') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('bar') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('bar') - PsiWhiteSpace(' ') - PsiElement(is)('is') - PsiWhiteSpace(' ') - DECOMPOSER_PATTERN - DOT_QUALIFIED_EXPRESSION - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('foo') - PsiElement(DOT)('.') - CALL_EXPRESSION + WHEN_CONDITION_IS_PATTERN + PsiElement(is)('is') + PsiWhiteSpace(' ') + DECOMPOSER_PATTERN + DOT_QUALIFIED_EXPRESSION REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('bar') - TYPE_ARGUMENT_LIST - PsiElement(LT)('<') - TYPE_PROJECTION + PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + TYPE_ARGUMENT_LIST + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiElement(GT)('>') + PsiWhiteSpace(' ') + PsiElement(AT)('@') + PsiWhiteSpace(' ') + DECOMPOSER_ARGUMENT_LIST + PsiElement(LPAR)('(') + TUPLE_PATTERN_ENTRY + TYPE_PATTERN TYPE_REFERENCE USER_TYPE REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') - PsiElement(GT)('>') - PsiWhiteSpace(' ') - PsiElement(AT)('@') - PsiWhiteSpace(' ') - DECOMPOSER_ARGUMENT_LIST - PsiElement(LPAR)('(') - TUPLE_PATTERN_ENTRY - TYPE_PATTERN - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') + PsiElement(RPAR)(')') PsiElement(RPAR)(')') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') @@ -998,16 +1014,17 @@ JetFile: When.jet PsiElement(is)('is') PsiWhiteSpace(' ') BINDING_PATTERN - PsiElement(val)('val') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - TYPE_REFERENCE - USER_TYPE - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('Foo') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Foo') PsiWhiteSpace(' ') PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') @@ -1088,9 +1105,10 @@ JetFile: When.jet PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('r') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('r') PsiElement(RPAR)(')') PsiElement(COMMA)(',') PsiWhiteSpace('\n ') @@ -1208,9 +1226,10 @@ JetFile: When.jet PsiElement(LPAR)('(') TUPLE_PATTERN_ENTRY BINDING_PATTERN - PsiElement(val)('val') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('b') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('b') PsiElement(COMMA)(',') PsiWhiteSpace(' ') TUPLE_PATTERN_ENTRY