mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] fix parsing of parenthesized cast operand (IDEA-194587)
This commit is contained in:
+43
-15
@@ -1758,6 +1758,44 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// priority1_4 <<noParenthesized>> | clear_variants_and_fail | cast_parenthesized_expression
|
||||
static boolean cast_operand(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "cast_operand")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = cast_operand_0(b, l + 1);
|
||||
if (!r) r = clear_variants_and_fail(b, l + 1);
|
||||
if (!r) r = cast_parenthesized_expression(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// priority1_4 <<noParenthesized>>
|
||||
private static boolean cast_operand_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "cast_operand_0")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = expression(b, l + 1, 13);
|
||||
r = r && noParenthesized(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// '(' expression ')'
|
||||
public static boolean cast_parenthesized_expression(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "cast_parenthesized_expression")) return false;
|
||||
if (!nextTokenIsFast(b, T_LPAREN)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = consumeTokenFast(b, T_LPAREN);
|
||||
r = r && expression(b, l + 1, -1);
|
||||
r = r && consumeToken(b, T_RPAREN);
|
||||
exit_section_(b, m, PARENTHESIZED_EXPRESSION, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// 'catch' '(' parse_catch_parameter ')' lazy_block
|
||||
public static boolean catch_clause(PsiBuilder b, int l) {
|
||||
@@ -7256,14 +7294,17 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// &cast_expression_start ('(' type_element ')' priority1_4)
|
||||
// &cast_expression_start '(' type_element ')' cast_operand
|
||||
public static boolean cast_expression(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "cast_expression")) return false;
|
||||
if (!nextTokenIsSmart(b, T_LPAREN)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = cast_expression_0(b, l + 1);
|
||||
r = r && cast_expression_1(b, l + 1);
|
||||
r = r && consumeTokenSmart(b, T_LPAREN);
|
||||
r = r && type_element(b, l + 1);
|
||||
r = r && consumeToken(b, T_RPAREN);
|
||||
r = r && cast_operand(b, l + 1);
|
||||
exit_section_(b, m, CAST_EXPRESSION, r);
|
||||
return r;
|
||||
}
|
||||
@@ -7278,19 +7319,6 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// '(' type_element ')' priority1_4
|
||||
private static boolean cast_expression_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "cast_expression_1")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = consumeTokenSmart(b, T_LPAREN);
|
||||
r = r && type_element(b, l + 1);
|
||||
r = r && consumeToken(b, T_RPAREN);
|
||||
r = r && expression(b, l + 1, 13);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// fast_question index_expression_argument_list not_colon
|
||||
private static boolean safe_index_expression_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "safe_index_expression_0")) return false;
|
||||
|
||||
@@ -985,8 +985,10 @@ private property_expression_identifiers ::= parenthesized_expression | lazy_bloc
|
||||
|
||||
private priority1_4 ::= not_expression | cast_expression
|
||||
not_expression ::= ('~' | '!') expression { elementType = unary_expression }
|
||||
cast_expression ::= &cast_expression_start ('(' type_element ')' priority1_4)
|
||||
cast_expression ::= &cast_expression_start '(' type_element ')' cast_operand
|
||||
private cast_expression_start ::= '(' (IDENTIFIER | primitive_type) { consumeTokenMethod = 'consumeTokenFast' }
|
||||
private cast_operand ::= priority1_4 <<noParenthesized>> | clear_variants_and_fail | cast_parenthesized_expression
|
||||
cast_parenthesized_expression ::= '(' expression ')' { elementType = parenthesized_expression }
|
||||
|
||||
private priority1_5 ::= index_expression | safe_index_expression | postfix_unary_expression
|
||||
index_expression ::= expression index_expression_argument_list
|
||||
|
||||
@@ -403,3 +403,7 @@ fun newLine(builder: PsiBuilder, level: Int): Boolean {
|
||||
}
|
||||
|
||||
fun noNewLine(builder: PsiBuilder, level: Int): Boolean = !newLine(builder, level)
|
||||
|
||||
fun noParenthesized(builder: PsiBuilder, level: Int): Boolean {
|
||||
return builder.latestDoneMarker?.tokenType != PARENTHESIZED_EXPRESSION
|
||||
}
|
||||
|
||||
+10
@@ -530,6 +530,16 @@ class ExpressionsParsingTest extends GroovyParsingTestCase {
|
||||
|
||||
void testtypecast$noExpression() { doTest() }
|
||||
|
||||
void testtypecast$parenthesizedOperand() { doTest() }
|
||||
|
||||
void testtypecast$parenthesizedQualifier() { doTest() }
|
||||
|
||||
void testtypecast$parenthesizedOperandError() { doTest() }
|
||||
|
||||
void testtypecast$nested() { doTest() }
|
||||
|
||||
void testtypecast$vsMethodCall() { doTest() }
|
||||
|
||||
void testtypecast$conditional() throws Throwable { doTest() }
|
||||
|
||||
void testAtHang() throws Throwable { doTest() }
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(a)(b)(c)
|
||||
-----
|
||||
Groovy script
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('b')
|
||||
PsiElement())(')')
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('c')
|
||||
PsiElement())(')')
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
(a)()
|
||||
(a)(1)
|
||||
(a)(1, 2)
|
||||
-----
|
||||
Groovy script
|
||||
Method call
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Arguments
|
||||
PsiElement(()('(')
|
||||
PsiElement())(')')
|
||||
PsiElement(new line)('\n')
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Literal
|
||||
PsiElement(Integer)('1')
|
||||
PsiElement())(')')
|
||||
PsiElement(new line)('\n')
|
||||
Method call
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Arguments
|
||||
PsiElement(()('(')
|
||||
Literal
|
||||
PsiElement(Integer)('1')
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
Literal
|
||||
PsiElement(Integer)('2')
|
||||
PsiElement())(')')
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
(a)(1 + )
|
||||
-----
|
||||
Groovy script
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Additive expression
|
||||
Literal
|
||||
PsiElement(Integer)('1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(+)('+')
|
||||
PsiErrorElement:<expression> expected, got ')'
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement())(')')
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
(a)(b).c
|
||||
-----
|
||||
Groovy script
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
Reference expression
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('b')
|
||||
PsiElement())(')')
|
||||
PsiElement(.)('.')
|
||||
PsiElement(identifier)('c')
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
(a) b (c)
|
||||
-----
|
||||
Groovy script
|
||||
Typecast expression
|
||||
PsiElement(()('(')
|
||||
Type element
|
||||
Reference element
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Method call
|
||||
Reference expression
|
||||
PsiElement(identifier)('b')
|
||||
PsiWhiteSpace(' ')
|
||||
Arguments
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('c')
|
||||
PsiElement())(')')
|
||||
Reference in New Issue
Block a user