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 * statement
* : declaration * : declaration
* : annotations expression * : blockLevelExpression
* ; * ;
*/ */
private void parseStatement(boolean isScriptTopLevel) { private void parseStatement(boolean isScriptTopLevel) {
@@ -1247,20 +1247,25 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
} }
else if (isScriptTopLevel){ else if (isScriptTopLevel){
PsiBuilder.Marker scriptInitializer = mark(); PsiBuilder.Marker scriptInitializer = mark();
parseStatementLevelExpression(); parseBlockLevelExpression();
scriptInitializer.done(SCRIPT_INITIALIZER); scriptInitializer.done(SCRIPT_INITIALIZER);
} }
else { else {
parseStatementLevelExpression(); parseBlockLevelExpression();
} }
} }
} }
private void parseStatementLevelExpression() { /*
* blockLevelExpression
* : annotations expression
* ;
*/
private void parseBlockLevelExpression() {
if (at(AT)) { if (at(AT)) {
PsiBuilder.Marker expression = mark(); PsiBuilder.Marker expression = mark();
myKotlinParsing.parseAnnotations(DEFAULT); myKotlinParsing.parseAnnotations(DEFAULT);
parseStatementLevelExpression(); parseBlockLevelExpression();
expression.done(ANNOTATED_EXPRESSION); expression.done(ANNOTATED_EXPRESSION);
return; return;
} }
@@ -1424,7 +1429,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
private void parseControlStructureBody() { private void parseControlStructureBody() {
if (!parseAnnotatedLambda(/* preferBlock = */true)) { 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() 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 = { val l: () -> Unit = {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt() i += block(x[0] as T, "" <!CAST_NEVER_SUCCEEDS!>as<!> Int).toInt()
@@ -14,10 +14,35 @@ fun foo() {
} }
for (i in 1..100) for (i in 1..100)
// annotation is attached to `x4`
@ann4 @ann4
x4 += foo4() 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 { a.filter {
@ann5 @ann5
x5 += foo5() x5 += foo5()
+232 -18
View File
@@ -150,31 +150,245 @@ JetFile: blockLevelExpressions.kt
PsiElement(INTEGER_LITERAL)('100') PsiElement(INTEGER_LITERAL)('100')
PsiElement(RPAR)(')') PsiElement(RPAR)(')')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
PsiComment(EOL_COMMENT)('// annotation is attached to `x4`')
PsiWhiteSpace('\n ')
BODY BODY
BINARY_EXPRESSION ANNOTATED_EXPRESSION
ANNOTATED_EXPRESSION ANNOTATION_ENTRY
ANNOTATION_ENTRY PsiElement(AT)('@')
PsiElement(AT)('@') CONSTRUCTOR_CALLEE
CONSTRUCTOR_CALLEE TYPE_REFERENCE
TYPE_REFERENCE USER_TYPE
USER_TYPE REFERENCE_EXPRESSION
REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('ann4')
PsiElement(IDENTIFIER)('ann4') PsiWhiteSpace('\n ')
PsiWhiteSpace('\n ') BINARY_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('x4') 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(' ') PsiWhiteSpace(' ')
OPERATION_REFERENCE OPERATION_REFERENCE
PsiElement(PLUSEQ)('+=') PsiElement(GT)('>')
PsiWhiteSpace(' ') 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 REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo4') PsiElement(IDENTIFIER)('x41')
VALUE_ARGUMENT_LIST PsiWhiteSpace(' ')
PsiElement(LPAR)('(') OPERATION_REFERENCE
PsiElement(RPAR)(')') 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 ') PsiWhiteSpace('\n\n ')
DOT_QUALIFIED_EXPRESSION DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
+9 -4
View File
@@ -4,8 +4,13 @@
See [Control structures](control-flow.html) See [Control structures](control-flow.html)
*/ */
controlStructureBody
: block
: blockLevelExpression
;
if if
: "if" "(" expression ")" expression SEMI? ("else" expression)? : "if" "(" expression ")" controlStructureBody SEMI? ("else" controlStructureBody)?
; ;
try try
@@ -27,13 +32,13 @@ loop
; ;
for for
: "for" "(" annotations (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression : "for" "(" annotations (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" controlStructureBody
; ;
while while
: "while" "(" expression ")" expression : "while" "(" expression ")" controlStructureBody
; ;
doWhile doWhile
: "do" expression "while" "(" expression ")" : "do" controlStructureBody "while" "(" expression ")"
; ;
+4
View File
@@ -172,6 +172,10 @@ declaration
statement statement
: declaration : declaration
: blockLevelExpression
;
blockLevelExpression
: annotations expression : annotations expression
; ;
+3 -3
View File
@@ -12,12 +12,12 @@ when
// TODO : consider empty after -> // TODO : consider empty after ->
whenEntry whenEntry
: whenCondition{","} "->" expression SEMI : whenCondition{","} "->" controlStructureBody SEMI
: "else" "->" expression SEMI : "else" "->" controlStructureBody SEMI
; ;
whenCondition whenCondition
: expression : expression
: ("in" | "!in") expression : ("in" | "!in") expression
: ("is" | "!is") isRHS : ("is" | "!is") isRHS
; ;