Parsing: support '@[ann1 ann2]', '@file:ann' and '@file:[ann]' cases

This commit is contained in:
Denis Zharkov
2015-05-15 12:25:55 +03:00
parent f6aadec7e2
commit e4f54b5d2e
25 changed files with 918 additions and 28 deletions
@@ -531,18 +531,44 @@ public class JetParsing extends AbstractJetParsing {
*/
private boolean parseAnnotation(AnnotationParsingMode mode) {
if (at(LBRACKET)) {
return parseAnnotationList(mode);
return parseAnnotationList(mode, false);
}
else if (mode.allowShortAnnotations && at(IDENTIFIER)) {
parseAnnotationEntry();
return true;
return parseAnnotationEntry(mode);
}
else if (at(AT)) {
if (myBuilder.rawLookup(1) == IDENTIFIER) {
parseAnnotationEntry();
IElementType nextRawToken = myBuilder.rawLookup(1);
IElementType tokenToMatch = nextRawToken;
boolean isTargetedAnnotation = false;
if ((nextRawToken == IDENTIFIER || nextRawToken == FILE_KEYWORD) && lookahead(2) == COLON) {
tokenToMatch = lookahead(3);
isTargetedAnnotation = true;
}
else if (lookahead(1) == COLON) {
// recovery for "@:ann"
isTargetedAnnotation = true;
tokenToMatch = lookahead(2);
}
if (tokenToMatch == IDENTIFIER) {
return parseAnnotationEntry(mode);
}
else if (tokenToMatch == LBRACKET) {
return parseAnnotationList(mode, true);
}
else {
errorAndAdvance("Expected annotation identifier after '@'", 1); // AT
if (isTargetedAnnotation) {
if (lookahead(1) == COLON) {
errorAndAdvance("Expected annotation identifier after ':'", 2); // AT, COLON
}
else {
errorAndAdvance("Expected annotation identifier after '@file:'", 3); // AT, FILE_KEYWORD, COLON
}
}
else {
errorAndAdvance("Expected annotation identifier after '@'", 1); // AT
}
}
return true;
}
@@ -550,11 +576,14 @@ public class JetParsing extends AbstractJetParsing {
return false;
}
private boolean parseAnnotationList(AnnotationParsingMode mode) {
private boolean parseAnnotationList(AnnotationParsingMode mode, boolean expectAtSymbol) {
assert !expectAtSymbol || _at(AT);
assert expectAtSymbol || _at(LBRACKET);
PsiBuilder.Marker annotation = mark();
myBuilder.disableNewlines();
advance(); // LBRACKET
advance(); // AT or LBRACKET
if (!parseAnnotationTargetIfNeeded(mode)) {
annotation.rollbackTo();
@@ -562,17 +591,22 @@ public class JetParsing extends AbstractJetParsing {
return false;
}
if (!at(IDENTIFIER)) {
if (expectAtSymbol) {
assert _at(LBRACKET);
advance(); // LBRACKET
}
if (!at(IDENTIFIER) && !at(AT)) {
error("Expecting a list of annotations");
}
else {
parseAnnotationEntry();
while (at(COMMA)) {
errorAndAdvance("No commas needed to separate annotations");
}
while (at(IDENTIFIER) || at(AT)) {
if (at(AT)) {
errorAndAdvance("No '@' needed in annotation list"); // AT
continue;
}
while (at(IDENTIFIER)) {
parseAnnotationEntry();
parseAnnotationEntry(ALLOW_UNESCAPED_REGULAR_ANNOTATIONS);
while (at(COMMA)) {
errorAndAdvance("No commas needed to separate annotations");
}
@@ -589,13 +623,26 @@ 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;
}
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));
expect(COLON, message, TokenSet.create(IDENTIFIER, RBRACKET, LBRACKET));
}
else if (at(FILE_KEYWORD) && lookahead(1) == COLON) {
errorAndAdvance("File annotations are only allowed before package declaration", 2);
@@ -609,8 +656,9 @@ public class JetParsing extends AbstractJetParsing {
* : SimpleName{"."} typeArguments? valueArguments?
* ;
*/
private void parseAnnotationEntry() {
assert _at(IDENTIFIER) || (_at(AT) && myBuilder.rawLookup(1) == IDENTIFIER);
private boolean parseAnnotationEntry(AnnotationParsingMode mode) {
assert _at(IDENTIFIER) ||
(_at(AT) && !WHITE_SPACE_OR_COMMENT_BIT_SET.contains(myBuilder.rawLookup(1)));
PsiBuilder.Marker annotation = mark();
@@ -618,6 +666,11 @@ public class JetParsing extends AbstractJetParsing {
advance(); // AT
}
if (!parseAnnotationTargetIfNeeded(mode)) {
annotation.rollbackTo();
return false;
}
PsiBuilder.Marker reference = mark();
PsiBuilder.Marker typeReference = mark();
parseUserType();
@@ -630,6 +683,8 @@ public class JetParsing extends AbstractJetParsing {
myExpressionParsing.parseValueArgumentList();
}
annotation.done(ANNOTATION_ENTRY);
return true;
}
public enum NameParsingMode {
@@ -0,0 +1,11 @@
@[abc("") cde]
class A {
@[ abc
cde]
@[private]
fun foo() {
@[data inline] class Local {}
@[suppress("a")] (1 + @[abc] 3)
}
}
@@ -0,0 +1,156 @@
JetFile: basic.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('abc')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('cde')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('abc')
PsiWhiteSpace('\n ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('cde')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('private')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('data')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('inline')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Local')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
ANNOTATED_EXPRESSION
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('suppress')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
LITERAL_STRING_TEMPLATE_ENTRY
PsiElement(REGULAR_STRING_PART)('a')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(RPAR)(')')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PARENTHESIZED
PsiElement(LPAR)('(')
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUS)('+')
PsiWhiteSpace(' ')
ANNOTATED_EXPRESSION
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('abc')
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,15 @@
@[]
class A {
@[] val x = 1
@[@q]
fun foo() {
@[] class A
}
@[@q1 @ @q2]
fun foo2() {}
@[
fun bar() {}
}
@@ -0,0 +1,135 @@
JetFile: recovery.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n\n ')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:No '@' needed in annotation list
PsiElement(AT)('@')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('q')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:No '@' needed in annotation list
PsiElement(AT)('@')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('q1')
PsiWhiteSpace(' ')
PsiErrorElement:No '@' needed in annotation list
PsiElement(AT)('@')
PsiWhiteSpace(' ')
PsiErrorElement:No '@' needed in annotation list
PsiElement(AT)('@')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('q2')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo2')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('bar')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,16 @@
package bar
@file:foo
val prop
@file:[bar baz]
fun func() {}
@file:[baz]
class C
@file:
trait T
@file:[]
trait T
@@ -0,0 +1,104 @@
JetFile: fileAnnotationInWrongPlace.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n\n')
PROPERTY
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('prop')
PsiWhiteSpace('\n\n')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('func')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('C')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiErrorElement:Expected annotation identifier after '@file:'
PsiElement(AT)('@')
PsiElement(IDENTIFIER)('file')
PsiElement(COLON)(':')
PsiWhiteSpace('\n')
PsiElement(trait)('trait')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('T')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
ANNOTATION
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(trait)('trait')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('T')
@@ -0,0 +1,3 @@
@file:foo
@file:[bar baz]
package bar
@@ -0,0 +1,37 @@
JetFile: manyAnnotationBlocks.kt
FILE_ANNOTATION_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
@@ -0,0 +1,2 @@
@file: [foo bar baz]
package bar
@@ -0,0 +1,35 @@
JetFile: manyInOneAnnotationBlock.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
@@ -0,0 +1,7 @@
@foo
@file @bar
@file:
@:baz
@fil:ann
@ :
package boo
@@ -0,0 +1,60 @@
JetFile: nonFIleAnnotationBeforePackage.kt
FILE_ANNOTATION_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiElement(file)('file')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting "file:" prefix for file annotations
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n')
PsiErrorElement:Expected annotation identifier after '@file:'
PsiElement(AT)('@')
PsiElement(IDENTIFIER)('file')
PsiElement(COLON)(':')
PsiWhiteSpace('\n')
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:Expected 'file' keyword before ':'
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiWhiteSpace('\n')
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:Expected 'file' keyword as target
PsiElement(IDENTIFIER)('fil')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann')
PsiWhiteSpace('\n')
PsiErrorElement:Expected annotation identifier after ':'
PsiElement(AT)('@')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('boo')
@@ -0,0 +1,2 @@
@file:foo
package bar
@@ -0,0 +1,17 @@
JetFile: single.kt
FILE_ANNOTATION_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
@@ -0,0 +1,3 @@
@ann fun foo(): String? = null
annotation class ann
@@ -0,0 +1,40 @@
JetFile: withoutFileAnnotationAndPackageDeclaration.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
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)(')')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('String')
PsiElement(QUEST)('?')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
NULL
PsiElement(null)('null')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(annotation)('annotation')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('ann')
@@ -0,0 +1,4 @@
@file:foo
@foo @bar
@file:[baz]
fun foo() {}
@@ -0,0 +1,56 @@
JetFile: withoutPackage.kt
FILE_ANNOTATION_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
<empty list>
FUN
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
@@ -0,0 +1,4 @@
@file:foo
foo bar
@file: baz
fun foo() {}
@@ -0,0 +1,52 @@
JetFile: withoutPackageWithSimpleAnnotation.kt
FILE_ANNOTATION_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiElement(file)('file')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
<empty list>
FUN
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n')
ANNOTATION_ENTRY
PsiElement(AT)('@')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiWhiteSpace('\n')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
@@ -49,9 +49,8 @@ JetFile: nonFIleAnnotationBeforePackage.kt
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiElement(COLON)(':')
PsiErrorElement:Expected 'file' keyword before ':'
PsiElement(COLON)(':')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
@@ -74,9 +73,8 @@ JetFile: nonFIleAnnotationBeforePackage.kt
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiElement(COLON)(':')
PsiErrorElement:Expected 'file' keyword before ':'
PsiElement(COLON)(':')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
@@ -810,6 +810,84 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
}
}
@TestMetadata("compiler/testData/psi/annotation/list")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class List extends AbstractJetParsingTest {
public void testAllFilesPresentInList() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/list"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/list/basic.kt");
doParsingTest(fileName);
}
@TestMetadata("recovery.kt")
public void testRecovery() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/list/recovery.kt");
doParsingTest(fileName);
}
}
@TestMetadata("compiler/testData/psi/annotation/onFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class OnFile extends AbstractJetParsingTest {
public void testAllFilesPresentInOnFile() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/onFile"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("fileAnnotationInWrongPlace.kt")
public void testFileAnnotationInWrongPlace() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/fileAnnotationInWrongPlace.kt");
doParsingTest(fileName);
}
@TestMetadata("manyAnnotationBlocks.kt")
public void testManyAnnotationBlocks() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/manyAnnotationBlocks.kt");
doParsingTest(fileName);
}
@TestMetadata("manyInOneAnnotationBlock.kt")
public void testManyInOneAnnotationBlock() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/manyInOneAnnotationBlock.kt");
doParsingTest(fileName);
}
@TestMetadata("nonFIleAnnotationBeforePackage.kt")
public void testNonFIleAnnotationBeforePackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/nonFIleAnnotationBeforePackage.kt");
doParsingTest(fileName);
}
@TestMetadata("single.kt")
public void testSingle() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/single.kt");
doParsingTest(fileName);
}
@TestMetadata("withoutFileAnnotationAndPackageDeclaration.kt")
public void testWithoutFileAnnotationAndPackageDeclaration() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/withoutFileAnnotationAndPackageDeclaration.kt");
doParsingTest(fileName);
}
@TestMetadata("withoutPackage.kt")
public void testWithoutPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/withoutPackage.kt");
doParsingTest(fileName);
}
@TestMetadata("withoutPackageWithSimpleAnnotation.kt")
public void testWithoutPackageWithSimpleAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/onFile/withoutPackageWithSimpleAnnotation.kt");
doParsingTest(fileName);
}
}
@TestMetadata("compiler/testData/psi/annotation/onFileObsolete")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
+3 -3
View File
@@ -7,10 +7,10 @@ annotations
;
annotation
: "[" annotationEntry+ "]"
: annotationEntry
: "@"? "[" annotationEntry+ "]"
: "@"? annotationEntry
;
annotationEntry
: "@"? ++ SimpleName{"."} typeArguments? valueArguments?
: SimpleName{"."} typeArguments? valueArguments?
;
+1 -1
View File
@@ -24,7 +24,7 @@ fileAnnotations
;
fileAnnotation
: "[" "file" ":" annotationEntry+ "]"
: "@" "file" ":" ("[" annotationEntry+ "]" | annotationEntry)
;
packageHeader