JET-174 Make continue work the same way in all contexts inside when

Guards are removed. Continue is not supported yet.
This commit is contained in:
Andrey Breslav
2011-07-07 17:18:29 +04:00
parent 026eadda7a
commit 704f153a31
9 changed files with 45 additions and 139 deletions
+2 -6
View File
@@ -12,12 +12,8 @@ when
whenEntry
// TODO : consider empty after =>
: whenConditionIf{","} (when | "=>" expression SEMI)
: "else" ("continue" | "=>" expression SEMI)
;
whenConditionIf
: whenCondition ("if" "(" expression ")")?
: whenCondition{","} "=>" expression SEMI
: "else" "=>" expression SEMI
;
whenCondition
@@ -630,9 +630,6 @@ public class JetControlFlowProcessor {
Label nextLabel = builder.createUnboundLabel();
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
JetWhenEntry whenEntry = iterator.next();
if (whenEntry.getSubWhen() != null) throw new UnsupportedOperationException(); // TODO
if (whenEntry.isElseContinue()) throw new UnsupportedOperationException(); // TODO
if (whenEntry.isElse()) {
if (iterator.hasNext()) {
@@ -635,8 +635,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenEntry
* // TODO : consider empty after =>
* : whenConditionIf{","} (when | "=>" element SEMI)
* : "else" ("continue" | "=>" element SEMI)
* : whenCondition{","} "=>" element SEMI
* : "else" "=>" element SEMI
* ;
*/
private void parseWhenEntry() {
@@ -645,8 +645,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
if (at(ELSE_KEYWORD)) {
advance(); // ELSE_KEYWORD
if (!at(CONTINUE_KEYWORD) && !at(DOUBLE_ARROW)) {
errorUntil("Expecting 'continue' or '=> element'", TokenSet.create(CONTINUE_KEYWORD, DOUBLE_ARROW,
if (!at(DOUBLE_ARROW)) {
errorUntil("Expecting '=>'", TokenSet.create(DOUBLE_ARROW,
RBRACE, EOL_OR_SEMICOLON));
}
@@ -658,10 +658,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
} else {
parseExpression();
}
} else if (at(CONTINUE_KEYWORD)) {
advance(); // CONTINUE_KEYWORD
} else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
errorAndAdvance("Expecting 'continue' or '=> element'");
errorAndAdvance("Expecting '=>'");
}
} else {
parseWhenEntryNotElse();
@@ -672,48 +670,22 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* : whenConditionIf{","} (when | "=>" element SEMI)
* : whenCondition{","} "=>" element SEMI
*/
private void parseWhenEntryNotElse() {
while (true) {
while (at(COMMA)) errorAndAdvance("Expecting a when-condition");
parseWhenConditionIf();
parseWhenCondition();
if (!at(COMMA)) break;
advance(); // COMMA
}
if (at(WHEN_KEYWORD)) {
parseWhen();
expect(DOUBLE_ARROW, "Expecting '=>' or 'when'", WHEN_CONDITION_RECOVERY_SET);
if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
error("Expecting an element");
} else {
expect(DOUBLE_ARROW, "Expecting '=>' or 'when'", WHEN_CONDITION_RECOVERY_SET);
if (atSet(WHEN_CONDITION_RECOVERY_SET)) {
error("Expecting an element");
} else {
parseExpression();
}
// SEMI is consumed in parseWhenEntry
}
}
/*
* whenConditionIf
* : pattern ("if" "(" element ")")?
* ;
*/
private void parseWhenConditionIf() {
parseWhenCondition();
if (at(IF_KEYWORD)) {
advance(); // IF_KEYWORD
// TODO : allow omitting these parentheses
myBuilder.disableNewlines();
expect(LPAR, "Expecting '('");
parseExpression();
expect(RPAR, "Expecting ')'");
myBuilder.restoreNewlinesState();
}
// SEMI is consumed in parseWhenEntry
}
/*
@@ -3,7 +3,6 @@ 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 org.jetbrains.jet.lexer.JetTokens;
/**
@@ -18,21 +17,11 @@ public class JetWhenEntry extends JetElement {
return findChildByType(JetTokens.ELSE_KEYWORD) != null;
}
public boolean isElseContinue() {
return isElse() && (findChildByType(JetTokens.DOUBLE_ARROW) == null) && (findChildByType(JetTokens.CONTINUE_KEYWORD) != null);
}
@Nullable
public JetExpression getExpression() {
return findChildByClass(JetExpression.class);
}
@Nullable
public JetWhenExpression getSubWhen() {
// TODO: this may be a WHEN that goes after "=>"
return (JetWhenExpression) findChildByType(JetNodeTypes.WHEN);
}
@Override
public void accept(@NotNull JetVisitor visitor) {
visitor.visitWhenEntry(this);
@@ -1324,8 +1324,7 @@ public class JetTypeInferrer {
newDataFlowInfo = newDataFlowInfo.and(context.dataFlowInfo);
}
}
JetWhenExpression subWhen = whenEntry.getSubWhen();
JetExpression bodyExpression = subWhen == null ? whenEntry.getExpression() : subWhen;
JetExpression bodyExpression = whenEntry.getExpression();
if (bodyExpression != null) {
JetType type = getTypeWithNewDataFlowInfo(scopeToExtend, bodyExpression, true, newDataFlowInfo);
if (type != null) {
@@ -1436,8 +1435,11 @@ public class JetTypeInferrer {
@Override
public void visitExpressionPattern(JetExpressionPattern pattern) {
JetType type = getType(scopeToExtend, pattern.getExpression(), false);
checkTypeCompatibility(type, subjectType, pattern);
JetExpression expression = pattern.getExpression();
if (expression != null) {
JetType type = getType(scopeToExtend, expression, false);
checkTypeCompatibility(type, subjectType, pattern);
}
}
@Override
+1 -4
View File
@@ -10,14 +10,13 @@ fun foo() {
fun foo() {
when (e) {
}
when (e) {
is a => foo
}
when (e) {
is Tree @ (a, b) => foo
is Tree @ (a, b) if (a > 5) => foo
is null => foo
is 1 => foo
is A.b => foo
@@ -58,7 +57,6 @@ fun foo() {
is (Int, Int) => 2
is val a : Foo => 2
else => foo
else continue
}
}
@@ -72,4 +70,3 @@ fun foo() {
is a.a @ (val b, b) if (b == a + 3) => c
}
}
+23 -68
View File
@@ -94,7 +94,7 @@ JetFile: When.jet
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n ')
PsiWhiteSpace('\n \n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
WHEN
@@ -167,53 +167,6 @@ JetFile: When.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN
PsiElement(is)('is')
PsiWhiteSpace(' ')
DECOMPOSER_PATTERN
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Tree')
PsiWhiteSpace(' ')
PsiElement(AT)('@')
PsiWhiteSpace(' ')
DECOMPOSER_ARGUMENT_LIST
PsiElement(LPAR)('(')
TUPLE_PATTERN_ENTRY
TYPE_PATTERN
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
TUPLE_PATTERN_ENTRY
TYPE_PATTERN
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(GT)('>')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('5')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(DOUBLE_ARROW)('=>')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN
PsiElement(is)('is')
@@ -1039,11 +992,6 @@ JetFile: When.jet
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiWhiteSpace(' ')
PsiElement(continue)('continue')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
@@ -1245,27 +1193,34 @@ JetFile: When.jet
PsiElement(IDENTIFIER)('b')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(if)('if')
PsiErrorElement:Expecting '=>' or 'when'
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(EQEQ)('==')
PsiWhiteSpace(' ')
PARENTHESIZED
PsiElement(LPAR)('(')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUS)('+')
PsiElement(EQEQ)('==')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUS)('+')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
WHEN_ENTRY
WHEN_CONDITION_IS_PATTERN
EXPRESSION_PATTERN
PsiErrorElement:Expecting an element, is-condition or in-condition
<empty list>
PsiElement(DOUBLE_ARROW)('=>')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
+2 -2
View File
@@ -91,7 +91,7 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiErrorElement:Expecting 'continue' or '=> element'
PsiErrorElement:Expecting '=>'
<empty list>
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
@@ -172,7 +172,7 @@ JetFile: When_ERR.jet
PsiWhiteSpace('\n ')
WHEN_ENTRY
PsiElement(else)('else')
PsiErrorElement:Expecting 'continue' or '=> element'
PsiErrorElement:Expecting '=>'
<empty list>
PsiWhiteSpace('\n ')
WHEN_ENTRY
@@ -121,8 +121,6 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("when (1) { is 1 => 2; is 1 => '2'} ", "Any");
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => null} ", "Any?");
assertType("when (1) { is 1 => 2; is 1 => '2'; else => null} ", "Any?");
assertType("when (1) { is 1 => 2; is 1 => '2'; else continue} ", "Any");
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 when(e) {is 1 => null}} ", "Any?");
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => when(e) {is 1 => null}} ", "Any?");
}