Dev-next-gen commented on code in PR #13139:
URL: https://github.com/apache/maven/pull/13139#discussion_r4015243378


##########
impl/maven-impl/src/main/java/org/apache/maven/impl/model/profile/ConditionParser.java:
##########
@@ -379,15 +419,24 @@ private Object parseVariableOrUnknownFunction() {
 
     /**
      * Parses a list of arguments for a function call.
+     * For the {@code if} function, only the branch selected by the condition 
is evaluated,
+     * the other one is skipped and passed as {@code null}.
      *
+     * @param functionName the name of the called function
      * @return a list of parsed arguments
      * @throws RuntimeException if there's a mismatch in parentheses
      */
-    private List<Object> parseArgumentList() {
+    private List<Object> parseArgumentList(String functionName) {
         List<Object> args = new ArrayList<>();
         current++; // Skip the opening parenthesis
         while (current < tokens.size() && !tokens.get(current).equals(")")) {
-            args.add(parseLogicalOr());
+            int index = args.size();
+            if ("if".equals(functionName) && (index == 1 || index == 2) && 
toBoolean(args.get(0)) != (index == 1)) {

Review Comment:
   You're right that this line is the only place where the parser, which 
otherwise only sees the injected function map, depends on a function name. I 
took the minimal path in 92a381c: the literal is now `private static final 
String IF_FUNCTION = "if"`, documented as the function whose unselected branch 
is skipped, so the coupling is visible from the top of the class. Spotless 
wrapped the condition over three lines, and `ConditionParserTest` plus 
`ConditionProfileActivatorTest` still pass (76 tests, 3 skipped as before).
   
   I stayed away from a `LazyExpressionFunction` sub-interface in this PR 
because it changes the public `ExpressionFunction` contract, and that feels 
like a call for the maintainers rather than for a bug fix. If you'd rather have 
it here, I'm glad to rework the change along those lines.
   



##########
impl/maven-impl/src/test/java/org/apache/maven/impl/model/profile/ConditionParserTest.java:
##########
@@ -182,6 +182,40 @@ void testIfFunction() {
         assertEquals("short", parser.parse("if(length('hi') > 3, 'long', 
'short')"));
     }
 
+    /**
+     * Only the selected branch of {@code if(..)} is evaluated. The other one 
may not be valid for
+     * the current input, as in the example from the {@code condition} 
documentation: with a
+     * {@code java.version} that has no {@code -}, the unselected {@code 
substring(..)} would get an
+     * end index of -1.
+     */
+    @Test
+    void testIfFunctionOnlyEvaluatesSelectedBranch() {
+        assertEquals(
+                "1.8.0_292",
+                parser.parse("if(contains(${java.version}, '-'), "
+                        + "substring(${java.version}, 0, 
indexOf(${java.version}, '-')), ${java.version})"));
+        assertEquals(
+                "21",
+                parser.parse("if(contains('21-ea', '-'), substring('21-ea', 0, 
indexOf('21-ea', '-')), '21-ea')"));
+        assertThrows(RuntimeException.class, () -> parser.parse("if(true, 
'a')"));
+        assertThrows(RuntimeException.class, () -> parser.parse("if(false, 
substring('a', 0, 5), 'b'"));

Review Comment:
   Good catch, that path was only covered by reasoning. I added 
`assertThrows(RuntimeException.class, () -> parser.parse("if(false, 'a')"))` 
right after the `if(true, 'a')` case in 92a381c. It takes the skip branch you 
describe, `if_` receives `[false, null]` and rejects the two-argument call, and 
the test passes along with the rest of `ConditionParserTest` (38 tests).
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to