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][built_value] Fix missing serializer factory builders for additionalProperties #11011

Merged
merged 1 commit into from
Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
super.postProcessModelProperty(model, property);
if (!model.isEnum && property.isEnum) {
// These are inner enums, enums which do not exist as models, just as properties.
// They are handled via the enum_inline template and and are generated in the
// They are handled via the enum_inline template and are generated in the
// same file as the containing class. To prevent name clashes the inline enum classes
// are prefix with the classname of the containing class in the template.
// Here the datatypeWithEnum template variable gets updated to match that scheme.
Expand All @@ -529,9 +529,9 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
final CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
for (CodegenResponse r : op.responses) {
// By default only set types are automatically added to operation imports, not sure why.
// By default, only set types are automatically added to operation imports, not sure why.
// Add all container type imports here, by default 'dart:core' imports are skipped
// but other sub classes may required specific container type imports.
// but other sub-classes may require specific container type imports.
if (r.containerType != null && typeMapping().containsKey(r.containerType)) {
final String value = typeMapping().get(r.containerType);
if (needToImport(value)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,21 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
// enums are generated with built_value and make use of BuiltSet
model.imports.add("BuiltSet");
}

if (property.isContainer) {
// Figure out if there are any container type additionalProperties
// that need a custom serializer builder factory added.
final CodegenProperty items = property.items;
if (items.getAdditionalProperties() != null) {
addBuiltValueSerializer(new BuiltValueSerializer(
items.isArray,
items.getUniqueItems(),
items.isMap,
items.items.isNullable,
items.getAdditionalProperties().dataType
));
}
}
}
}

Expand All @@ -332,7 +347,6 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");

Set<Map<String, Object>> serializers = new HashSet<>();
Set<String> resultImports = new HashSet<>();

for (CodegenOperation op : operationList) {
Expand Down Expand Up @@ -370,12 +384,13 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
// Generate serializer factories for all container type parameters.
// But skip binary and file parameters, JSON serializers don't make sense there.
if (param.isContainer && !(param.isBinary || param.isFile )) {
final Map<String, Object> serializer = new HashMap<>();
serializer.put("isArray", param.isArray);
serializer.put("uniqueItems", param.uniqueItems);
serializer.put("isMap", param.isMap);
serializer.put("baseType", param.baseType);
serializers.add(serializer);
addBuiltValueSerializer(new BuiltValueSerializer(
param.isArray,
param.uniqueItems,
param.isMap,
param.items.isNullable,
param.baseType
));
}
}

Expand All @@ -387,17 +402,17 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
// Generate serializer factories for response types.
// But skip binary and file response, JSON serializers don't make sense there.
if (op.returnContainer != null && !(op.isResponseBinary || op.isResponseFile)) {
final Map<String, Object> serializer = new HashMap<>();
serializer.put("isArray", Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer));
serializer.put("uniqueItems", op.uniqueItems);
serializer.put("isMap", Objects.equals("map", op.returnContainer));
serializer.put("baseType", op.returnBaseType);
serializers.add(serializer);
addBuiltValueSerializer(new BuiltValueSerializer(
Objects.equals("array", op.returnContainer) || Objects.equals("set", op.returnContainer),
op.uniqueItems,
Objects.equals("map", op.returnContainer),
false,
op.returnBaseType
));
}
}

objs.put("imports", resultImports.stream().sorted().collect(Collectors.toList()));
objs.put("serializers", serializers);

return objs;
}
Expand All @@ -410,6 +425,19 @@ private void addBuiltValueSerializerImport(String type) {
});
}

/**
* Adds the serializer to the global list of custom built_value serializers.
* @param serializer
*/
private void addBuiltValueSerializer(BuiltValueSerializer serializer) {
System.out.println("######## Add serializer!");
additionalProperties.compute("builtValueSerializers", (k, v) -> {
Set<BuiltValueSerializer> serializers = v == null ? Sets.newHashSet() : ((Set<BuiltValueSerializer>) v);
serializers.add(serializer);
return serializers;
});
}

