Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dart-dio] Incorrect hashCode and == overide for fields withList #18198

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/dart-dio.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|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|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|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|
|equalityCheckMethod|Specify equality check method|<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|
|finalProperties|Whether properties are marked as final when using Json Serializable for serialization| |true|
|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|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8552,7 +8552,7 @@ protected void handleConstantParams(CodegenOperation operation) {
// Also, adds back non constant params to allParams.
for (CodegenParameter p : copy) {
if (p.isEnum && p.required && p._enum != null && p._enum.size() == 1) {
// Add to constantParams for use in the code generation templates.
// Add to constantParams for use in the code generation templates.
operation.constantParams.add(p);
if (p.isQueryParam) {
operation.queryParams.removeIf(param -> param.baseName.equals(p.baseName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
public static final String DATE_LIBRARY_TIME_MACHINE = "timemachine";
public static final String DATE_LIBRARY_DEFAULT = DATE_LIBRARY_CORE;

public static final String EQUALITY_CHECK_METHOD = "equalityCheckMethod";
public static final String EQUALITY_CHECK_METHOD_DEFAULT = "default";
public static final String EQUALITY_CHECK_METHOD_EQUATABLE = "equatable";
public static final String SERIALIZATION_LIBRARY_BUILT_VALUE = "built_value";
public static final String SERIALIZATION_LIBRARY_JSON_SERIALIZABLE = "json_serializable";
public static final String SERIALIZATION_LIBRARY_DEFAULT = SERIALIZATION_LIBRARY_BUILT_VALUE;
Expand All @@ -71,6 +74,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
private static final String CLIENT_NAME = "clientName";

private String dateLibrary;
private String equalityCheckMethod;

private String clientName;

Expand Down Expand Up @@ -107,19 +111,30 @@ public DartDioClientCodegen() {
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_DEFAULT);
cliOptions.add(serializationLibrary);

// Equality check option
final CliOption equalityCheckOption = CliOption.newString(EQUALITY_CHECK_METHOD, "Specify equality check method");
equalityCheckOption.setDefault(EQUALITY_CHECK_METHOD_DEFAULT);

final Map<String, String> equalityCheckOptions = new HashMap<>();
equalityCheckOptions.put(EQUALITY_CHECK_METHOD_DEFAULT, "[DEFAULT] Built in hash code generation method");
equalityCheckOptions.put(EQUALITY_CHECK_METHOD_EQUATABLE, "Uses equatable library for equality checking");
equalityCheckOption.setEnum(equalityCheckOptions);
cliOptions.add(equalityCheckOption);

// Date Library Option
final CliOption dateOption = CliOption.newString(DATE_LIBRARY, "Specify Date library");
dateOption.setDefault(DATE_LIBRARY_DEFAULT);

final CliOption finalProperties = CliOption.newBoolean(FINAL_PROPERTIES, "Whether properties are marked as final when using Json Serializable for serialization");
finalProperties.setDefault("true");
cliOptions.add(finalProperties);

final Map<String, String> dateOptions = new HashMap<>();
dateOptions.put(DATE_LIBRARY_CORE, "[DEFAULT] Dart core library (DateTime)");
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.");
dateOption.setEnum(dateOptions);
cliOptions.add(dateOption);

// Final Properties Option
final CliOption finalProperties = CliOption.newBoolean(FINAL_PROPERTIES, "Whether properties are marked as final when using Json Serializable for serialization");
finalProperties.setDefault("true");
cliOptions.add(finalProperties);
}

public String getDateLibrary() {
Expand All @@ -130,6 +145,14 @@ public void setDateLibrary(String library) {
this.dateLibrary = library;
}

public String getEqualityCheckMethod() {
return equalityCheckMethod;
}

public void setEqualityCheckMethod(String equalityCheckMethod) {
this.equalityCheckMethod = equalityCheckMethod;
}

public String getClientName() {
return clientName;
}
Expand Down Expand Up @@ -172,6 +195,12 @@ public void processOpts() {
}
setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());

if (!additionalProperties.containsKey(EQUALITY_CHECK_METHOD)) {
additionalProperties.put(EQUALITY_CHECK_METHOD, EQUALITY_CHECK_METHOD_DEFAULT);
LOGGER.debug("Equality check method not set, using default {}", EQUALITY_CHECK_METHOD_DEFAULT);
}
setEqualityCheckMethod(additionalProperties.get(EQUALITY_CHECK_METHOD).toString());

if (!additionalProperties.containsKey(FINAL_PROPERTIES)) {
additionalProperties.put(FINAL_PROPERTIES, Boolean.parseBoolean(FINAL_PROPERTIES_DEFAULT_VALUE));
LOGGER.debug("finalProperties not set, using default {}", FINAL_PROPERTIES_DEFAULT_VALUE);
Expand Down Expand Up @@ -205,6 +234,7 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("auth/auth.mustache", authFolder, "auth.dart"));

configureSerializationLibrary(srcFolder);
configureEqualityCheckMethod(srcFolder);
configureDateLibrary(srcFolder);
}

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

private void configureEqualityCheckMethod(String srcFolder) {
switch (equalityCheckMethod) {
case EQUALITY_CHECK_METHOD_EQUATABLE:
additionalProperties.put("useEquatable", "true");
break;
default:
case EQUALITY_CHECK_METHOD_DEFAULT:
break;
}
}

private void configureDateLibrary(String srcFolder) {
switch (dateLibrary) {
case DATE_LIBRARY_TIME_MACHINE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ dependencies:
built_value: '>=8.4.0 <9.0.0'
built_collection: '>=5.1.1 <6.0.0'
{{/useBuiltValue}}
{{#useEquatable}}
equatable: '^2.0.5'
{{/useEquatable}}
{{#useJsonSerializable}}
json_annotation: '^4.4.0'
{{/useJsonSerializable}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:json_annotation/json_annotation.dart';
{{#useEquatable}}
import 'package:equatable/src/equatable_utils.dart';
{{/useEquatable}}

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

Expand Down Expand Up @@ -61,17 +64,50 @@ class {{{classname}}} {


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

@override
int get hashCode =>
{{#vars}}
{{#isNullable}}({{{name}}} == null ? 0 : {{{name}}}.hashCode){{/isNullable}}{{^isNullable}}{{{name}}}.hashCode{{/isNullable}}{{^-last}} +{{/-last}}{{#-last}};{{/-last}}
{{/vars}}
{{#useEquatable}}
bool operator ==(Object other) {
return identical(this, other) ||
other is {{{classname}}} &&
runtimeType == other.runtimeType &&
equals(
[
{{#vars}}
{{{name}}},
{{/vars}}
],
[
{{#vars}}
other.{{{name}}},
{{/vars}}
]
);
}
{{/useEquatable}}

{{^useEquatable}}
@override
bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
{{#vars}}
other.{{{name}}} == {{{name}}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
{{/vars}}
{{/useEquatable}}

{{#useEquatable}}
@override
int get hashCode => runtimeType.hashCode ^ mapPropsToHashCode([
{{#vars}}
{{{name}}},
{{/vars}}
],);
{{/useEquatable}}
{{^useEquatable}}
@override
int get hashCode =>
{{#vars}}
{{#isNullable}}({{{name}}} == null ? 0 : {{{name}}}.hashCode){{/isNullable}}{{^isNullable}}{{{name}}}.hashCode{{/isNullable}}{{^-last}} +{{/-last}}{{#-last}};{{/-last}}
{{/vars}}
{{/useEquatable}}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import 'package:json_annotation/json_annotation.dart';
enum {{{classname}}} {
{{#allowableValues}}
{{#enumVars}}
{{#description}}
/// {{{.}}}
{{/description}}
@JsonValue({{#isString}}r{{/isString}}{{{value}}})
{{{name}}}({{^isString}}'{{/isString}}{{#isString}}r{{/isString}}{{{value}}}{{^isString}}'{{/isString}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{^isNull}}
{{#description}}
/// {{{.}}}
{{/description}}
@JsonValue({{#isString}}r{{/isString}}{{{value}}})
{{{name}}}({{^isString}}'{{/isString}}{{#isString}}r{{/isString}}{{{value}}}{{^isString}}'{{/isString}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
{{/isNull}}
{{/enumVars}}
{{/allowableValues}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.openapitools.codegen.AbstractOptionsTest;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.languages.DartClientCodegen;
import org.openapitools.codegen.languages.DartDioClientCodegen;
import org.openapitools.codegen.options.DartClientOptionsProvider;

import static org.mockito.Mockito.mock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ protected void verifyOptions() {
verify(clientCodegen).setUseEnumExtension(Boolean.parseBoolean(DartDioClientOptionsProvider.USE_ENUM_EXTENSION));
verify(clientCodegen).setDateLibrary(DartDioClientCodegen.DATE_LIBRARY_DEFAULT);
verify(clientCodegen).setLibrary(DartDioClientCodegen.SERIALIZATION_LIBRARY_DEFAULT);
verify(clientCodegen).setEqualityCheckMethod(DartDioClientCodegen.EQUALITY_CHECK_METHOD_DEFAULT);
verify(clientCodegen).setEnumUnknownDefaultCase(Boolean.parseBoolean(DartDioClientOptionsProvider.ENUM_UNKNOWN_DEFAULT_CASE_VALUE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.SERIALIZATION_LIBRARY, DartDioClientCodegen.SERIALIZATION_LIBRARY_DEFAULT)
.put(DartDioClientCodegen.DATE_LIBRARY, DartDioClientCodegen.DATE_LIBRARY_DEFAULT)
.put(DartDioClientCodegen.FINAL_PROPERTIES, DartDioClientCodegen.FINAL_PROPERTIES_DEFAULT_VALUE)
.put(DartDioClientCodegen.EQUALITY_CHECK_METHOD, DartDioClientCodegen.EQUALITY_CHECK_METHOD_DEFAULT)
.put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE)
.put(DartDioClientCodegen.USE_ENUM_EXTENSION, USE_ENUM_EXTENSION)
.put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,17 @@ class AdditionalPropertiesClass {



@override
bool operator ==(Object other) => identical(this, other) || other is AdditionalPropertiesClass &&
other.mapProperty == mapProperty &&
other.mapOfMapProperty == mapOfMapProperty;

@override
int get hashCode =>
mapProperty.hashCode +
mapOfMapProperty.hashCode;

@override
bool operator ==(Object other) => identical(this, other) || other is AdditionalPropertiesClass &&
other.mapProperty == mapProperty &&
other.mapOfMapProperty == mapOfMapProperty;

@override
int get hashCode =>
mapProperty.hashCode +
mapOfMapProperty.hashCode;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ class AllOfWithSingleRef {



@override
bool operator ==(Object other) => identical(this, other) || other is AllOfWithSingleRef &&
other.username == username &&
other.singleRefType == singleRefType;

@override
int get hashCode =>
username.hashCode +
singleRefType.hashCode;

@override
bool operator ==(Object other) => identical(this, other) || other is AllOfWithSingleRef &&
other.username == username &&
other.singleRefType == singleRefType;

@override
int get hashCode =>
username.hashCode +
singleRefType.hashCode;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,17 @@ class Animal {



@override
bool operator ==(Object other) => identical(this, other) || other is Animal &&
other.className == className &&
other.color == color;

@override
int get hashCode =>
className.hashCode +
color.hashCode;

@override
bool operator ==(Object other) => identical(this, other) || other is Animal &&
other.className == className &&
other.color == color;

@override
int get hashCode =>
className.hashCode +
color.hashCode;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,19 @@ class ApiResponse {



@override
bool operator ==(Object other) => identical(this, other) || other is ApiResponse &&
other.code == code &&
other.type == type &&
other.message == message;

@override
int get hashCode =>
code.hashCode +
type.hashCode +
message.hashCode;

@override
bool operator ==(Object other) => identical(this, other) || other is ApiResponse &&
other.code == code &&
other.type == type &&
other.message == message;

@override
int get hashCode =>
code.hashCode +
type.hashCode +
message.hashCode;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class ArrayOfArrayOfNumberOnly {



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

@override
int get hashCode =>
arrayArrayNumber.hashCode;

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

@override
int get hashCode =>
arrayArrayNumber.hashCode;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class ArrayOfNumberOnly {



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

@override
int get hashCode =>
arrayNumber.hashCode;

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

@override
int get hashCode =>
arrayNumber.hashCode;

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

Expand Down
Loading
Loading