Skip to content
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 @@ -21,23 +21,17 @@
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.servers.Server;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.ClientModificationFeature;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
Expand Down Expand Up @@ -106,9 +100,6 @@ public DartClientCodegen() {
)
);

// clear import mapping (from default generator) as dart does not use it at the moment
importMapping.clear();

outputFolder = "generated-code/dart";
modelTemplateFiles.put("model.mustache", ".dart");
apiTemplateFiles.put("api.mustache", ".dart");
Expand Down Expand Up @@ -174,8 +165,6 @@ public DartClientCodegen() {

// These are needed as they prevent models from being generated
// which would clash with existing types, e.g. List
// Importing dart:core doesn't hurt but a subclass may choose to skip
// dart:core imports.
importMapping.put("dynamic", "dart:core");
importMapping.put("Object", "dart:core");
importMapping.put("String", "dart:core");
Expand All @@ -188,6 +177,8 @@ public DartClientCodegen() {
importMapping.put("Set", "dart:core");
importMapping.put("DateTime", "dart:core");

defaultIncludes = new HashSet<>(Collections.singletonList("dart:core"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Sets.newHashSet from guava


cliOptions.add(new CliOption(PUB_LIBRARY, "Library name in generated code"));
cliOptions.add(new CliOption(PUB_NAME, "Name in generated pubspec"));
cliOptions.add(new CliOption(PUB_VERSION, "Version in generated pubspec"));
Expand Down Expand Up @@ -474,34 +465,62 @@ public String toDefaultValue(Schema schema) {

@Override
public String getTypeDeclaration(Schema p) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add unit tests to this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are tests for dart and dart-dio that test the type returned for array and map OAS types.

if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return instantiationTypes().get("array") + "<" + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = getAdditionalProperties(p);
return instantiationTypes().get("map") + "<String, " + getTypeDeclaration(inner) + ">";
Schema<?> schema = ModelUtils.unaliasSchema(this.openAPI, p, importMapping);
Schema<?> target = ModelUtils.isGenerateAliasAsModel() ? p : schema;
if (ModelUtils.isArraySchema(target)) {
Schema<?> items = getSchemaItems((ArraySchema) schema);
return getSchemaType(target) + "<" + getTypeDeclaration(items) + ">";
} else if (ModelUtils.isMapSchema(target)) {
// Note: ModelUtils.isMapSchema(p) returns true when p is a composed schema that also defines
// additionalproperties: true
Schema<?> inner = getAdditionalProperties(target);
if (inner == null) {
LOGGER.error("`{}` (map property) does not have a proper inner type defined. Default to type:string", p.getName());
inner = new StringSchema().description("TODO default missing map inner type to string");
p.setAdditionalProperties(inner);
}
return getSchemaType(target) + "<String, " + getTypeDeclaration(inner) + ">";
}
return super.getTypeDeclaration(p);
}

@Override
public String getSchemaType(Schema p) {
String type = super.getSchemaType(p);
if (typeMapping.containsKey(type)) {
return typeMapping.get(type);
String openAPIType = super.getSchemaType(p);
if (openAPIType == null) {
LOGGER.error("No Type defined for Schema " + p);
}
if (languageSpecificPrimitives.contains(type)) {
return type;
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
}
return toModelName(type);
if (languageSpecificPrimitives.contains(openAPIType)) {
return openAPIType;
}
return toModelName(openAPIType);
}

@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
return postProcessModelsEnum(objs);
}

@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
final CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add unit tests for this method? is it worth to make it more dart-dio specific as the rest of the changes are dart-dio?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could possibly be moved to the dart-dio generator.

Copy link
Contributor

Choose a reason for hiding this comment

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

makes sense to keep it here for all darts.

for (CodegenResponse r : op.responses) {
// 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.
if (r.containerType != null && typeMapping().containsKey(r.containerType)) {
final String value = typeMapping().get(r.containerType);
if (needToImport(value)) {
op.imports.add(value);
}
}
}
return op;
}

@Override
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
if (vendorExtensions != null && useEnumExtension && vendorExtensions.containsKey("x-enum-values")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

import io.swagger.v3.oas.models.media.Schema;

import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;

public class DartDioClientCodegen extends DartClientCodegen {
Expand Down Expand Up @@ -65,9 +64,15 @@ public DartDioClientCodegen() {
dateLibrary.setEnum(dateOptions);
cliOptions.add(dateLibrary);

typeMapping.put("Array", "BuiltList");
typeMapping.put("array", "BuiltList");
typeMapping.put("List", "BuiltList");
typeMapping.put("set", "BuiltSet");
typeMapping.put("map", "BuiltMap");
typeMapping.put("file", "Uint8List");
typeMapping.put("binary", "Uint8List");
typeMapping.put("AnyType", "Object");
typeMapping.put("object", "JsonObject");
typeMapping.put("AnyType", "JsonObject");

importMapping.put("BuiltList", "package:built_collection/built_collection.dart");
importMapping.put("BuiltSet", "package:built_collection/built_collection.dart");
Expand Down Expand Up @@ -247,7 +252,7 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {
for (String modelImport : cm.imports) {
if (importMapping().containsKey(modelImport)) {
final String value = importMapping().get(modelImport);
if (!Objects.equals(value, "dart:core")) {
if (needToImport(value)) {
modelImports.add(value);
}
} else {
Expand All @@ -264,31 +269,11 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {

@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (nullableFields) {
property.isNullable = true;
}

property.setDatatype(property.getDataType()
.replaceAll("\\bList\\b", "BuiltList")
.replaceAll("\\bMap\\b", "BuiltMap")
.replaceAll("\\bObject\\b", "JsonObject")
);
property.setBaseType(property.getBaseType()
.replaceAll("\\bList\\b", "BuiltList")
.replaceAll("\\bMap\\b", "BuiltMap")
.replaceAll("\\bObject\\b", "JsonObject")
);

if (property.dataType.contains("BuiltList")) {
model.imports.add("BuiltList");
}
if (property.dataType.contains("BuiltMap")) {
model.imports.add("BuiltMap");
}
if (property.dataType.contains("JsonObject")) {
model.imports.add("JsonObject");
}

if (property.isEnum) {
// enums are generated with built_value and make use of BuiltSet
model.imports.add("BuiltSet");
Expand Down Expand Up @@ -340,7 +325,7 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
for (String item : op.imports) {
if (importMapping().containsKey(item)) {
final String value = importMapping().get(item);
if (!Objects.equals(value, "dart:core")) {
if (needToImport(value)) {
fullImports.add(value);
}
} else {
Expand Down
38 changes: 16 additions & 22 deletions modules/openapi-generator/src/main/resources/dart-dio/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';

{{#operations}}
Expand Down Expand Up @@ -64,13 +63,13 @@ class {{classname}} {

{{#bodyParam}}
{{#isArray}}
final type = const FullType(BuiltList, const [const FullType({{baseType}})]);
var serializedBody = _serializers.serialize(BuiltList<{{baseType}}>.from({{paramName}}), specifiedType: type);
const type = FullType(BuiltList, [FullType({{baseType}})]);
final serializedBody = _serializers.serialize({{paramName}}, specifiedType: type);
{{/isArray}}
{{^isArray}}
var serializedBody = _serializers.serialize({{paramName}});
final serializedBody = _serializers.serialize({{paramName}});
{{/isArray}}
var json{{paramName}} = json.encode(serializedBody);
final json{{paramName}} = json.encode(serializedBody);
bodyData = json{{paramName}};
{{/bodyParam}}

Expand All @@ -94,30 +93,25 @@ class {{classname}} {
onReceiveProgress: onReceiveProgress,
){{#returnType}}.then((response) {

{{#returnTypeIsPrimitive}}
var data = response.data as {{{returnType}}};
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
{{#isResponseFile}}
final data = response.data;
{{/isResponseFile}}
{{^isResponseFile}}
{{#isArray}}
final FullType type = const FullType(BuiltList, const [const FullType({{returnBaseType}})]);
final BuiltList<{{returnBaseType}}> dataList = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
final data = dataList.toList();
{{/isArray}}
{{^isArray}}
{{#isMap}}
final serializer = _serializers.serializerForType(Map);
{{/isMap}}
{{^isMap}}
{{#returnSimpleType}}
{{#returnTypeIsPrimitive}}
final data = response.data as {{{returnType}}};
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
final serializer = _serializers.serializerForType({{{returnType}}});
{{/isMap}}
final data = _serializers.deserializeWith<{{{returnType}}}>(serializer, response.data is String ? jsonDecode(response.data) : response.data);
{{/isArray}}
{{/isResponseFile}}
{{/returnTypeIsPrimitive}}
{{/returnSimpleType}}
{{^returnSimpleType}}
const collectionType = {{#isMap}}BuiltMap{{/isMap}}{{^isMap}}BuiltList{{/isMap}};
const type = FullType(collectionType, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{returnBaseType}}})]);
final {{{returnType}}} data = _serializers.deserialize(response.data is String ? jsonDecode(response.data) : response.data, specifiedType: type);
{{/returnSimpleType}}
{{/isResponseFile}}

return Response<{{{returnType}}}>(
data: data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void (empty response body)
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

# **findPetsByStatus**
> List<Pet> findPetsByStatus(status)
> BuiltList<Pet> findPetsByStatus(status)

Finds Pets by status

Expand All @@ -119,7 +119,7 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<OAuth>('petstore_auth').accessToken = 'YOUR_ACCESS_TOKEN';

var api_instance = new PetApi();
var status = []; // List<String> | Status values that need to be considered for filter
var status = []; // BuiltList<String> | Status values that need to be considered for filter

try {
var result = api_instance.findPetsByStatus(status);
Expand All @@ -133,11 +133,11 @@ try {

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**status** | [**List&lt;String&gt;**](String.md)| Status values that need to be considered for filter | [default to const []]
**status** | [**BuiltList&lt;String&gt;**](String.md)| Status values that need to be considered for filter | [default to const []]

### Return type

[**List<Pet>**](Pet.md)
[**BuiltList<Pet>**](Pet.md)

### Authorization

Expand All @@ -151,7 +151,7 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

# **findPetsByTags**
> List<Pet> findPetsByTags(tags)
> BuiltList<Pet> findPetsByTags(tags)

Finds Pets by tags

Expand All @@ -164,7 +164,7 @@ import 'package:openapi/api.dart';
//defaultApiClient.getAuthentication<OAuth>('petstore_auth').accessToken = 'YOUR_ACCESS_TOKEN';

var api_instance = new PetApi();
var tags = []; // List<String> | Tags to filter by
var tags = []; // BuiltList<String> | Tags to filter by

try {
var result = api_instance.findPetsByTags(tags);
Expand All @@ -178,11 +178,11 @@ try {

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**tags** | [**List&lt;String&gt;**](String.md)| Tags to filter by | [default to const []]
**tags** | [**BuiltList&lt;String&gt;**](String.md)| Tags to filter by | [default to const []]

### Return type

[**List<Pet>**](Pet.md)
[**BuiltList<Pet>**](Pet.md)

### Authorization

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ No authorization required
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

# **getInventory**
> Map<String, int> getInventory()
> BuiltMap<String, int> getInventory()

Returns pet inventories by status

Expand Down Expand Up @@ -87,7 +87,7 @@ This endpoint does not need any parameter.

### Return type

**Map<String, int>**
**BuiltMap<String, int>**

### Authorization

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Creates list of users with given input array
import 'package:openapi/api.dart';

var api_instance = new UserApi();
var body = [new List&lt;User&gt;()]; // List<User> | List of user object
var body = [new BuiltList&lt;User&gt;()]; // BuiltList<User> | List of user object

try {
api_instance.createUsersWithArrayInput(body);
Expand All @@ -84,7 +84,7 @@ try {

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**List&lt;User&gt;**](User.md)| List of user object |
**body** | [**BuiltList&lt;User&gt;**](User.md)| List of user object |

### Return type

Expand All @@ -111,7 +111,7 @@ Creates list of users with given input array
import 'package:openapi/api.dart';

var api_instance = new UserApi();
var body = [new List&lt;User&gt;()]; // List<User> | List of user object
var body = [new BuiltList&lt;User&gt;()]; // BuiltList<User> | List of user object

try {
api_instance.createUsersWithListInput(body);
Expand All @@ -124,7 +124,7 @@ try {

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**List&lt;User&gt;**](User.md)| List of user object |
**body** | [**BuiltList&lt;User&gt;**](User.md)| List of user object |

### Return type

Expand Down
Loading