private Set<String> rewriteImports(Set<String> originalImports, boolean isModel) {
Set<String> resultImports = Sets.newHashSet();
for (String modelImport : originalImports) {
Expand All @@ -428,4 +456,58 @@ private Set<String> rewriteImports(Set<String> originalImports, boolean isModel)
}
return resultImports;
}

static class BuiltValueSerializer {

final boolean isArray;

final boolean uniqueItems;

final boolean isMap;

final boolean isNullable;

final String dataType;

private BuiltValueSerializer(boolean isArray, boolean uniqueItems, boolean isMap, boolean isNullable, String dataType) {
this.isArray = isArray;
this.uniqueItems = uniqueItems;
this.isMap = isMap;
this.isNullable = isNullable;
this.dataType = dataType;
}

public boolean isArray() {
return isArray;
}

public boolean isUniqueItems() {
return uniqueItems;
}

public boolean isMap() {
return isMap;
}

public boolean isNullable() {
return isNullable;
}

public String getDataType() {
return dataType;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BuiltValueSerializer that = (BuiltValueSerializer) o;
return isArray == that.isArray && uniqueItems == that.uniqueItems && isMap == that.isMap && isNullable == that.isNullable && dataType.equals(that.dataType);
}

@Override
public int hashCode() {
return Objects.hash(isArray, uniqueItems, isMap, isNullable, dataType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ part 'serializers.g.dart';
@SerializersFor([{{#models}}{{#model}}
{{classname}},{{/model}}{{/models}}
])
Serializers serializers = (_$serializers.toBuilder(){{#apiInfo}}{{#apis}}{{#serializers}}
Serializers serializers = (_$serializers.toBuilder(){{#builtValueSerializers}}
..addBuilderFactory(
{{#isArray}}
const FullType(Built{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}, [FullType({{baseType}})]),
() => {{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}Builder<{{baseType}}>(),
const FullType(Built{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}, [FullType{{#isNullable}}.nullable{{/isNullable}}({{dataType}})]),
() => {{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}Builder<{{dataType}}>(),
{{/isArray}}
{{#isMap}}
const FullType(BuiltMap, [FullType(String), FullType({{baseType}})]),
() => MapBuilder<String, {{baseType}}>(),
const FullType(BuiltMap, [FullType(String), FullType{{#isNullable}}.nullable{{/isNullable}}({{dataType}})]),
() => MapBuilder<String, {{dataType}}>(),
{{/isMap}}
){{/serializers}}{{/apis}}{{/apiInfo}}{{#useDateLibTimeMachine}}
){{/builtValueSerializers}}{{#useDateLibTimeMachine}}
..add(const OffsetDateSerializer())
..add(const OffsetDateTimeSerializer()){{/useDateLibTimeMachine}}{{#useDateLibCore}}
..add(const DateSerializer())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,22 @@ part 'serializers.g.dart';
User,
])
Serializers serializers = (_$serializers.toBuilder()
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltMap, [FullType(String), FullType(String)]),
() => MapBuilder<String, String>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(String)]),
() => SetBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(Pet)]),
() => ListBuilder<Pet>(),
Expand All @@ -139,8 +135,8 @@ Serializers serializers = (_$serializers.toBuilder()
() => MapBuilder<String, int>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,22 @@ part 'serializers.g.dart';
User,
])
Serializers serializers = (_$serializers.toBuilder()
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltMap, [FullType(String), FullType(String)]),
() => MapBuilder<String, String>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(String)]),
() => SetBuilder<String>(),
)
..addBuilderFactory(
const FullType(BuiltSet, [FullType(Pet)]),
() => SetBuilder<Pet>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(Pet)]),
() => ListBuilder<Pet>(),
Expand All @@ -139,8 +135,8 @@ Serializers serializers = (_$serializers.toBuilder()
() => MapBuilder<String, int>(),
)
..addBuilderFactory(
const FullType(BuiltList, [FullType(User)]),
() => ListBuilder<User>(),
const FullType(BuiltList, [FullType(String)]),
() => ListBuilder<String>(),
)
..add(const DateSerializer())
..add(Iso8601DateTimeSerializer()))
Expand Down