Skip to content

Commit 3d15864

Browse files
authored
[dart-dio] Incorrect hashCode and == overide for fields withList (#18198)
* [dart-dio] Incorrect hashCode and == overide for fields withList * fix * extend description --------- Co-authored-by: Vasiliy Ditsyak <vasilich6107@users.noreply.github.com>
1 parent 8924083 commit 3d15864

File tree

59 files changed

+684
-510
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+684
-510
lines changed

docs/generators/dart-dio.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2323
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
2424
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
2525
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
26+
|equalityCheckMethod|Specify equality check method. Takes effect only in case if serializationLibrary is json_serializable.|<dl><dt>**default**</dt><dd>[DEFAULT] Built in hash code generation method</dd><dt>**equatable**</dt><dd>Uses equatable library for equality checking</dd></dl>|default|
2627
|finalProperties|Whether properties are marked as final when using Json Serializable for serialization| |true|
2728
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
2829
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -8545,7 +8545,7 @@ protected void handleConstantParams(CodegenOperation operation) {
85458545
// Also, adds back non constant params to allParams.
85468546
for (CodegenParameter p : copy) {
85478547
if (p.isEnum && p.required && p._enum != null && p._enum.size() == 1) {
8548-
// Add to constantParams for use in the code generation templates.
8548+
// Add to constantParams for use in the code generation templates.
85498549
operation.constantParams.add(p);
85508550
if (p.isQueryParam) {
85518551
operation.queryParams.removeIf(param -> param.baseName.equals(p.baseName));

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java

+45-4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
6060
public static final String DATE_LIBRARY_TIME_MACHINE = "timemachine";
6161
public static final String DATE_LIBRARY_DEFAULT = DATE_LIBRARY_CORE;
6262

63+
public static final String EQUALITY_CHECK_METHOD = "equalityCheckMethod";
64+
public static final String EQUALITY_CHECK_METHOD_DEFAULT = "default";
65+
public static final String EQUALITY_CHECK_METHOD_EQUATABLE = "equatable";
6366
public static final String SERIALIZATION_LIBRARY_BUILT_VALUE = "built_value";
6467
public static final String SERIALIZATION_LIBRARY_JSON_SERIALIZABLE = "json_serializable";
6568
public static final String SERIALIZATION_LIBRARY_DEFAULT = SERIALIZATION_LIBRARY_BUILT_VALUE;
@@ -71,6 +74,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
7174
private static final String CLIENT_NAME = "clientName";
7275

7376
private String dateLibrary;
77+
private String equalityCheckMethod;
7478

7579
private String clientName;
7680

@@ -107,19 +111,30 @@ public DartDioClientCodegen() {
107111
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_DEFAULT);
108112
cliOptions.add(serializationLibrary);
109113

114+
// Equality check option
115+
final CliOption equalityCheckOption = CliOption.newString(EQUALITY_CHECK_METHOD, "Specify equality check method. Takes effect only in case if serializationLibrary is json_serializable.");
116+
equalityCheckOption.setDefault(EQUALITY_CHECK_METHOD_DEFAULT);
117+
118+
final Map<String, String> equalityCheckOptions = new HashMap<>();
119+
equalityCheckOptions.put(EQUALITY_CHECK_METHOD_DEFAULT, "[DEFAULT] Built in hash code generation method");
120+
equalityCheckOptions.put(EQUALITY_CHECK_METHOD_EQUATABLE, "Uses equatable library for equality checking");
121+
equalityCheckOption.setEnum(equalityCheckOptions);
122+
cliOptions.add(equalityCheckOption);
123+
110124
// Date Library Option
111125
final CliOption dateOption = CliOption.newString(DATE_LIBRARY, "Specify Date library");
112126
dateOption.setDefault(DATE_LIBRARY_DEFAULT);
113127

114-
final CliOption finalProperties = CliOption.newBoolean(FINAL_PROPERTIES, "Whether properties are marked as final when using Json Serializable for serialization");
115-
finalProperties.setDefault("true");
116-
cliOptions.add(finalProperties);
117-
118128
final Map<String, String> dateOptions = new HashMap<>();
119129
dateOptions.put(DATE_LIBRARY_CORE, "[DEFAULT] Dart core library (DateTime)");
120130
dateOptions.put(DATE_LIBRARY_TIME_MACHINE, "Time Machine is date and time library for Flutter, Web, and Server with support for timezones, calendars, cultures, formatting and parsing.");
121131
dateOption.setEnum(dateOptions);
122132
cliOptions.add(dateOption);
133+
134+
// Final Properties Option
135+
final CliOption finalProperties = CliOption.newBoolean(FINAL_PROPERTIES, "Whether properties are marked as final when using Json Serializable for serialization");
136+
finalProperties.setDefault("true");
137+
cliOptions.add(finalProperties);
123138
}
124139

125140
public String getDateLibrary() {
@@ -130,6 +145,14 @@ public void setDateLibrary(String library) {
130145
this.dateLibrary = library;
131146
}
132147

148+
public String getEqualityCheckMethod() {
149+
return equalityCheckMethod;
150+
}
151+
152+
public void setEqualityCheckMethod(String equalityCheckMethod) {
153+
this.equalityCheckMethod = equalityCheckMethod;
154+
}
155+
133156
public String getClientName() {
134157
return clientName;
135158
}
@@ -172,6 +195,12 @@ public void processOpts() {
172195
}
173196
setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());
174197

198+
if (!additionalProperties.containsKey(EQUALITY_CHECK_METHOD)) {
199+
additionalProperties.put(EQUALITY_CHECK_METHOD, EQUALITY_CHECK_METHOD_DEFAULT);
200+
LOGGER.debug("Equality check method not set, using default {}", EQUALITY_CHECK_METHOD_DEFAULT);
201+
}
202+
setEqualityCheckMethod(additionalProperties.get(EQUALITY_CHECK_METHOD).toString());
203+
175204
if (!additionalProperties.containsKey(FINAL_PROPERTIES)) {
176205
additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(FINAL_PROPERTIES_DEFAULT_VALUE));
177206
LOGGER.debug("finalProperties not set, using default {}", FINAL_PROPERTIES_DEFAULT_VALUE);
@@ -205,6 +234,7 @@ public void processOpts() {
205234
supportingFiles.add(new SupportingFile("auth/auth.mustache", authFolder, "auth.dart"));
206235

207236
configureSerializationLibrary(srcFolder);
237+
configureEqualityCheckMethod(srcFolder);
208238
configureDateLibrary(srcFolder);
209239
}
210240

@@ -278,6 +308,17 @@ private void configureSerializationLibraryJsonSerializable(String srcFolder) {
278308
imports.put("MultipartFile", DIO_IMPORT);
279309
}
280310

311+
private void configureEqualityCheckMethod(String srcFolder) {
312+
switch (equalityCheckMethod) {
313+
case EQUALITY_CHECK_METHOD_EQUATABLE:
314+
additionalProperties.put("useEquatable", "true");
315+
break;
316+
default:
317+
case EQUALITY_CHECK_METHOD_DEFAULT:
318+
break;
319+
}
320+
}
321+
281322
private void configureDateLibrary(String srcFolder) {
282323
switch (dateLibrary) {
283324
case DATE_LIBRARY_TIME_MACHINE:

modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ dependencies:
2020
built_value: '>=8.4.0 <9.0.0'
2121
built_collection: '>=5.1.1 <6.0.0'
2222
{{/useBuiltValue}}
23+
{{#useEquatable}}
24+
equatable: '^2.0.5'
25+
{{/useEquatable}}
2326
{{#useJsonSerializable}}
2427
json_annotation: '^4.4.0'
2528
{{/useJsonSerializable}}

modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/class.mustache

+46-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import 'package:json_annotation/json_annotation.dart';
2+
{{#useEquatable}}
3+
import 'package:equatable/src/equatable_utils.dart';
4+
{{/useEquatable}}
25

36
part '{{classFilename}}.g.dart';
47

@@ -61,17 +64,50 @@ class {{{classname}}} {
6164

6265

6366
{{/vars}}
64-
@override
65-
bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
66-
{{#vars}}
67-
other.{{{name}}} == {{{name}}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
68-
{{/vars}}
6967

70-
@override
71-
int get hashCode =>
72-
{{#vars}}
73-
{{#isNullable}}({{{name}}} == null ? 0 : {{{name}}}.hashCode){{/isNullable}}{{^isNullable}}{{{name}}}.hashCode{{/isNullable}}{{^-last}} +{{/-last}}{{#-last}};{{/-last}}
74-
{{/vars}}
68+
{{#useEquatable}}
69+
bool operator ==(Object other) {
70+
return identical(this, other) ||
71+
other is {{{classname}}} &&
72+
runtimeType == other.runtimeType &&
73+
equals(
74+
[
75+
{{#vars}}
76+
{{{name}}},
77+
{{/vars}}
78+
],
79+
[
80+
{{#vars}}
81+
other.{{{name}}},
82+
{{/vars}}
83+
]
84+
);
85+
}
86+
{{/useEquatable}}
87+
88+
{{^useEquatable}}
89+
@override
90+
bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
91+
{{#vars}}
92+
other.{{{name}}} == {{{name}}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
93+
{{/vars}}
94+
{{/useEquatable}}
95+
96+
{{#useEquatable}}
97+
@override
98+
int get hashCode => runtimeType.hashCode ^ mapPropsToHashCode([
99+
{{#vars}}
100+
{{{name}}},
101+
{{/vars}}
102+
],);
103+
{{/useEquatable}}
104+
{{^useEquatable}}
105+
@override
106+
int get hashCode =>
107+
{{#vars}}
108+
{{#isNullable}}({{{name}}} == null ? 0 : {{{name}}}.hashCode){{/isNullable}}{{^isNullable}}{{{name}}}.hashCode{{/isNullable}}{{^-last}} +{{/-last}}{{#-last}};{{/-last}}
109+
{{/vars}}
110+
{{/useEquatable}}
75111

76112
factory {{{classname}}}.fromJson(Map<String, dynamic> json) => _${{{classname}}}FromJson(json);
77113

modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/json_serializable/enum.mustache

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import 'package:json_annotation/json_annotation.dart';
77
enum {{{classname}}} {
88
{{#allowableValues}}
99
{{#enumVars}}
10-
{{#description}}
11-
/// {{{.}}}
12-
{{/description}}
13-
@JsonValue({{#isString}}r{{/isString}}{{{value}}})
14-
{{{name}}}({{^isString}}'{{/isString}}{{#isString}}r{{/isString}}{{{value}}}{{^isString}}'{{/isString}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
10+
{{^isNull}}
11+
{{#description}}
12+
/// {{{.}}}
13+
{{/description}}
14+
@JsonValue({{#isString}}r{{/isString}}{{{value}}})
15+
{{{name}}}({{^isString}}'{{/isString}}{{#isString}}r{{/isString}}{{{value}}}{{^isString}}'{{/isString}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
16+
{{/isNull}}
1517
{{/enumVars}}
1618
{{/allowableValues}}
1719

modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/DartClientOptionsTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.openapitools.codegen.AbstractOptionsTest;
2121
import org.openapitools.codegen.CodegenConfig;
2222
import org.openapitools.codegen.languages.DartClientCodegen;
23+
import org.openapitools.codegen.languages.DartDioClientCodegen;
2324
import org.openapitools.codegen.options.DartClientOptionsProvider;
2425

2526
import static org.mockito.Mockito.mock;

modules/openapi-generator/src/test/java/org/openapitools/codegen/dart/dio/DartDioClientOptionsTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ protected void verifyOptions() {
5353
verify(clientCodegen).setUseEnumExtension(Boolean.parseBoolean(DartDioClientOptionsProvider.USE_ENUM_EXTENSION));
5454
verify(clientCodegen).setDateLibrary(DartDioClientCodegen.DATE_LIBRARY_DEFAULT);
5555
verify(clientCodegen).setLibrary(DartDioClientCodegen.SERIALIZATION_LIBRARY_DEFAULT);
56+
verify(clientCodegen).setEqualityCheckMethod(DartDioClientCodegen.EQUALITY_CHECK_METHOD_DEFAULT);
5657
verify(clientCodegen).setEnumUnknownDefaultCase(Boolean.parseBoolean(DartDioClientOptionsProvider.ENUM_UNKNOWN_DEFAULT_CASE_VALUE));
5758
}
5859
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public Map<String, String> createOptions() {
6464
.put(CodegenConstants.SERIALIZATION_LIBRARY, DartDioClientCodegen.SERIALIZATION_LIBRARY_DEFAULT)
6565
.put(DartDioClientCodegen.DATE_LIBRARY, DartDioClientCodegen.DATE_LIBRARY_DEFAULT)
6666
.put(DartDioClientCodegen.FINAL_PROPERTIES, DartDioClientCodegen.FINAL_PROPERTIES_DEFAULT_VALUE)
67+
.put(DartDioClientCodegen.EQUALITY_CHECK_METHOD, DartDioClientCodegen.EQUALITY_CHECK_METHOD_DEFAULT)
6768
.put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE)
6869
.put(DartDioClientCodegen.USE_ENUM_EXTENSION, USE_ENUM_EXTENSION)
6970
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/additional_properties_class.dart

+10-8
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ class AdditionalPropertiesClass {
4747

4848

4949

50-
@override
51-
bool operator ==(Object other) => identical(this, other) || other is AdditionalPropertiesClass &&
52-
other.mapProperty == mapProperty &&
53-
other.mapOfMapProperty == mapOfMapProperty;
5450

55-
@override
56-
int get hashCode =>
57-
mapProperty.hashCode +
58-
mapOfMapProperty.hashCode;
51+
52+
@override
53+
bool operator ==(Object other) => identical(this, other) || other is AdditionalPropertiesClass &&
54+
other.mapProperty == mapProperty &&
55+
other.mapOfMapProperty == mapOfMapProperty;
56+
57+
@override
58+
int get hashCode =>
59+
mapProperty.hashCode +
60+
mapOfMapProperty.hashCode;
5961

6062
factory AdditionalPropertiesClass.fromJson(Map<String, dynamic> json) => _$AdditionalPropertiesClassFromJson(json);
6163

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/all_of_with_single_ref.dart

+10-8
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,17 @@ class AllOfWithSingleRef {
4848

4949

5050

51-
@override
52-
bool operator ==(Object other) => identical(this, other) || other is AllOfWithSingleRef &&
53-
other.username == username &&
54-
other.singleRefType == singleRefType;
5551

56-
@override
57-
int get hashCode =>
58-
username.hashCode +
59-
singleRefType.hashCode;
52+
53+
@override
54+
bool operator ==(Object other) => identical(this, other) || other is AllOfWithSingleRef &&
55+
other.username == username &&
56+
other.singleRefType == singleRefType;
57+
58+
@override
59+
int get hashCode =>
60+
username.hashCode +
61+
singleRefType.hashCode;
6062

6163
factory AllOfWithSingleRef.fromJson(Map<String, dynamic> json) => _$AllOfWithSingleRefFromJson(json);
6264

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/animal.dart

+10-8
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ class Animal {
4747

4848

4949

50-
@override
51-
bool operator ==(Object other) => identical(this, other) || other is Animal &&
52-
other.className == className &&
53-
other.color == color;
5450

55-
@override
56-
int get hashCode =>
57-
className.hashCode +
58-
color.hashCode;
51+
52+
@override
53+
bool operator ==(Object other) => identical(this, other) || other is Animal &&
54+
other.className == className &&
55+
other.color == color;
56+
57+
@override
58+
int get hashCode =>
59+
className.hashCode +
60+
color.hashCode;
5961

6062
factory Animal.fromJson(Map<String, dynamic> json) => _$AnimalFromJson(json);
6163

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/api_response.dart

+12-10
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,19 @@ class ApiResponse {
6161

6262

6363

64-
@override
65-
bool operator ==(Object other) => identical(this, other) || other is ApiResponse &&
66-
other.code == code &&
67-
other.type == type &&
68-
other.message == message;
6964

70-
@override
71-
int get hashCode =>
72-
code.hashCode +
73-
type.hashCode +
74-
message.hashCode;
65+
66+
@override
67+
bool operator ==(Object other) => identical(this, other) || other is ApiResponse &&
68+
other.code == code &&
69+
other.type == type &&
70+
other.message == message;
71+
72+
@override
73+
int get hashCode =>
74+
code.hashCode +
75+
type.hashCode +
76+
message.hashCode;
7577

7678
factory ApiResponse.fromJson(Map<String, dynamic> json) => _$ApiResponseFromJson(json);
7779

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/array_of_array_of_number_only.dart

+8-6
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ class ArrayOfArrayOfNumberOnly {
3333

3434

3535

36-
@override
37-
bool operator ==(Object other) => identical(this, other) || other is ArrayOfArrayOfNumberOnly &&
38-
other.arrayArrayNumber == arrayArrayNumber;
3936

40-
@override
41-
int get hashCode =>
42-
arrayArrayNumber.hashCode;
37+
38+
@override
39+
bool operator ==(Object other) => identical(this, other) || other is ArrayOfArrayOfNumberOnly &&
40+
other.arrayArrayNumber == arrayArrayNumber;
41+
42+
@override
43+
int get hashCode =>
44+
arrayArrayNumber.hashCode;
4345

4446
factory ArrayOfArrayOfNumberOnly.fromJson(Map<String, dynamic> json) => _$ArrayOfArrayOfNumberOnlyFromJson(json);
4547

samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake-json_serializable/lib/src/model/array_of_number_only.dart

+8-6
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ class ArrayOfNumberOnly {
3333

3434

3535

36-
@override
37-
bool operator ==(Object other) => identical(this, other) || other is ArrayOfNumberOnly &&
38-
other.arrayNumber == arrayNumber;
3936

40-
@override
41-
int get hashCode =>
42-
arrayNumber.hashCode;
37+
38+
@override
39+
bool operator ==(Object other) => identical(this, other) || other is ArrayOfNumberOnly &&
40+
other.arrayNumber == arrayNumber;
41+
42+
@override
43+
int get hashCode =>
44+
arrayNumber.hashCode;
4345

4446
factory ArrayOfNumberOnly.fromJson(Map<String, dynamic> json) => _$ArrayOfNumberOnlyFromJson(json);
4547

0 commit comments

Comments
 (0)