KT-657 Semantic checks for when without condition

This commit is contained in:
svtk
2012-01-18 19:28:39 +04:00
parent cbcfeaa1b7
commit cc3a7448dc
19 changed files with 170 additions and 83 deletions
@@ -14,7 +14,6 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
@@ -2753,7 +2752,6 @@ If finally block is present, its last expression is the value of try expression.
} }
private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition, @Nullable Label nextEntry) { private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition, @Nullable Label nextEntry) {
StackValue conditionValue;
if (condition instanceof JetWhenConditionInRange) { if (condition instanceof JetWhenConditionInRange) {
JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition;
JetExpression rangeExpression = conditionInRange.getRangeExpression(); JetExpression rangeExpression = conditionInRange.getRangeExpression();
@@ -2768,16 +2766,22 @@ If finally block is present, its last expression is the value of try expression.
} }
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
} }
else if (condition instanceof JetWhenConditionIsPattern) { JetPattern pattern;
boolean isNegated;
if (condition instanceof JetWhenConditionIsPattern) {
JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition;
JetPattern pattern = patternCondition.getPattern(); pattern = patternCondition.getPattern();
conditionValue = generatePatternMatch(pattern, patternCondition.isNegated(), isNegated = patternCondition.isNegated();
subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType), nextEntry); }
else if (condition instanceof JetWhenConditionWithExpression) {
pattern = ((JetWhenConditionWithExpression) condition).getPattern();
isNegated = false;
} }
else { else {
throw new UnsupportedOperationException("unsupported kind of when condition"); throw new UnsupportedOperationException("unsupported kind of when condition");
} }
return conditionValue; return generatePatternMatch(pattern, isNegated,
subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType), nextEntry);
} }
private boolean isIntRangeExpr(JetExpression rangeExpression) { private boolean isIntRangeExpr(JetExpression rangeExpression) {
@@ -139,6 +139,7 @@ public interface JetNodeTypes {
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class); JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class);
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class); JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class);
JetNodeType WHEN_CONDITION_EXPRESSION = new JetNodeType("WHEN_CONDITION_WITH_EXPRESSION", JetWhenConditionWithExpression.class);
JetNodeType NAMESPACE_HEADER = new JetNodeType("NAMESPACE_HEADER", JetNamespaceHeader.class); JetNodeType NAMESPACE_HEADER = new JetNodeType("NAMESPACE_HEADER", JetNamespaceHeader.class);
} }
@@ -81,6 +81,14 @@ public class JetControlFlowProcessor {
} }
} }
@Override
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
JetExpressionPattern pattern = condition.getPattern();
if (pattern != null) {
pattern.accept(patternVisitor);
}
}
@Override @Override
public void visitJetElement(JetElement element) { public void visitJetElement(JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
@@ -320,6 +320,7 @@ public interface Errors {
ParameterizedDiagnosticFactory2<JetType, Integer> TYPE_MISMATCH_IN_TUPLE_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message ParameterizedDiagnosticFactory2<JetType, Integer> TYPE_MISMATCH_IN_TUPLE_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message
ParameterizedDiagnosticFactory2<JetType, JetType> TYPE_MISMATCH_IN_BINDING_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}"); ParameterizedDiagnosticFactory2<JetType, JetType> TYPE_MISMATCH_IN_BINDING_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}");
ParameterizedDiagnosticFactory2<JetType, JetType> INCOMPATIBLE_TYPES = ParameterizedDiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}"); ParameterizedDiagnosticFactory2<JetType, JetType> INCOMPATIBLE_TYPES = ParameterizedDiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}");
SimpleDiagnosticFactory EXPECTED_CONDITION = SimpleDiagnosticFactory.create(ERROR, "Expected condition of Boolean type");
ParameterizedDiagnosticFactory1<JetType> CANNOT_CHECK_FOR_ERASED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot check for instance of erased type: {0}"); ParameterizedDiagnosticFactory1<JetType> CANNOT_CHECK_FOR_ERASED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot check for instance of erased type: {0}");
ParameterizedDiagnosticFactory2<JetType, JetType> UNCHECKED_CAST = ParameterizedDiagnosticFactory2.create(WARNING, "Unchecked cast: {0} to {1}"); ParameterizedDiagnosticFactory2<JetType, JetType> UNCHECKED_CAST = ParameterizedDiagnosticFactory2.create(WARNING, "Unchecked cast: {0} to {1}");
@@ -844,7 +844,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseExpression(); parseExpression();
} }
expressionPattern.done(EXPRESSION_PATTERN); expressionPattern.done(EXPRESSION_PATTERN);
condition.done(WHEN_CONDITION_IS_PATTERN); condition.done(WHEN_CONDITION_EXPRESSION);
} }
myBuilder.restoreNewlinesState(); myBuilder.restoreNewlinesState();
} }
@@ -360,6 +360,10 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitJetElement(condition, data); return visitJetElement(condition, data);
} }
public R visitWhenConditionExpression(JetWhenConditionWithExpression condition, D data) {
return visitJetElement(condition, data);
}
public R visitTypePattern(JetTypePattern pattern, D data) { public R visitTypePattern(JetTypePattern pattern, D data) {
return visitPattern(pattern, data); return visitPattern(pattern, data);
} }
@@ -358,6 +358,10 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitJetElement(condition); visitJetElement(condition);
} }
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
visitJetElement(condition);
}
public void visitTypePattern(JetTypePattern pattern) { public void visitTypePattern(JetTypePattern pattern) {
visitPattern(pattern); visitPattern(pattern);
} }
@@ -0,0 +1,31 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author svtk
*/
public class JetWhenConditionWithExpression extends JetWhenCondition {
public JetWhenConditionWithExpression(@NotNull ASTNode node) {
super(node);
}
@Nullable
@IfNotParsed
public JetExpressionPattern getPattern() {
return findChildByClass(JetExpressionPattern.class);
}
@Override
public void accept(@NotNull JetVisitorVoid visitor) {
visitor.visitWhenConditionExpression(this);
}
@Override
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitWhenConditionExpression(this, data);
}
}
@@ -814,7 +814,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return DataFlowUtils.checkType(result, expression, contextWithExpectedType); return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
} }
public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) { public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
String name = "contains"; String name = "contains";
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE)); ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE));
OverloadResolutionResults<FunctionDescriptor> functionDescriptor = context.resolveCallWithGivenNameToDescriptor( OverloadResolutionResults<FunctionDescriptor> functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
@@ -23,7 +23,7 @@ import org.jetbrains.jet.lang.types.JetType;
@Nullable @Nullable
JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context); JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context);
void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context); void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context);
void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context); void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context);
} }
@@ -59,7 +59,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
} }
@Override @Override
public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) { public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
basic.checkInExpression(callElement, operationSign, left, right, context); basic.checkInExpression(callElement, operationSign, left, right, context);
} }
@@ -38,7 +38,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetPattern pattern = expression.getPattern(); JetPattern pattern = expression.getPattern();
if (pattern != null) { if (pattern != null) {
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in 'is'"); WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in 'is'");
DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, scopeToExtend, context, DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext())); DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext()));
context.patternsToDataFlowInfo.put(pattern, newDataFlowInfo); context.patternsToDataFlowInfo.put(pattern, newDataFlowInfo);
context.patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables()); context.patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables());
} }
@@ -56,7 +56,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
final JetExpression subjectExpression = expression.getSubjectExpression(); final JetExpression subjectExpression = expression.getSubjectExpression();
final JetType subjectType = subjectExpression != null ? context.getServices().safeGetType(context.scope, subjectExpression, TypeUtils.NO_EXPECTED_TYPE) : ErrorUtils.createErrorType("Unknown type"); final JetType subjectType = subjectExpression != null ? context.getServices().safeGetType(context.scope, subjectExpression, TypeUtils.NO_EXPECTED_TYPE) : ErrorUtils.createErrorType("Unknown type");
final DataFlowValue variableDescriptor = subjectExpression != null ? DataFlowValueFactory.INSTANCE.createDataFlowValue(subjectExpression, subjectType, context.trace.getBindingContext()) : null; final DataFlowValue variableDescriptor = subjectExpression != null ? DataFlowValueFactory.INSTANCE.createDataFlowValue(subjectExpression, subjectType, context.trace.getBindingContext()) : DataFlowValue.NULL;
// TODO : exhaustive patterns // TODO : exhaustive patterns
@@ -70,14 +70,14 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
newDataFlowInfo = context.dataFlowInfo; newDataFlowInfo = context.dataFlowInfo;
JetWhenCondition condition = conditions[0]; JetWhenCondition condition = conditions[0];
if (condition != null) { if (condition != null) {
newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, context, variableDescriptor); newDataFlowInfo = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition, scopeToExtend, context, variableDescriptor);
} }
} }
else { else {
scopeToExtend = newWritableScopeImpl(context); // We don't write to this scope scopeToExtend = newWritableScopeImpl(context); // We don't write to this scope
newDataFlowInfo = null; newDataFlowInfo = null;
for (JetWhenCondition condition : conditions) { for (JetWhenCondition condition : conditions) {
DataFlowInfo dataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, newWritableScopeImpl(context), context, variableDescriptor); DataFlowInfo dataFlowInfo = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition, newWritableScopeImpl(context), context, variableDescriptor);
if (newDataFlowInfo == null) { if (newDataFlowInfo == null) {
newDataFlowInfo = dataFlowInfo; newDataFlowInfo = dataFlowInfo;
} }
@@ -113,47 +113,59 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
return null; return null;
} }
private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final ExpressionTypingContext context, final DataFlowValue... subjectVariables) { private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final boolean expectedCondition, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final ExpressionTypingContext context, final DataFlowValue... subjectVariables) {
final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{context.dataFlowInfo}; final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{context.dataFlowInfo};
condition.accept(new JetVisitorVoid() { condition.accept(new JetVisitorVoid() {
@Override @Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) { public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
JetExpression rangeExpression = condition.getRangeExpression(); JetExpression rangeExpression = condition.getRangeExpression();
if (rangeExpression != null) { if (rangeExpression == null) return;
assert subjectExpression != null; if (expectedCondition) {
facade.checkInExpression(condition, condition.getOperationReference(), subjectExpression, rangeExpression, context); context.trace.report(EXPECTED_CONDITION.on(condition));
facade.getType(rangeExpression, context);
return;
} }
facade.checkInExpression(condition, condition.getOperationReference(), subjectExpression, rangeExpression, context);
} }
@Override @Override
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
JetPattern pattern = condition.getPattern(); JetPattern pattern = condition.getPattern();
if (expectedCondition) {
context.trace.report(EXPECTED_CONDITION.on(condition));
}
if (pattern != null) { if (pattern != null) {
newDataFlowInfo[0] = checkPatternType(pattern, subjectType, scopeToExtend, context, subjectVariables); newDataFlowInfo[0] = checkPatternType(pattern, subjectType, subjectExpression == null, scopeToExtend, context, subjectVariables);
}
}
@Override
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
JetPattern pattern = condition.getPattern();
if (pattern != null) {
newDataFlowInfo[0] = checkPatternType(pattern, subjectType, subjectExpression == null, scopeToExtend, context, subjectVariables);
} }
} }
@Override @Override
public void visitJetElement(JetElement element) { public void visitJetElement(JetElement element) {
// context.trace.getErrorHandler().genericError(element.getNode(), "Unsupported [OperatorConventions] : " + element);
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName())); context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
} }
}); });
return newDataFlowInfo[0]; return newDataFlowInfo[0];
} }
private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, @NotNull final WritableScope scopeToExtend, final ExpressionTypingContext context, @NotNull final DataFlowValue... subjectVariables) { private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, final boolean conditionExpected, @NotNull final WritableScope scopeToExtend, final ExpressionTypingContext context, @NotNull final DataFlowValue... subjectVariables) {
final Ref<DataFlowInfo> result = new Ref<DataFlowInfo>(context.dataFlowInfo); final Ref<DataFlowInfo> result = new Ref<DataFlowInfo>(context.dataFlowInfo);
pattern.accept(new JetVisitorVoid() { pattern.accept(new JetVisitorVoid() {
@Override @Override
public void visitTypePattern(JetTypePattern typePattern) { public void visitTypePattern(JetTypePattern typePattern) {
JetTypeReference typeReference = typePattern.getTypeReference(); JetTypeReference typeReference = typePattern.getTypeReference();
if (typeReference != null) { if (typeReference == null) return;
JetType type = context.getTypeResolver().resolveType(context.scope, typeReference); JetType type = context.getTypeResolver().resolveType(context.scope, typeReference);
checkTypeCompatibility(type, subjectType, typePattern); checkTypeCompatibility(type, subjectType, typePattern);
result.set(context.dataFlowInfo.establishSubtyping(subjectVariables, type)); result.set(context.dataFlowInfo.establishSubtyping(subjectVariables, type));
}
} }
@Override @Override
@@ -162,25 +174,23 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
TypeConstructor typeConstructor = subjectType.getConstructor(); TypeConstructor typeConstructor = subjectType.getConstructor();
if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor) if (!JetStandardClasses.getTuple(entries.size()).getTypeConstructor().equals(typeConstructor)
|| typeConstructor.getParameters().size() != entries.size()) { || typeConstructor.getParameters().size() != entries.size()) {
// context.trace.getErrorHandler().genericError(pattern.getNode(), "Type mismatch: subject is of type " + subjectType + " but the pattern is of type Tuple" + entries.size());
context.trace.report(TYPE_MISMATCH_IN_TUPLE_PATTERN.on(pattern, subjectType, entries.size())); context.trace.report(TYPE_MISMATCH_IN_TUPLE_PATTERN.on(pattern, subjectType, entries.size()));
return;
} }
else { for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) { JetTuplePatternEntry entry = entries.get(i);
JetTuplePatternEntry entry = entries.get(i); JetType type = subjectType.getArguments().get(i).getType();
JetType type = subjectType.getArguments().get(i).getType();
// TODO : is a name always allowed, ie for tuple patterns, not decomposer arg lists? // TODO : is a name always allowed, ie for tuple patterns, not decomposer arg lists?
ASTNode nameLabelNode = entry.getNameLabelNode(); ASTNode nameLabelNode = entry.getNameLabelNode();
if (nameLabelNode != null) { if (nameLabelNode != null) {
// context.trace.getErrorHandler().genericError(nameLabelNode, "Unsupported [OperatorConventions]"); // context.trace.getErrorHandler().genericError(nameLabelNode, "Unsupported [OperatorConventions]");
context.trace.report(UNSUPPORTED.on(nameLabelNode, getClass().getCanonicalName())); context.trace.report(UNSUPPORTED.on(nameLabelNode, getClass().getCanonicalName()));
} }
JetPattern entryPattern = entry.getPattern(); JetPattern entryPattern = entry.getPattern();
if (entryPattern != null) { if (entryPattern != null) {
result.set(result.get().and(checkPatternType(entryPattern, type, scopeToExtend, context))); result.set(result.get().and(checkPatternType(entryPattern, type, false, scopeToExtend, context)));
}
} }
} }
} }
@@ -194,7 +204,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
result.set(checkPatternType(pattern.getArgumentList(), selectorReturnType == null result.set(checkPatternType(pattern.getArgumentList(), selectorReturnType == null
? ErrorUtils.createErrorType("No type") ? ErrorUtils.createErrorType("No type")
: selectorReturnType, scopeToExtend, context)); : selectorReturnType, false, scopeToExtend, context));
} }
} }
@@ -206,10 +216,16 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
@Override @Override
public void visitExpressionPattern(JetExpressionPattern pattern) { public void visitExpressionPattern(JetExpressionPattern pattern) {
JetExpression expression = pattern.getExpression(); JetExpression expression = pattern.getExpression();
if (expression != null) { if (expression == null) return;
JetType type = facade.getType(expression, context.replaceScope(scopeToExtend)); JetType type = facade.getType(expression, context.replaceScope(scopeToExtend));
checkTypeCompatibility(type, subjectType, pattern); if (conditionExpected) {
JetType booleanType = context.semanticServices.getStandardLibrary().getBooleanType();
if (type != null && !context.semanticServices.getTypeChecker().equalTypes(booleanType, type)) {
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(pattern, type));
}
return;
} }
checkTypeCompatibility(type, subjectType, pattern);
} }
@Override @Override
@@ -221,7 +237,6 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
scopeToExtend.addVariableDescriptor(variableDescriptor); scopeToExtend.addVariableDescriptor(variableDescriptor);
if (propertyTypeRef != null) { if (propertyTypeRef != null) {
if (!context.semanticServices.getTypeChecker().isSubtypeOf(subjectType, type)) { if (!context.semanticServices.getTypeChecker().isSubtypeOf(subjectType, type)) {
// context.trace.getErrorHandler().genericError(propertyTypeRef.getNode(), type + " must be a supertype of " + subjectType + ". Use 'is' to match against " + type);
context.trace.report(TYPE_MISMATCH_IN_BINDING_PATTERN.on(propertyTypeRef, type, subjectType)); context.trace.report(TYPE_MISMATCH_IN_BINDING_PATTERN.on(propertyTypeRef, type, subjectType));
} }
} }
@@ -232,7 +247,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowValue[] newSubjectVariables = new DataFlowValue[oldLength + 1]; DataFlowValue[] newSubjectVariables = new DataFlowValue[oldLength + 1];
System.arraycopy(subjectVariables, 0, newSubjectVariables, 0, oldLength); System.arraycopy(subjectVariables, 0, newSubjectVariables, 0, oldLength);
newSubjectVariables[oldLength] = DataFlowValueFactory.INSTANCE.createDataFlowValue(variableDescriptor); newSubjectVariables[oldLength] = DataFlowValueFactory.INSTANCE.createDataFlowValue(variableDescriptor);
result.set(checkWhenCondition(null, subjectType, condition, scopeToExtend, context, newSubjectVariables)); result.set(checkWhenCondition(null, false, subjectType, condition, scopeToExtend, context, newSubjectVariables));
} }
} }
@@ -245,7 +260,6 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
return; return;
} }
if (TypeUtils.intersect(context.semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) { if (TypeUtils.intersect(context.semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
// context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType);
context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType)); context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType));
return; return;
} }
@@ -257,7 +271,6 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
@Override @Override
public void visitJetElement(JetElement element) { public void visitJetElement(JetElement element) {
// context.trace.getErrorHandler().genericError(element.getNode(), "Unsupported [OperatorConventions]");
context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName())); context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName()));
} }
}); });
@@ -0,0 +1,21 @@
//KT-657 Semantic checks for when without condition
package kt657
fun foo() =
when {
cond1() -> 12
cond2() -> 2
<!TYPE_MISMATCH_IN_CONDITION!>4<!> -> 34
<!TYPE_MISMATCH_IN_CONDITION!>#(1, 2)<!> -> 3
<!EXPECTED_CONDITION!>in 1..10<!> -> 34
<!TYPE_MISMATCH_IN_CONDITION!>4<!> -> 38
<!EXPECTED_CONDITION!>is val a in 1..10<!> -> 23
<!EXPECTED_CONDITION!>is Int<!> -> 33
<!EXPECTED_CONDITION!>is <!TYPE_MISMATCH_IN_TUPLE_PATTERN!>#(val a, 3)<!><!> -> 2
<!EXPECTED_CONDITION!>!is <!TYPE_MISMATCH_IN_TUPLE_PATTERN!>#(*, 1100)<!><!> -> 3
<!EXPECTED_CONDITION!>is *<!> -> 34
}
fun cond1() = false
fun cond2() = true
+8 -8
View File
@@ -23,7 +23,7 @@ JetFile: CallsInWhen.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -38,7 +38,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -57,7 +57,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -81,7 +81,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -111,7 +111,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -146,7 +146,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -166,7 +166,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -189,7 +189,7 @@ JetFile: CallsInWhen.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -309,7 +309,7 @@ JetFile: NewlinesInParentheses.jet
PsiElement(IDENTIFIER)('a') PsiElement(IDENTIFIER)('a')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
+1 -1
View File
@@ -1068,7 +1068,7 @@ JetFile: ShortAnnotations.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
INTEGER_CONSTANT INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
+10 -10
View File
@@ -762,7 +762,7 @@ JetFile: When.jet
PsiElement(IDENTIFIER)('Bar') PsiElement(IDENTIFIER)('Bar')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
PsiErrorElement:Expecting an expression, is-condition or in-condition PsiErrorElement:Expecting an expression, is-condition or in-condition
<empty list> <empty list>
@@ -1086,13 +1086,13 @@ JetFile: When.jet
PsiElement(IDENTIFIER)('c') PsiElement(IDENTIFIER)('c')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
INTEGER_CONSTANT INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiElement(COMMA)(',') PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -1102,13 +1102,13 @@ JetFile: When.jet
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiElement(COMMA)(',') PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar') PsiElement(IDENTIFIER)('bar')
PsiElement(COMMA)(',') PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
BINARY_EXPRESSION BINARY_EXPRESSION
INTEGER_CONSTANT INTEGER_CONSTANT
@@ -1228,7 +1228,7 @@ JetFile: When.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
INTEGER_CONSTANT INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3') PsiElement(INTEGER_LITERAL)('3')
@@ -1242,7 +1242,7 @@ JetFile: When.jet
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
BINARY_EXPRESSION BINARY_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -1263,7 +1263,7 @@ JetFile: When.jet
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
BINARY_EXPRESSION BINARY_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -1276,7 +1276,7 @@ JetFile: When.jet
PsiElement(IDENTIFIER)('i') PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',') PsiElement(COMMA)(',')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
BINARY_EXPRESSION BINARY_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
@@ -1297,7 +1297,7 @@ JetFile: When.jet
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
BINARY_WITH_PATTERN BINARY_WITH_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
+2 -2
View File
@@ -81,7 +81,7 @@ JetFile: When_ERR.jet
PsiElement(IDENTIFIER)('foo') PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
PsiErrorElement:Expecting an expression, is-condition or in-condition PsiErrorElement:Expecting an expression, is-condition or in-condition
<empty list> <empty list>
@@ -163,7 +163,7 @@ JetFile: When_ERR.jet
PsiElement(SEMICOLON)(';') PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
PsiErrorElement:Expecting an expression, is-condition or in-condition PsiErrorElement:Expecting an expression, is-condition or in-condition
<empty list> <empty list>
+12 -12
View File
@@ -433,7 +433,7 @@ JetFile: BinaryTree.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('EQ') PsiElement(IDENTIFIER)('EQ')
@@ -444,7 +444,7 @@ JetFile: BinaryTree.jet
PsiElement(true)('true') PsiElement(true)('true')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('LS') PsiElement(IDENTIFIER)('LS')
@@ -471,7 +471,7 @@ JetFile: BinaryTree.jet
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('GT') PsiElement(IDENTIFIER)('GT')
@@ -708,7 +708,7 @@ JetFile: BinaryTree.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('EQ') PsiElement(IDENTIFIER)('EQ')
@@ -719,7 +719,7 @@ JetFile: BinaryTree.jet
PsiElement(false)('false') PsiElement(false)('false')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('LS') PsiElement(IDENTIFIER)('LS')
@@ -748,7 +748,7 @@ JetFile: BinaryTree.jet
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('GT') PsiElement(IDENTIFIER)('GT')
@@ -886,7 +886,7 @@ JetFile: BinaryTree.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('EQ') PsiElement(IDENTIFIER)('EQ')
@@ -900,7 +900,7 @@ JetFile: BinaryTree.jet
PsiElement(false)('false') PsiElement(false)('false')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('LS') PsiElement(IDENTIFIER)('LS')
@@ -986,7 +986,7 @@ JetFile: BinaryTree.jet
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('GT') PsiElement(IDENTIFIER)('GT')
@@ -1257,7 +1257,7 @@ JetFile: BinaryTree.jet
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('EQ') PsiElement(IDENTIFIER)('EQ')
@@ -1268,7 +1268,7 @@ JetFile: BinaryTree.jet
PsiElement(IDENTIFIER)('node') PsiElement(IDENTIFIER)('node')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('LS') PsiElement(IDENTIFIER)('LS')
@@ -1290,7 +1290,7 @@ JetFile: BinaryTree.jet
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
WHEN_ENTRY WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN WHEN_CONDITION_WITH_EXPRESSION
EXPRESSION_PATTERN EXPRESSION_PATTERN
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('GT') PsiElement(IDENTIFIER)('GT')