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); consumeIf(SEMICOLON);
} }
if (parsePropertyGetterOrSetter()) { AccessorKind accessorKind = parsePropertyGetterOrSetter(null);
parsePropertyGetterOrSetter(); if (accessorKind != null) {
parsePropertyGetterOrSetter(accessorKind);
} }
if (!atSet(EOL_OR_SEMICOLON, RBRACE)) { if (!atSet(EOL_OR_SEMICOLON, RBRACE)) {
if (getLastToken() != SEMICOLON) { if (getLastToken() != SEMICOLON) {
errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE)); errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON, LBRACE, RBRACE));
@@ -1346,6 +1348,8 @@ public class JetParsing extends AbstractJetParsing {
myBuilder.restoreNewlinesState(); myBuilder.restoreNewlinesState();
} }
private enum AccessorKind { GET, SET}
/* /*
* getterOrSetter * getterOrSetter
* : modifiers ("get" | "set") * : modifiers ("get" | "set")
@@ -1356,17 +1360,29 @@ public class JetParsing extends AbstractJetParsing {
* ) functionBody * ) functionBody
* ; * ;
*/ */
private boolean parsePropertyGetterOrSetter() { @Nullable
private AccessorKind parsePropertyGetterOrSetter(@Nullable AccessorKind notAllowedKind) {
PsiBuilder.Marker getterOrSetter = mark(); PsiBuilder.Marker getterOrSetter = mark();
parseModifierList(DEFAULT, TokenSet.EMPTY); 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(); getterOrSetter.rollbackTo();
return false; return null;
}
if (accessorKind == notAllowedKind) {
getterOrSetter.rollbackTo();
return null;
} }
boolean setter = at(SET_KEYWORD);
advance(); // GET_KEYWORD or SET_KEYWORD advance(); // GET_KEYWORD or SET_KEYWORD
if (!at(LPAR)) { if (!at(LPAR)) {
@@ -1377,13 +1393,13 @@ public class JetParsing extends AbstractJetParsing {
} }
else { else {
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false); closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true; return accessorKind;
} }
} }
myBuilder.disableNewlines(); myBuilder.disableNewlines();
expect(LPAR, "Expecting '('", TokenSet.create(RPAR, IDENTIFIER, COLON, LBRACE, EQ)); expect(LPAR, "Expecting '('", TokenSet.create(RPAR, IDENTIFIER, COLON, LBRACE, EQ));
if (setter) { if (accessorKind == AccessorKind.SET) {
PsiBuilder.Marker parameterList = mark(); PsiBuilder.Marker parameterList = mark();
PsiBuilder.Marker setterParameter = mark(); PsiBuilder.Marker setterParameter = mark();
parseModifierList(DEFAULT, TokenSet.create(COMMA, COLON, RPAR)); parseModifierList(DEFAULT, TokenSet.create(COMMA, COLON, RPAR));
@@ -1414,7 +1430,7 @@ public class JetParsing extends AbstractJetParsing {
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false); 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); doParsingTest(fileName);
} }
@TestMetadata("DuplicateAccessor.kt")
public void testDuplicateAccessor() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DuplicateAccessor.kt");
doParsingTest(fileName);
}
@TestMetadata("DynamicReceiver.kt") @TestMetadata("DynamicReceiver.kt")
public void testDynamicReceiver() throws Exception { public void testDynamicReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DynamicReceiver.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DynamicReceiver.kt");
@@ -10,12 +10,6 @@ class Some {
// EXIST: enum class // EXIST: enum class
// EXIST: final // EXIST: final
// EXIST: fun // EXIST: fun
/*TODO*/
// EXIST: get
// EXIST: "get() = "
// EXIST: "get() {}"
// EXIST: inner // EXIST: inner
// EXIST: internal // EXIST: internal
// EXIST: object // EXIST: object