No duplicate property accessor should be allowed

This commit is contained in:
Valentin Kipyatkov
2015-10-21 19:23:17 +03:00
parent 6eba45febd
commit 74f2d60e19
5 changed files with 73 additions and 15 deletions
@@ -1277,9 +1277,11 @@ public class JetParsing extends AbstractJetParsing {
consumeIf(SEMICOLON);
}
if (parsePropertyGetterOrSetter()) {
parsePropertyGetterOrSetter();
AccessorKind accessorKind = parsePropertyGetterOrSetter(null);
if (accessorKind != null) {
parsePropertyGetterOrSetter(accessorKind);
}
if (!atSet(EOL_OR_SEMICOLON, RBRACE)) {
if (getLastToken() != SEMICOLON) {
errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE));
@@ -1346,6 +1348,8 @@ public class JetParsing extends AbstractJetParsing {
myBuilder.restoreNewlinesState();
}
private enum AccessorKind { GET, SET}
/*
* getterOrSetter
* : modifiers ("get" | "set")
@@ -1356,17 +1360,29 @@ public class JetParsing extends AbstractJetParsing {
* ) functionBody
* ;
*/
private boolean parsePropertyGetterOrSetter() {
@Nullable
private AccessorKind parsePropertyGetterOrSetter(@Nullable AccessorKind notAllowedKind) {
PsiBuilder.Marker getterOrSetter = mark();
parseModifierList(DEFAULT, TokenSet.EMPTY);
if (!at(GET_KEYWORD) && !at(SET_KEYWORD)) {
AccessorKind accessorKind;
if (at(GET_KEYWORD)) {
accessorKind = AccessorKind.GET;
}
else if (at(SET_KEYWORD)) {
accessorKind = AccessorKind.SET;
}
else {
getterOrSetter.rollbackTo();
return false;
return null;
}
if (accessorKind == notAllowedKind) {
getterOrSetter.rollbackTo();
return null;
}
boolean setter = at(SET_KEYWORD);
advance(); // GET_KEYWORD or SET_KEYWORD
if (!at(LPAR)) {
@@ -1377,13 +1393,13 @@ public class JetParsing extends AbstractJetParsing {
}
else {
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true;
return accessorKind;
}
}
myBuilder.disableNewlines();
expect(LPAR, "Expecting '('", TokenSet.create(RPAR, IDENTIFIER, COLON, LBRACE, EQ));
if (setter) {
if (accessorKind == AccessorKind.SET) {
PsiBuilder.Marker parameterList = mark();
PsiBuilder.Marker setterParameter = mark();
parseModifierList(DEFAULT, TokenSet.create(COMMA, COLON, RPAR));
@@ -1414,7 +1430,7 @@ public class JetParsing extends AbstractJetParsing {
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true;
return accessorKind;
}
/*
+3
View File
@@ -0,0 +1,3 @@
val a : Int
get() = 0
get() = 0
+39
View File
@@ -0,0 +1,39 @@
JetFile: DuplicateAccessor.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR
PsiElement(get)('get')
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiWhiteSpace('\n ')
PsiErrorElement:Expecting a top level declaration
PsiElement(get)('get')
PsiErrorElement:Expecting a top level declaration
PsiElement(LPAR)('(')
PsiErrorElement:Expecting a top level declaration
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting a top level declaration
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting a top level declaration
PsiElement(INTEGER_LITERAL)('0')
@@ -169,6 +169,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("DuplicateAccessor.kt")
public void testDuplicateAccessor() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DuplicateAccessor.kt");
doParsingTest(fileName);
}
@TestMetadata("DynamicReceiver.kt")
public void testDynamicReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DynamicReceiver.kt");
@@ -10,12 +10,6 @@ class Some {
// EXIST: enum class
// EXIST: final
// EXIST: fun
/*TODO*/
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner
// EXIST: internal
// EXIST: object