FIC: Parse fun keyword in front of interface as a modifier

This commit is contained in:
Mikhail Zarechenskiy
2019-11-12 01:07:59 +03:00
parent 174b3db723
commit 4aa195e912
7 changed files with 218 additions and 4 deletions
@@ -57,7 +57,7 @@ public interface KtTokens {
KtKeywordToken SUPER_KEYWORD = KtKeywordToken.keyword("super");
KtKeywordToken VAL_KEYWORD = KtKeywordToken.keyword("val");
KtKeywordToken VAR_KEYWORD = KtKeywordToken.keyword("var");
KtKeywordToken FUN_KEYWORD = KtKeywordToken.keyword("fun");
KtModifierKeywordToken FUN_KEYWORD = KtModifierKeywordToken.keywordModifier("fun");
KtKeywordToken FOR_KEYWORD = KtKeywordToken.keyword("for");
KtKeywordToken NULL_KEYWORD = KtKeywordToken.keyword("null");
KtKeywordToken TRUE_KEYWORD = KtKeywordToken.keyword("true");
@@ -229,7 +229,7 @@ public interface KtTokens {
REIFIED_KEYWORD, COMPANION_KEYWORD, SEALED_KEYWORD, LATEINIT_KEYWORD,
DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD, ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD,
CONST_KEYWORD, OPERATOR_KEYWORD, INFIX_KEYWORD, SUSPEND_KEYWORD,
HEADER_KEYWORD, IMPL_KEYWORD, EXPECT_KEYWORD, ACTUAL_KEYWORD
HEADER_KEYWORD, IMPL_KEYWORD, EXPECT_KEYWORD, ACTUAL_KEYWORD, FUN_KEYWORD
};
TokenSet MODIFIER_KEYWORDS = TokenSet.create(MODIFIER_KEYWORDS_ARRAY);
@@ -51,9 +51,15 @@ public class KotlinParsing extends AbstractKotlinParsing {
private static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, LPAR, HASH, DYNAMIC_KEYWORD);
private static final TokenSet RECEIVER_TYPE_TERMINATORS = TokenSet.create(DOT, SAFE_ACCESS);
private static final TokenSet VALUE_PARAMETER_FIRST =
TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET, VAL_KEYWORD, VAR_KEYWORD), MODIFIER_KEYWORDS);
TokenSet.orSet(
TokenSet.create(IDENTIFIER, LBRACKET, VAL_KEYWORD, VAR_KEYWORD),
TokenSet.andNot(MODIFIER_KEYWORDS, TokenSet.create(FUN_KEYWORD))
);
private static final TokenSet LAMBDA_VALUE_PARAMETER_FIRST =
TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
TokenSet.orSet(
TokenSet.create(IDENTIFIER, LBRACKET),
TokenSet.andNot(MODIFIER_KEYWORDS, TokenSet.create(FUN_KEYWORD))
);
private static final TokenSet SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD);
private static final TokenSet ANNOTATION_TARGETS = TokenSet.create(
FILE_KEYWORD, FIELD_KEYWORD, GET_KEYWORD, SET_KEYWORD, PROPERTY_KEYWORD,
@@ -585,6 +591,12 @@ public class KotlinParsing extends AbstractKotlinParsing {
if (atSet(modifierKeywords)) {
IElementType lookahead = lookahead(1);
if (at(FUN_KEYWORD) && lookahead != INTERFACE_KEYWORD) {
marker.rollbackTo();
return false;
}
if (lookahead != null && !noModifiersBefore.contains(lookahead)) {
IElementType tt = tt();
if (tokenConsumer != null) {
+11
View File
@@ -0,0 +1,11 @@
interface fun Foo
fun private interface Foo
fun @Bar interface Foo
fun class Foo
fun abstract class Foo
fun object Foo
+79
View File
@@ -0,0 +1,79 @@
KtFile: kotlinFunInterface_ERR.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
CLASS
PsiElement(interface)('interface')
PsiErrorElement:Name expected
<empty list>
PsiWhiteSpace(' ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('private')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace(' ')
CLASS
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiErrorElement:Annotations are not allowed in this position
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
PsiErrorElement:Expecting function name or receiver type
<empty list>
PsiWhiteSpace(' ')
CLASS
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiErrorElement:Expecting function name or receiver type
<empty list>
PsiWhiteSpace(' ')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('abstract')
PsiErrorElement:Expecting '('
<empty list>
PsiWhiteSpace(' ')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiErrorElement:Expecting function name or receiver type
<empty list>
PsiWhiteSpace(' ')
OBJECT_DECLARATION
PsiElement(object)('object')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
+17
View File
@@ -0,0 +1,17 @@
fun interface Foo
fun interface Foo {
fun invoke()
}
private fun interface Foo
@Bar
fun interface Foo
class TopLevel {
fun interface Foo
}
fun
interface Foo
+85
View File
@@ -0,0 +1,85 @@
KtFile: validKotlinFunInterface.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
CLASS
MODIFIER_LIST
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('invoke')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(private)('private')
PsiWhiteSpace(' ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Bar')
PsiWhiteSpace('\n')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n\n')
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('TopLevel')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
CLASS
MODIFIER_LIST
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
MODIFIER_LIST
PsiElement(fun)('fun')
PsiWhiteSpace('\n')
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('Foo')
@@ -450,6 +450,11 @@ public class ParsingTestGenerated extends AbstractParsingTest {
runTest("compiler/testData/psi/InterfaceWithEnumKeyword.kt");
}
@TestMetadata("kotlinFunInterface_ERR.kt")
public void testKotlinFunInterface_ERR() throws Exception {
runTest("compiler/testData/psi/kotlinFunInterface_ERR.kt");
}
@TestMetadata("Labels.kt")
public void testLabels() throws Exception {
runTest("compiler/testData/psi/Labels.kt");
@@ -715,6 +720,11 @@ public class ParsingTestGenerated extends AbstractParsingTest {
runTest("compiler/testData/psi/UnsignedLiteral.kt");
}
@TestMetadata("validKotlinFunInterface.kt")
public void testValidKotlinFunInterface() throws Exception {
runTest("compiler/testData/psi/validKotlinFunInterface.kt");
}
@TestMetadata("When.kt")
public void testWhen() throws Exception {
runTest("compiler/testData/psi/When.kt");