From 77d9e91d10fd2f302dd02eb6bad87b6e35edb279 Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Tue, 3 Nov 2026 20:32:03 +0300 Subject: [PATCH 1/5] [dart-dio] fix: URI-encode path parameters The query_param helpers pass strings through unchanged (built_value) or interpolate raw values (freezed, json_serializable), so path parameters containing '/', spaces or other reserved characters broke the request path. Substitute path params through a new api/path_param partial that wraps the value in Uri.encodeComponent for all three serialization libraries. Fixes #25527 --- .../resources/dart/libraries/dio/api.mustache | 2 +- .../built_value/api/path_param.mustache | 3 ++ .../freezed/api/path_param.mustache | 3 ++ .../json_serializable/api/path_param.mustache | 3 ++ .../dart/dio/DartDioClientCodegenTest.java | 31 +++++++++++++++++++ .../lib/src/api/pet_api.dart | 20 +++++++++--- .../lib/src/api/store_api.dart | 10 ++++-- .../lib/src/api/user_api.dart | 15 +++++++-- .../lib/src/api/pet_api.dart | 25 ++++++++++++--- .../lib/src/api/store_api.dart | 10 ++++-- .../lib/src/api/user_api.dart | 15 +++++++-- .../lib/src/api/pet_api.dart | 25 ++++++++++++--- .../lib/src/api/store_api.dart | 10 ++++-- .../lib/src/api/user_api.dart | 15 +++++++-- .../lib/src/api/pet_api.dart | 25 ++++++++++++--- .../lib/src/api/store_api.dart | 10 ++++-- .../lib/src/api/user_api.dart | 15 +++++++-- 17 files changed, 197 insertions(+), 40 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache create mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache create mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache index ac0e989c6141..1914de69254d 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache @@ -51,7 +51,7 @@ class {{classname}} { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{{baseName}}}' '}', {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()){{/pathParams}}; + final _path = r'{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{{baseName}}}' '}', {{#includeLibraryTemplate}}api/path_param{{/includeLibraryTemplate}},){{/pathParams}}; final _options = Options( method: r'{{#lambda.uppercase}}{{httpMethod}}{{/lambda.uppercase}}', {{#isResponseFile}} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache new file mode 100644 index 000000000000..8241f8e9914d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache @@ -0,0 +1,3 @@ +Uri.encodeComponent( + {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), +) diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache new file mode 100644 index 000000000000..8241f8e9914d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache @@ -0,0 +1,3 @@ +Uri.encodeComponent( + {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), +) diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache new file mode 100644 index 000000000000..8241f8e9914d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache @@ -0,0 +1,3 @@ +Uri.encodeComponent( + {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), +) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java index acdf8de1cffc..c4f74ec7014f 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java @@ -471,6 +471,37 @@ public void testFreezedIgnoresUseOptional() throws IOException { TestUtils.assertFileNotContains(output.toPath().resolve("lib/src/model/pet.dart"), "Optional<"); } + /** + * Path parameters must be URI-encoded as path components: the query_param helpers pass + * strings through unchanged, so a value containing '/' or spaces would otherwise break + * the request path. + */ + @Test + public void testPathParamsAreUriEncoded() throws IOException { + for (Object[] libraryOption : serializationLibraries()) { + String serializationLibrary = (String) libraryOption[0]; + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("dart-dio") + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")) + .addAdditionalProperty(CodegenConstants.SERIALIZATION_LIBRARY, serializationLibrary); + + ClientOptInput opts = configurator.toClientOptInput(); + Generator generator = new DefaultGenerator().opts(opts); + List files = generator.generate(); + files.forEach(File::deleteOnExit); + + Path petApi = output.toPath().resolve("lib/src/api/pet_api.dart"); + String content = Files.readString(petApi, StandardCharsets.UTF_8); + Assert.assertTrue(content.contains(".replaceAll("), content); + Assert.assertTrue(content.contains("Uri.encodeComponent("), + "path parameter should be URI-encoded in " + serializationLibrary + ": " + content); + } + } + private Path generateFormParamsClient(String serializationLibrary) throws IOException { File output = Files.createTempDirectory("test").toFile(); output.deleteOnExit(); diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart index 8aaf646e3051..8f6b3d378552 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart @@ -146,7 +146,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -370,7 +373,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -558,7 +564,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -636,7 +645,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart index 5ad35b28d39a..ce3dff4b1aee 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart @@ -43,7 +43,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, orderId, const FullType(String)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -170,7 +173,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, orderId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart index c052b91ccf63..68ee84324d50 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart @@ -266,7 +266,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -320,7 +323,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -529,7 +535,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart index ada4f50fa6bb..ba954c9411e1 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart @@ -118,7 +118,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -336,7 +339,10 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -494,7 +500,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -572,7 +581,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -675,7 +687,10 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart index f3d48dc3d1f1..aee10338f9a5 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart @@ -40,7 +40,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + orderId.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -164,7 +167,10 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + orderId.toString(), +) +,); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart index ad5d89369ea4..1053514435ca 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart @@ -250,7 +250,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -297,7 +300,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -496,7 +502,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart index 60aaece86905..d2f23f84ef7a 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart @@ -114,7 +114,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -332,7 +335,10 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -486,7 +492,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -564,7 +573,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -667,7 +679,10 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', petId.toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + petId.toString(), +) +,); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart index 272e45a0ef6c..b52b8b8dea2e 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart @@ -40,7 +40,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + orderId.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -164,7 +167,10 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', orderId.toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + orderId.toString(), +) +,); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart index 87ceeccc6b4a..5f5717b8f9b0 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart @@ -238,7 +238,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -285,7 +288,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -484,7 +490,10 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', username.toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + username.toString(), +) +,); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart index a4da1c5ff6db..a8c1527fa1ff 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart @@ -118,7 +118,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -342,7 +345,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -500,7 +506,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -578,7 +587,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'POST', headers: { @@ -684,7 +696,10 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', encodeQueryParameter(_serializers, petId, const FullType(int)).toString()); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart index 6f519ff8ee51..1a3e0765284e 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart @@ -43,7 +43,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, orderId, const FullType(String)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -170,7 +173,10 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, orderId, const FullType(int)).toString(), +) +,); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart index 2a7e5132a60a..f9a4d0ca1615 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart @@ -244,7 +244,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'DELETE', headers: { @@ -291,7 +294,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'GET', headers: { @@ -493,7 +499,10 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', encodeQueryParameter(_serializers, username, const FullType(String)).toString()); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( + encodeQueryParameter(_serializers, username, const FullType(String)).toString(), +) +,); final _options = Options( method: r'PUT', headers: { From c55ffc3690f9df327cc0a91585c90cbb9a3c086f Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Tue, 3 Nov 2026 20:36:17 +0300 Subject: [PATCH 2/5] [ruby-nextgen] fix: always use explicit Zeitwerk loader with moduleName namespace Zeitwerk::Loader.for_gem derives its namespace from gemName, so a single-level moduleName that is not the camelized gemName (e.g. gemName=things_api, moduleName=Things) autoloaded nothing. Drive Zeitwerk explicitly with push_dir(namespace: self) in all cases - the nested branch already did, and it never depended on the names matching. Fixes #24997 --- .../main/resources/ruby-nextgen/gem.mustache | 11 +++----- .../RubyNextgenClientCodegenTest.java | 25 +++++++++++++++++++ .../others/ruby-nextgen-qdrant/lib/qdrant.rb | 11 +++++++- .../petstore/ruby-nextgen/lib/petstore.rb | 11 +++++++- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache b/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache index e411a4277681..68ee988370d9 100644 --- a/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-nextgen/gem.mustache @@ -21,10 +21,9 @@ module {{moduleName}} attr_reader :loader end -{{#moduleNameNested}} - # Nested moduleName: for_gem can't target a nested namespace, so drive Zeitwerk - # explicitly. The parent module(s) above are pre-defined so `module {{moduleName}}` - # (here and in every generated file) reopens rather than raising NameError. + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module {{moduleName}}` reopens rather than raising NameError. @loader = Zeitwerk::Loader.new @loader.push_dir("#{__dir__}/{{gemName}}", namespace: self) # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases @@ -32,10 +31,6 @@ module {{moduleName}} # {{moduleName}}::VERSION available. @loader.ignore("#{__dir__}/{{gemName}}/version.rb") require_relative "{{gemName}}/version" -{{/moduleNameNested}} -{{^moduleNameNested}} - @loader = Zeitwerk::Loader.for_gem -{{/moduleNameNested}} {{#zeitwerkInflections.0}} # Model names keep their acronym casing (e.g. HTTPConfig), but Zeitwerk's default # inflector would expect HttpConfig from the file name. Register the exceptions so diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java index 4158d40b4961..d914f9527319 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/rubynextgen/RubyNextgenClientCodegenTest.java @@ -443,6 +443,31 @@ public void testAcronymModelsGetZeitwerkInflections() throws Exception { "@two_fa_whitelist ||= DedicatedCloud::TwoFAWhitelist.new(@connection)"); } + @Test + public void testZeitwerkLoaderWhenModuleNameDiffersFromGemName() throws Exception { + java.nio.file.Path target = java.nio.file.Files.createTempDirectory("test"); + target.toFile().deleteOnExit(); + org.openapitools.codegen.ClientOptInput input = + new org.openapitools.codegen.config.CodegenConfigurator() + .setGeneratorName("ruby-nextgen") + .setInputSpec("src/test/resources/3_0/ruby-nextgen/acronym.yaml") + .setOutputDir(target.toString()) + // camelized gemName would be ThingsApi, but the namespace is Things: + // Zeitwerk::Loader.for_gem would target ThingsApi and autoload nothing + .addAdditionalProperty("gemName", "things_api") + .addAdditionalProperty("moduleName", "Things") + .toClientOptInput(); + new org.openapitools.codegen.DefaultGenerator(false).opts(input).generate(); + + // the explicit loader targets the moduleName namespace regardless of gemName + org.openapitools.codegen.TestUtils.assertFileContains( + target.resolve("lib/things_api.rb"), + "Zeitwerk::Loader.new", + "@loader.push_dir(\"#{__dir__}/things_api\", namespace: self)"); + org.openapitools.codegen.TestUtils.assertFileNotContains( + target.resolve("lib/things_api.rb"), "Zeitwerk::Loader.for_gem"); + } + @Test public void testNestedResourcesAreReachableFromClient() throws Exception { java.nio.file.Path target = java.nio.file.Files.createTempDirectory("test"); diff --git a/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb b/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb index 5be13f72f31e..612cc605f078 100644 --- a/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb +++ b/samples/client/others/ruby-nextgen-qdrant/lib/qdrant.rb @@ -20,7 +20,16 @@ class << self attr_reader :loader end - @loader = Zeitwerk::Loader.for_gem + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module Qdrant` reopens rather than raising NameError. + @loader = Zeitwerk::Loader.new + @loader.push_dir("#{__dir__}/qdrant", namespace: self) + # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases + # this; a plain Loader doesn't, so ignore it for autoloading and require it directly to keep + # Qdrant::VERSION available. + @loader.ignore("#{__dir__}/qdrant/version.rb") + require_relative "qdrant/version" # The `api/` directory on disk is fixed regardless of the `apiNamespace` CliOption, # but api.mustache only nests classes under an `Api` module when the wrapper is # enabled (true). When it's disabled, tell Zeitwerk to collapse diff --git a/samples/client/petstore/ruby-nextgen/lib/petstore.rb b/samples/client/petstore/ruby-nextgen/lib/petstore.rb index 19e492b7a84c..8ee009b7e8c1 100644 --- a/samples/client/petstore/ruby-nextgen/lib/petstore.rb +++ b/samples/client/petstore/ruby-nextgen/lib/petstore.rb @@ -19,7 +19,16 @@ class << self attr_reader :loader end - @loader = Zeitwerk::Loader.for_gem + # for_gem derives the namespace from gemName, which need not match moduleName (and + # can't target a nested one), so drive Zeitwerk explicitly. Any parent module(s) above + # are pre-defined so `module Petstore` reopens rather than raising NameError. + @loader = Zeitwerk::Loader.new + @loader.push_dir("#{__dir__}/petstore", namespace: self) + # version.rb defines VERSION (not a `Version` class). for_gem's GemInflector special-cases + # this; a plain Loader doesn't, so ignore it for autoloading and require it directly to keep + # Petstore::VERSION available. + @loader.ignore("#{__dir__}/petstore/version.rb") + require_relative "petstore/version" # The `api/` directory on disk is fixed regardless of the `apiNamespace` CliOption, # but api.mustache only nests classes under an `Api` module when the wrapper is # enabled (true). When it's disabled, tell Zeitwerk to collapse From 8349ba66f0f9b7e35cf18a624e877e00486c091a Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Tue, 3 Nov 2026 23:42:45 +0300 Subject: [PATCH 3/5] [dart-dio] pin source_helper <1.4.0 in the freezed variant source_helper 1.4.0 (published 2026-10-19) added extension members that clash with json_serializable 6.x's internal copies, breaking compilation of the build_runner build script ('toStringNonNullable is defined in multiple extensions'). The json_serializable variant is unaffected because copy_with_extension_gen's source_gen constraint holds source_helper below 1.4.0; the freezed variant has no such guard and floated to 1.4.0. Verified with Dart 3.9: pub get resolves source_helper 1.3.13, build_runner builds, dart test passes (190 tests). --- .../src/main/resources/dart/libraries/dio/pubspec.mustache | 5 +++++ .../dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache index 1d7352f8cc26..0fd014044c8e 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache @@ -54,5 +54,10 @@ dev_dependencies: build_runner: any freezed: '^3.0.0' json_serializable: '^6.9.3' + # unlike the json_serializable variant, this one has no copy_with_extension_gen + # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 + # added extension members that clash with json_serializable 6.x's internal + # copies and break the build_runner build script, so hold it below 1.4.0 + source_helper: '>=1.3.13 <1.4.0' {{/useFreezed}} test: '^1.16.0' diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml index 5bde8eacee67..3615b34d416c 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml @@ -16,4 +16,9 @@ dev_dependencies: build_runner: any freezed: '^3.0.0' json_serializable: '^6.9.3' + # unlike the json_serializable variant, this one has no copy_with_extension_gen + # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 + # added extension members that clash with json_serializable 6.x's internal + # copies and break the build_runner build script, so hold it below 1.4.0 + source_helper: '>=1.3.13 <1.4.0' test: '^1.16.0' From d067857c6a0615b9ba44b4d066eb204cf0b60327 Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Tue, 3 Nov 2026 23:48:47 +0300 Subject: [PATCH 4/5] [dart-dio] single-line path_param template and stronger encoding test - render Uri.encodeComponent on one line so generated paths keep the previous single-line style - assert in testPathParamsAreUriEncoded that the number of Uri.encodeComponent calls equals the number of path substitutions in every generated api class, not just that one occurrence exists Addresses review feedback in #25544. --- .../built_value/api/path_param.mustache | 4 +-- .../freezed/api/path_param.mustache | 4 +-- .../json_serializable/api/path_param.mustache | 4 +-- .../dart/dio/DartDioClientCodegenTest.java | 22 +++++++++++----- .../lib/src/api/pet_api.dart | 20 +++------------ .../lib/src/api/store_api.dart | 10 ++------ .../lib/src/api/user_api.dart | 15 +++-------- .../lib/src/api/pet_api.dart | 25 ++++--------------- .../lib/src/api/store_api.dart | 10 ++------ .../lib/src/api/user_api.dart | 15 +++-------- .../lib/src/api/pet_api.dart | 25 ++++--------------- .../lib/src/api/store_api.dart | 10 ++------ .../lib/src/api/user_api.dart | 15 +++-------- .../lib/src/api/pet_api.dart | 25 ++++--------------- .../lib/src/api/store_api.dart | 10 ++------ .../lib/src/api/user_api.dart | 15 +++-------- 16 files changed, 58 insertions(+), 171 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache index 8241f8e9914d..1d633242d7cd 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api/path_param.mustache @@ -1,3 +1 @@ -Uri.encodeComponent( - {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), -) +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache index 8241f8e9914d..1d633242d7cd 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/path_param.mustache @@ -1,3 +1 @@ -Uri.encodeComponent( - {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), -) +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache index 8241f8e9914d..1d633242d7cd 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/api/path_param.mustache @@ -1,3 +1 @@ -Uri.encodeComponent( - {{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString(), -) +Uri.encodeComponent({{#includeLibraryTemplate}}api/query_param{{/includeLibraryTemplate}}.toString()) \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java index c4f74ec7014f..e501bb1d5c0d 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientCodegenTest.java @@ -474,7 +474,8 @@ public void testFreezedIgnoresUseOptional() throws IOException { /** * Path parameters must be URI-encoded as path components: the query_param helpers pass * strings through unchanged, so a value containing '/' or spaces would otherwise break - * the request path. + * the request path. Every path substitution must therefore go through + * Uri.encodeComponent. */ @Test public void testPathParamsAreUriEncoded() throws IOException { @@ -494,11 +495,20 @@ public void testPathParamsAreUriEncoded() throws IOException { List files = generator.generate(); files.forEach(File::deleteOnExit); - Path petApi = output.toPath().resolve("lib/src/api/pet_api.dart"); - String content = Files.readString(petApi, StandardCharsets.UTF_8); - Assert.assertTrue(content.contains(".replaceAll("), content); - Assert.assertTrue(content.contains("Uri.encodeComponent("), - "path parameter should be URI-encoded in " + serializationLibrary + ": " + content); + // check every generated api class, not just one + Path apiDir = output.toPath().resolve("lib/src/api"); + try (var apiFiles = Files.list(apiDir)) { + for (Path apiFile : apiFiles.filter(p -> p.getFileName().toString().endsWith("_api.dart")) + .collect(java.util.stream.Collectors.toList())) { + String content = Files.readString(apiFile, StandardCharsets.UTF_8); + int substitutions = content.split("\\.replaceAll\\(", -1).length - 1; + Assert.assertTrue(substitutions > 0, + "expected path substitutions in " + apiFile + ": " + content); + int encodings = content.split("Uri\\.encodeComponent\\(", -1).length - 1; + Assert.assertEquals(encodings, substitutions, + "every path substitution in " + apiFile + " must be URI-encoded: " + content); + } + } } } diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart index 8f6b3d378552..6161c2f7eb2d 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/pet_api.dart @@ -146,10 +146,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -373,10 +370,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { @@ -564,10 +558,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -645,10 +636,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart index ce3dff4b1aee..ebd11aef63e3 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/store_api.dart @@ -43,10 +43,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, orderId, const FullType(String)).toString(), -) -,); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -173,10 +170,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, orderId, const FullType(int)).toString(), -) -,); + final _path = r'/store/order/{orderId}'.replaceAll('{' r'orderId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart index 68ee84324d50..7555893e7eb5 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore-timemachine/lib/src/api/user_api.dart @@ -266,10 +266,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -323,10 +320,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'GET', headers: { @@ -535,10 +529,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart index ba954c9411e1..8c6df90231db 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/pet_api.dart @@ -118,10 +118,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -339,10 +336,7 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'GET', headers: { @@ -500,10 +494,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -581,10 +572,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -687,10 +675,7 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart index aee10338f9a5..0b9117eeb2f8 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/store_api.dart @@ -40,10 +40,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - orderId.toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -167,10 +164,7 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - orderId.toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart index 1053514435ca..0076a6f55775 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/lib/src/api/user_api.dart @@ -250,10 +250,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -300,10 +297,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'GET', headers: { @@ -502,10 +496,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart index d2f23f84ef7a..56b029ed8ca0 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/pet_api.dart @@ -114,10 +114,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -335,10 +332,7 @@ _responseData = rawData == null ? null : deserialize, Pet>(rawData, 'Se ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'GET', headers: { @@ -492,10 +486,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -573,10 +564,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'Pet', g ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { @@ -679,10 +667,7 @@ _responseData = rawData == null ? null : deserialize(r ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - petId.toString(), -) -,); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(petId.toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart index b52b8b8dea2e..4ffc14056b5a 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/store_api.dart @@ -40,10 +40,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - orderId.toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -167,10 +164,7 @@ _responseData = rawData == null ? null : deserialize, int>(rawD ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - orderId.toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(orderId.toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart index 5f5717b8f9b0..166786eed585 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/api/user_api.dart @@ -238,10 +238,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'DELETE', headers: { @@ -288,10 +285,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'GET', headers: { @@ -490,10 +484,7 @@ _responseData = rawData == null ? null : deserialize(rawData, 'S ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - username.toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(username.toString()),); final _options = Options( method: r'PUT', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart index a8c1527fa1ff..379f664abef8 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/pet_api.dart @@ -118,10 +118,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -345,10 +342,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { @@ -506,10 +500,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -587,10 +578,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/pet/{petId}/uploadImage'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { @@ -696,10 +684,7 @@ class PetApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, petId, const FullType(int)).toString(), -) -,); + final _path = r'/fake/{petId}/uploadImageWithRequiredFile'.replaceAll('{' r'petId' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, petId, const FullType(int)).toString()),); final _options = Options( method: r'POST', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart index 1a3e0765284e..3c3e6ccb8f8d 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/store_api.dart @@ -43,10 +43,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, orderId, const FullType(String)).toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -173,10 +170,7 @@ class StoreApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, orderId, const FullType(int)).toString(), -) -,); + final _path = r'/store/order/{order_id}'.replaceAll('{' r'order_id' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, orderId, const FullType(int)).toString()),); final _options = Options( method: r'GET', headers: { diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart index f9a4d0ca1615..f7b22e1a2bf2 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake/lib/src/api/user_api.dart @@ -244,10 +244,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'DELETE', headers: { @@ -294,10 +291,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'GET', headers: { @@ -499,10 +493,7 @@ class UserApi { ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, }) async { - final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent( - encodeQueryParameter(_serializers, username, const FullType(String)).toString(), -) -,); + final _path = r'/user/{username}'.replaceAll('{' r'username' '}', Uri.encodeComponent(encodeQueryParameter(_serializers, username, const FullType(String)).toString()),); final _options = Options( method: r'PUT', headers: { From 685e5df1c6596b2e2c1d0def1af816005cf0e437 Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Tue, 3 Nov 2026 23:52:15 +0300 Subject: [PATCH 5/5] [dart-dio] widen source_helper lower bound to 1.3.8 source_helper 1.3.9+ requires Dart 3.9, but the freezed variant advertises sdk >=3.8.0 - 1.3.8 (source_gen >=3.1.0 <5.0.0, Dart ^3.7.0) keeps 3.8 users able to resolve while 3.9+ users still get 1.3.13. Addresses review feedback in #25544. --- .../src/main/resources/dart/libraries/dio/pubspec.mustache | 6 ++++-- .../dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache index 0fd014044c8e..40a3771c4fec 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache @@ -57,7 +57,9 @@ dev_dependencies: # unlike the json_serializable variant, this one has no copy_with_extension_gen # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 # added extension members that clash with json_serializable 6.x's internal - # copies and break the build_runner build script, so hold it below 1.4.0 - source_helper: '>=1.3.13 <1.4.0' + # copies and break the build_runner build script, so hold it below 1.4.0. + # 1.3.9+ requires Dart 3.9 while this variant advertises >=3.8.0, so keep the + # 1.3.8 lower bound resolvable for 3.8 users + source_helper: '>=1.3.8 <1.4.0' {{/useFreezed}} test: '^1.16.0' diff --git a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml index 3615b34d416c..4d08924131e1 100644 --- a/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml +++ b/samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-freezed/pubspec.yaml @@ -19,6 +19,8 @@ dev_dependencies: # unlike the json_serializable variant, this one has no copy_with_extension_gen # whose source_gen constraint would hold source_helper back; source_helper 1.4.0 # added extension members that clash with json_serializable 6.x's internal - # copies and break the build_runner build script, so hold it below 1.4.0 - source_helper: '>=1.3.13 <1.4.0' + # copies and break the build_runner build script, so hold it below 1.4.0. + # 1.3.9+ requires Dart 3.9 while this variant advertises >=3.8.0, so keep the + # 1.3.8 lower bound resolvable for 3.8 users + source_helper: '>=1.3.8 <1.4.0' test: '^1.16.0'