Add 'default' keyword

Parser: allow objects that are marked as default to have no name
This commit is contained in:
Pavel V. Talanov
2015-03-05 14:27:36 +03:00
parent 0ca2f3f336
commit 2b51e4f2d4
7 changed files with 507 additions and 30 deletions
@@ -152,6 +152,7 @@ public interface JetTokens {
JetModifierKeywordToken VARARG_KEYWORD = JetModifierKeywordToken.softKeywordModifier("vararg");
JetModifierKeywordToken REIFIED_KEYWORD = JetModifierKeywordToken.softKeywordModifier("reified");
JetModifierKeywordToken DYNAMIC_KEYWORD = JetModifierKeywordToken.softKeywordModifier("dynamic");
JetModifierKeywordToken DEFAULT_KEYWORD = JetModifierKeywordToken.softKeywordModifier("default");
JetKeywordToken FINALLY_KEYWORD = JetKeywordToken.softKeyword("finally");
JetModifierKeywordToken FINAL_KEYWORD = JetModifierKeywordToken.softKeywordModifier("final");
@@ -169,7 +170,7 @@ public interface JetTokens {
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD,
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD,
DYNAMIC_KEYWORD
DYNAMIC_KEYWORD, DEFAULT_KEYWORD
);
/*
@@ -181,7 +182,7 @@ public interface JetTokens {
new JetModifierKeywordToken[] {
ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD,
PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD,
REIFIED_KEYWORD
REIFIED_KEYWORD, DEFAULT_KEYWORD
};
TokenSet MODIFIER_KEYWORDS = TokenSet.create(MODIFIER_KEYWORDS_ARRAY);
@@ -954,10 +954,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
*/
private boolean parseLocalDeclaration() {
PsiBuilder.Marker decl = mark();
JetParsing.TokenDetector enumDetector = new JetParsing.TokenDetector(ENUM_KEYWORD);
myJetParsing.parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
JetParsing.ModifierDetector detector = new JetParsing.ModifierDetector();
myJetParsing.parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected());
IElementType declType = parseLocalDeclarationRest(detector.isEnumDetected());
if (declType != null) {
// we do not attach preceding comments (non-doc) to local variables because they are likely commenting a few statements below
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.JetNodeType;
import org.jetbrains.kotlin.lexer.JetKeywordToken;
import org.jetbrains.kotlin.lexer.JetTokens;
import java.util.HashMap;
import java.util.Map;
@@ -354,7 +355,7 @@ public class JetParsing extends AbstractJetParsing {
private void parseTopLevelObject() {
PsiBuilder.Marker decl = mark();
TokenDetector detector = new TokenDetector(ENUM_KEYWORD);
ModifierDetector detector = new ModifierDetector();
parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
IElementType keywordToken = tt();
@@ -364,7 +365,7 @@ public class JetParsing extends AbstractJetParsing {
// }
// else
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) {
declType = parseClass(detector.isDetected());
declType = parseClass(detector.isEnumDetected());
}
else if (keywordToken == FUN_KEYWORD) {
declType = parseFunction();
@@ -682,8 +683,8 @@ public class JetParsing extends AbstractJetParsing {
TokenSet constructorNameFollow = TokenSet.create(SEMICOLON, COLON, LPAR, LT, LBRACE);
int lastId = findLastBefore(ENUM_MEMBER_FIRST, constructorNameFollow, false);
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
ModifierDetector detector = new ModifierDetector();
createTruncatedBuilder(lastId).parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS);
IElementType type;
if (at(IDENTIFIER)) {
@@ -691,7 +692,7 @@ public class JetParsing extends AbstractJetParsing {
type = ENUM_ENTRY;
}
else {
type = parseMemberDeclarationRest(enumDetector.isDetected());
type = parseMemberDeclarationRest(detector.isEnumDetected(), detector.isDefaultDetected());
}
if (type == null) {
@@ -779,10 +780,10 @@ public class JetParsing extends AbstractJetParsing {
private void parseMemberDeclaration() {
PsiBuilder.Marker decl = mark();
TokenDetector enumDetector = new TokenDetector(ENUM_KEYWORD);
parseModifierList(MODIFIER_LIST, enumDetector, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
ModifierDetector detector = new ModifierDetector();
parseModifierList(MODIFIER_LIST, detector, REGULAR_ANNOTATIONS_ALLOW_SHORTS);
IElementType declType = parseMemberDeclarationRest(enumDetector.isDetected());
IElementType declType = parseMemberDeclarationRest(detector.isEnumDetected(), detector.isDefaultDetected());
if (declType == null) {
errorWithRecovery("Expecting member declaration", TokenSet.create(RBRACE));
@@ -793,12 +794,12 @@ public class JetParsing extends AbstractJetParsing {
}
}
private IElementType parseMemberDeclarationRest(boolean isEnum) {
private IElementType parseMemberDeclarationRest(boolean isEnum, boolean isDefault) {
IElementType keywordToken = tt();
IElementType declType = null;
if (keywordToken == CLASS_KEYWORD) {
if (lookahead(1) == OBJECT_KEYWORD) {
declType = parseDefaultObject();
declType = parseDeprecatedClassObject();
}
else {
declType = parseClass(isEnum);
@@ -817,7 +818,7 @@ public class JetParsing extends AbstractJetParsing {
declType = parseTypeAlias();
}
else if (keywordToken == OBJECT_KEYWORD) {
parseObject(NameParsingMode.REQUIRED, true);
parseObject(isDefault ? NameParsingMode.ALLOWED : NameParsingMode.REQUIRED, true);
declType = OBJECT_DECLARATION;
}
else if (keywordToken == LBRACE) {
@@ -880,7 +881,7 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "class" object
* ;
*/
private IElementType parseDefaultObject() {
private IElementType parseDeprecatedClassObject() {
assert _at(CLASS_KEYWORD) && lookahead(1) == OBJECT_KEYWORD;
advance(); // CLASS_KEYWORD
parseObject(NameParsingMode.ALLOWED, true);
@@ -1990,24 +1991,26 @@ public class JetParsing extends AbstractJetParsing {
return createForTopLevel(builder);
}
/*package*/ static class TokenDetector implements Consumer<IElementType> {
private boolean detected = false;
private final TokenSet tokens;
public TokenDetector(JetKeywordToken token) {
this.tokens = TokenSet.create(token);
}
/*package*/ static class ModifierDetector implements Consumer<IElementType> {
private boolean enumDetected = false;
private boolean defaultDetected = false;
@Override
public void consume(IElementType item) {
if (tokens.contains(item)) {
detected = true;
if (item == JetTokens.ENUM_KEYWORD) {
enumDetected = true;
}
else if (item == JetTokens.DEFAULT_KEYWORD) {
defaultDetected = true;
}
}
public boolean isDetected() {
return detected;
public boolean isEnumDetected() {
return enumDetected;
}
public boolean isDefaultDetected() {
return defaultDetected;
}
}
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinFileStubImpl;
import java.io.IOException;
public class JetFileElementType extends IStubFileElementType<KotlinFileStub> {
public static final int STUB_VERSION = 36;
public static final int STUB_VERSION = 37;
private static final String NAME = "kotlin.FILE";
+85
View File
@@ -0,0 +1,85 @@
class A {
default object {
}
}
class A {
default object
val c: Int = 1
}
class B {
public default object A {
}
}
class B {
default object A {
default object {
}
}
}
default object B
//should be error
default object {
}
object A {
default object
}
trait A {
default object
class C {
default object C {
default object
}
}
}
enum class D {
A B
default object
}
class A {
default class object
}
//should be error
class A {
class default object
}
class A {
default public final object
}
//should be error
default class {}
//should be error
val t = default object {
}
enum class I {
A
B
default object
}
enum class I {
A
B
default object {}
}
+382
View File
@@ -0,0 +1,382 @@
JetFile: DefaultKeyword.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('c')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(public)('public')
PsiWhiteSpace(' ')
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace('\n')
OBJECT_DECLARATION
PsiComment(EOL_COMMENT)('//should be error')
PsiWhiteSpace('\n')
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiErrorElement:Name expected
<empty list>
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
OBJECT_DECLARATION
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(trait)('trait')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n\n ')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('C')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('C')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('D')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace('\n\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiComment(EOL_COMMENT)('//should be error')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('default')
PsiWhiteSpace(' ')
OBJECT_DECLARATION
PsiElement(object)('object')
PsiWhiteSpace('\n')
OBJECT_DECLARATION_NAME
PsiErrorElement:Name expected
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(public)('public')
PsiWhiteSpace(' ')
PsiElement(final)('final')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
PsiComment(EOL_COMMENT)('//should be error')
PsiWhiteSpace('\n')
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiErrorElement:Name expected
<empty list>
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
PROPERTY
PsiComment(EOL_COMMENT)('//should be error')
PsiWhiteSpace('\n')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('t')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('default')
PsiWhiteSpace(' ')
PsiErrorElement:Property getter or setter expected
PsiElement(object)('object')
PsiWhiteSpace(' ')
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('I')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace('\n ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace('\n\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('I')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace('\n ')
ENUM_ENTRY
OBJECT_DECLARATION_NAME
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace('\n\n ')
OBJECT_DECLARATION
MODIFIER_LIST
PsiElement(default)('default')
PsiWhiteSpace(' ')
PsiElement(object)('object')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -151,6 +151,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("DefaultKeyword.kt")
public void testDefaultKeyword() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DefaultKeyword.kt");
doParsingTest(fileName);
}
@TestMetadata("DocCommentAfterFileAnnotations.kt")
public void testDocCommentAfterFileAnnotations() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DocCommentAfterFileAnnotations.kt");