Refine recovery for constructors

This commit is contained in:
Denis Zharkov
2015-03-25 11:26:51 +03:00
parent b1de2066c7
commit 8c048c3e43
12 changed files with 477 additions and 47 deletions
@@ -873,7 +873,7 @@ public class JetParsing extends AbstractJetParsing {
advance(); // CONSTRUCTOR_KEYWORD
TokenSet valueArgsRecoverySet = TokenSet.create(COLON, LBRACE, SEMICOLON, RPAR);
TokenSet valueArgsRecoverySet = TokenSet.create(COLON, LBRACE, SEMICOLON, RPAR, EOL_OR_SEMICOLON, RBRACE);
if (at(LPAR)) {
parseValueParameterList(false, /*typeRequired = */ true, valueArgsRecoverySet);
}
@@ -888,16 +888,26 @@ public class JetParsing extends AbstractJetParsing {
if (at(THIS_KEYWORD) || at(SUPER_KEYWORD)) {
parseThisOrSuper();
myExpressionParsing.parseValueArgumentList();
}
else {
// if we're on LPAR it's probably start of value arguments list
if (!at(LPAR)) {
advance(); // wrong delegation call keyword?
}
error("Expecting a 'this' or 'super' constructor call");
}
PsiBuilder.Marker beforeWrongDelegationCallee = null;
if (!at(LPAR)) {
beforeWrongDelegationCallee = mark();
advance(); // wrong delegation callee
}
myExpressionParsing.parseValueArgumentList();
myExpressionParsing.parseValueArgumentList();
if (beforeWrongDelegationCallee != null) {
if (at(LBRACE)) {
beforeWrongDelegationCallee.drop();
}
else {
beforeWrongDelegationCallee.rollbackTo();
}
}
}
delegationCall.done(CONSTRUCTOR_DELEGATION_CALL);
}
@@ -0,0 +1,14 @@
class A {
constructor
val x: Int
constructor
constructor() {}
constructor {}
fun foo()
constructor
}
class B
@@ -0,0 +1,85 @@
JetFile: recoveryJustConstructorKeyword.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
@@ -0,0 +1,14 @@
class A {
constructor
val x: Int
constructor
constructor() {}
constructor {}
fun foo()
constructor} class B {
}
@@ -0,0 +1,89 @@
JetFile: recoveryJustConstructorKeywordSameLineBrace.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
PsiErrorElement:Expecting '('
<empty list>
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
PsiElement(RBRACE)('}')
PsiWhiteSpace(' ')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,13 @@
class A {
constructor():
val x = 1
constructor():
constructor()
constructor(): {}
fun foo()
constructor():
}
class B
@@ -0,0 +1,88 @@
JetFile: recoveryNoDelegationCallAfterColon.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace('\n ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
CONSTRUCTOR_DELEGATION_CALL
CONSTRUCTOR_DELEGATION_REFERENCE
<empty list>
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace('\n')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
@@ -0,0 +1,14 @@
class A {
constructor(): thi()
val x: Int
constructor():
ann fun foo()
constructor(): sup
constructor(): thi()
}
class B
@@ -0,0 +1,116 @@
JetFile: recoveryWithoutBodyWrongDelegationName.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
PROPERTY
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('thi')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace('\n\n ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
FUN
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann')
PsiWhiteSpace(' ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
SECONDARY_CONSTRUCTOR
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('sup')
PsiWhiteSpace('\n\n ')
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('thi')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiErrorElement:Expecting member declaration
<empty list>
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
@@ -3,8 +3,5 @@ class A {
val x: Int
}
class B {
constructor() : thhiis(3, 4)
}
val x: Int = 1
val x: Int = 1
@@ -18,9 +18,9 @@ JetFile: recoveryWrongDelegationName.kt
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiElement(IDENTIFIER)('superr')
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
PsiElement(IDENTIFIER)('superr')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
@@ -48,41 +48,7 @@ JetFile: recoveryWrongDelegationName.kt
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
SECONDARY_CONSTRUCTOR
PsiElement(constructor)('constructor')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_DELEGATION_CALL
PsiElement(IDENTIFIER)('thhiis')
PsiErrorElement:Expecting a 'this' or 'super' constructor call
<empty list>
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('4')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PsiWhiteSpace('\n\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
@@ -1935,6 +1935,30 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("recoveryJustConstructorKeyword.kt")
public void testRecoveryJustConstructorKeyword() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/secondaryConstructors/recoveryJustConstructorKeyword.kt");
doParsingTest(fileName);
}
@TestMetadata("recoveryJustConstructorKeywordSameLineBrace.kt")
public void testRecoveryJustConstructorKeywordSameLineBrace() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/secondaryConstructors/recoveryJustConstructorKeywordSameLineBrace.kt");
doParsingTest(fileName);
}
@TestMetadata("recoveryNoDelegationCallAfterColon.kt")
public void testRecoveryNoDelegationCallAfterColon() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/secondaryConstructors/recoveryNoDelegationCallAfterColon.kt");
doParsingTest(fileName);
}
@TestMetadata("recoveryWithoutBodyWrongDelegationName.kt")
public void testRecoveryWithoutBodyWrongDelegationName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/secondaryConstructors/recoveryWithoutBodyWrongDelegationName.kt");
doParsingTest(fileName);
}
@TestMetadata("recoveryWithoutParameterList.kt")
public void testRecoveryWithoutParameterList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/secondaryConstructors/recoveryWithoutParameterList.kt");