Change annotations parsing in bodies of operators

This change only matters in cases of if/when/for/while having braceless
blocks

Annotations on them are parsed now as on block-level expressions, i.e.
they're attached to the whole expression
This commit is contained in:
Denis Zharkov
2016-10-06 16:05:38 +03:00
parent c01b4156d8
commit 9ff439e39e
7 changed files with 315 additions and 32 deletions
@@ -1237,7 +1237,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
/*
* statement
* : declaration
* : annotations expression
* : blockLevelExpression
* ;
*/
private void parseStatement(boolean isScriptTopLevel) {
@@ -1247,20 +1247,25 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
}
else if (isScriptTopLevel){
PsiBuilder.Marker scriptInitializer = mark();
parseStatementLevelExpression();
parseBlockLevelExpression();
scriptInitializer.done(SCRIPT_INITIALIZER);
}
else {
parseStatementLevelExpression();
parseBlockLevelExpression();
}
}
}
private void parseStatementLevelExpression() {
/*
* blockLevelExpression
* : annotations expression
* ;
*/
private void parseBlockLevelExpression() {
if (at(AT)) {
PsiBuilder.Marker expression = mark();
myKotlinParsing.parseAnnotations(DEFAULT);
parseStatementLevelExpression();
parseBlockLevelExpression();
expression.done(ANNOTATED_EXPRESSION);
return;
}
@@ -1424,7 +1429,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
private void parseControlStructureBody() {
if (!parseAnnotatedLambda(/* preferBlock = */true)) {
parseExpression();
parseBlockLevelExpression();
}
}
@@ -14,6 +14,36 @@ fun <T : CharSequence> foo(x: Array<Any>, y: IntArray, block: (T, Int) -> Int) {
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
if (i != 1)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
if (i != 2)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
else
@Suppress("UNCHECKED_CAST")
i += block(x[1] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
while (i != 1)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
do
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
while (i != 1)
for (j in 1..100)
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
when (i) {
1 ->
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
}
val l: () -> Unit = {
@Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
@@ -14,10 +14,35 @@ fun foo() {
}
for (i in 1..100)
// annotation is attached to `x4`
@ann4
x4 += foo4()
if (1 > 2)
@ann41
x41 += foo41()
if (3 > 4)
@ann42
x42 += foo42()
else
@ann43
x43 += foo43()
while (true)
@ann44
x44 += foo44()
do
@ann
x45 += foo45()
while (true)
when (1) {
1 ->
@ann46
x46 += foo46()
}
a.filter {
@ann5
x5 += foo5()
+232 -18
View File
@@ -150,31 +150,245 @@ JetFile: blockLevelExpressions.kt
PsiElement(INTEGER_LITERAL)('100')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiComment(EOL_COMMENT)('// annotation is attached to `x4`')
PsiWhiteSpace('\n ')
BODY
BINARY_EXPRESSION
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann4')
PsiWhiteSpace('\n ')
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann4')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x4')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo4')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiElement(GT)('>')
PsiWhiteSpace(' ')
CALL_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
THEN
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann41')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo4')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(IDENTIFIER)('x41')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo41')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
IF
PsiElement(if)('if')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('3')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(GT)('>')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('4')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
THEN
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann42')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x42')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo42')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(else)('else')
PsiWhiteSpace('\n ')
ELSE
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann43')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x43')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo43')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
WHILE
PsiElement(while)('while')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
BODY
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann44')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x44')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo44')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
DO_WHILE
PsiElement(do)('do')
PsiWhiteSpace('\n ')
BODY
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x45')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo45')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(while)('while')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
CONDITION
BOOLEAN_CONSTANT
PsiElement(true)('true')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
WHEN
PsiElement(when)('when')
PsiWhiteSpace(' ')
PsiElement(LPAR)('(')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
WHEN_ENTRY
WHEN_CONDITION_WITH_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
PsiElement(ARROW)('->')
PsiWhiteSpace('\n ')
ANNOTATED_EXPRESSION
ANNOTATION_ENTRY
PsiElement(AT)('@')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('ann46')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x46')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo46')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
+9 -4
View File
@@ -4,8 +4,13 @@
See [Control structures](control-flow.html)
*/
controlStructureBody
: block
: blockLevelExpression
;
if
: "if" "(" expression ")" expression SEMI? ("else" expression)?
: "if" "(" expression ")" controlStructureBody SEMI? ("else" controlStructureBody)?
;
try
@@ -27,13 +32,13 @@ loop
;
for
: "for" "(" annotations (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression
: "for" "(" annotations (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" controlStructureBody
;
while
: "while" "(" expression ")" expression
: "while" "(" expression ")" controlStructureBody
;
doWhile
: "do" expression "while" "(" expression ")"
: "do" controlStructureBody "while" "(" expression ")"
;
+4
View File
@@ -172,6 +172,10 @@ declaration
statement
: declaration
: blockLevelExpression
;
blockLevelExpression
: annotations expression
;
+3 -3
View File
@@ -12,12 +12,12 @@ when
// TODO : consider empty after ->
whenEntry
: whenCondition{","} "->" expression SEMI
: "else" "->" expression SEMI
: whenCondition{","} "->" controlStructureBody SEMI
: "else" "->" controlStructureBody SEMI
;
whenCondition
: expression
: ("in" | "!in") expression
: ("is" | "!is") isRHS
;
;