FIC: Parse fun keyword in front of interface as a modifier
This commit is contained in:
@@ -57,7 +57,7 @@ public interface KtTokens {
|
|||||||
KtKeywordToken SUPER_KEYWORD = KtKeywordToken.keyword("super");
|
KtKeywordToken SUPER_KEYWORD = KtKeywordToken.keyword("super");
|
||||||
KtKeywordToken VAL_KEYWORD = KtKeywordToken.keyword("val");
|
KtKeywordToken VAL_KEYWORD = KtKeywordToken.keyword("val");
|
||||||
KtKeywordToken VAR_KEYWORD = KtKeywordToken.keyword("var");
|
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 FOR_KEYWORD = KtKeywordToken.keyword("for");
|
||||||
KtKeywordToken NULL_KEYWORD = KtKeywordToken.keyword("null");
|
KtKeywordToken NULL_KEYWORD = KtKeywordToken.keyword("null");
|
||||||
KtKeywordToken TRUE_KEYWORD = KtKeywordToken.keyword("true");
|
KtKeywordToken TRUE_KEYWORD = KtKeywordToken.keyword("true");
|
||||||
@@ -229,7 +229,7 @@ public interface KtTokens {
|
|||||||
REIFIED_KEYWORD, COMPANION_KEYWORD, SEALED_KEYWORD, LATEINIT_KEYWORD,
|
REIFIED_KEYWORD, COMPANION_KEYWORD, SEALED_KEYWORD, LATEINIT_KEYWORD,
|
||||||
DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD, ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD,
|
DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD, ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD,
|
||||||
CONST_KEYWORD, OPERATOR_KEYWORD, INFIX_KEYWORD, SUSPEND_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);
|
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 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 RECEIVER_TYPE_TERMINATORS = TokenSet.create(DOT, SAFE_ACCESS);
|
||||||
private static final TokenSet VALUE_PARAMETER_FIRST =
|
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 =
|
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 SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD);
|
||||||
private static final TokenSet ANNOTATION_TARGETS = TokenSet.create(
|
private static final TokenSet ANNOTATION_TARGETS = TokenSet.create(
|
||||||
FILE_KEYWORD, FIELD_KEYWORD, GET_KEYWORD, SET_KEYWORD, PROPERTY_KEYWORD,
|
FILE_KEYWORD, FIELD_KEYWORD, GET_KEYWORD, SET_KEYWORD, PROPERTY_KEYWORD,
|
||||||
@@ -585,6 +591,12 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
|||||||
|
|
||||||
if (atSet(modifierKeywords)) {
|
if (atSet(modifierKeywords)) {
|
||||||
IElementType lookahead = lookahead(1);
|
IElementType lookahead = lookahead(1);
|
||||||
|
|
||||||
|
if (at(FUN_KEYWORD) && lookahead != INTERFACE_KEYWORD) {
|
||||||
|
marker.rollbackTo();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (lookahead != null && !noModifiersBefore.contains(lookahead)) {
|
if (lookahead != null && !noModifiersBefore.contains(lookahead)) {
|
||||||
IElementType tt = tt();
|
IElementType tt = tt();
|
||||||
if (tokenConsumer != null) {
|
if (tokenConsumer != null) {
|
||||||
|
|||||||
+11
@@ -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
|
||||||
@@ -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')
|
||||||
@@ -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
|
||||||
@@ -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");
|
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")
|
@TestMetadata("Labels.kt")
|
||||||
public void testLabels() throws Exception {
|
public void testLabels() throws Exception {
|
||||||
runTest("compiler/testData/psi/Labels.kt");
|
runTest("compiler/testData/psi/Labels.kt");
|
||||||
@@ -715,6 +720,11 @@ public class ParsingTestGenerated extends AbstractParsingTest {
|
|||||||
runTest("compiler/testData/psi/UnsignedLiteral.kt");
|
runTest("compiler/testData/psi/UnsignedLiteral.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("validKotlinFunInterface.kt")
|
||||||
|
public void testValidKotlinFunInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/psi/validKotlinFunInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("When.kt")
|
@TestMetadata("When.kt")
|
||||||
public void testWhen() throws Exception {
|
public void testWhen() throws Exception {
|
||||||
runTest("compiler/testData/psi/When.kt");
|
runTest("compiler/testData/psi/When.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user