提交 891aebf3 编写于 作者: A Andrey Breslav

Basic support for when() expressions

上级 169f45b9
......@@ -16,7 +16,7 @@ whenConditionIf
whenCondition
: expression
: "." postfixUnaryExpression typeArguments? valueArguments?
: ("." | "?.") postfixUnaryExpression typeArguments? valueArguments?
: ("in" | "!in") expression
: ("is" | "!is") isRHS
;
......
......@@ -111,22 +111,22 @@ public interface JetNodeTypes {
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
JetNodeType DECOMPOSER_PATTERN = new JetNodeType("DECOMPOSER_PATTERN");
JetNodeType TUPLE_PATTERN = new JetNodeType("TUPLE_PATTERN");
JetNodeType DECOMPOSER_PATTERN = new JetNodeType("DECOMPOSER_PATTERN", JetPattern.class); // TODO
JetNodeType TUPLE_PATTERN = new JetNodeType("TUPLE_PATTERN", JetPattern.class); // TODO
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
JetNodeType DECOMPOSER_ARGUMENT_LIST = new JetNodeType("DECOMPOSER_ARGUMENT_LIST");
JetNodeType DECOMPOSER_ARGUMENT = new JetNodeType("DECOMPOSER_ARGUMENT");
JetNodeType TYPE_PATTERN = new JetNodeType("TYPE_PATTERN", JetTypePattern.class);
JetNodeType EXPRESSION_PATTERN = new JetNodeType("EXPRESSION_PATTERN");
JetNodeType BINDING_PATTERN = new JetNodeType("BINDING_PATTERN");
JetNodeType WILDCARD_PATTERN = new JetNodeType("WILDCARD_PATTERN");
JetNodeType EXPRESSION_PATTERN = new JetNodeType("EXPRESSION_PATTERN", JetPattern.class); // TODO
JetNodeType BINDING_PATTERN = new JetNodeType("BINDING_PATTERN", JetPattern.class); // TODO
JetNodeType WILDCARD_PATTERN = new JetNodeType("WILDCARD_PATTERN", JetPattern.class); // TODO
JetNodeType WHEN = new JetNodeType("WHEN", JetWhenExpression.class);
JetNodeType WHEN_ENTRY = new JetNodeType("WHEN_ENTRY", JetWhenEntry.class);
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE");
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN");
JetNodeType WHEN_CONDITION_CALL = new JetNodeType("WHEN_CONDITION_CALL");
JetNodeType WHEN_CONDITION_EXPRESSION = new JetNodeType("WHEN_CONDITION_EXPRESSION");
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_CALL = new JetNodeType("WHEN_CONDITION_CALL", JetWhenConditionCall.class);
JetNodeType WHEN_CONDITION_EXPRESSION = new JetNodeType("WHEN_CONDITION_EXPRESSION", JetWhenConditionWithExpression.class);
JetNodeType TUPLE_PATTERN_ENTRY = new JetNodeType("TUPLE_PATTERN_ENTRY");
JetNodeType NULLABLE_TYPE = new JetNodeType("NULLABLE_TYPE", JetNullableType.class);
JetNodeType TYPE_PROJECTION = new JetNodeType("TYPE_PROJECTION", JetTypeProjection.class);
......
......@@ -96,7 +96,8 @@ public class JetControlFlowProcessor {
this.inCondition = inCondition;
}
private void value(@NotNull JetElement element, boolean preferBlock, boolean inCondition) {
private void value(@Nullable JetElement element, boolean preferBlock, boolean inCondition) {
if (element == null) return;
CFPVisitor visitor;
if (this.preferBlock == preferBlock && this.inCondition == inCondition) {
visitor = this;
......@@ -609,6 +610,61 @@ public class JetControlFlowProcessor {
builder.read(expression);
}
@Override
public void visitWhenExpression(JetWhenExpression expression) {
// TODO : no more than one else
// TODO : else must be the last
JetExpression subjectExpression = expression.getSubjectExpression();
if (subjectExpression != null) {
value(subjectExpression, false, inCondition);
}
Label nextLabel = builder.createUnboundLabel();
for (JetWhenEntry whenEntry : expression.getEntries()) {
if (whenEntry.getSubWhen() != null) throw new UnsupportedOperationException(); // TODO
if (whenEntry.isElseContinue()) throw new UnsupportedOperationException(); // TODO
JetWhenCondition condition = whenEntry.getCondition();
if (condition != null) {
condition.accept(new JetVisitor() {
@Override
public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
value(condition.getExpression(), false, inCondition); // TODO : inCondition?
}
@Override
public void visitWhenConditionCall(JetWhenConditionCall condition) {
value(condition.getCallSuffixExpression(), false, inCondition); // TODO : inCondition?
}
@Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
value(condition.getRangeExpression(), false, inCondition); // TODO : inCondition?
value(condition.getOperationReference(), false, inCondition); // TODO : inCondition?
// TODO : read the call to contains()...
}
@Override
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
super.visitWhenConditionIsPattern(condition); // TODO
}
@Override
public void visitJetElement(JetElement elem) {
throw new UnsupportedOperationException();
}
});
}
builder.nondeterministicJump(nextLabel);
value(whenEntry.getExpression(), true, inCondition);
builder.bindLabel(nextLabel);
nextLabel = builder.createUnboundLabel();
}
}
@Override
public void visitTypeProjection(JetTypeProjection typeProjection) {
// TODO : Support Type Arguments. Class object may be initialized at this point");
......
......@@ -706,7 +706,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenCondition
* : expression
* : "." postfixExpression typeArguments? valueArguments?
* : ("." | "?." postfixExpression typeArguments? valueArguments?
* : ("in" | "!in") expression
* : ("is" | "!is") isRHS
* ;
......@@ -715,7 +715,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker condition = mark();
myBuilder.disableNewlines();
if (at(IN_KEYWORD) || at(NOT_IN)) {
PsiBuilder.Marker mark = mark();
advance(); // IN_KEYWORD or NOT_IN
mark.done(OPERATION_REFERENCE);
if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) {
error("Expecting an element");
......@@ -732,13 +735,20 @@ public class JetExpressionParsing extends AbstractJetParsing {
parsePattern();
}
condition.done(WHEN_CONDITION_IS_PATTERN);
} else if (at(DOT)) {
advance(); // DOT
} else if (at(DOT) || at(SAFE_ACCESS)) {
advance(); // DOT or SAFE_ACCESS
PsiBuilder.Marker mark = mark();
parsePostfixExpression();
myJetParsing.parseTypeArgumentList();
if (at(LPAR)) {
parseValueArgumentList();
if (parseCallSuffix()) {
mark.done(CALL_EXPRESSION);
}
else {
mark.drop();
}
// myJetParsing.parseTypeArgumentList();
// if (at(LPAR)) {
// parseValueArgumentList();
// }
condition.done(WHEN_CONDITION_CALL);
} else {
if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) {
......
......@@ -349,4 +349,20 @@ public class JetVisitor extends PsiElementVisitor {
public void visitIsExpression(JetIsExpression expression) {
visitExpression(expression);
}
public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
visitJetElement(condition);
}
public void visitWhenConditionCall(JetWhenConditionCall condition) {
visitJetElement(condition);
}
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
visitJetElement(condition);
}
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
visitJetElement(condition);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public abstract class JetWhenCondition extends JetElement {
public JetWhenCondition(@NotNull ASTNode node) {
super(node);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author abreslav
*/
public class JetWhenConditionCall extends JetWhenCondition {
public JetWhenConditionCall(@NotNull ASTNode node) {
super(node);
}
public boolean isSafeCall() {
return getNode().findChildByType(JetTokens.SAFE_ACCESS) != null;
}
@NotNull
public ASTNode getOperationTokenNode() {
return getNode().findChildByType(TokenSet.create(JetTokens.SAFE_ACCESS, JetTokens.DOT));
}
@Nullable @IfNotParsed
public JetExpression getCallSuffixExpression() {
return findChildByClass(JetExpression.class);
}
@Override
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenConditionCall(this);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author abreslav
*/
public class JetWhenConditionInRange extends JetWhenCondition {
public JetWhenConditionInRange(@NotNull ASTNode node) {
super(node);
}
public boolean isNegated() {
return getNode().findChildByType(JetTokens.NOT_IN) != null;
}
@Nullable @IfNotParsed
public JetExpression getRangeExpression() {
// Copied from JetBinaryExpression
ASTNode node = getOperationReference().getNode().getTreeNext();
while (node != null) {
PsiElement psi = node.getPsi();
if (psi instanceof JetExpression) {
return (JetExpression) psi;
}
node = node.getTreeNext();
}
return null;
}
@Override
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenConditionInRange(this);
}
public JetSimpleNameExpression getOperationReference() {
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author abreslav
*/
public class JetWhenConditionIsPattern extends JetWhenCondition {
public JetWhenConditionIsPattern(@NotNull ASTNode node) {
super(node);
}
public boolean isNegated() {
return getNode().findChildByType(JetTokens.NOT_IS) != null;
}
@Nullable @IfNotParsed
public JetPattern getPattern() {
return findChildByClass(JetPattern.class);
}
@Override
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenConditionIsPattern(this);
}
}
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author abreslav
*/
public class JetWhenConditionWithExpression extends JetWhenCondition {
public JetWhenConditionWithExpression(@NotNull ASTNode node) {
super(node);
}
@Nullable
@IfNotParsed
public JetExpression getExpression() {
return findChildByClass(JetExpression.class);
}
@Override
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenConditionWithExpression(this);
}
}
......@@ -37,4 +37,9 @@ public class JetWhenEntry extends JetElement {
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenEntry(this);
}
@Nullable
public JetWhenCondition getCondition() {
return findChildByClass(JetWhenCondition.class);
}
}
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.List;
......@@ -19,6 +20,11 @@ public class JetWhenExpression extends JetExpression {
return findChildrenByType(JetNodeTypes.WHEN_ENTRY);
}
@Nullable @IfNotParsed
public JetExpression getSubjectExpression() {
return findChildByClass(JetExpression.class);
}
@Override
public void accept(JetVisitor visitor) {
visitor.visitWhenExpression(this);
......
package org.jetbrains.jet.lang.types;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
......@@ -151,7 +152,7 @@ public class JetTypeInferrer {
public void visitQualifiedExpression(JetQualifiedExpression expression) {
// . or ?.
JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
checkNullSafety(receiverType, expression);
checkNullSafety(receiverType, expression.getOperationTokenNode());
JetExpression selectorExpression = expression.getSelectorExpression();
if (selectorExpression instanceof JetSimpleNameExpression) {
......@@ -191,19 +192,20 @@ public class JetTypeInferrer {
return wrapForTracing(result[0], reference[0], argumentList, true);
}
private void checkNullSafety(JetType receiverType, JetQualifiedExpression expression) {
private void checkNullSafety(JetType receiverType, ASTNode operationTokenNode) {
if (receiverType != null) {
boolean namespaceType = receiverType instanceof NamespaceType;
boolean nullable = !namespaceType && receiverType.isNullable();
if (nullable && expression.getOperationSign() == JetTokens.DOT) {
trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
IElementType operationSign = operationTokenNode.getElementType();
if (nullable && operationSign == JetTokens.DOT) {
trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
}
else if (!nullable && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
else if (!nullable && operationSign == JetTokens.SAFE_ACCESS) {
if (namespaceType) {
trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Safe calls are not allowed on namespaces");
trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
}
else {
trace.getErrorHandler().genericWarning(expression.getOperationTokenNode(), "Unnecessary safe call on a non-null receiver of type " + receiverType);
trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type " + receiverType);
}
}
}
......@@ -378,7 +380,10 @@ public class JetTypeInferrer {
} else {
JetExpression resultExpression = entry.getExpression();
if (resultExpression != null) {
result.add(getType(scope, resultExpression, true));
JetType type = getType(scope, resultExpression, true);
if (type != null) {
result.add(type);
}
}
}
}
......@@ -964,11 +969,75 @@ public class JetTypeInferrer {
}
@Override
public void visitWhenExpression(JetWhenExpression expression) {
public void visitWhenExpression(final JetWhenExpression expression) {
// TODO :change scope according to the bound value in the when header
List<JetType> expressions = new ArrayList<JetType>();
collectAllReturnTypes(expression, scope, expressions);
result = semanticServices.getTypeChecker().commonSupertype(expressions);
final JetExpression subjectExpression = expression.getSubjectExpression();
JetType subjectType = null;
if (subjectExpression != null) {
subjectType = getType(scope, subjectExpression, false);
}
// TODO : exhaustive patterns
for (JetWhenEntry whenEntry : expression.getEntries()) {
final JetType finalSubjectType = subjectType;
JetWhenCondition condition = whenEntry.getCondition();
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) {
checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType);
if (callSuffixExpression != null) {
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
}
}
@Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
JetExpression rangeExpression = condition.getRangeExpression();
if (rangeExpression != null) {
checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression);
}
}
@Override
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
super.visitWhenConditionIsPattern(condition); // TODO
}
@Override
public void visitJetElement(JetElement elem) {
trace.getErrorHandler().genericError(elem.getNode(), "Unsupported [JetTypeInferrer] : " + elem);
}
});
}
}
List<JetType> expressionTypes = new ArrayList<JetType>();
collectAllReturnTypes(expression, scope, expressionTypes);
if (!expressionTypes.isEmpty()) {
result = semanticServices.getTypeChecker().commonSupertype(expressionTypes);
}
else {
trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression"); // TODO : Scope, and maybe this should not an error
}
}
@Override
......@@ -1226,10 +1295,10 @@ public class JetTypeInferrer {
JetExpression receiverExpression = expression.getReceiverExpression();
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
if (receiverType != null) {
checkNullSafety(receiverType, expression);
checkNullSafety(receiverType, expression.getOperationTokenNode());
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
if (expression.getOperationSign() == JetTokens.QUEST) {
if (selectorReturnType != null && !isBoolean(selectorReturnType)) {
if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) {
// TODO : more comprehensible error message
trace.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
}
......@@ -1395,9 +1464,7 @@ public class JetTypeInferrer {
result = ErrorUtils.createErrorType("No right argument"); // TODO
return;
}
String name = "contains";
JetType containsType = getTypeForBinaryCall(scope, right, expression.getOperationReference(), expression.getLeft(), name, true);
ensureBooleanResult(operationSign, name, containsType);
checkInExpression(operationSign, left, right);
result = semanticServices.getStandardLibrary().getBooleanType();
}
else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) {
......@@ -1428,6 +1495,12 @@ public class JetTypeInferrer {
}
}
private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right) {
String name = "contains";
JetType containsType = getTypeForBinaryCall(scope, right, operationSign, left, name, true);
ensureBooleanResult(operationSign, name, containsType);
}
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression) {
JetSimpleNameExpression operationSign = expression.getOperationReference();
JetExpression left = expression.getLeft();
......@@ -1459,11 +1532,15 @@ public class JetTypeInferrer {
trace.getErrorHandler().genericError(expression.getNode(), "Assignments are not expressions, and only expressions are allowed in this context");
}
private boolean ensureBooleanResult(JetSimpleNameExpression operationSign, String name, JetType resultType) {
private boolean ensureBooleanResult(JetExpression operationSign, String name, JetType resultType) {
return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'");
}
private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName) {
if (resultType != null) {
// TODO : Relax?
if (!isBoolean(resultType)) {
trace.getErrorHandler().genericError(operationSign.getNode(), "'" + name + "' must return Boolean but returns " + resultType);
trace.getErrorHandler().genericError(operationSign.getNode(), subjectName + " must return Boolean but returns " + resultType);
return false;
}
}
......
fun foo() {
val s = ""
val x = 1
when (x) {
<error>s</error> => 1
1 => 1
1 + <error>a</error> => 1
in 1..<error>a</error> => 1
!in 1..<error>a</error> => 1
.<error>a</error> => 1
.equals(1).<error>a</error> => 1
<warning>?.</warning>equals(1) => 1
}
when (<warning>x</warning>?:null) {
<error>.</error>equals(1) => 1
?.equals(1).equals(2) => 1
}
}
\ No newline at end of file
......@@ -254,7 +254,8 @@ JetFile: NewlinesInParentheses.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
......@@ -290,7 +291,8 @@ JetFile: NewlinesInParentheses.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
......
......@@ -755,7 +755,8 @@ JetFile: When.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
INTEGER_CONSTANT
......@@ -772,7 +773,8 @@ JetFile: When.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
......
......@@ -59,7 +59,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
......@@ -70,7 +71,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
......@@ -127,7 +129,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(in)('in')
OPERATION_REFERENCE
PsiElement(in)('in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
......@@ -137,7 +140,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
......@@ -147,7 +151,8 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IN_RANGE
PsiElement(NOT_IN)('!in')
OPERATION_REFERENCE
PsiElement(NOT_IN)('!in')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace(' ')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册