Parse delegated property

This commit is contained in:
Natalia.Ukhorskaya
2013-04-26 10:36:54 +04:00
parent e72b177adc
commit 29984efe76
30 changed files with 501 additions and 7 deletions
@@ -45,6 +45,7 @@ public interface JetNodeTypes {
JetNodeType DELEGATOR_BY = new JetNodeType("DELEGATOR_BY", JetDelegatorByExpressionSpecifier.class);
JetNodeType DELEGATOR_SUPER_CALL = new JetNodeType("DELEGATOR_SUPER_CALL", JetDelegatorToSuperCall.class);
JetNodeType DELEGATOR_SUPER_CLASS = new JetNodeType("DELEGATOR_SUPER_CLASS", JetDelegatorToSuperClass.class);
JetNodeType PROPERTY_DELEGATE = new JetNodeType("PROPERTY_DELEGATE", JetPropertyDelegate.class);
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
IElementType VALUE_PARAMETER_LIST = JetStubElementTypes.VALUE_PARAMETER_LIST;
IElementType VALUE_PARAMETER = JetStubElementTypes.VALUE_PARAMETER;
@@ -819,7 +819,7 @@ public class JetParsing extends AbstractJetParsing {
* typeParameters? (type "." | annotations)?
* ("(" variableDeclarationEntry{","} ")" | variableDeclarationEntry)
* typeConstraints
* ("=" element SEMI?)?
* ("by" | "=" expression SEMI?)?
* (getter? setter? | setter? getter?) SEMI?
* ;
*/
@@ -887,14 +887,21 @@ public class JetParsing extends AbstractJetParsing {
parseTypeConstraintsGuarded(typeParametersDeclared);
if (local) {
if (at(EQ)) {
if (at(BY_KEYWORD)) {
parsePropertyDelegate();
}
else if (at(EQ)) {
advance(); // EQ
myExpressionParsing.parseExpression();
// "val a = 1; b" must not be an infix call of b on "val ...;"
}
}
else {
if (at(EQ)) {
if (at(BY_KEYWORD)) {
parsePropertyDelegate();
consumeIf(SEMICOLON);
}
else if (at(EQ)) {
advance(); // EQ
myExpressionParsing.parseExpression();
consumeIf(SEMICOLON);
@@ -903,7 +910,7 @@ public class JetParsing extends AbstractJetParsing {
if (parsePropertyGetterOrSetter()) {
parsePropertyGetterOrSetter();
}
if (!atSet(EOL_OR_SEMICOLON, RBRACE)) {
if (!atSet(EOL_OR_SEMICOLON, RBRACE)) {
if (getLastToken() != SEMICOLON) {
errorUntil("Property getter or setter expected", TokenSet.create(EOL_OR_SEMICOLON));
}
@@ -916,6 +923,19 @@ public class JetParsing extends AbstractJetParsing {
return multiDeclaration ? MULTI_VARIABLE_DECLARATION : PROPERTY;
}
/*
* propertyDelegate
* : "by" expression
* ;
*/
private void parsePropertyDelegate() {
assert _at(BY_KEYWORD);
PsiBuilder.Marker delegate = mark();
advance(); // BY_KEYWORD
myExpressionParsing.parseExpression();
delegate.done(PROPERTY_DELEGATE);
}
/*
* (SimpleName (":" type)){","}
*/
@@ -1456,7 +1476,7 @@ public class JetParsing extends AbstractJetParsing {
receiverType.done(FUNCTION_TYPE_RECEIVER);
advance(); // DOT
if (at(LPAR)) {
parseFunctionTypeContents().drop();
}
@@ -1707,7 +1727,7 @@ public class JetParsing extends AbstractJetParsing {
}
}
}
expect(RPAR, "Expecting ')'", recoverySet);
myBuilder.restoreNewlinesState();
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.JetNodeTypes.PROPERTY_ACCESSOR;
import static org.jetbrains.jet.JetNodeTypes.PROPERTY_DELEGATE;
import static org.jetbrains.jet.lexer.JetTokens.*;
public class JetProperty extends JetTypeParameterListOwnerStub<PsiJetPropertyStub> implements JetVariableDeclaration {
@@ -155,12 +156,35 @@ public class JetProperty extends JetTypeParameterListOwnerStub<PsiJetPropertyStu
return null;
}
@Nullable
public JetPropertyDelegate getDelegate() {
return (JetPropertyDelegate) findChildByType(PROPERTY_DELEGATE);
}
@Nullable
public JetExpression getDelegateExpression() {
JetPropertyDelegate delegate = getDelegate();
if (delegate != null) {
return delegate.getExpression();
}
return null;
}
@Override
@Nullable
public JetExpression getInitializer() {
return PsiTreeUtil.getNextSiblingOfType(findChildByType(EQ), JetExpression.class);
}
@Nullable
public JetExpression getDelegateExpressionOrInitializer() {
JetExpression expression = getDelegateExpression();
if (expression == null) {
return getInitializer();
}
return expression;
}
@Override
@NotNull
public ASTNode getValOrVarNode() {
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JetPropertyDelegate extends JetElementImpl {
public JetPropertyDelegate(@NotNull ASTNode node) {
super(node);
}
@Nullable
public JetExpression getExpression() {
return findChildByClass(JetExpression.class);
}
@Override
public void accept(@NotNull JetVisitorVoid visitor) {
visitor.visitPropertyDelegate(this);
}
@Override
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitPropertyDelegate(this, data);
}
}
@@ -129,6 +129,10 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitDelegationSpecifier(thisCall, data);
}
public R visitPropertyDelegate(JetPropertyDelegate delegate, D data) {
return visitJetElement(delegate, data);
}
public R visitTypeReference(JetTypeReference typeReference, D data) {
return visitJetElement(typeReference, data);
}
@@ -119,6 +119,10 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitDelegationSpecifier(thisCall);
}
public void visitPropertyDelegate(JetPropertyDelegate delegate) {
visitJetElement(delegate);
}
public void visitTypeReference(JetTypeReference typeReference) {
visitJetElement(typeReference);
}
@@ -0,0 +1 @@
val a by A {}
@@ -0,0 +1,21 @@
JetFile: BracketsInDelegate.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiWhiteSpace(' ')
FUNCTION_LITERAL_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
BLOCK
<empty list>
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
val a: Int = 1 by A()
val b: Int = 1 by A()
val c: Int by A(); = 3
@@ -0,0 +1,84 @@
JetFile: DelegateAndInitializer.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('b')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('c')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting package directive or top level declaration
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting package directive or top level declaration
PsiElement(INTEGER_LITERAL)('3')
@@ -0,0 +1 @@
val a by A(); get() = 1;
@@ -0,0 +1,29 @@
JetFile: GetterInSameLine.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace(' ')
PROPERTY_ACCESSOR
PsiElement(get)('get')
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(SEMICOLON)(';')
@@ -0,0 +1,5 @@
class B {
fun foo() {
val p: Int by A()
}
}
@@ -0,0 +1,48 @@
JetFile: LocalProperty.kt
NAMESPACE_HEADER
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
val a by
val b = 1
@@ -0,0 +1,22 @@
JetFile: OnlyBy.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiErrorElement:Expecting an expression
<empty list>
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
@@ -0,0 +1,3 @@
class B {
val p: Int by A()
}
@@ -0,0 +1,35 @@
JetFile: PropertyInClass.kt
NAMESPACE_HEADER
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
TYPE_PARAMETER_LIST
<empty list>
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,2 @@
val p: Int by A()
get() = 1
@@ -0,0 +1,33 @@
JetFile: PropertyWithGetter.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR
PsiElement(get)('get')
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
@@ -0,0 +1 @@
val p: Int by A() = 1
@@ -0,0 +1,30 @@
JetFile: PropertyWithInitializer.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
@@ -0,0 +1 @@
val p by A()
@@ -0,0 +1,17 @@
JetFile: PropertyWithoutTypeRef.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
@@ -0,0 +1 @@
val p: Int by A()
@@ -0,0 +1,23 @@
JetFile: TopLevelProperty.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
@@ -0,0 +1 @@
val a by A(); val b by A();
@@ -0,0 +1,34 @@
JetFile: TwoProperties.kt
NAMESPACE_HEADER
<empty list>
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace(' ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
@@ -138,6 +138,7 @@ public class JetParsingTest extends ParsingTestCase {
suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "greatSyntacticShift", true, factory));
suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "script", true, factory));
suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "recovery", true, factory));
suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "propertyDelegate", true, factory));
return suite;
}
+1 -1
View File
@@ -93,7 +93,7 @@ property
typeParameters? (type "." | annotations)?
(multipleVariableDeclarations | variableDeclarationEntry)
typeConstraints
("=" expression SEMI?)?
("by" | "=" expression SEMI?)?
(getter? setter? | setter? getter?) SEMI?
;