Support modifiers on types in parser
(required for 'suspend' on functional types).
TYPE_REFERENCE element now has MODIFIER_LIST child, which hosts annotations and modifiers for the corresponding type reference.
Annotations and modifiers written before an extension function type are now parsed as annotations and modifiers for the functional type, not the receiver type.
So, '@Ann A.(B) -> C' was '(@Ann A).(B) -> C', and became '@Ann (A.(B) -> C)'.
NB: DSL_SCOPE_VIOLATION testData updated accordingly.
Type projection variance modifiers ('in', 'out') belong to a separate modifier list under corresponding type projection (not under a type reference).
'A<in suspend T>' is 'A<(in (suspend T))>', 'A<suspend in T>' is an error.
In stub builder, create a modifier list node to host annotations and modifiers (none so far; TODO properly serialize/deserialize types with modifiers).
This commit is contained in:
committed by
Stanislav Erokhin
parent
6649f64e9f
commit
a15d423db4
@@ -231,6 +231,9 @@ public interface KtTokens {
|
||||
|
||||
TokenSet MODIFIER_KEYWORDS = TokenSet.create(MODIFIER_KEYWORDS_ARRAY);
|
||||
|
||||
TokenSet TYPE_MODIFIER_KEYWORDS = TokenSet.create(SUSPEND_KEYWORD);
|
||||
TokenSet TYPE_ARGUMENT_MODIFIER_KEYWORDS = TokenSet.create(IN_KEYWORD, OUT_KEYWORD);
|
||||
|
||||
TokenSet VISIBILITY_MODIFIERS = TokenSet.create(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD);
|
||||
|
||||
TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE);
|
||||
|
||||
@@ -457,6 +457,23 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
@Nullable Consumer<IElementType> tokenConsumer,
|
||||
@NotNull AnnotationParsingMode annotationParsingMode,
|
||||
@NotNull TokenSet noModifiersBefore
|
||||
) {
|
||||
return doParseModifierList(tokenConsumer, MODIFIER_KEYWORDS, annotationParsingMode, noModifiersBefore);
|
||||
}
|
||||
|
||||
private boolean parseTypeModifierList() {
|
||||
return doParseModifierList(null, TYPE_MODIFIER_KEYWORDS, DEFAULT, TokenSet.EMPTY);
|
||||
}
|
||||
|
||||
private boolean parseTypeArgumentModifierList() {
|
||||
return doParseModifierList(null, TYPE_ARGUMENT_MODIFIER_KEYWORDS, NO_ANNOTATIONS, TokenSet.create(COMMA, COLON, GT));
|
||||
}
|
||||
|
||||
private boolean doParseModifierList(
|
||||
@Nullable Consumer<IElementType> tokenConsumer,
|
||||
@NotNull TokenSet modifierKeywords,
|
||||
@NotNull AnnotationParsingMode annotationParsingMode,
|
||||
@NotNull TokenSet noModifiersBefore
|
||||
) {
|
||||
PsiBuilder.Marker list = mark();
|
||||
boolean empty = true;
|
||||
@@ -464,7 +481,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
if (at(AT) && annotationParsingMode.allowAnnotations) {
|
||||
parseAnnotationOrList(annotationParsingMode);
|
||||
}
|
||||
else if (tryParseModifier(tokenConsumer, noModifiersBefore)) {
|
||||
else if (tryParseModifier(tokenConsumer, noModifiersBefore, modifierKeywords)) {
|
||||
// modifier advanced
|
||||
}
|
||||
else {
|
||||
@@ -481,10 +498,14 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
return !empty;
|
||||
}
|
||||
|
||||
private boolean tryParseModifier(@Nullable Consumer<IElementType> tokenConsumer, @NotNull TokenSet noModifiersBefore) {
|
||||
private boolean tryParseModifier(
|
||||
@Nullable Consumer<IElementType> tokenConsumer,
|
||||
@NotNull TokenSet noModifiersBefore,
|
||||
@NotNull TokenSet modifierKeywords
|
||||
) {
|
||||
PsiBuilder.Marker marker = mark();
|
||||
|
||||
if (atSet(MODIFIER_KEYWORDS)) {
|
||||
if (atSet(modifierKeywords)) {
|
||||
IElementType lookahead = lookahead(1);
|
||||
if (lookahead != null && !noModifiersBefore.contains(lookahead)) {
|
||||
IElementType tt = tt();
|
||||
@@ -1865,7 +1886,8 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
// on expression-indicating symbols or not
|
||||
private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) {
|
||||
PsiBuilder.Marker typeRefMarker = mark();
|
||||
parseAnnotations(DEFAULT);
|
||||
|
||||
parseTypeModifierList();
|
||||
|
||||
PsiBuilder.Marker typeElementMarker = mark();
|
||||
|
||||
@@ -1930,9 +1952,11 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
// A.(B) -> C
|
||||
// ^
|
||||
|
||||
PsiBuilder.Marker functionType = typeRefMarker.precede();
|
||||
PsiBuilder.Marker receiverType = typeRefMarker.precede();
|
||||
typeRefMarker.done(TYPE_REFERENCE);
|
||||
PsiBuilder.Marker functionType = typeElementMarker.precede();
|
||||
|
||||
PsiBuilder.Marker receiverTypeRef = typeElementMarker.precede();
|
||||
PsiBuilder.Marker receiverType = receiverTypeRef.precede();
|
||||
receiverTypeRef.done(TYPE_REFERENCE);
|
||||
receiverType.done(FUNCTION_TYPE_RECEIVER);
|
||||
|
||||
advance(); // DOT
|
||||
@@ -1943,7 +1967,6 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
else {
|
||||
error("Expecting function type");
|
||||
}
|
||||
typeRefMarker = functionType.precede();
|
||||
|
||||
functionType.done(FUNCTION_TYPE);
|
||||
}
|
||||
@@ -2089,7 +2112,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
|
||||
// Currently we do not allow annotations on star projections and probably we should not
|
||||
// Annotations on other kinds of type arguments should be parsed as common type annotations (within parseTypeRef call)
|
||||
parseModifierList(NO_ANNOTATIONS, TokenSet.create(COMMA, COLON, GT));
|
||||
parseTypeArgumentModifierList();
|
||||
|
||||
if (at(MUL)) {
|
||||
advance(); // MUL
|
||||
|
||||
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
* Type reference element.
|
||||
* Underlying token is [org.jetbrains.kotlin.KtNodeTypes.TYPE_REFERENCE]
|
||||
*/
|
||||
class KtTypeReference : KtElementImplStub<KotlinPlaceHolderStub<KtTypeReference>>, KtAnnotated, KtAnnotationsContainer {
|
||||
class KtTypeReference : KtModifierListOwnerStub<KotlinPlaceHolderStub<KtTypeReference>>,
|
||||
KtAnnotated, KtAnnotationsContainer {
|
||||
|
||||
constructor(node: ASTNode) : super(node)
|
||||
|
||||
@@ -41,11 +42,11 @@ class KtTypeReference : KtElementImplStub<KotlinPlaceHolderStub<KtTypeReference>
|
||||
get() = KtStubbedPsiUtil.getStubOrPsiChild(this, KtStubElementTypes.TYPE_ELEMENT_TYPES, KtTypeElement.ARRAY_FACTORY)
|
||||
|
||||
override fun getAnnotations(): List<KtAnnotation> {
|
||||
return getStubOrPsiChildrenAsList(KtStubElementTypes.ANNOTATION)
|
||||
return modifierList?.annotations.orEmpty()
|
||||
}
|
||||
|
||||
override fun getAnnotationEntries(): List<KtAnnotationEntry> {
|
||||
return this.collectAnnotationEntriesFromStubOrPsi()
|
||||
return modifierList?.annotationEntries.orEmpty()
|
||||
}
|
||||
|
||||
fun hasParentheses(): Boolean {
|
||||
|
||||
@@ -28,7 +28,7 @@ object KotlinStubVersions {
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 55
|
||||
private const val BINARY_STUB_VERSION = 56
|
||||
|
||||
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
|
||||
// Increasing this version will lead to reindexing of all classfiles.
|
||||
|
||||
Reference in New Issue
Block a user