From 86e40073c59d4d9215be9ffe113d8f4fba869f6a Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 17 Aug 2012 15:00:17 +0400 Subject: [PATCH] KT-2625 Parse multiple assignment to variables New PSI element types introduced. Parsing procedure for properties reused. Extra syntactic elements (receiver, type) are prohibited in the parser #KT-2625 Fixed --- .../src/org/jetbrains/jet/JetNodeTypes.java | 2 + .../jet/lang/parsing/AbstractJetParsing.java | 9 + .../jet/lang/parsing/JetParsing.java | 73 ++- .../jet/lang/psi/JetMultiDeclaration.java | 56 ++ .../lang/psi/JetMultiDeclarationEntry.java | 39 ++ .../jetbrains/jet/lang/psi/JetProperty.java | 4 +- .../jet/lang/psi/JetVariableDeclaration.java | 14 + .../psi/MultiVariableDeclarations.jet | 37 ++ .../psi/MultiVariableDeclarations.txt | 619 ++++++++++++++++++ grammar/src/class_members.grm | 3 +- 10 files changed, 838 insertions(+), 18 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclaration.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVariableDeclaration.java create mode 100644 compiler/testData/psi/MultiVariableDeclarations.jet create mode 100644 compiler/testData/psi/MultiVariableDeclarations.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java b/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java index 44031edd153..6e09267c53b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java +++ b/compiler/frontend/src/org/jetbrains/jet/JetNodeTypes.java @@ -31,6 +31,8 @@ public interface JetNodeTypes { IElementType CLASS = JetStubElementTypes.CLASS; IElementType FUN = JetStubElementTypes.FUNCTION; IElementType PROPERTY = JetStubElementTypes.PROPERTY; + IElementType MULTI_VARIABLE_DECLARATION = new JetNodeType("MULTI_VARIABLE_DECLARATION", JetMultiDeclaration.class); + IElementType MULTI_VARIABLE_DECLARATION_ENTRY = new JetNodeType("MULTI_VARIABLE_DECLARATION_ENTRY", JetMultiDeclarationEntry.class); JetNodeType TYPEDEF = new JetNodeType("TYPEDEF", JetTypedef.class); IElementType OBJECT_DECLARATION = JetStubElementTypes.OBJECT_DECLARATION; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java index 6528d205818..db1a1d5fefc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java @@ -260,6 +260,15 @@ import static org.jetbrains.jet.lexer.JetTokens.*; error.error(mesage); } + protected static void errorIf(PsiBuilder.Marker marker, boolean condition, String message) { + if (condition) { + marker.error(message); + } + else { + marker.drop(); + } + } + protected int matchTokenStreamPredicate(TokenStreamPattern pattern) { PsiBuilder.Marker currentPosition = mark(); Stack opens = new Stack(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index e58e5988c05..0ff1e8914f6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -802,7 +802,7 @@ public class JetParsing extends AbstractJetParsing { * property * : modifiers ("val" | "var") * typeParameters? (type "." | attributes)? - * SimpleName (":" type)? + * (SimpleName (":" type)?){","} * typeConstraints * ("=" element SEMI?)? * (getter? setter? | setter? getter?) SEMI? @@ -841,16 +841,32 @@ public class JetParsing extends AbstractJetParsing { } })); + PsiBuilder.Marker receiver = mark(); parseReceiverType("property", propertyNameFollow, lastDot); - parseFunctionOrPropertyName(lastDot != -1, "property", propertyNameFollow); + + boolean multiDeclaration = at(LPAR); + boolean receiverTypeDeclared = lastDot != -1; + + errorIf(receiver, multiDeclaration && receiverTypeDeclared, "Receiver type is not allowed on a multi-declaration"); + + if (multiDeclaration) { + PsiBuilder.Marker multiDecl = mark(); + parseMultiDeclarationName(propertyNameFollow); + errorIf(multiDecl, !local, "Multi-declarations are only allowed for local variables/values"); + } + else { + parseFunctionOrPropertyName(receiverTypeDeclared, "property", propertyNameFollow); + } myBuilder.restoreJoiningComplexTokensState(); if (at(COLON)) { + PsiBuilder.Marker type = mark(); advance(); // COLON if (!parseIdeTemplate()) { parseTypeRef(); } + errorIf(type, multiDeclaration, "Type annotations are not allowed on multi-declarations"); } parseTypeConstraintsGuarded(typeParametersDeclared); @@ -882,8 +898,44 @@ public class JetParsing extends AbstractJetParsing { } } + return multiDeclaration ? MULTI_VARIABLE_DECLARATION : PROPERTY; + } - return PROPERTY; + /* + * (SimpleName (":" type)){","} + */ + private void parseMultiDeclarationName(TokenSet propertyNameFollow) { + // Parsing multi-name, e.g. + // val (a, b) = foo() + myBuilder.disableNewlines(); + advance(); // LPAR + + TokenSet recoverySet = TokenSet.orSet(PARAMETER_NAME_RECOVERY_SET, propertyNameFollow); + if (!atSet(propertyNameFollow)) { + while (true) { + if (at(COMMA)) { + errorAndAdvance("Expecting a name"); + } + else if (at(RPAR)) { + error("Expecting a name"); + break; + } + PsiBuilder.Marker property = mark(); + expect(IDENTIFIER, "Expecting a name", recoverySet); + + if (at(COLON)) { + advance(); // COLON + parseTypeRef(); + } + property.done(MULTI_VARIABLE_DECLARATION_ENTRY); + + if (!at(COMMA)) break; + advance(); // COMMA + } + } + + expect(RPAR, "Expecting ')'", propertyNameFollow); + myBuilder.restoreNewlinesState(); } /* @@ -996,12 +1048,7 @@ public class JetParsing extends AbstractJetParsing { if (at(LT)) { PsiBuilder.Marker error = mark(); parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow)); - if (typeParameterListOccurred) { - error.error("Only one type parameter list is allowed for a function"); // TODO : discuss - } - else { - error.drop(); - } + errorIf(error, typeParameterListOccurred, "Only one type parameter list is allowed for a function"); typeParameterListOccurred = true; } @@ -1028,7 +1075,6 @@ public class JetParsing extends AbstractJetParsing { } /* - * : * (type "." | attributes)? */ private void parseReceiverType(String title, TokenSet nameFollow, int lastDot) { @@ -1201,12 +1247,7 @@ public class JetParsing extends AbstractJetParsing { private void parseTypeConstraintsGuarded(boolean typeParameterListOccurred) { PsiBuilder.Marker error = mark(); boolean constraints = parseTypeConstraints(); - if (constraints && !typeParameterListOccurred) { - error.error("Type constraints are not allowed when no type parameters declared"); - } - else { - error.drop(); - } + errorIf(error, constraints && !typeParameterListOccurred, "Type constraints are not allowed when no type parameters declared"); } private boolean parseTypeConstraints() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclaration.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclaration.java new file mode 100644 index 00000000000..f00d9ddadb0 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclaration.java @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2012 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 com.intellij.psi.tree.TokenSet; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lexer.JetTokens; + +import static org.jetbrains.jet.lexer.JetTokens.EQ; +import static org.jetbrains.jet.lexer.JetTokens.VAL_KEYWORD; +import static org.jetbrains.jet.lexer.JetTokens.VAR_KEYWORD; + +/** + * @author abreslav + */ +public class JetMultiDeclaration extends JetDeclarationImpl implements JetVariableDeclaration { + public JetMultiDeclaration(@NotNull ASTNode node) { + super(node); + } + + @Override + public boolean isVar() { + return getNode().findChildByType(JetTokens.VAR_KEYWORD) != null; + } + + @Nullable + @Override + public JetExpression getInitializer() { + return PsiTreeUtil.getNextSiblingOfType(findChildByType(EQ), JetExpression.class); + } + + @NotNull + @Override + public ASTNode getValOrVarNode() { + ASTNode node = getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD)); + assert node != null : "Val or var should always exist for property"; + return node; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java new file mode 100644 index 00000000000..8c260f2dc18 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2012 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; +import org.jetbrains.jet.JetNodeTypes; + +/** + * @author abreslav + */ +public class JetMultiDeclarationEntry extends JetNamedDeclarationNotStubbed { + public JetMultiDeclarationEntry(@NotNull ASTNode node) { + super(node); + } + + @Nullable + public JetTypeReference getTypeRef() { + return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); + } + + + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java index e89ffdb050d..a6077f002d1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java @@ -39,7 +39,7 @@ import static org.jetbrains.jet.lexer.JetTokens.*; /** * @author max */ -public class JetProperty extends JetTypeParameterListOwnerStub implements JetWithExpressionInitializer { +public class JetProperty extends JetTypeParameterListOwnerStub implements JetVariableDeclaration { public JetProperty(@NotNull ASTNode node) { super(node); } @@ -64,6 +64,7 @@ public class JetProperty extends JetTypeParameterListOwnerStub + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiErrorElement:Expecting a name + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiErrorElement:Expecting a name + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(COMMA)(',') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiErrorElement:Expecting a name + + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiErrorElement:Expecting ')' + + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiErrorElement:Expecting a name + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Receiver type is not allowed on a multi-declaration + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiElement(DOT)('.') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiErrorElement:Type annotations are not allowed on multi-declarations + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Receiver type is not allowed on a multi-declaration + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiElement(DOT)('.') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiErrorElement:Type annotations are not allowed on multi-declarations + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Receiver type is not allowed on a multi-declaration + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(DOT)('.') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiErrorElement:Type annotations are not allowed on multi-declarations + PsiElement(COLON)(':') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('X') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Receiver type is not allowed on a multi-declaration + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(DOT)('.') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n ') + MULTI_VARIABLE_DECLARATION + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiErrorElement:Multi-declarations are only allowed for local variables/values + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiErrorElement:Type annotations are not allowed on multi-declarations + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/grammar/src/class_members.grm b/grammar/src/class_members.grm index 535cbfd31ef..580cb06d1cf 100644 --- a/grammar/src/class_members.grm +++ b/grammar/src/class_members.grm @@ -84,11 +84,12 @@ functionBody property : modifiers ("val" | "var") typeParameters? (type "." | annotations)? - SimpleName (":" type)? + (SimpleName (":" type)?){","} typeConstraints ("=" expression SEMI?)? (getter? setter? | setter? getter?) SEMI? ; + /** bq. See [Properties and Fields] */