This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 92040109d14c CAMEL-25761: camel-jbang - the AI validator finds the 
parameters of an endpoint wherever they stand in the step (#28057)
92040109d14c is described below

commit 92040109d14c466cdcf85b4365558769f4865616
Author: Claus Ibsen <[email protected]>
AuthorDate: Sun Oct 18 18:04:19 2026 +0200

    CAMEL-25761: camel-jbang - the AI validator finds the parameters of an 
endpoint wherever they stand in the step (#28057)
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../dsl/jbang/core/commands/ai/EndpointChecks.java | 29 ++++++++++---
 .../ai/SourceValidatorPlaceholderTest.java         | 48 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 5 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
index ef0ddd26f006..801e9e50addf 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/EndpointChecks.java
@@ -137,11 +137,13 @@ final class EndpointChecks {
             boolean consumerOnly = eipName != null && 
CONSUMER_EIPS.contains(eipName);
             boolean producerOnly = eipName != null && 
PRODUCER_EIPS.contains(eipName);
 
-            // look ahead for a parameters: block at the same indent level as 
uri
+            // the parameters: block is a key of the same mapping as uri:, 
after it or before it, and other keys of the
+            // step (id:, variableReceive:) may stand in between (CAMEL-25761)
             StringBuilder uriBuilder = new StringBuilder(uri);
             boolean hasParams = uri.contains("?");
             Map<String, Integer> optionLineMap = new LinkedHashMap<>();
-            for (int j = i + 1; j < lines.length; j++) {
+            int paramsBefore = keyBefore(lines, i, lineIndent, "parameters:");
+            for (int j = paramsBefore >= 0 ? paramsBefore : i + 1; j < 
lines.length; j++) {
                 String next = lines[j];
                 if (next.isBlank()) {
                     continue;
@@ -214,9 +216,6 @@ final class EndpointChecks {
                     }
                     break;
                 }
-                if (nextIndent == lineIndent) {
-                    break;
-                }
             }
 
             checkUri(errors, catalog, uriBuilder.toString(), line, i, 
optionLineMap, eipName, consumerOnly, producerOnly,
@@ -225,6 +224,26 @@ final class EndpointChecks {
         return errors;
     }
 
+    /**
+     * The line of the key (such as parameters:) of the same mapping as the 
line at idx that comes before it: the same
+     * indent, up to the line that starts the mapping, or -1.
+     */
+    static int keyBefore(String[] lines, int idx, int indent, String key) {
+        for (int j = idx - 1; j >= 0; j--) {
+            if (lines[j].isBlank()) {
+                continue;
+            }
+            int ind = countLeadingSpaces(lines[j]);
+            if (ind < indent) {
+                return -1;
+            }
+            if (ind == indent && lines[j].trim().startsWith(key)) {
+                return j;
+            }
+        }
+        return -1;
+    }
+
     /**
      * The checks of one endpoint uri, whatever the DSL it is written in: the 
options against the catalog, then the
      * mistakes the catalog does not see.
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorPlaceholderTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorPlaceholderTest.java
index 4019b2a2dcfe..b13621e9297e 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorPlaceholderTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/SourceValidatorPlaceholderTest.java
@@ -118,6 +118,54 @@ class SourceValidatorPlaceholderTest {
                 .noneMatch(e -> e.contains("required option"));
     }
 
+    /** CAMEL-25761: another key of the step between uri: and parameters:, or 
parameters: above uri: */
+    @Test
+    void theParametersAreFoundWhereverTheyStandInTheStep() {
+        String keyBetween = """
+                - route:
+                    from:
+                      uri: timer
+                      parameters:
+                        timerName: tick
+                      steps:
+                        - to:
+                            uri: jms
+                            variableReceive: answer
+                            parameters:
+                              destinationType: queue
+                              destinationName: stock
+                        - to:
+                            uri: jms
+                            id: send-order
+                            parameters:
+                              destinationName: orders
+                              destinationTyp: queue
+                """;
+        List<String> errors = 
SourceValidator.validateYamlEndpoints(keyBetween, catalog);
+        assertThat(errors).noneMatch(e -> e.contains("required option"));
+        // the options behind the other key are checked as well: a misspelled 
one is reported on its own line
+        assertThat(errors).anyMatch(e -> e.startsWith("Line 18:") && 
e.contains("destinationTyp"));
+
+        String paramsFirst = """
+                - route:
+                    from:
+                      uri: timer
+                      parameters:
+                        timerName: tick
+                      steps:
+                        - to:
+                            parameters:
+                              destinationName: stock
+                            uri: jms
+                """;
+        assertThat(SourceValidator.validateYamlEndpoints(paramsFirst, 
catalog)).noneMatch(e -> e.contains("required option"));
+
+        // without the option anywhere in the step, it is still reported
+        
assertThat(SourceValidator.validateYamlEndpoints(keyBetween.replace("\n         
     destinationName: stock", ""),
+                catalog))
+                .anyMatch(e -> e.startsWith("Line 8: jms: the required option 
'destinationName' is missing"));
+    }
+
     @Test
     void aSimplePlaceholderInABeanPropertySaysToWriteAPropertyPlaceholder() {
         String yaml = """

Reply via email to