Fix annotation list parsing: @identifier:[a b c]

This commit is contained in:
Yan Zhulanow
2015-08-25 21:01:52 +03:00
parent 440379dfad
commit 0c87639514
2 changed files with 45 additions and 25 deletions
@@ -634,35 +634,54 @@ public class JetParsing extends AbstractJetParsing {
// Returns true if we should continue parse annotation
private boolean parseAnnotationTargetIfNeeded(AnnotationParsingMode mode) {
if (mode.isFileAnnotationParsingMode) {
if (at(COLON)) {
// recovery for "@:ann"
errorAndAdvance("Expected 'file' keyword before ':'"); // COLON
return true;
}
String expectedAnnotationTargetBeforeColon = "Expected 'file' keyword before ':'";
if (lookahead(1) == COLON && !at(FILE_KEYWORD) && at(IDENTIFIER)) {
// recovery for "@fil:ann"
errorAndAdvance("Expected 'file' keyword as target"); // IDENTIFIER
advance(); // COLON
return true;
}
if (mode == FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED && !(at(FILE_KEYWORD) && lookahead(1) == COLON)) {
return false;
}
String message = "Expecting \"" + FILE_KEYWORD.getValue() + COLON.getValue() + "\" prefix for file annotations";
expect(FILE_KEYWORD, message);
expect(COLON, message, TokenSet.create(IDENTIFIER, RBRACKET, LBRACKET));
if (at(COLON)) {
// recovery for "@:ann"
errorAndAdvance(expectedAnnotationTargetBeforeColon); // COLON
return true;
}
else if (at(FILE_KEYWORD) && lookahead(1) == COLON) {
errorAndAdvance("File annotations are only allowed before package declaration", 2);
JetKeywordToken targetKeyword = atTargetKeyword();
if (mode == FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED && !(targetKeyword == FILE_KEYWORD && lookahead(1) == COLON)) {
return false;
}
if (lookahead(1) == COLON && targetKeyword == null && at(IDENTIFIER)) {
// recovery for "@fil:ann"
errorAndAdvance(expectedAnnotationTargetBeforeColon); // IDENTIFIER
advance(); // COLON
return true;
}
if (targetKeyword == null && mode.isFileAnnotationParsingMode) {
parseAnnotationTarget(mode, FILE_KEYWORD);
}
else if (targetKeyword != null) {
parseAnnotationTarget(mode, targetKeyword);
}
return true;
}
private void parseAnnotationTarget(AnnotationParsingMode mode, JetKeywordToken keyword) {
if (keyword == FILE_KEYWORD && !mode.isFileAnnotationParsingMode && at(keyword) && lookahead(1) == COLON) {
errorAndAdvance("File annotations are only allowed before package declaration", 2);
return;
}
String message = "Expecting \"" + keyword.getValue() + COLON.getValue() + "\" prefix for " + keyword.getValue() + " annotations";
expect(keyword, message);
expect(COLON, message, TokenSet.create(IDENTIFIER, RBRACKET, LBRACKET));
}
@Nullable
private JetKeywordToken atTargetKeyword() {
if (at(FILE_KEYWORD)) return (JetKeywordToken) FILE_KEYWORD;
return null;
}
/*
* annotation
* : annotationPrefix? unescapedAnnotation
@@ -678,11 +697,12 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker annotation = mark();
if (at(AT)) {
boolean atAt = at(AT);
if (atAt) {
advance(); // AT
}
if (!parseAnnotationTargetIfNeeded(mode)) {
if (atAt && !parseAnnotationTargetIfNeeded(mode)) {
annotation.rollbackTo();
return false;
}
@@ -39,7 +39,7 @@ JetFile: nonFIleAnnotationBeforePackage.kt
PsiWhiteSpace('\n')
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:Expected 'file' keyword as target
PsiErrorElement:Expected 'file' keyword before ':'
PsiElement(IDENTIFIER)('fil')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE