Parse collection literals as atomic expressions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 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.
|
||||
@@ -201,6 +201,8 @@ public interface KtNodeTypes {
|
||||
KtNodeType WHEN_CONDITION_IS_PATTERN = new KtNodeType("WHEN_CONDITION_IS_PATTERN", KtWhenConditionIsPattern.class);
|
||||
KtNodeType WHEN_CONDITION_EXPRESSION = new KtNodeType("WHEN_CONDITION_WITH_EXPRESSION", KtWhenConditionWithExpression.class);
|
||||
|
||||
KtNodeType COLLECTION_LITERAL_EXPRESSION = new KtNodeType("COLLECTION_LITERAL_EXPRESSION", KtCollectionLiteralExpression.class);
|
||||
|
||||
IElementType PACKAGE_DIRECTIVE = KtStubElementTypes.PACKAGE_DIRECTIVE;
|
||||
|
||||
IElementType SCRIPT = KtStubElementTypes.SCRIPT;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 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.
|
||||
@@ -111,7 +111,9 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
|
||||
IDENTIFIER, // SimpleName
|
||||
|
||||
AT // Just for better recovery and maybe for annotations
|
||||
AT, // Just for better recovery and maybe for annotations
|
||||
|
||||
LBRACKET // Collection literal expression
|
||||
);
|
||||
|
||||
private static final TokenSet STATEMENT_FIRST = TokenSet.orSet(
|
||||
@@ -613,6 +615,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* : functionLiteral
|
||||
* : declaration
|
||||
* : SimpleName
|
||||
* : collectionLiteral
|
||||
* ;
|
||||
*/
|
||||
private boolean parseAtomicExpression() {
|
||||
@@ -621,6 +624,9 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
if (at(LPAR)) {
|
||||
parseParenthesizedExpression();
|
||||
}
|
||||
else if (at(LBRACKET)) {
|
||||
parseCollectionLiteralExpression();
|
||||
}
|
||||
else if (at(THIS_KEYWORD)) {
|
||||
parseThisExpression();
|
||||
}
|
||||
@@ -987,28 +993,59 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* ;
|
||||
*/
|
||||
private void parseArrayAccess() {
|
||||
parseAsCollectionLiteralExpression(INDICES, false, "Expecting an index element");
|
||||
}
|
||||
|
||||
/*
|
||||
* collectionLiteral
|
||||
* : "[" element{","}? "]"
|
||||
* ;
|
||||
*/
|
||||
private void parseCollectionLiteralExpression() {
|
||||
parseAsCollectionLiteralExpression(COLLECTION_LITERAL_EXPRESSION, true, "Expecting an element");
|
||||
}
|
||||
|
||||
private void parseAsCollectionLiteralExpression(KtNodeType nodeType, boolean canBeEmpty, String missingElementErrorMessage) {
|
||||
assert _at(LBRACKET);
|
||||
|
||||
PsiBuilder.Marker indices = mark();
|
||||
PsiBuilder.Marker innerExpressions = mark();
|
||||
|
||||
myBuilder.disableNewlines();
|
||||
advance(); // LBRACKET
|
||||
|
||||
while (true) {
|
||||
if (at(COMMA)) errorAndAdvance("Expecting an index element");
|
||||
if (at(RBRACKET)) {
|
||||
error("Expecting an index element");
|
||||
break;
|
||||
}
|
||||
parseExpression();
|
||||
if (!at(COMMA)) break;
|
||||
advance(); // COMMA
|
||||
if (!canBeEmpty && at(RBRACKET)) {
|
||||
error(missingElementErrorMessage);
|
||||
}
|
||||
else {
|
||||
parseInnerExpressions(missingElementErrorMessage);
|
||||
}
|
||||
|
||||
expect(RBRACKET, "Expecting ']'");
|
||||
myBuilder.restoreNewlinesState();
|
||||
|
||||
indices.done(INDICES);
|
||||
innerExpressions.done(nodeType);
|
||||
}
|
||||
|
||||
private void parseInnerExpressions(String missingElementErrorMessage) {
|
||||
boolean firstElement = true;
|
||||
while (true) {
|
||||
if (at(COMMA)) errorAndAdvance(missingElementErrorMessage);
|
||||
if (at(RBRACKET)) {
|
||||
if (firstElement) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
error(missingElementErrorMessage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
parseExpression();
|
||||
|
||||
firstElement = false;
|
||||
|
||||
if (!at(COMMA)) break;
|
||||
advance(); // COMMA
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.kotlin.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
class KtCollectionLiteralExpression(node: ASTNode) : KtExpressionImpl(node)
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
fun test() {
|
||||
[]
|
||||
[1]
|
||||
[1, 2]
|
||||
[[]]
|
||||
[[1]]
|
||||
[1, []]
|
||||
[[], 1]
|
||||
[[], [1, []]]
|
||||
[1,
|
||||
2]
|
||||
[1,
|
||||
[2]]
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
JetFile: CollectionLiterals.kt
|
||||
PACKAGE_DIRECTIVE
|
||||
<empty list>
|
||||
IMPORT_LIST
|
||||
<empty list>
|
||||
FUN
|
||||
PsiElement(fun)('fun')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(IDENTIFIER)('test')
|
||||
VALUE_PARAMETER_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
BLOCK
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(RBRACE)('}')
|
||||
@@ -0,0 +1,8 @@
|
||||
fun test() {
|
||||
[,]
|
||||
[1, ]
|
||||
[, 1]
|
||||
[1, 2 3]
|
||||
[1, 2 3, ]
|
||||
[
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
JetFile: CollectionLiterals_ERR.kt
|
||||
PACKAGE_DIRECTIVE
|
||||
<empty list>
|
||||
IMPORT_LIST
|
||||
<empty list>
|
||||
FUN
|
||||
PsiElement(fun)('fun')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(IDENTIFIER)('test')
|
||||
VALUE_PARAMETER_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
BLOCK
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiErrorElement:Expecting an element
|
||||
PsiElement(COMMA)(',')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiErrorElement:Expecting an element
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiErrorElement:Expecting an element
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiErrorElement:Expecting ']'
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
PsiElement(INTEGER_LITERAL)('3')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('2')
|
||||
PsiErrorElement:Expecting ']'
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
PsiElement(INTEGER_LITERAL)('3')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace('\n ')
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
PsiErrorElement:Expecting an expression
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(RBRACE)('}')
|
||||
+32
-31
@@ -35,49 +35,50 @@ JetFile: oldAnnotationsRecovery.kt
|
||||
BLOCK
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiErrorElement:Expecting an element
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('inline')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('inline')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
FUN
|
||||
PsiElement(fun)('fun')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(IDENTIFIER)('bar')
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
LAMBDA_EXPRESSION
|
||||
FUNCTION_LITERAL
|
||||
VALUE_PARAMETER_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
BLOCK
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
BLOCK
|
||||
RETURN
|
||||
PsiElement(return)('return')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
RETURN
|
||||
PsiElement(return)('return')
|
||||
PsiWhiteSpace(' ')
|
||||
INTEGER_CONSTANT
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(RBRACE)('}')
|
||||
PsiWhiteSpace('\n\n ')
|
||||
PsiErrorElement:Expecting an element
|
||||
COLLECTION_LITERAL_EXPRESSION
|
||||
PsiElement(LBRACKET)('[')
|
||||
CALL_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('suppress')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
STRING_TEMPLATE
|
||||
PsiElement(OPEN_QUOTE)('"')
|
||||
LITERAL_STRING_TEMPLATE_ENTRY
|
||||
PsiElement(REGULAR_STRING_PART)('1')
|
||||
PsiElement(CLOSING_QUOTE)('"')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
CALL_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('suppress')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
VALUE_ARGUMENT
|
||||
STRING_TEMPLATE
|
||||
PsiElement(OPEN_QUOTE)('"')
|
||||
LITERAL_STRING_TEMPLATE_ENTRY
|
||||
PsiElement(REGULAR_STRING_PART)('1')
|
||||
PsiElement(CLOSING_QUOTE)('"')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiElement(RBRACKET)(']')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
PsiElement(PLUS)('+')
|
||||
PsiElement(INTEGER_LITERAL)('1')
|
||||
|
||||
@@ -122,6 +122,18 @@ public class ParsingTestGenerated extends AbstractParsingTest {
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("CollectionLiterals.kt")
|
||||
public void testCollectionLiterals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/CollectionLiterals.kt");
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("CollectionLiterals_ERR.kt")
|
||||
public void testCollectionLiterals_ERR() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/CollectionLiterals_ERR.kt");
|
||||
doParsingTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("CommentsBinding.kt")
|
||||
public void testCommentsBinding() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/CommentsBinding.kt");
|
||||
|
||||
@@ -120,6 +120,7 @@ atomicExpression
|
||||
: objectLiteral
|
||||
: jump
|
||||
: loop
|
||||
: collectionLiteral
|
||||
: SimpleName
|
||||
;
|
||||
|
||||
@@ -275,3 +276,7 @@ arrayAccess
|
||||
objectLiteral
|
||||
: "object" (":" delegationSpecifier{","})? classBody
|
||||
;
|
||||
|
||||
collectionLiteral
|
||||
: "[" element{","}? "]"
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user