Prohibit unescaped annotations on primary constructor of local class
This commit is contained in:
@@ -35,6 +35,7 @@ import static org.jetbrains.kotlin.JetNodeTypes.*;
|
|||||||
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
||||||
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ALLOW_UNESCAPED_REGULAR_ANNOTATIONS;
|
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ALLOW_UNESCAPED_REGULAR_ANNOTATIONS;
|
||||||
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ONLY_ESCAPED_REGULAR_ANNOTATIONS;
|
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.ONLY_ESCAPED_REGULAR_ANNOTATIONS;
|
||||||
|
import static org.jetbrains.kotlin.parsing.JetParsing.DeclarationParsingMode.LOCAL;
|
||||||
|
|
||||||
public class JetExpressionParsing extends AbstractJetParsing {
|
public class JetExpressionParsing extends AbstractJetParsing {
|
||||||
private static final TokenSet WHEN_CONDITION_RECOVERY_SET = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD);
|
private static final TokenSet WHEN_CONDITION_RECOVERY_SET = TokenSet.create(RBRACE, IN_KEYWORD, NOT_IN, IS_KEYWORD, NOT_IS, ELSE_KEYWORD);
|
||||||
@@ -1376,7 +1377,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
IElementType keywordToken = tt();
|
IElementType keywordToken = tt();
|
||||||
IElementType declType = null;
|
IElementType declType = null;
|
||||||
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
||||||
declType = myJetParsing.parseClass(isEnum);
|
declType = myJetParsing.parseClass(isEnum, LOCAL);
|
||||||
}
|
}
|
||||||
else if (keywordToken == FUN_KEYWORD) {
|
else if (keywordToken == FUN_KEYWORD) {
|
||||||
declType = myJetParsing.parseFunction();
|
declType = myJetParsing.parseFunction();
|
||||||
@@ -1400,7 +1401,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
myJetParsing.parseObject(NameParsingMode.REQUIRED, true);
|
myJetParsing.parseObject(NameParsingMode.REQUIRED, true, LOCAL);
|
||||||
declType = OBJECT_DECLARATION;
|
declType = OBJECT_DECLARATION;
|
||||||
}
|
}
|
||||||
return declType;
|
return declType;
|
||||||
@@ -1934,7 +1935,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
public void parseObjectLiteral() {
|
public void parseObjectLiteral() {
|
||||||
PsiBuilder.Marker literal = mark();
|
PsiBuilder.Marker literal = mark();
|
||||||
PsiBuilder.Marker declaration = mark();
|
PsiBuilder.Marker declaration = mark();
|
||||||
myJetParsing.parseObject(NameParsingMode.PROHIBITED, false); // Body is not optional because of foo(object : A, B)
|
myJetParsing.parseObject(NameParsingMode.PROHIBITED, false, LOCAL); // Body is not optional because of foo(object : A, B)
|
||||||
declaration.done(OBJECT_DECLARATION);
|
declaration.done(OBJECT_DECLARATION);
|
||||||
literal.done(OBJECT_LITERAL);
|
literal.done(OBJECT_LITERAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.Map;
|
|||||||
import static org.jetbrains.kotlin.JetNodeTypes.*;
|
import static org.jetbrains.kotlin.JetNodeTypes.*;
|
||||||
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
import static org.jetbrains.kotlin.lexer.JetTokens.*;
|
||||||
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.*;
|
import static org.jetbrains.kotlin.parsing.JetParsing.AnnotationParsingMode.*;
|
||||||
|
import static org.jetbrains.kotlin.parsing.JetParsing.DeclarationParsingMode.*;
|
||||||
|
|
||||||
public class JetParsing extends AbstractJetParsing {
|
public class JetParsing extends AbstractJetParsing {
|
||||||
private static final Logger LOG = Logger.getInstance(JetParsing.class);
|
private static final Logger LOG = Logger.getInstance(JetParsing.class);
|
||||||
@@ -387,7 +388,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
||||||
declType = parseClass(detector.isEnumDetected());
|
declType = parseClass(detector.isEnumDetected(), TOP_LEVEL);
|
||||||
}
|
}
|
||||||
else if (keywordToken == FUN_KEYWORD) {
|
else if (keywordToken == FUN_KEYWORD) {
|
||||||
declType = parseFunction();
|
declType = parseFunction();
|
||||||
@@ -399,7 +400,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
declType = parseTypeAlias();
|
declType = parseTypeAlias();
|
||||||
}
|
}
|
||||||
else if (keywordToken == OBJECT_KEYWORD) {
|
else if (keywordToken == OBJECT_KEYWORD) {
|
||||||
parseObject(NameParsingMode.REQUIRED, true);
|
parseObject(NameParsingMode.REQUIRED, true, TOP_LEVEL);
|
||||||
declType = OBJECT_DECLARATION;
|
declType = OBJECT_DECLARATION;
|
||||||
}
|
}
|
||||||
else if (at(LBRACE)) {
|
else if (at(LBRACE)) {
|
||||||
@@ -439,7 +440,8 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
boolean empty = true;
|
boolean empty = true;
|
||||||
while (!eof()) {
|
while (!eof()) {
|
||||||
if (annotationParsingMode.atMemberStart && atSet(SOFT_KEYWORDS_AT_MEMBER_START)) break;
|
if (annotationParsingMode.atMemberStart && atSet(SOFT_KEYWORDS_AT_MEMBER_START)) break;
|
||||||
if (annotationParsingMode == PRIMARY_CONSTRUCTOR_MODIFIER_LIST && atSet(CONSTRUCTOR_KEYWORD, WHERE_KEYWORD)) break;
|
if ((annotationParsingMode == PRIMARY_CONSTRUCTOR_MODIFIER_LIST || annotationParsingMode == PRIMARY_CONSTRUCTOR_MODIFIER_LIST_LOCAL) &&
|
||||||
|
atSet(CONSTRUCTOR_KEYWORD, WHERE_KEYWORD)) break;
|
||||||
|
|
||||||
if (at(AT)) {
|
if (at(AT)) {
|
||||||
if (!tryParseModifier(tokenConsumer)) {
|
if (!tryParseModifier(tokenConsumer)) {
|
||||||
@@ -693,6 +695,12 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
PROHIBITED
|
PROHIBITED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum DeclarationParsingMode {
|
||||||
|
TOP_LEVEL,
|
||||||
|
CLASS_MEMBER,
|
||||||
|
LOCAL
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class
|
* class
|
||||||
* : modifiers ("class" | "interface") SimpleName
|
* : modifiers ("class" | "interface") SimpleName
|
||||||
@@ -707,7 +715,13 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
* : "object" SimpleName? ":" delegationSpecifier{","}? classBody?
|
* : "object" SimpleName? ":" delegationSpecifier{","}? classBody?
|
||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
IElementType parseClassOrObject(boolean object, NameParsingMode nameParsingMode, boolean optionalBody, boolean enumClass) {
|
IElementType parseClassOrObject(
|
||||||
|
boolean object,
|
||||||
|
NameParsingMode nameParsingMode,
|
||||||
|
boolean optionalBody,
|
||||||
|
boolean enumClass,
|
||||||
|
DeclarationParsingMode declarationParsingMode
|
||||||
|
) {
|
||||||
if (object) {
|
if (object) {
|
||||||
assert _at(OBJECT_KEYWORD);
|
assert _at(OBJECT_KEYWORD);
|
||||||
}
|
}
|
||||||
@@ -743,7 +757,9 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
OptionalMarker constructorModifiersMarker = new OptionalMarker(object);
|
OptionalMarker constructorModifiersMarker = new OptionalMarker(object);
|
||||||
PsiBuilder.Marker beforeConstructorModifiers = mark();
|
PsiBuilder.Marker beforeConstructorModifiers = mark();
|
||||||
PsiBuilder.Marker primaryConstructorMarker = mark();
|
PsiBuilder.Marker primaryConstructorMarker = mark();
|
||||||
boolean hasConstructorModifiers = parseModifierList(PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
|
boolean hasConstructorModifiers = parseModifierList(
|
||||||
|
declarationParsingMode != LOCAL ? PRIMARY_CONSTRUCTOR_MODIFIER_LIST : PRIMARY_CONSTRUCTOR_MODIFIER_LIST_LOCAL
|
||||||
|
);
|
||||||
|
|
||||||
// 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 ((object && at(CONSTRUCTOR_KEYWORD)) || (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD))) {
|
if ((object && at(CONSTRUCTOR_KEYWORD)) || (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD))) {
|
||||||
@@ -808,12 +824,12 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
return object ? OBJECT_DECLARATION : CLASS;
|
return object ? OBJECT_DECLARATION : CLASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IElementType parseClass(boolean enumClass) {
|
IElementType parseClass(boolean enumClass, DeclarationParsingMode declarationParsingMode) {
|
||||||
return parseClassOrObject(false, NameParsingMode.REQUIRED, true, enumClass);
|
return parseClassOrObject(false, NameParsingMode.REQUIRED, true, enumClass, declarationParsingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseObject(NameParsingMode nameParsingMode, boolean optionalBody) {
|
void parseObject(NameParsingMode nameParsingMode, boolean optionalBody, DeclarationParsingMode declarationParsingMode) {
|
||||||
parseClassOrObject(true, nameParsingMode, optionalBody, false);
|
parseClassOrObject(true, nameParsingMode, optionalBody, false, declarationParsingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1023,7 +1039,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
IElementType keywordToken = tt();
|
IElementType keywordToken = tt();
|
||||||
IElementType declType = null;
|
IElementType declType = null;
|
||||||
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD || keywordToken == INTERFACE_KEYWORD) {
|
||||||
declType = parseClass(isEnum);
|
declType = parseClass(isEnum, CLASS_MEMBER);
|
||||||
}
|
}
|
||||||
else if (keywordToken == FUN_KEYWORD) {
|
else if (keywordToken == FUN_KEYWORD) {
|
||||||
declType = parseFunction();
|
declType = parseFunction();
|
||||||
@@ -1035,7 +1051,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
declType = parseTypeAlias();
|
declType = parseTypeAlias();
|
||||||
}
|
}
|
||||||
else if (keywordToken == OBJECT_KEYWORD) {
|
else if (keywordToken == OBJECT_KEYWORD) {
|
||||||
parseObject(isDefault ? NameParsingMode.ALLOWED : NameParsingMode.REQUIRED, true);
|
parseObject(isDefault ? NameParsingMode.ALLOWED : NameParsingMode.REQUIRED, true, CLASS_MEMBER);
|
||||||
declType = OBJECT_DECLARATION;
|
declType = OBJECT_DECLARATION;
|
||||||
}
|
}
|
||||||
else if (at(INIT_KEYWORD)) {
|
else if (at(INIT_KEYWORD)) {
|
||||||
@@ -2313,7 +2329,8 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
ONLY_ESCAPED_REGULAR_ANNOTATIONS(false, false, false),
|
ONLY_ESCAPED_REGULAR_ANNOTATIONS(false, false, false),
|
||||||
ALLOW_UNESCAPED_REGULAR_ANNOTATIONS(true, false, false),
|
ALLOW_UNESCAPED_REGULAR_ANNOTATIONS(true, false, false),
|
||||||
ALLOW_UNESCAPED_REGULAR_ANNOTATIONS_AT_MEMBER_MODIFIER_LIST(true, false, true),
|
ALLOW_UNESCAPED_REGULAR_ANNOTATIONS_AT_MEMBER_MODIFIER_LIST(true, false, true),
|
||||||
PRIMARY_CONSTRUCTOR_MODIFIER_LIST(true, false, false);
|
PRIMARY_CONSTRUCTOR_MODIFIER_LIST(true, false, false),
|
||||||
|
PRIMARY_CONSTRUCTOR_MODIFIER_LIST_LOCAL(false, false, false);
|
||||||
|
|
||||||
boolean allowShortAnnotations;
|
boolean allowShortAnnotations;
|
||||||
boolean isFileAnnotationParsingMode;
|
boolean isFileAnnotationParsingMode;
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
fun foo() {
|
fun foo() {
|
||||||
class A1 constructor()
|
class A1 constructor()
|
||||||
class A2 Ann private constructor()
|
class A2 Ann private constructor()
|
||||||
|
|
||||||
|
class A3 private @Ann("") constructor()
|
||||||
|
class A4 @Ann("") constructor()
|
||||||
|
|
||||||
|
class A5
|
||||||
|
Ann
|
||||||
|
constructor()
|
||||||
|
|
||||||
|
class A6
|
||||||
|
Ann("")
|
||||||
|
constructor()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,21 +27,108 @@ JetFile: local.kt
|
|||||||
PsiElement(class)('class')
|
PsiElement(class)('class')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(IDENTIFIER)('A2')
|
PsiElement(IDENTIFIER)('A2')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||||
|
PsiElement(IDENTIFIER)('Ann')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('private')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('constructor')
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
CLASS
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('A3')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PRIMARY_CONSTRUCTOR
|
PRIMARY_CONSTRUCTOR
|
||||||
MODIFIER_LIST
|
MODIFIER_LIST
|
||||||
|
PsiElement(private)('private')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
ANNOTATION_ENTRY
|
ANNOTATION_ENTRY
|
||||||
|
PsiElement(AT)('@')
|
||||||
CONSTRUCTOR_CALLEE
|
CONSTRUCTOR_CALLEE
|
||||||
TYPE_REFERENCE
|
TYPE_REFERENCE
|
||||||
USER_TYPE
|
USER_TYPE
|
||||||
REFERENCE_EXPRESSION
|
REFERENCE_EXPRESSION
|
||||||
PsiElement(IDENTIFIER)('Ann')
|
PsiElement(IDENTIFIER)('Ann')
|
||||||
PsiWhiteSpace(' ')
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(private)('private')
|
PsiElement(LPAR)('(')
|
||||||
|
VALUE_ARGUMENT
|
||||||
|
STRING_TEMPLATE
|
||||||
|
PsiElement(OPEN_QUOTE)('"')
|
||||||
|
PsiElement(CLOSING_QUOTE)('"')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(constructor)('constructor')
|
PsiElement(constructor)('constructor')
|
||||||
VALUE_PARAMETER_LIST
|
VALUE_PARAMETER_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
PsiElement(RPAR)(')')
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CLASS
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('A4')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PRIMARY_CONSTRUCTOR
|
||||||
|
MODIFIER_LIST
|
||||||
|
ANNOTATION_ENTRY
|
||||||
|
PsiElement(AT)('@')
|
||||||
|
CONSTRUCTOR_CALLEE
|
||||||
|
TYPE_REFERENCE
|
||||||
|
USER_TYPE
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('Ann')
|
||||||
|
VALUE_ARGUMENT_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
VALUE_ARGUMENT
|
||||||
|
STRING_TEMPLATE
|
||||||
|
PsiElement(OPEN_QUOTE)('"')
|
||||||
|
PsiElement(CLOSING_QUOTE)('"')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(constructor)('constructor')
|
||||||
|
VALUE_PARAMETER_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
CLASS
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('A5')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('Ann')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CALL_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('constructor')
|
||||||
|
VALUE_ARGUMENT_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace('\n\n ')
|
||||||
|
CLASS
|
||||||
|
PsiElement(class)('class')
|
||||||
|
PsiWhiteSpace(' ')
|
||||||
|
PsiElement(IDENTIFIER)('A6')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CALL_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('Ann')
|
||||||
|
VALUE_ARGUMENT_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
VALUE_ARGUMENT
|
||||||
|
STRING_TEMPLATE
|
||||||
|
PsiElement(OPEN_QUOTE)('"')
|
||||||
|
PsiElement(CLOSING_QUOTE)('"')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
|
PsiWhiteSpace('\n ')
|
||||||
|
CALL_EXPRESSION
|
||||||
|
REFERENCE_EXPRESSION
|
||||||
|
PsiElement(IDENTIFIER)('constructor')
|
||||||
|
VALUE_ARGUMENT_LIST
|
||||||
|
PsiElement(LPAR)('(')
|
||||||
|
PsiElement(RPAR)(')')
|
||||||
PsiWhiteSpace('\n')
|
PsiWhiteSpace('\n')
|
||||||
PsiElement(RBRACE)('}')
|
PsiElement(RBRACE)('}')
|
||||||
Reference in New Issue
Block a user