This is an automated email from the ASF dual-hosted git repository. sunlan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push: new 553f52c GROOVY-9522: Throwing NPE when I use ternary operator with something special (#1246) 553f52c is described below commit 553f52c5403f873fae7b9b66872d48a8cbb54a20 Author: Daniel.Sun <sun...@apache.org> AuthorDate: Tue May 12 22:02:04 2020 +0800 GROOVY-9522: Throwing NPE when I use ternary operator with something special (#1246) --- src/antlr/GroovyParser.g4 | 46 ++++++++++++++++++++-- .../apache/groovy/parser/antlr4/AstBuilder.java | 18 ++++----- .../groovy/parser/antlr4/GroovyParserTest.groovy | 4 ++ .../src/test/resources/bugs/BUG-GROOVY-9522.groovy | 37 +++++++++++++++++ 4 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4 index 29f347c..47b212c 100644 --- a/src/antlr/GroovyParser.g4 +++ b/src/antlr/GroovyParser.g4 @@ -1008,6 +1008,13 @@ options { baseContext = primary; } | parExpression #parenPrmrAlt ; +namedArgPrimary +options { baseContext = primary; } + : identifier #identifierPrmrAlt + | literal #literalPrmrAlt + | gstring #gstringPrmrAlt + ; + commandPrimary options { baseContext = primary; } : identifier #identifierPrmrAlt @@ -1047,6 +1054,12 @@ options { baseContext = mapEntry; } | MUL COLON nls expression ; +namedArg +options { baseContext = mapEntry; } + : namedArgLabel COLON nls expression + | MUL COLON nls expression + ; + mapEntryLabel : keywords | primary @@ -1058,6 +1071,12 @@ options { baseContext = mapEntryLabel; } | namedPropertyArgPrimary ; +namedArgLabel +options { baseContext = mapEntryLabel; } + : keywords + | namedArgPrimary + ; + /** * t 0: general creation; 1: non-static inner class creation */ @@ -1100,30 +1119,51 @@ typeArgumentsOrDiamond ; arguments - : LPAREN enhancedArgumentList? COMMA? rparen + : LPAREN enhancedArgumentListInPar? COMMA? rparen ; argumentList -options { baseContext = enhancedArgumentList; } - : argumentListElement +options { baseContext = enhancedArgumentListInPar; } + : firstArgumentListElement ( COMMA nls argumentListElement )* ; enhancedArgumentList +options { baseContext = enhancedArgumentListInPar; } + : firstEnhancedArgumentListElement + ( COMMA nls + enhancedArgumentListElement + )* + ; + +enhancedArgumentListInPar : enhancedArgumentListElement ( COMMA nls enhancedArgumentListElement )* ; +firstArgumentListElement +options { baseContext = enhancedArgumentListElement; } + : expressionListElement[true] + | namedArg + ; + argumentListElement options { baseContext = enhancedArgumentListElement; } : expressionListElement[true] | namedPropertyArg ; +firstEnhancedArgumentListElement +options { baseContext = enhancedArgumentListElement; } + : expressionListElement[true] + | standardLambdaExpression + | namedArg + ; + enhancedArgumentListElement : expressionListElement[true] | standardLambdaExpression diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java index b366212..d5f80d1 100644 --- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java +++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java @@ -201,8 +201,8 @@ import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairs import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuesContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EmptyDimsContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EmptyDimsOptContext; -import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListElementContext; +import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListInParContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedForControlContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedStatementExpressionContext; import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantContext; @@ -2018,7 +2018,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { @Override public Expression visitCommandExpression(CommandExpressionContext ctx) { - boolean hasArgumentList = asBoolean(ctx.enhancedArgumentList()); + boolean hasArgumentList = asBoolean(ctx.enhancedArgumentListInPar()); boolean hasCommandArgument = asBoolean(ctx.commandArgument()); if (visitingArrayInitializerCnt > 0 && (hasArgumentList || hasCommandArgument)) { @@ -2042,7 +2042,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { MethodCallExpression methodCallExpression = null; if (hasArgumentList) { - Expression arguments = this.visitEnhancedArgumentList(ctx.enhancedArgumentList()); + Expression arguments = this.visitEnhancedArgumentListInPar(ctx.enhancedArgumentListInPar()); if (baseExpr instanceof PropertyExpression) { // e.g. obj.a 1, 2 methodCallExpression = @@ -2104,7 +2104,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { Expression primaryExpr = (Expression) this.visit(ctx.primary()); - if (asBoolean(ctx.enhancedArgumentList())) { // e.g. x y a b + if (asBoolean(ctx.enhancedArgumentListInPar())) { // e.g. x y a b if (baseExpr instanceof PropertyExpression) { // the branch should never reach, because a.b.c will be parsed as a path expression, not a method call throw createParsingFailedException("Unsupported command argument: " + ctx.getText(), ctx); } @@ -2114,7 +2114,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { new MethodCallExpression( baseExpr, this.createConstantExpression(primaryExpr), - this.visitEnhancedArgumentList(ctx.enhancedArgumentList()) + this.visitEnhancedArgumentListInPar(ctx.enhancedArgumentListInPar()) ); methodCallExpression.setImplicitThis(false); @@ -2493,19 +2493,19 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { @Override public Expression visitArguments(ArgumentsContext ctx) { - if (asBoolean(ctx) && asBoolean(ctx.COMMA()) && !asBoolean(ctx.enhancedArgumentList())) { + if (asBoolean(ctx) && asBoolean(ctx.COMMA()) && !asBoolean(ctx.enhancedArgumentListInPar())) { throw createParsingFailedException("Expression expected", ctx.COMMA()); } - if (!asBoolean(ctx) || !asBoolean(ctx.enhancedArgumentList())) { + if (!asBoolean(ctx) || !asBoolean(ctx.enhancedArgumentListInPar())) { return new ArgumentListExpression(); } - return configureAST(this.visitEnhancedArgumentList(ctx.enhancedArgumentList()), ctx); + return configureAST(this.visitEnhancedArgumentListInPar(ctx.enhancedArgumentListInPar()), ctx); } @Override - public Expression visitEnhancedArgumentList(EnhancedArgumentListContext ctx) { + public Expression visitEnhancedArgumentListInPar(EnhancedArgumentListInParContext ctx) { if (!asBoolean(ctx)) { return null; } diff --git a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy index cf841e5..83e63f9 100644 --- a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy +++ b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy @@ -462,4 +462,8 @@ final class GroovyParserTest extends GroovyTestCase { void "test groovy core - GROOVY-9507"() { doTest('bugs/BUG-GROOVY-9507.groovy'); } + + void "test groovy core - GROOVY-9522"() { + doTest('bugs/BUG-GROOVY-9522.groovy'); + } } diff --git a/subprojects/parser-antlr4/src/test/resources/bugs/BUG-GROOVY-9522.groovy b/subprojects/parser-antlr4/src/test/resources/bugs/BUG-GROOVY-9522.groovy new file mode 100644 index 0000000..2b4e332 --- /dev/null +++ b/subprojects/parser-antlr4/src/test/resources/bugs/BUG-GROOVY-9522.groovy @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +static String a() { + null +} + +static String b() { + '' +} + +def x = a() ? [b(), a()].join(',') : b() +def x = a() ? [b(), a()] : b() +def x = a() ? ([b(), a()]).join(',') : b() + +x == '' + +ds = DB_DATASOURCE.newInstance( + (DB_DS_KEY): DB_URL_PREFIX + getMethodName(), + user: DB_USER, + password: DB_PASSWORD)