Parser: added the support file annotations.

This commit is contained in:
Zalim Bashorov
2014-09-08 13:43:45 +04:00
parent 506610302a
commit 3c60d0de93
29 changed files with 824 additions and 46 deletions
@@ -52,6 +52,7 @@ public interface JetNodeTypes {
IElementType CLASS_BODY = JetStubElementTypes.CLASS_BODY; IElementType CLASS_BODY = JetStubElementTypes.CLASS_BODY;
IElementType IMPORT_LIST = JetStubElementTypes.IMPORT_LIST; IElementType IMPORT_LIST = JetStubElementTypes.IMPORT_LIST;
IElementType FILE_ANNOTATION_LIST = JetStubElementTypes.FILE_ANNOTATION_LIST;
IElementType IMPORT_DIRECTIVE = JetStubElementTypes.IMPORT_DIRECTIVE; IElementType IMPORT_DIRECTIVE = JetStubElementTypes.IMPORT_DIRECTIVE;
IElementType MODIFIER_LIST = JetStubElementTypes.MODIFIER_LIST; IElementType MODIFIER_LIST = JetStubElementTypes.MODIFIER_LIST;
IElementType PRIMARY_CONSTRUCTOR_MODIFIER_LIST = JetStubElementTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST; IElementType PRIMARY_CONSTRUCTOR_MODIFIER_LIST = JetStubElementTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST;
@@ -19,14 +19,13 @@ package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import com.intellij.util.containers.Stack;
import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.intellij.util.containers.Stack;
import static org.jetbrains.jet.lexer.JetTokens.*; import static org.jetbrains.jet.lexer.JetTokens.*;
@@ -109,8 +108,14 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
} }
protected boolean errorAndAdvance(String message) { protected boolean errorAndAdvance(String message) {
return errorAndAdvance(message, 1);
}
protected boolean errorAndAdvance(String message, int advanceTokenCount) {
PsiBuilder.Marker err = mark(); PsiBuilder.Marker err = mark();
advance(); // erroneous token for (int i = 0; i < advanceTokenCount; i++) {
advance(); // erroneous token
}
err.error(message); err.error(message);
return false; return false;
} }
@@ -30,6 +30,8 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import static org.jetbrains.jet.JetNodeTypes.*; import static org.jetbrains.jet.JetNodeTypes.*;
import static org.jetbrains.jet.lang.parsing.JetParsing.AnnotationParsingMode.REGULAR_ANNOTATIONS_ALLOW_SHORTS;
import static org.jetbrains.jet.lang.parsing.JetParsing.AnnotationParsingMode.REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS;
import static org.jetbrains.jet.lexer.JetTokens.*; import static org.jetbrains.jet.lexer.JetTokens.*;
public class JetExpressionParsing extends AbstractJetParsing { public class JetExpressionParsing extends AbstractJetParsing {
@@ -339,13 +341,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
if (at(LBRACKET)) { if (at(LBRACKET)) {
if (!parseLocalDeclaration()) { if (!parseLocalDeclaration()) {
PsiBuilder.Marker expression = mark(); PsiBuilder.Marker expression = mark();
myJetParsing.parseAnnotations(false); myJetParsing.parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
parsePrefixExpression(); parsePrefixExpression();
expression.done(ANNOTATED_EXPRESSION); expression.done(ANNOTATED_EXPRESSION);
} }
else {
return;
}
} }
else { else {
myBuilder.disableJoiningComplexTokens(); myBuilder.disableJoiningComplexTokens();
@@ -770,7 +769,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
int valPos = matchTokenStreamPredicate(new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ))); int valPos = matchTokenStreamPredicate(new FirstBefore(new At(VAL_KEYWORD), new AtSet(RPAR, LBRACE, RBRACE, SEMICOLON, EQ)));
if (valPos >= 0) { if (valPos >= 0) {
PsiBuilder.Marker property = mark(); PsiBuilder.Marker property = mark();
myJetParsing.parseModifierList(MODIFIER_LIST, true); myJetParsing.parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
myJetParsing.parseProperty(true); myJetParsing.parseProperty(true);
property.done(PROPERTY); property.done(PROPERTY);
} }
@@ -954,7 +953,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
private boolean parseLocalDeclaration() { private boolean parseLocalDeclaration() {
PsiBuilder.Marker decl = mark(); PsiBuilder.Marker decl = mark();
JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD); JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD);
myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, false); myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected()); IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected());
@@ -1200,7 +1199,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
PsiBuilder.Marker parameter = mark(); PsiBuilder.Marker parameter = mark();
int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW))); int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtSet(COMMA, RPAR, COLON, ARROW)));
createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false); createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
expect(IDENTIFIER, "Expecting parameter declaration"); expect(IDENTIFIER, "Expecting parameter declaration");
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.parsing; package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -28,9 +29,12 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.jetbrains.jet.JetNodeTypes.*; import static org.jetbrains.jet.JetNodeTypes.*;
import static org.jetbrains.jet.lang.parsing.JetParsing.AnnotationParsingMode.*;
import static org.jetbrains.jet.lexer.JetTokens.*; import static org.jetbrains.jet.lexer.JetTokens.*;
public class JetParsing extends AbstractJetParsing { public class JetParsing extends AbstractJetParsing {
private static final Logger LOG = Logger.getInstance(JetParsing.class);
// TODO: token sets to constants, including derived methods // TODO: token sets to constants, including derived methods
public static final Map<String, IElementType> MODIFIER_KEYWORD_MAP = new HashMap<String, IElementType>(); public static final Map<String, IElementType> MODIFIER_KEYWORD_MAP = new HashMap<String, IElementType>();
static { static {
@@ -167,18 +171,25 @@ public class JetParsing extends AbstractJetParsing {
/* /*
*preamble *preamble
* : packageDirective? import* * : fileAnnotationList? packageDirective? import*
* ; * ;
*/ */
private void parsePreamble() { private void parsePreamble() {
PsiBuilder.Marker firstEntry = mark();
/*
* fileAnnotationList
* : fileAnnotations*
*/
parseFileAnnotationList(FILE_ANNOTATIONS_BEFORE_PACKAGE);
/* /*
* packageDirective * packageDirective
* : modifiers "package" SimpleName{"."} SEMI? * : modifiers "package" SimpleName{"."} SEMI?
* ; * ;
*/ */
PsiBuilder.Marker packageDirective = mark(); PsiBuilder.Marker packageDirective = mark();
PsiBuilder.Marker firstEntry = mark(); parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
parseModifierList(MODIFIER_LIST, true);
if (at(PACKAGE_KEYWORD)) { if (at(PACKAGE_KEYWORD)) {
advance(); // PACKAGE_KEYWORD advance(); // PACKAGE_KEYWORD
@@ -188,7 +199,11 @@ public class JetParsing extends AbstractJetParsing {
if (at(LBRACE)) { if (at(LBRACE)) {
// Because it's blocked package and it will be parsed as one of top level objects // Because it's blocked package and it will be parsed as one of top level objects
packageDirective.drop();
firstEntry.rollbackTo(); firstEntry.rollbackTo();
parseFileAnnotationList(/*reportErrorForNonFileAnnotations =*/ false);
packageDirective = mark();
packageDirective.done(PACKAGE_DIRECTIVE); packageDirective.done(PACKAGE_DIRECTIVE);
return; return;
} }
@@ -198,7 +213,12 @@ public class JetParsing extends AbstractJetParsing {
consumeIf(SEMICOLON); consumeIf(SEMICOLON);
} }
else { else {
// When package directive is omitted we should not report error on non-file annotations at the beginning of the file.
// So, we rollback the parsing position and reparse file annotation list without report error on non-file annotations.
firstEntry.rollbackTo(); firstEntry.rollbackTo();
parseFileAnnotationList(FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED);
packageDirective = mark();
} }
packageDirective.done(PACKAGE_DIRECTIVE); packageDirective.done(PACKAGE_DIRECTIVE);
@@ -342,7 +362,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker decl = mark(); PsiBuilder.Marker decl = mark();
TokenDetector detector = new TokenDetector(ENUM_KEYWORD); TokenDetector detector = new TokenDetector(ENUM_KEYWORD);
parseModifierList(MODIFIER_LIST, detector, true); parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
IElementType keywordToken = tt(); IElementType keywordToken = tt();
IElementType declType = null; IElementType declType = null;
@@ -379,8 +399,11 @@ public class JetParsing extends AbstractJetParsing {
/* /*
* (modifier | attribute)* * (modifier | attribute)*
*/ */
boolean parseModifierList(IElementType nodeType, boolean allowShortAnnotations) { boolean parseModifierList(
return parseModifierList(nodeType, null, allowShortAnnotations); @NotNull IElementType nodeType,
@NotNull AnnotationParsingMode annotationParsingMode
) {
return parseModifierList(nodeType, null, annotationParsingMode);
} }
/** /**
@@ -388,7 +411,11 @@ public class JetParsing extends AbstractJetParsing {
* *
* Feeds modifiers (not attributes) into the passed consumer, if it is not null * Feeds modifiers (not attributes) into the passed consumer, if it is not null
*/ */
boolean parseModifierList(IElementType nodeType, @Nullable Consumer<IElementType> tokenConsumer, boolean allowShortAnnotations) { boolean parseModifierList(
@NotNull IElementType nodeType,
@Nullable Consumer<IElementType> tokenConsumer,
@NotNull AnnotationParsingMode annotationParsingMode
) {
PsiBuilder.Marker list = mark(); PsiBuilder.Marker list = mark();
boolean empty = true; boolean empty = true;
while (!eof()) { while (!eof()) {
@@ -396,8 +423,8 @@ public class JetParsing extends AbstractJetParsing {
if (tokenConsumer != null) tokenConsumer.consume(tt()); if (tokenConsumer != null) tokenConsumer.consume(tt());
advance(); // MODIFIER advance(); // MODIFIER
} }
else if (at(LBRACKET) || (allowShortAnnotations && at(IDENTIFIER))) { else if (at(LBRACKET) || (annotationParsingMode.allowShortAnnotations && at(IDENTIFIER))) {
parseAnnotation(allowShortAnnotations); parseAnnotation(annotationParsingMode);
} }
else { else {
break; break;
@@ -414,29 +441,68 @@ public class JetParsing extends AbstractJetParsing {
} }
/* /*
* annotations * fileAnnotationList
* : annotation* * : ("[" "file:" annotationEntry+ "]")*
* ; * ;
*/ */
void parseAnnotations(boolean allowShortAnnotations) { private void parseFileAnnotationList(AnnotationParsingMode mode) {
while (true) { if (!mode.isFileAnnotationParsingMode) {
if (!(parseAnnotation(allowShortAnnotations))) break; LOG.error("expected file annotation parsing mode, but:" + mode);
}
PsiBuilder.Marker fileAnnotationsList = mark();
if (parseAnnotations(mode)) {
fileAnnotationsList.done(FILE_ANNOTATION_LIST);
}
else {
fileAnnotationsList.drop();
} }
} }
/*
* annotations
* : annotation*
* ;
*/
boolean parseAnnotations(AnnotationParsingMode mode) {
if (!parseAnnotation(mode)) return false;
while (parseAnnotation(mode)) {
// do nothing
}
return true;
}
/* /*
* annotation * annotation
* : "[" annotationEntry+ "]" * : "[" ("file" ":")? annotationEntry+ "]"
* : annotationEntry * : annotationEntry
* ; * ;
*/ */
private boolean parseAnnotation(boolean allowShortAnnotations) { private boolean parseAnnotation(AnnotationParsingMode mode) {
if (at(LBRACKET)) { if (at(LBRACKET)) {
PsiBuilder.Marker annotation = mark(); PsiBuilder.Marker annotation = mark();
myBuilder.disableNewlines(); myBuilder.disableNewlines();
advance(); // LBRACKET advance(); // LBRACKET
if (mode.isFileAnnotationParsingMode) {
if (mode == FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED && !(at(FILE_KEYWORD) && lookahead(1) == COLON)) {
annotation.rollbackTo();
myBuilder.restoreNewlinesState();
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));
}
else if (at(FILE_KEYWORD) && lookahead(1) == COLON) {
errorAndAdvance("File annotations are only allowed before package declaration", 2);
}
if (!at(IDENTIFIER)) { if (!at(IDENTIFIER)) {
error("Expecting a list of attributes"); error("Expecting a list of attributes");
} }
@@ -460,10 +526,11 @@ public class JetParsing extends AbstractJetParsing {
annotation.done(ANNOTATION); annotation.done(ANNOTATION);
return true; return true;
} }
else if (allowShortAnnotations && at(IDENTIFIER)) { else if (mode.allowShortAnnotations && at(IDENTIFIER)) {
parseAnnotationEntry(); parseAnnotationEntry();
return true; return true;
} }
return false; return false;
} }
@@ -509,7 +576,7 @@ public class JetParsing extends AbstractJetParsing {
boolean typeParametersDeclared = parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET); boolean typeParametersDeclared = parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET);
PsiBuilder.Marker beforeConstructorModifiers = mark(); PsiBuilder.Marker beforeConstructorModifiers = mark();
boolean hasConstructorModifiers = parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST, false); boolean hasConstructorModifiers = parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
// Some modifiers found, but no parentheses following: class has already ended, and we are looking at something else // Some modifiers found, but no parentheses following: class has already ended, and we are looking at something else
if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON) ) { if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON) ) {
@@ -569,7 +636,7 @@ public class JetParsing extends AbstractJetParsing {
TokenSet constructorNameFollow = TokenSet.create(SEMICOLON, COLON, LPAR, LT, LBRACE); TokenSet constructorNameFollow = TokenSet.create(SEMICOLON, COLON, LPAR, LT, LBRACE);
int lastId = findLastBefore(ENUM_MEMBER_FIRST, constructorNameFollow, false); int lastId = findLastBefore(ENUM_MEMBER_FIRST, constructorNameFollow, false);
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD); TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, enumDetector, false); createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
IElementType type; IElementType type;
if (at(IDENTIFIER)) { if (at(IDENTIFIER)) {
@@ -666,7 +733,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker decl = mark(); PsiBuilder.Marker decl = mark();
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD); TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
parseModifierList(MODIFIER_LIST, enumDetector, true); parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
IElementType declType = parseMemberDeclarationRest(enumDetector.isDetected()); IElementType declType = parseMemberDeclarationRest(enumDetector.isDetected());
@@ -777,7 +844,7 @@ public class JetParsing extends AbstractJetParsing {
*/ */
private void parseInitializer() { private void parseInitializer() {
PsiBuilder.Marker initializer = mark(); PsiBuilder.Marker initializer = mark();
parseAnnotations(false); parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
IElementType type; IElementType type;
if (at(THIS_KEYWORD)) { if (at(THIS_KEYWORD)) {
@@ -1020,7 +1087,7 @@ public class JetParsing extends AbstractJetParsing {
private boolean parsePropertyGetterOrSetter() { private boolean parsePropertyGetterOrSetter() {
PsiBuilder.Marker getterOrSetter = mark(); PsiBuilder.Marker getterOrSetter = mark();
parseModifierList(MODIFIER_LIST, false); parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) { if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) {
getterOrSetter.rollbackTo(); getterOrSetter.rollbackTo();
@@ -1150,7 +1217,7 @@ public class JetParsing extends AbstractJetParsing {
*/ */
private void parseReceiverType(String title, TokenSet nameFollow, int lastDot) { private void parseReceiverType(String title, TokenSet nameFollow, int lastDot) {
if (lastDot == -1) { // There's no explicit receiver type specified if (lastDot == -1) { // There's no explicit receiver type specified
parseAnnotations(false); parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
} }
else { else {
createTruncatedBuilder(lastDot).parseTypeRef(); createTruncatedBuilder(lastDot).parseTypeRef();
@@ -1249,7 +1316,7 @@ public class JetParsing extends AbstractJetParsing {
*/ */
private void parseDelegationSpecifier() { private void parseDelegationSpecifier() {
PsiBuilder.Marker delegator = mark(); PsiBuilder.Marker delegator = mark();
parseAnnotations(false); parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
PsiBuilder.Marker reference = mark(); PsiBuilder.Marker reference = mark();
parseTypeRef(); parseTypeRef();
@@ -1349,7 +1416,7 @@ public class JetParsing extends AbstractJetParsing {
private void parseTypeConstraint() { private void parseTypeConstraint() {
PsiBuilder.Marker constraint = mark(); PsiBuilder.Marker constraint = mark();
parseAnnotations(false); parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
if (at(CLASS_KEYWORD)) { if (at(CLASS_KEYWORD)) {
advance(); // CLASS_KEYWORD advance(); // CLASS_KEYWORD
@@ -1431,7 +1498,7 @@ public class JetParsing extends AbstractJetParsing {
// we don't support this case now // we don't support this case now
// myBuilder.disableJoiningComplexTokens(); // myBuilder.disableJoiningComplexTokens();
PsiBuilder.Marker typeRefMarker = mark(); PsiBuilder.Marker typeRefMarker = mark();
parseAnnotations(false); parseAnnotations(REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
if (at(IDENTIFIER) || at(PACKAGE_KEYWORD)) { if (at(IDENTIFIER) || at(PACKAGE_KEYWORD)) {
parseUserType(); parseUserType();
@@ -1533,7 +1600,8 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker reference = mark(); PsiBuilder.Marker reference = mark();
while (true) { while (true) {
if (expect(IDENTIFIER, "Expecting type name", TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW))) { if (expect(IDENTIFIER, "Expecting type name",
TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW))) {
reference.done(REFERENCE_EXPRESSION); reference.done(REFERENCE_EXPRESSION);
} }
else { else {
@@ -1600,7 +1668,7 @@ public class JetParsing extends AbstractJetParsing {
// TokenSet stopAt = TokenSet.create(COMMA, COLON, GT); // TokenSet stopAt = TokenSet.create(COMMA, COLON, GT);
// parseModifierListWithShortAnnotations(MODIFIER_LIST, lookFor, stopAt); // parseModifierListWithShortAnnotations(MODIFIER_LIST, lookFor, stopAt);
// Currently we do not allow annotations // Currently we do not allow annotations
parseModifierList(MODIFIER_LIST, false); parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
if (at(MUL)) { if (at(MUL)) {
advance(); // MUL advance(); // MUL
@@ -1626,7 +1694,7 @@ public class JetParsing extends AbstractJetParsing {
private void parseModifierListWithShortAnnotations(IElementType modifierList, TokenSet lookFor, TokenSet stopAt) { private void parseModifierListWithShortAnnotations(IElementType modifierList, TokenSet lookFor, TokenSet stopAt) {
int lastId = findLastBefore(lookFor, stopAt, false); int lastId = findLastBefore(lookFor, stopAt, false);
createTruncatedBuilder(lastId).parseModifierList(modifierList, true); createTruncatedBuilder(lastId).parseModifierList(modifierList, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
} }
/* /*
@@ -1741,7 +1809,7 @@ public class JetParsing extends AbstractJetParsing {
if (isFunctionTypeContents) { if (isFunctionTypeContents) {
if (!tryParseValueParameter()) { if (!tryParseValueParameter()) {
PsiBuilder.Marker valueParameter = mark(); PsiBuilder.Marker valueParameter = mark();
parseModifierList(MODIFIER_LIST, false); // lazy, out, ref parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); // lazy, out, ref
parseTypeRef(); parseTypeRef();
valueParameter.done(VALUE_PARAMETER); valueParameter.done(VALUE_PARAMETER);
} }
@@ -1857,4 +1925,19 @@ public class JetParsing extends AbstractJetParsing {
return detected; return detected;
} }
} }
static enum AnnotationParsingMode {
FILE_ANNOTATIONS_BEFORE_PACKAGE(false, true),
FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED(false, true),
REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS(false, false),
REGULAR_ANNOTATIONS_ALLOW_SHORTS(true, false);
boolean allowShortAnnotations;
boolean isFileAnnotationParsingMode;
AnnotationParsingMode(boolean allowShortAnnotations, boolean onlyFileAnnotations) {
this.allowShortAnnotations = allowShortAnnotations;
this.isFileAnnotationParsingMode = onlyFileAnnotations;
}
}
} }
@@ -30,6 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub; import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub;
import org.jetbrains.jet.lang.psi.stubs.elements.JetPlaceHolderStubElementType;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
@@ -39,7 +40,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class JetFile extends PsiFileBase implements JetDeclarationContainer, JetElement, PsiClassOwner { public class JetFile extends PsiFileBase implements JetDeclarationContainer, JetAnnotated, JetElement, PsiClassOwner {
private final boolean isCompiled; private final boolean isCompiled;
@@ -80,12 +81,25 @@ public class JetFile extends PsiFileBase implements JetDeclarationContainer, Jet
@Nullable @Nullable
public JetImportList getImportList() { public JetImportList getImportList() {
return findChildByTypeOrClass(JetStubElementTypes.IMPORT_LIST, JetImportList.class);
}
@Nullable
public JetFileAnnotationList getFileAnnotationList() {
return findChildByTypeOrClass(JetStubElementTypes.FILE_ANNOTATION_LIST, JetFileAnnotationList.class);
}
@Nullable
public <T extends JetElementImplStub<? extends StubElement<?>>> T findChildByTypeOrClass(
@NotNull JetPlaceHolderStubElementType<T> elementType,
@NotNull Class<T> elementClass
) {
PsiJetFileStub stub = getStub(); PsiJetFileStub stub = getStub();
if (stub != null) { if (stub != null) {
StubElement<JetImportList> importListStub = stub.findChildStubByType(JetStubElementTypes.IMPORT_LIST); StubElement<T> importListStub = stub.findChildStubByType(elementType);
return importListStub != null ? importListStub.getPsi() : null; return importListStub != null ? importListStub.getPsi() : null;
} }
return findChildByClass(JetImportList.class); return findChildByClass(elementClass);
} }
@NotNull @NotNull
@@ -205,4 +219,22 @@ public class JetFile extends PsiFileBase implements JetDeclarationContainer, Jet
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) { public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitJetFile(this, data); return visitor.visitJetFile(this, data);
} }
@NotNull
@Override
public List<JetAnnotation> getAnnotations() {
JetFileAnnotationList fileAnnotationList = getFileAnnotationList();
if (fileAnnotationList == null) return Collections.emptyList();
return fileAnnotationList.getAnnotations();
}
@NotNull
@Override
public List<JetAnnotationEntry> getAnnotationEntries() {
JetFileAnnotationList fileAnnotationList = getFileAnnotationList();
if (fileAnnotationList == null) return Collections.emptyList();
return fileAnnotationList.getAnnotationEntries();
}
} }
@@ -0,0 +1,57 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.stubs.PsiJetPlaceHolderStub;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
import java.util.List;
public class JetFileAnnotationList extends JetElementImplStub<PsiJetPlaceHolderStub<JetFileAnnotationList>> {
public JetFileAnnotationList(@NotNull ASTNode node) {
super(node);
}
public JetFileAnnotationList(@NotNull PsiJetPlaceHolderStub<JetFileAnnotationList> stub) {
super(stub, JetStubElementTypes.FILE_ANNOTATION_LIST);
}
@Override
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitFileAnnotationList(this, data);
}
@NotNull
public List<JetAnnotation> getAnnotations() {
return getStubOrPsiChildrenAsList(JetStubElementTypes.ANNOTATION);
}
@NotNull
public List<JetAnnotationEntry> getAnnotationEntries() {
return KotlinPackage.flatMap(getAnnotations(), new Function1<JetAnnotation, List<JetAnnotationEntry>>() {
@Override
public List<JetAnnotationEntry> invoke(JetAnnotation annotation) {
return annotation.getEntries();
}
});
}
}
@@ -74,6 +74,10 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitJetElement(importList, data); return visitJetElement(importList, data);
} }
public R visitFileAnnotationList(@NotNull JetFileAnnotationList fileAnnotationList, D data) {
return visitJetElement(fileAnnotationList, data);
}
public R visitClassBody(@NotNull JetClassBody classBody, D data) { public R visitClassBody(@NotNull JetClassBody classBody, D data) {
return visitJetElement(classBody, data); return visitJetElement(classBody, data);
} }
@@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
import java.io.IOException; import java.io.IOException;
public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> { public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
public static final int STUB_VERSION = 29; public static final int STUB_VERSION = 30;
public JetFileElementType() { public JetFileElementType() {
super("jet.FILE", JetLanguage.INSTANCE); super("jet.FILE", JetLanguage.INSTANCE);
@@ -52,6 +52,9 @@ public interface JetStubElementTypes {
JetPlaceHolderStubElementType<JetImportList> IMPORT_LIST = JetPlaceHolderStubElementType<JetImportList> IMPORT_LIST =
new JetPlaceHolderStubElementType<JetImportList>("IMPORT_LIST", JetImportList.class); new JetPlaceHolderStubElementType<JetImportList>("IMPORT_LIST", JetImportList.class);
JetPlaceHolderStubElementType<JetFileAnnotationList> FILE_ANNOTATION_LIST =
new JetPlaceHolderStubElementType<JetFileAnnotationList>("FILE_ANNOTATION_LIST", JetFileAnnotationList.class);
JetImportDirectiveElementType IMPORT_DIRECTIVE = new JetImportDirectiveElementType("IMPORT_DIRECTIVE"); JetImportDirectiveElementType IMPORT_DIRECTIVE = new JetImportDirectiveElementType("IMPORT_DIRECTIVE");
JetPlaceHolderStubElementType<JetPackageDirective> PACKAGE_DIRECTIVE = JetPlaceHolderStubElementType<JetPackageDirective> PACKAGE_DIRECTIVE =
@@ -131,6 +131,7 @@ public interface JetTokens {
JetSingleValueToken COMMA = new JetSingleValueToken("COMMA", ","); JetSingleValueToken COMMA = new JetSingleValueToken("COMMA", ",");
JetToken EOL_OR_SEMICOLON = new JetToken("EOL_OR_SEMICOLON"); JetToken EOL_OR_SEMICOLON = new JetToken("EOL_OR_SEMICOLON");
JetKeywordToken FILE_KEYWORD = JetKeywordToken.softKeyword("file");
JetKeywordToken IMPORT_KEYWORD = JetKeywordToken.softKeyword("import"); JetKeywordToken IMPORT_KEYWORD = JetKeywordToken.softKeyword("import");
JetKeywordToken WHERE_KEYWORD = JetKeywordToken.softKeyword("where"); JetKeywordToken WHERE_KEYWORD = JetKeywordToken.softKeyword("where");
JetKeywordToken BY_KEYWORD = JetKeywordToken.softKeyword("by"); JetKeywordToken BY_KEYWORD = JetKeywordToken.softKeyword("by");
@@ -163,7 +164,7 @@ public interface JetTokens {
NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE
); );
TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD, TokenSet SOFT_KEYWORDS = TokenSet.create(FILE_KEYWORD, IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD,
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD,
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD
@@ -0,0 +1,13 @@
package bar
[file: foo]
val prop
[file:bar baz]
fun func() {}
[file:baz]
class C
[file:]
trait T
@@ -0,0 +1,93 @@
JetFile: fileAnnotationInWrongPlace.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n\n')
PROPERTY
MODIFIER_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('prop')
PsiWhiteSpace('\n\n')
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
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(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
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
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiErrorElement:Expecting a list of attributes
<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,39 @@
JetFile: manyAnnotationBlocks.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
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,3 @@
[file: foo bar
baz]
package bar
@@ -0,0 +1,34 @@
JetFile: manyInOneAnnotationBlock.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
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
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,8 @@
[foo]
[file bar]
[file, baz]
[file]
[:foo.bar]
[file:]
[:]
package boo
@@ -0,0 +1,88 @@
JetFile: nonFIleAnnotationBeforePackage.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiErrorElement:Expecting "file:" prefix for file annotations
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('baz')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiElement(COLON)(':')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:Expecting "file:" prefix for file annotations
<empty list>
PsiElement(COLON)(':')
PsiErrorElement:Expecting a list of annotations
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('boo')
@@ -0,0 +1,2 @@
[file: foo]
package bar
@@ -0,0 +1,20 @@
JetFile: single.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
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,42 @@
JetFile: withoutFileAnnotationAndPackageDeclaration.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
MODIFIER_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann')
PsiElement(RBRACKET)(']')
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,60 @@
JetFile: withoutPackage.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
PACKAGE_DIRECTIVE
<empty list>
FUN
MODIFIER_LIST
ANNOTATION
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')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
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,57 @@
JetFile: withoutPackageWithSimpleAnnotation.kt
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
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
PsiElement(LBRACKET)('[')
PsiErrorElement:File annotations are only allowed before package declaration
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
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,3 @@
[file: foo]
[file:bar baz]
package bar
@@ -0,0 +1,42 @@
JetFile: manyAnnotationsOnFile.kts
FILE_ANNOTATION_LIST
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n')
ANNOTATION
PsiElement(LBRACKET)('[')
PsiElement(file)('file')
PsiElement(COLON)(':')
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')
SCRIPT
BLOCK
<empty list>
@@ -35,7 +35,7 @@ import java.util.regex.Pattern;
public class JetParsingTestGenerated extends AbstractJetParsingTest { public class JetParsingTestGenerated extends AbstractJetParsingTest {
@TestMetadata("compiler/testData/psi") @TestMetadata("compiler/testData/psi")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Psi.Examples.class, Psi.FunctionReceivers.class, Psi.GreatSyntacticShift.class, Psi.Kdoc.class, Psi.PropertyDelegate.class, Psi.Recovery.class, Psi.Script.class, Psi.StringTemplates.class}) @InnerTestClasses({Psi.Annotation.class, Psi.Examples.class, Psi.FunctionReceivers.class, Psi.GreatSyntacticShift.class, Psi.Kdoc.class, Psi.PropertyDelegate.class, Psi.Recovery.class, Psi.Script.class, Psi.StringTemplates.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class Psi extends AbstractJetParsingTest { public static class Psi extends AbstractJetParsingTest {
@TestMetadata("AbsentInnerType.kt") @TestMetadata("AbsentInnerType.kt")
@@ -546,6 +546,75 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName); doParsingTest(fileName);
} }
@TestMetadata("compiler/testData/psi/annotation")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Annotation.OnFile.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public static class Annotation extends AbstractJetParsingTest {
public void testAllFilesPresentInAnnotation() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("compiler/testData/psi/annotation/onFile")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.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/examples") @TestMetadata("compiler/testData/psi/examples")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({Examples.Array.class, Examples.Collections.class, Examples.Io.class, Examples.Map.class, Examples.Priorityqueues.class, Examples.Util.class}) @InnerTestClasses({Examples.Array.class, Examples.Collections.class, Examples.Io.class, Examples.Map.class, Examples.Priorityqueues.class, Examples.Util.class})
@@ -1251,6 +1320,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName); doParsingTest(fileName);
} }
@TestMetadata("manyAnnotationsOnFile.kts")
public void testManyAnnotationsOnFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/script/manyAnnotationsOnFile.kts");
doParsingTest(fileName);
}
@TestMetadata("Shebang.kts") @TestMetadata("Shebang.kts")
public void testShebang() throws Exception { public void testShebang() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/script/Shebang.kts"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/script/Shebang.kts");