Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -429,11 +429,12 @@ extension {{projectName}}API {
{{/hasFormParams}}
{{/bodyParam}}{{#hasQueryParams}}
var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [{{^queryParams}}:{{/queryParams}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When an operation has a query parameter named localVariableQueryParameters, this declaration collides with the generated method parameter and makes the Swift client fail to compile. Generate a collision-free local name or scope the typed dictionary separately.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/api.mustache, line 432:

<comment>When an operation has a query parameter named `localVariableQueryParameters`, this declaration collides with the generated method parameter and makes the Swift client fail to compile. Generate a collision-free local name or scope the typed dictionary separately.</comment>

<file context>
@@ -429,11 +429,12 @@ extension {{projectName}}API {
 {{/bodyParam}}{{#hasQueryParams}}
         var localVariableUrlComponents = URLComponents(string: localVariableURLString)
-        localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([{{^queryParams}}:{{/queryParams}}
+        let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [{{^queryParams}}:{{/queryParams}}
             {{#queryParams}}
             {{> _param}},
</file context>

{{#queryParams}}
{{> _param}},
{{/queryParams}}
]){{/hasQueryParams}}{{^hasQueryParams}}
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters){{/hasQueryParams}}{{^hasQueryParams}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The PR description states the typed-dictionary fix was also applied to the Swift6 template and that Swift6 samples should be re-generated, but the diff only changes swift5/api.mustache. swift6/api.mustache:307 still passes the unannotated dictionary literal directly to mapValuesToQueryItems, so Swift6-generated code for operations with many query parameters keeps hitting the same 'expression too complex' compile-time blow-up this PR fixes. Either apply the same annotation to the Swift6 template (using the (wrappedValue: (any Sendable)?, isExplode: Bool) tuple type matching its APIHelper signature) or correct the PR description and rollout notes so they don't claim Swift6 was changed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/api.mustache, line 437:

<comment>The PR description states the typed-dictionary fix was also applied to the Swift6 template and that Swift6 samples should be re-generated, but the diff only changes swift5/api.mustache. swift6/api.mustache:307 still passes the unannotated dictionary literal directly to mapValuesToQueryItems, so Swift6-generated code for operations with many query parameters keeps hitting the same 'expression too complex' compile-time blow-up this PR fixes. Either apply the same annotation to the Swift6 template (using the `(wrappedValue: (any Sendable)?, isExplode: Bool)` tuple type matching its APIHelper signature) or correct the PR description and rollout notes so they don't claim Swift6 was changed.</comment>

<file context>
@@ -429,11 +429,12 @@ extension {{projectName}}API {
             {{/queryParams}}
-        ]){{/hasQueryParams}}{{^hasQueryParams}}
+        ]
+        localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters){{/hasQueryParams}}{{^hasQueryParams}}
         let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}}
 
</file context>

let localVariableUrlComponents = URLComponents(string: localVariableURLString){{/hasQueryParams}}

let localVariableNillableHeaders: [String: Any?] = [{{^headerParams}}{{^hasFormParams}}{{^hasConsumes}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,44 @@ public void oneOfDiscriminatorFirstDecodingTest() throws IOException {
}
}

@Test(description = "query parameter dictionaries carry an explicit type annotation so swiftc does not have to infer them", enabled = true)
public void queryParameterDictionaryIsTypeAnnotatedTest() throws IOException {
Path target = Files.createTempDirectory("test");
File output = target.toFile();
try {
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("swift5")
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setOutputDir(target.toAbsolutePath().toString());

final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");

List<File> files = generator.opts(clientOptInput).generate();

File apiFile = files.stream()
.filter(f -> f.getName().equals("PetAPI.swift"))
.findFirst()
.orElseThrow(() -> new RuntimeException("PetAPI.swift not found"));

String content = Files.readString(apiFile.toPath());

// The dictionary literal of (wrappedValue:, isExplode:) tuples must be bound to an
// explicitly typed local: without the annotation the constraint solver has to infer
// the type from every entry's encodeToJSON() overload at once, which times out
// ("the compiler is unable to type-check this expression in reasonable time")
// for operations with many query parameters.
Assert.assertTrue(content.contains("let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = ["));
Assert.assertTrue(content.contains("APIHelper.mapValuesToQueryItems(localVariableQueryParameters)"));

} finally {
output.deleteOnExit();
}
}

@Test
public void testAdditionalModelObjectAttributesParsing() {
Swift5ClientCodegen codegen = new Swift5ClientCodegen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,10 @@ open class FakeAPI {
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: body)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"query": (wrappedValue: query.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/json",
Expand Down Expand Up @@ -522,12 +523,13 @@ open class FakeAPI {
let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"enum_query_string_array": (wrappedValue: enumQueryStringArray?.encodeToJSON(), isExplode: false),
"enum_query_string": (wrappedValue: enumQueryString?.encodeToJSON(), isExplode: false),
"enum_query_integer": (wrappedValue: enumQueryInteger?.encodeToJSON(), isExplode: false),
"enum_query_double": (wrappedValue: enumQueryDouble?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/x-www-form-urlencoded",
Expand Down Expand Up @@ -584,12 +586,13 @@ open class FakeAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"required_string_group": (wrappedValue: requiredStringGroup.encodeToJSON(), isExplode: false),
"required_int64_group": (wrappedValue: requiredInt64Group.encodeToJSON(), isExplode: false),
"string_group": (wrappedValue: stringGroup?.encodeToJSON(), isExplode: false),
"int64_group": (wrappedValue: int64Group?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"required_boolean_group": requiredBooleanGroup.encodeToJSON(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"status": (wrappedValue: status.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down Expand Up @@ -208,9 +209,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"tags": (wrappedValue: tags.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,11 @@ open class UserAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"username": (wrappedValue: username.encodeToJSON(), isExplode: false),
"password": (wrappedValue: password.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,10 @@ open class FakeAPI {
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: body)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"query": (wrappedValue: query.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/json",
Expand Down Expand Up @@ -450,12 +451,13 @@ open class FakeAPI {
let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"enum_query_string_array": (wrappedValue: enumQueryStringArray?.encodeToJSON(), isExplode: false),
"enum_query_string": (wrappedValue: enumQueryString?.encodeToJSON(), isExplode: false),
"enum_query_integer": (wrappedValue: enumQueryInteger?.encodeToJSON(), isExplode: false),
"enum_query_double": (wrappedValue: enumQueryDouble?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/x-www-form-urlencoded",
Expand Down Expand Up @@ -504,12 +506,13 @@ open class FakeAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"required_string_group": (wrappedValue: requiredStringGroup.encodeToJSON(), isExplode: false),
"required_int64_group": (wrappedValue: requiredInt64Group.encodeToJSON(), isExplode: false),
"string_group": (wrappedValue: stringGroup?.encodeToJSON(), isExplode: false),
"int64_group": (wrappedValue: int64Group?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"required_boolean_group": requiredBooleanGroup.encodeToJSON(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"status": (wrappedValue: status.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down Expand Up @@ -176,9 +177,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"tags": (wrappedValue: tags.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,11 @@ open class UserAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"username": (wrappedValue: username.encodeToJSON(), isExplode: false),
"password": (wrappedValue: password.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,10 @@ open class FakeAPI {
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: body)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"query": (wrappedValue: query.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/json",
Expand Down Expand Up @@ -606,12 +607,13 @@ open class FakeAPI {
let localVariableParameters = APIHelper.convertBoolToString(localVariableNonNullParameters)

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"enum_query_string_array": (wrappedValue: enumQueryStringArray?.encodeToJSON(), isExplode: false),
"enum_query_string": (wrappedValue: enumQueryString?.encodeToJSON(), isExplode: false),
"enum_query_integer": (wrappedValue: enumQueryInteger?.encodeToJSON(), isExplode: false),
"enum_query_double": (wrappedValue: enumQueryDouble?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"Content-Type": "application/x-www-form-urlencoded",
Expand Down Expand Up @@ -677,12 +679,13 @@ open class FakeAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"required_string_group": (wrappedValue: requiredStringGroup.encodeToJSON(), isExplode: false),
"required_int64_group": (wrappedValue: requiredInt64Group.encodeToJSON(), isExplode: false),
"string_group": (wrappedValue: stringGroup?.encodeToJSON(), isExplode: false),
"int64_group": (wrappedValue: int64Group?.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
"required_boolean_group": requiredBooleanGroup.encodeToJSON(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"status": (wrappedValue: status.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down Expand Up @@ -247,9 +248,10 @@ open class PetAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"tags": (wrappedValue: tags.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,11 @@ open class UserAPI {
let localVariableParameters: [String: Any]? = nil

var localVariableUrlComponents = URLComponents(string: localVariableURLString)
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems([
let localVariableQueryParameters: [String: (wrappedValue: Any?, isExplode: Bool)] = [
"username": (wrappedValue: username.encodeToJSON(), isExplode: false),
"password": (wrappedValue: password.encodeToJSON(), isExplode: false),
])
]
localVariableUrlComponents?.queryItems = APIHelper.mapValuesToQueryItems(localVariableQueryParameters)

let localVariableNillableHeaders: [String: Any?] = [
:
Expand Down
Loading