Parser recovers on platform types notation:

- Foo!
- Array<(out) Foo>!
- (Mutable)List<Foo>!
This commit is contained in:
Andrey Breslav
2014-10-10 16:21:21 +04:00
parent 21d31a1a4f
commit 8eb57f5a75
23 changed files with 1225 additions and 6 deletions
@@ -113,9 +113,7 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
protected boolean errorAndAdvance(String message, int advanceTokenCount) {
PsiBuilder.Marker err = mark();
for (int i = 0; i < advanceTokenCount; i++) {
advance(); // erroneous token
}
advance(advanceTokenCount);
err.error(message);
return false;
}
@@ -129,6 +127,12 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
myBuilder.advanceLexer();
}
protected void advance(int advanceTokenCount) {
for (int i = 0; i < advanceTokenCount; i++) {
advance(); // erroneous token
}
}
protected void advanceAt(IElementType current) {
assert _at(current);
myBuilder.advanceLexer();
@@ -1488,7 +1488,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker typeRefMarker = mark();
parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
if (at(IDENTIFIER) || at(PACKAGE_KEYWORD)) {
if (at(IDENTIFIER) || at(PACKAGE_KEYWORD) || atParenthesizedMutableForPlatformTypes(0)) {
parseUserType();
}
else if (at(HASH)) {
@@ -1577,6 +1577,11 @@ public class JetParsing extends AbstractJetParsing {
* userType
* : ("package" ".")? simpleUserType{"."}
* ;
*
* recovers on platform types:
* - Foo!
* - (Mutable)List<Foo>!
* - Array<(out) Foo>!
*/
void parseUserType() {
PsiBuilder.Marker userType = mark();
@@ -1588,6 +1593,8 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker reference = mark();
while (true) {
recoverOnParenthesizedWordForPlatformTypes(0, "Mutable", true);
if (expect(IDENTIFIER, "Expecting type name",
TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW))) {
reference.done(REFERENCE_EXPRESSION);
@@ -1598,10 +1605,13 @@ public class JetParsing extends AbstractJetParsing {
}
parseTypeArgumentList();
recoverOnPlatformTypeSuffix();
if (!at(DOT)) {
break;
}
if (lookahead(1) == LPAR) {
if (lookahead(1) == LPAR && !atParenthesizedMutableForPlatformTypes(1)) {
// This may be a receiver for a function type
// Int.(Int) -> Int
break;
@@ -1618,6 +1628,49 @@ public class JetParsing extends AbstractJetParsing {
userType.done(USER_TYPE);
}
private boolean atParenthesizedMutableForPlatformTypes(int offset) {
return recoverOnParenthesizedWordForPlatformTypes(offset, "Mutable", false);
}
private boolean recoverOnParenthesizedWordForPlatformTypes(int offset, String word, boolean consume) {
// Array<(out) Foo>! or (Mutable)List<Bar>!
if (lookahead(offset) == LPAR && lookahead(offset + 1) == IDENTIFIER && lookahead(offset + 2) == RPAR && lookahead(offset + 3) == IDENTIFIER) {
PsiBuilder.Marker error = mark();
advance(offset);
advance(); // LPAR
if (!word.equals(myBuilder.getTokenText())) {
// something other than "out" / "Mutable"
error.rollbackTo();
return false;
}
else {
advance(); // IDENTIFIER('out')
advance(); // RPAR
if (consume) {
error.error("Unexpected tokens");
}
else {
error.rollbackTo();
}
return true;
}
}
return false;
}
private void recoverOnPlatformTypeSuffix() {
// Recovery for platform types
if (at(EXCL)) {
PsiBuilder.Marker error = mark();
advance(); // EXCL
error.error("Unexpected token");
}
}
/*
* selfType
* : "This"
@@ -1652,6 +1705,8 @@ public class JetParsing extends AbstractJetParsing {
while (true) {
PsiBuilder.Marker projection = mark();
recoverOnParenthesizedWordForPlatformTypes(0, "out", true);
// TokenSet lookFor = TokenSet.create(IDENTIFIER);
// TokenSet stopAt = TokenSet.create(COMMA, COLON, GT);
// parseModifierListWithShortAnnotations(MODIFIER_LIST, lookFor, stopAt);