Repository: smithy-lang/smithy
Pull request #2680 (2025-06-26 10:28:33)

Add model discovery args to smithy select
The gradle plugin's select isn't very useful without being able to pass along the classpath gradle is responsible for producing.

---
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.



Patch:
diff --git a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/QueryErrorCodeValidator.java b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/QueryErrorCodeValidator.java
index f97455a9b..5db5d8902 100644
--- a/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/QueryErrorCodeValidator.java
+++ b/smithy-aws-traits/src/main/java/software/amazon/smithy/aws/traits/protocols/QueryErrorCodeValidator.java
@@ -5,15 +5,16 @@
 package software.amazon.smithy.aws.traits.protocols;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.stream.Collectors;
 import software.amazon.smithy.model.Model;
 import software.amazon.smithy.model.knowledge.TopDownIndex;
+import software.amazon.smithy.model.shapes.OperationShape;
 import software.amazon.smithy.model.shapes.ServiceShape;
 import software.amazon.smithy.model.shapes.Shape;
 import software.amazon.smithy.model.shapes.ShapeId;
@@ -26,25 +27,33 @@ import software.amazon.smithy.utils.SmithyInternalApi;
  */
 @SmithyInternalApi
 public class QueryErrorCodeValidator extends AbstractValidator {
+
     @Override
     public List<ValidationEvent> validate(Model model) {
-        List<ValidationEvent> events = new ArrayList<>();
+        List<ValidationEvent> events = Collections.emptyList();
         for (ServiceShape service : model.getServiceShapes()) {
             if (service.hasTrait(AwsQueryCompatibleTrait.class) || service.hasTrait(AwsQueryTrait.class)
                     || service.hasTrait(Ec2QueryTrait.class)) {
-                events.addAll(validateService(model, service));
+                List<ValidationEvent> serviceEvents = validateService(model, service);
+                if (!serviceEvents.isEmpty()) {
+                    if (events.isEmpty()) {
+                        events = new ArrayList<>();
+                    }
+                    events.addAll(serviceEvents);
+                }
             }
         }
         return events;
     }
 
     private List<ValidationEvent> validateService(Model model, ServiceShape service) {
-        List<ValidationEvent> events = new ArrayList<>();
         TopDownIndex index = TopDownIndex.of(model);
-        List<ShapeId> errors = new ArrayList<>(service.getErrors());
-        index.getContainedOperations(service).forEach(operation -> errors.addAll(operation.getErrors()));
+        Set<ShapeId> errors = new HashSet<>(service.getErrors());
+        for (OperationShape operation : index.getContainedOperations(service)) {
+            errors.addAll(operation.getErrors());
+        }
 
-        Map<String, Set<ShapeId>> errorCodeBindings = new HashMap<>();
+        Map<String, Set<String>> errorCodeBindings = new HashMap<>();
         for (ShapeId errorId : errors) {
             String errorCode = errorId.getName();
             Shape errorShape = model.expectShape(errorId);
@@ -52,16 +61,19 @@ public class QueryErrorCodeValidator extends AbstractValidator {
                 AwsQueryErrorTrait trait = errorShape.expectTrait(AwsQueryErrorTrait.class);
                 errorCode = trait.getCode();
             }
-            errorCodeBindings.computeIfAbsent(errorCode, k -> new TreeSet<>()).add(errorId);
+            errorCodeBindings.computeIfAbsent(errorCode, k -> new TreeSet<>()).add(errorId.toString());
         }
-
-        for (Map.Entry<String, Set<ShapeId>> entry : errorCodeBindings.entrySet()) {
+        List<ValidationEvent> events = Collections.emptyList();
+        for (Map.Entry<String, Set<String>> entry : errorCodeBindings.entrySet()) {
             if (entry.getValue().size() == 1) {
                 continue;
             }
             String errorCode = entry.getKey();
-            String shapes = entry.getValue().stream().map(Objects::toString).collect(Collectors.joining(", "));
-            events.add(danger(service,
+            String shapes = String.join(", ", entry.getValue());
+            if (events.isEmpty()) {
+                events = new ArrayList<>();
+            }
+            events.add(warning(service,
                     String.format("Multiple error shapes with the error code `%s` found: [%s]. This error code "
                             + "ambiguity will result in the wrong error shape being deserialized when running the "
                             + "query protocol. This pain will be carried forward when migrating to a new protocol "
diff --git a/smithy-cli/src/main/java/software/amazon/smithy/cli/commands/SelectCommand.java b/smithy-cli/src/main/java/software/amazon/smithy/cli/commands/SelectCommand.java
index cc59387d4..9542423ec 100644
--- a/smithy-cli/src/main/java/software/amazon/smithy/cli/commands/SelectCommand.java
+++ b/smithy-cli/src/main/java/software/amazon/smithy/cli/commands/SelectCommand.java
@@ -62,6 +62,7 @@ final class SelectCommand implements Command {
     @Override
     public int execute(Arguments arguments, Env env) {
         arguments.addReceiver(new ConfigOptions());
+        arguments.addReceiver(new DiscoveryOptions());
         arguments.addReceiver(new BuildOptions());
         arguments.addReceiver(new Options());
 


Test patch:
diff --git a/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy b/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy
index 2bd766810..4dcabeaec 100644
--- a/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy
+++ b/smithy-aws-protocol-tests/model/awsJson1_0/main.smithy
@@ -6,8 +6,6 @@ use aws.api#service
 use aws.auth#sigv4
 use aws.protocols#awsJson1_0
 use aws.protocols#awsQueryCompatible
-use smithy.test#httpRequestTests
-use smithy.test#httpResponseTests
 
 @service(sdkId: "JSON RPC 10")
 @sigv4(name: "jsonrpc10")
@@ -50,7 +48,7 @@ service JsonRpc10 {
 
 
 @service(sdkId: "Query Compatible JSON RPC 10")
-@sigv4(name: "query-compatible-jsonrpc10")
+@sigv4(name: "querycompatiblejsonrpc10")
 @awsJson1_0
 @title("Query Compatible Json 1.0 Protocol Service")
 @awsQueryCompatible
diff --git a/smithy-aws-protocol-tests/model/rpcv2Cbor/main.smithy b/smithy-aws-protocol-tests/model/rpcv2Cbor/main.smithy
deleted file mode 100644
index 371a32600..000000000
--- a/smithy-aws-protocol-tests/model/rpcv2Cbor/main.smithy
+++ /dev/null
@@ -1,31 +0,0 @@
-$version: "2"
-
-namespace aws.protocoltests.rpcv2cbor
-
-use aws.api#service
-use aws.auth#sigv4
-use aws.protocols#awsQueryCompatible
-use smithy.protocols#rpcv2Cbor
-
-@service(sdkId: "Query Compatible RpcV2 Protocol")
-@sigv4(name: "query-compatible-rpcv2")
-@rpcv2Cbor
-@title("Query Compatible RpcV2 Protocol Service")
-@awsQueryCompatible
-service QueryCompatibleRpcV2Protocol {
-    version: "2025-06-20"
-    operations: [
-        QueryCompatibleOperation
-    ]
-}
-
-@service(sdkId: "Non Query Compatible RpcV2 Protocol")
-@sigv4(name: "non-query-compatible-rpcv2")
-@rpcv2Cbor
-@title("Non Query Compatible RpcV2 Protocol Service")
-service NonQueryCompatibleRpcV2Protocol {
-    version: "2025-06-20"
-    operations: [
-        QueryIncompatibleOperation
-    ]
-}
diff --git a/smithy-aws-protocol-tests/model/rpcv2Cbor/non-query-compatible.smithy b/smithy-aws-protocol-tests/model/rpcv2Cbor/non-query-compatible.smithy
new file mode 100644
index 000000000..69e029090
--- /dev/null
+++ b/smithy-aws-protocol-tests/model/rpcv2Cbor/non-query-compatible.smithy
@@ -0,0 +1,34 @@
+$version: "2"
+
+namespace aws.protocoltests.rpcv2cbor
+
+use aws.api#service
+use aws.auth#sigv4
+use smithy.protocols#rpcv2Cbor
+use smithy.test#httpRequestTests
+
+@service(sdkId: "Non Query Compatible RpcV2 Protocol")
+@sigv4(name: "nonquerycompatiblerpcv2protocol")
+@rpcv2Cbor
+@title("Non Query Compatible RpcV2 Protocol Service")
+service NonQueryCompatibleRpcV2Protocol {
+    version: "2025-06-20"
+    operations: [
+        NonQueryCompatibleOperation
+    ]
+}
+
+@httpRequestTests([
+    {
+        id: "NonQueryCompatibleRpcV2CborForbidsQueryModeHeader"
+        documentation: "The query mode header MUST NOT be set on non-query-compatible services."
+        protocol: rpcv2Cbor
+        method: "POST"
+        headers: { "smithy-protocol": "rpc-v2-cbor", Accept: "application/cbor" }
+        forbidHeaders: ["x-amzn-query-mode"]
+        uri: "/service/NonQueryCompatibleRpcV2Protocol/operation/QueryIncompatibleOperation"
+        body: ""
+    }
+])
+@idempotent
+operation NonQueryCompatibleOperation {}
diff --git a/smithy-aws-protocol-tests/model/rpcv2Cbor/query-compatible.smithy b/smithy-aws-protocol-tests/model/rpcv2Cbor/query-compatible.smithy
index d53f591e1..d0707005a 100644
--- a/smithy-aws-protocol-tests/model/rpcv2Cbor/query-compatible.smithy
+++ b/smithy-aws-protocol-tests/model/rpcv2Cbor/query-compatible.smithy
@@ -2,27 +2,28 @@ $version: "2"
 
 namespace aws.protocoltests.rpcv2cbor
 
+use aws.api#service
+use aws.auth#sigv4
+use aws.protocols#awsQueryCompatible
 use aws.protocols#awsQueryError
 use aws.protocoltests.config#ErrorCodeParams
 use smithy.protocols#rpcv2Cbor
 use smithy.test#httpRequestTests
 use smithy.test#httpResponseTests
 
-@httpRequestTests([
-    {
-        id: "NonQueryCompatibleRpcV2CborForbidsQueryModeHeader"
-        documentation: "The query mode header MUST NOT be set on non-query-compatible services."
-        protocol: rpcv2Cbor
-        method: "POST"
-        headers: { "smithy-protocol": "rpc-v2-cbor", Accept: "application/cbor" }
-        forbidHeaders: ["x-amzn-query-mode"]
-        uri: "/service/NonQueryCompatibleRpcV2Protocol/operation/QueryIncompatibleOperation"
-        body: "{}"
-        bodyMediaType: "application/json"
-    }
-])
-@idempotent
-operation QueryIncompatibleOperation {}
+
+@service(sdkId: "Query Compatible RpcV2 Protocol")
+@sigv4(name: "querycompatiblerpcv2protocol")
+@rpcv2Cbor
+@title("Query Compatible RpcV2 Protocol Service")
+@awsQueryCompatible
+service QueryCompatibleRpcV2Protocol {
+    version: "2025-06-20"
+    operations: [
+        QueryCompatibleOperation
+    ]
+}
+
 
 @idempotent
 operation QueryCompatibleOperation {
diff --git a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/protocols/query-errors-must-be-unique.errors b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/protocols/query-errors-must-be-unique.errors
index 9406380d9..19809b6d2 100644
--- a/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/protocols/query-errors-must-be-unique.errors
+++ b/smithy-aws-traits/src/test/resources/software/amazon/smithy/aws/traits/errorfiles/protocols/query-errors-must-be-unique.errors
@@ -1,2 +1,2 @@
-[DANGER] smithy.example#QueryCompatibleService: Multiple error shapes with the error code `ResourceNotFound` found: [smithy.example#DocumentNotFound, smithy.example#ResourceNotFound]. This error code ambiguity will result in the wrong error shape being deserialized when running the query protocol. This pain will be carried forward when migrating to a new protocol when using the awsQueryCompatible trait. | QueryErrorCode
-[DANGER] smithy.example#QueryService: Multiple error shapes with the error code `ResourceNotFound` found: [smithy.example#DocumentNotFound, smithy.example#ResourceNotFound]. This error code ambiguity will result in the wrong error shape being deserialized when running the query protocol. This pain will be carried forward when migrating to a new protocol when using the awsQueryCompatible trait. | QueryErrorCode
+[WARNING] smithy.example#QueryCompatibleService: Multiple error shapes with the error code `ResourceNotFound` found: [smithy.example#DocumentNotFound, smithy.example#ResourceNotFound]. This error code ambiguity will result in the wrong error shape being deserialized when running the query protocol. This pain will be carried forward when migrating to a new protocol when using the awsQueryCompatible trait. | QueryErrorCode
+[WARNING] smithy.example#QueryService: Multiple error shapes with the error code `ResourceNotFound` found: [smithy.example#DocumentNotFound, smithy.example#ResourceNotFound]. This error code ambiguity will result in the wrong error shape being deserialized when running the query protocol. This pain will be carried forward when migrating to a new protocol when using the awsQueryCompatible trait. | QueryErrorCode