-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
[BUG][Dart] Generator creates a model class name that conflicts with a core lib class name (Type) #9029
Comments
So far, the only workaround I've found is to use
|
I could add this to the reserved words, it is not optimal but we also did this for |
Actually we have this place where it should be added: // DataTypes of the above values which are automatically imported.
// They are also not allowed to be model names.
defaultIncludes = Sets.newHashSet(
"String",
"bool",
"int",
"num",
"double",
"dynamic",
"List",
"Set",
"Map",
"DateTime",
"Object",
"MultipartFile"
); |
Can you try running this with |
I created a PR, would be great if you could test this with the |
Oops I missed the earlier notification. Yes, let me give it a try. |
@kuhnroyal I built and verified that #9167 works great to map Type to RecordType with |
Hi @kuhnroyal I have an issue with imports in *_api.dart (generated by .templates/dart-dio/api.mustache), see details below: .templates/dart-dio/api.mustache {{>header}}
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:built_value/serializer.dart';
{{#operations}}
{{#imports}}import '{{.}}';
{{/imports}}
class {{classname}} {
final Dio _dio;
final Serializers _serializers;
const {{classname}}(this._dio, this._serializers);
{{#operation}}
/// {{{summary}}}
///
/// {{{notes}}}
Future<Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}>> {{nickname}}({{^hasRequiredParams}}{ {{/hasRequiredParams}}{{#requiredParams}}
{{{dataType}}} {{paramName}},{{#-last}} { {{/-last}}{{/requiredParams}}{{#optionalParams}}
{{{dataType}}} {{paramName}},{{/optionalParams}}
CancelToken cancelToken,
Map<String, dynamic> headers,
Map<String, dynamic> extra,
ValidateStatus validateStatus,
ProgressCallback onSendProgress,
ProgressCallback onReceiveProgress,
}) async {
final _request = RequestOptions(
path: r'{{{path}}}'{{#pathParams}}.replaceAll('{' r'{{{baseName}}}' '}', {{{paramName}}}.toString()){{/pathParams}},
method: '{{#lambda.uppercase}}{{httpMethod}}{{/lambda.uppercase}}',
{{#isResponseFile}}
responseType: ResponseType.bytes,
{{/isResponseFile}}
headers: <String, dynamic>{
{{#httpUserAgent}}
r'User-Agent': r'{{{.}}}',
{{/httpUserAgent}}
{{#headerParams}}
{{^required}}{{^nullable}}if ({{{paramName}}} != null) {{/nullable}}{{/required}}r'{{baseName}}': {{paramName}},
{{/headerParams}}
...?headers,
},
{{#hasQueryParams}}
queryParameters: <String, dynamic>{
{{#queryParams}}
{{^required}}{{^nullable}}if ({{{paramName}}} != null) {{/nullable}}{{/required}}r'{{baseName}}': {{paramName}},
{{/queryParams}}
},
{{/hasQueryParams}}
extra: <String, dynamic>{
'secure': <Map<String, String>>[{{^hasAuthMethods}}],{{/hasAuthMethods}}{{#hasAuthMethods}}
{{#authMethods}}{
'type': '{{type}}',
'name': '{{name}}',{{#isApiKey}}
'keyName': '{{keyParamName}}',
'where': '{{#isKeyInQuery}}query{{/isKeyInQuery}}{{#isKeyInHeader}}header{{/isKeyInHeader}}',{{/isApiKey}}
},{{/authMethods}}
],{{/hasAuthMethods}}
...?extra,
},
validateStatus: validateStatus,
contentType: [{{^hasConsumes}}
'application/json',{{/hasConsumes}}{{#hasConsumes}}{{#consumes}}
'{{{mediaType}}}',{{/consumes}}{{/hasConsumes}}
].first,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
dynamic _bodyData;
{{#hasFormParams}}
_bodyData = {{#isMultipart}}FormData.fromMap({{/isMultipart}}<String, dynamic>{
{{#formParams}}
{{^required}}{{^nullable}}if ({{{paramName}}} != null) {{/nullable}}{{/required}}r'{{{baseName}}}': {{#isFile}}MultipartFile.fromBytes({{{paramName}}}, filename: r'{{{baseName}}}'){{/isFile}}{{^isFile}}encodeFormParameter(_serializers, {{{paramName}}}, const FullType({{^isContainer}}{{{baseType}}}{{/isContainer}}{{#isContainer}}Built{{#isMap}}Map{{/isMap}}{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isArray}}, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{baseType}}})]{{/isContainer}})){{/isFile}},
{{/formParams}}
}{{#isMultipart}}){{/isMultipart}};
{{/hasFormParams}}
{{#bodyParam}}
{{#isPrimitiveType}}
_bodyData = {{paramName}};
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{#isContainer}}
const _type = FullType(Built{{#isMap}}Map{{/isMap}}{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isArray}}, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{baseType}}})]);
_bodyData = _serializers.serialize({{paramName}}, specifiedType: _type);
{{/isContainer}}
{{^isContainer}}
const _type = FullType({{{baseType}}});
_bodyData = _serializers.serialize({{paramName}}, specifiedType: _type);
{{/isContainer}}
{{/isPrimitiveType}}
{{/bodyParam}}
final _response = await _dio.request<dynamic>(
_request.path,
data: _bodyData,
options: _request,
);
{{#returnType}}
{{#isResponseFile}}
final {{{returnType}}} _responseData = _response.data as {{{returnType}}};
{{/isResponseFile}}
{{^isResponseFile}}
{{#returnSimpleType}}
{{#returnTypeIsPrimitive}}
final {{{returnType}}} _responseData = _response.data as {{{returnType}}};
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
const _responseType = FullType({{{returnType}}});
final _responseData = _serializers.deserialize(
_response.data,
specifiedType: _responseType,
) as {{{returnType}}};
{{/returnTypeIsPrimitive}}
{{/returnSimpleType}}
{{^returnSimpleType}}
const _responseType = FullType(Built{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isArray}}{{#isMap}}Map{{/isMap}}, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{returnBaseType}}})]);
final {{{returnType}}} _responseData = _serializers.deserialize(
_response.data,
specifiedType: _responseType,
) as {{{returnType}}};
{{/returnSimpleType}}
{{/isResponseFile}}
return Response<{{{returnType}}}>(
data: _responseData,
headers: _response.headers,
isRedirect: _response.isRedirect,
request: _response.request,
redirects: _response.redirects,
statusCode: _response.statusCode,
statusMessage: _response.statusMessage,
extra: _response.extra,
);{{/returnType}}{{^returnType}}
return _response;{{/returnType}}
}
{{/operation}}
}
{{/operations}} *_api.dart // ignore_for_file: unused_import
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:built_value/serializer.dart';
import '{import=lib.model.Body, classname=Body}';
import '{import=lib.model.Body1, classname=Body1}';
import '{import=lib.model.Body10, classname=Body10}';
import '{import=lib.model.Body11, classname=Body11}';
import '{import=lib.model.Body12, classname=Body12}';
import '{import=lib.model.Body13, classname=Body13}';
import '{import=lib.model.Body15, classname=Body15}';
import '{import=lib.model.Body2, classname=Body2}';
import '{import=lib.model.Body3, classname=Body3}';
import '{import=lib.model.Body4, classname=Body4}';
import '{import=lib.model.Body5, classname=Body5}';
import '{import=lib.model.Body6, classname=Body6}';
import '{import=lib.model.Body7, classname=Body7}';
import '{import=lib.model.Body8, classname=Body8}';
import '{import=lib.model.Body9, classname=Body9}';
import '{import=lib.model.InlineResponse200, classname=InlineResponse200}';
import '{import=lib.model.InlineResponse2001, classname=InlineResponse2001}';
import '{import=lib.model.InlineResponse20010, classname=InlineResponse20010}';
import '{import=lib.model.InlineResponse20011, classname=InlineResponse20011}';
import '{import=lib.model.InlineResponse20012, classname=InlineResponse20012}';
import '{import=lib.model.InlineResponse20013, classname=InlineResponse20013}';
import '{import=lib.model.InlineResponse20015, classname=InlineResponse20015}';
import '{import=lib.model.InlineResponse2002, classname=InlineResponse2002}';
import '{import=lib.model.InlineResponse2003, classname=InlineResponse2003}';
import '{import=lib.model.InlineResponse2004, classname=InlineResponse2004}';
import '{import=lib.model.InlineResponse2005, classname=InlineResponse2005}';
import '{import=lib.model.InlineResponse2006, classname=InlineResponse2006}';
import '{import=lib.model.InlineResponse2007, classname=InlineResponse2007}';
import '{import=lib.model.InlineResponse2008, classname=InlineResponse2008}';
import '{import=lib.model.InlineResponse2009, classname=InlineResponse2009}';
import '{import=lib.model.InlineResponse503, classname=InlineResponse503}';
class AuthenticationApi {
final Dio _dio;
final Serializers _serializers; config.yaml generatorName: dart-dio
inputSpec: spec.yaml
outputFolder: .
templateDir: .templates/dart-dio
pubName: openapi
pubLibrary: openapi
useEnumExtension: true
serializationLibrary: built_value
additionalProperties:
clientName: openApi
serializableModel: "true"
dateLibrary: core
# # dateLibrary: timeMachine
hideGenerationTimestamp: "true"
useBuiltValue: "true"
typeMappings:
Array: BuiltList
array: BuiltList
List: BuiltList
set: BuiltSet
map: BuiltMap
file: Uint8List
binary: Uint8List
object: JsonObject
AnyType: JsonObject
Type: RecordType generator version is 5.1.0 .Could you have a look? or help me correct it? |
The changes from #9167 (which you are trying to use) have not been released yet. You need to build from master if you want to use this. |
Hi @kuhnroyal, I just checked with the build from master (5.1.1-SNAPSHOT), but it still the same result. Kindly check with this statement:
Could you have a look? |
Not sure what you want me to check, the samples and the test are working. This is very likely a problem on your end. Please provided a fully reproducible sample if you think that is not the case. |
Ah, I checked the samples, it's working, I think I need to check again my spec.yaml and local template as well. Thanks for supported, @kuhnroyal. |
Hi @kuhnroyal I have generated it successfully by customizing the
thanks for your support |
Whatever works for you. You can also always use docker with the |
Bug Report Checklist
Description
When generating Dart code, an OAS is using a reserved(ish) word (
Type
) which the generator defines a class for which then conflicts and causes errors. (It's not technically a reserved word of the language, it's a class in the core library. Something that's always available and you can't import it with a namespace)openapi-generator version
5.1.0 release
on both dart-dio and dart-dio-next
OpenAPI declaration file content or url
https://cdn-prod.wdesk.com/endpoints-admin/1.342.0/openapi/platform-v1.yaml
Problem arises from line 813
Generation Details
I used the jar release for 5.1.0 with this command:
java -jar openapi-generator-cli.jar generate -i https://cdn-prod.wdesk.com/endpoints-admin/1.342.0/openapi/platform-v1.yaml -g dart-dio -o ./ --additional-properties="pubDescription=Workiva Platform API (Dart),pubName=wk,pubVersion=1.0.0"
Steps to reproduce
Generate Dart code with the above command.
Have Dart installed (2.12.2)
Then run
pub get
pub run build_runner build --delete-conflicting-outputs -o build
(then remove the build directory .. you only need to run a build to do built_value code generation
Then either open in an IDE with the Dart plugin (VS Code, intelliJ) or just run
dartanalyzer .
which will show the errors.Related issues/PRs
Suggest a fix
I'm not actually sure what a good fix would be. I might actually prefer if generation failed when creating the code and suggested a way to work around it, possibly by using the
[--reserved-words-mappings <reserved word mappings>...]
option ?The text was updated successfully, but these errors were encountered: