Fix recovery for 'for' expression

This commit is contained in:
Nikolay Krasko
2014-06-20 15:28:42 +04:00
parent 2571797411
commit f36f1796d6
24 changed files with 458 additions and 42 deletions
@@ -1370,35 +1370,40 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // FOR_KEYWORD
myBuilder.disableNewlines();
expect(LPAR, "Expecting '(' to open a loop range", TokenSet.create(RPAR, VAL_KEYWORD, VAR_KEYWORD, IDENTIFIER));
if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
myBuilder.disableNewlines();
PsiBuilder.Marker parameter = mark();
if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
if (at(LPAR)) {
myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
if (!at(RPAR)) {
PsiBuilder.Marker parameter = mark();
if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
if (at(LPAR)) {
myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
parameter.done(MULTI_VARIABLE_DECLARATION);
}
else {
expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
parameter.done(MULTI_VARIABLE_DECLARATION);
}
else {
expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON));
if (at(COLON)) {
advance(); // COLON
myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
}
parameter.done(VALUE_PARAMETER);
}
if (at(COLON)) {
advance(); // COLON
myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
PsiBuilder.Marker range = mark();
parseExpression();
range.done(LOOP_RANGE);
}
}
parameter.done(VALUE_PARAMETER);
else {
error("Expecting a variable name");
}
expectNoAdvance(RPAR, "Expecting ')'");
myBuilder.restoreNewlinesState();
}
expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE));
PsiBuilder.Marker range = mark();
parseExpression();
range.done(LOOP_RANGE);
expectNoAdvance(RPAR, "Expecting ')'");
myBuilder.restoreNewlinesState();
parseControlStructureBody();
loop.done(FOR);
@@ -9,6 +9,6 @@ fun test(nothing: Nothing?) {
}
fun sum(<!UNUSED_PARAMETER!>a<!> : IntArray) : Int {
for (n
<!SYNTAX!>return<!> <!ITERATOR_MISSING!>"?"<!><!SYNTAX!><!>
<!SYNTAX!><!>}
for (n
<!SYNTAX!>return<!><!SYNTAX!><!> "?"
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>}<!>
+4 -12
View File
@@ -658,17 +658,9 @@ JetFile: ForWithMultiDecl.kt
PsiErrorElement:Expecting 'in'
<empty list>
PsiWhiteSpace(' ')
LOOP_RANGE
FUNCTION_LITERAL_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
BLOCK
<empty list>
PsiElement(RBRACE)('}')
PsiErrorElement:Expecting ')'
<empty list>
PsiWhiteSpace('\n')
BODY
PsiErrorElement:Expecting an expression
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,7 @@
fun test(): Int {
for () {
}
return 1
}
@@ -0,0 +1,41 @@
JetFile: ForEmptyParentheses.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a variable name
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
RETURN
PsiElement(return)('return')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,5 @@
fun test(): Int {
for ()
return 1
}
@@ -0,0 +1,36 @@
JetFile: ForEmptyWithoutBody.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a variable name
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
BODY
RETURN
PsiElement(return)('return')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,5 @@
fun test() {
while (true) {
for ()
}
}
@@ -0,0 +1,41 @@
JetFile: ForNoBodyBeforeRBrace.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
WHILE
PsiElement(while)('while')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a variable name
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
BODY
PsiErrorElement:Expecting an expression
<empty list>
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1 @@
fun test() = for (
@@ -0,0 +1,26 @@
JetFile: ForWithOnlyOneLParInEOF.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
PsiErrorElement:Expecting a variable name
<empty list>
PsiErrorElement:Expecting 'in'
<empty list>
PsiErrorElement:Expecting ')'
<empty list>
BODY
<empty list>
@@ -0,0 +1 @@
fun test() = for ()
@@ -0,0 +1,23 @@
JetFile: ForWithoutBodyInEOF.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a variable name
<empty list>
PsiElement(RPAR)(')')
BODY
PsiErrorElement:Expecting an expression
<empty list>
@@ -0,0 +1,5 @@
fun test(): Int {
for
return 1
}
@@ -0,0 +1,33 @@
JetFile: ForWithoutLPar.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiErrorElement:Expecting '(' to open a loop range
<empty list>
PsiWhiteSpace('\n\n ')
BODY
RETURN
PsiElement(return)('return')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1 @@
fun test() = for
@@ -0,0 +1,20 @@
JetFile: ForWithoutLParInEOF.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
FOR
PsiElement(for)('for')
PsiErrorElement:Expecting '(' to open a loop range
<empty list>
BODY
PsiErrorElement:Expecting an expression
<empty list>
@@ -0,0 +1,4 @@
fun test() {
for (in some()) {
}
}
@@ -0,0 +1,39 @@
JetFile: ForWithoutParamButWithRange.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
PsiErrorElement:Expecting a variable name
<empty list>
PsiElement(in)('in')
PsiWhiteSpace(' ')
LOOP_RANGE
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('some')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BODY
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,5 @@
fun test() {
for (some)
bar()
}
@@ -0,0 +1,33 @@
JetFile: ForWithoutRange.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
VALUE_PARAMETER
PsiElement(IDENTIFIER)('some')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
BODY
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,5 @@
fun test() {
for ((i, j))
foo()
}
@@ -0,0 +1,40 @@
JetFile: WithWithoutInAndMultideclaration.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FOR
PsiElement(for)('for')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
MULTI_VARIABLE_DECLARATION
PsiElement(LPAR)('(')
MULTI_VARIABLE_DECLARATION_ENTRY
PsiElement(IDENTIFIER)('i')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
MULTI_VARIABLE_DECLARATION_ENTRY
PsiElement(IDENTIFIER)('j')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting 'in'
<empty list>
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
BODY
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -882,9 +882,7 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
}
public void testAllFilesPresentInRecovery() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage",
new File("compiler/testData/psi/recovery"), Pattern.compile("^(.*)\\.kts?$"),
true);
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/psi/recovery"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("DoWhileWithEmptyCondition.kt")
@@ -901,12 +899,57 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
public void testEnumEntryInitList() throws Exception {
doParsingTest("compiler/testData/psi/recovery/EnumEntryInitList.kt");
}
@TestMetadata("ForEmptyParentheses.kt")
public void testForEmptyParentheses() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForEmptyParentheses.kt");
}
@TestMetadata("ForEmptyWithoutBody.kt")
public void testForEmptyWithoutBody() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForEmptyWithoutBody.kt");
}
@TestMetadata("ForNoBodyBeforeRBrace.kt")
public void testForNoBodyBeforeRBrace() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.kt");
}
@TestMetadata("ForRecovery.kt")
public void testForRecovery() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForRecovery.kt");
}
@TestMetadata("ForWithOnlyOneLParInEOF.kt")
public void testForWithOnlyOneLParInEOF() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.kt");
}
@TestMetadata("ForWithoutBodyInEOF.kt")
public void testForWithoutBodyInEOF() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithoutBodyInEOF.kt");
}
@TestMetadata("ForWithoutLPar.kt")
public void testForWithoutLPar() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithoutLPar.kt");
}
@TestMetadata("ForWithoutLParInEOF.kt")
public void testForWithoutLParInEOF() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithoutLParInEOF.kt");
}
@TestMetadata("ForWithoutParamButWithRange.kt")
public void testForWithoutParamButWithRange() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithoutParamButWithRange.kt");
}
@TestMetadata("ForWithoutRange.kt")
public void testForWithoutRange() throws Exception {
doParsingTest("compiler/testData/psi/recovery/ForWithoutRange.kt");
}
@TestMetadata("IfWithEmptyCondition.kt")
public void testIfWithEmptyCondition() throws Exception {
doParsingTest("compiler/testData/psi/recovery/IfWithEmptyCondition.kt");
@@ -982,6 +1025,11 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest("compiler/testData/psi/recovery/WhileWithoutLPar.kt");
}
@TestMetadata("WithWithoutInAndMultideclaration.kt")
public void testWithWithoutInAndMultideclaration() throws Exception {
doParsingTest("compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.kt");
}
}
@TestMetadata("compiler/testData/psi/script")