From 704f153a31804c50eaa0cb615d820c0727e45e84 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 7 Jul 2011 17:18:29 +0400 Subject: [PATCH] JET-174 Make continue work the same way in all contexts inside when Guards are removed. Continue is not supported yet. --- grammar/src/when.grm | 8 +- .../jet/lang/cfg/JetControlFlowProcessor.java | 3 - .../lang/parsing/JetExpressionParsing.java | 50 +++------- .../jetbrains/jet/lang/psi/JetWhenEntry.java | 11 --- .../jet/lang/types/JetTypeInferrer.java | 10 +- idea/testData/psi/When.jet | 5 +- idea/testData/psi/When.txt | 91 +++++-------------- idea/testData/psi/When_ERR.txt | 4 +- .../jet/types/JetTypeCheckerTest.java | 2 - 9 files changed, 45 insertions(+), 139 deletions(-) diff --git a/grammar/src/when.grm b/grammar/src/when.grm index 241e0b649c9..c307019e68c 100644 --- a/grammar/src/when.grm +++ b/grammar/src/when.grm @@ -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 diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 837e160cbf2..09073b30ebe 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -630,9 +630,6 @@ public class JetControlFlowProcessor { Label nextLabel = builder.createUnboundLabel(); for (Iterator 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()) { diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 6c3218ecd93..49d839fe92a 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -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 } /* diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java index 259d11cb479..da16d7b4cc5 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index c83339eedf3..8db448c1dce 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -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 diff --git a/idea/testData/psi/When.jet b/idea/testData/psi/When.jet index 2ae6def484b..961e746c053 100644 --- a/idea/testData/psi/When.jet +++ b/idea/testData/psi/When.jet @@ -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 } } - diff --git a/idea/testData/psi/When.txt b/idea/testData/psi/When.txt index b931f85f976..fed4ec1dea6 100644 --- a/idea/testData/psi/When.txt +++ b/idea/testData/psi/When.txt @@ -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 + PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') REFERENCE_EXPRESSION diff --git a/idea/testData/psi/When_ERR.txt b/idea/testData/psi/When_ERR.txt index a1df1260eca..dba08d47c7f 100644 --- a/idea/testData/psi/When_ERR.txt +++ b/idea/testData/psi/When_ERR.txt @@ -91,7 +91,7 @@ JetFile: When_ERR.jet PsiWhiteSpace('\n ') WHEN_ENTRY PsiElement(else)('else') - PsiErrorElement:Expecting 'continue' or '=> element' + PsiErrorElement:Expecting '=>' 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 '=>' PsiWhiteSpace('\n ') WHEN_ENTRY diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index be443bc7944..fc046fd5ac3 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -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?"); }