From 72786d677d92c56baa99dcbbf6e450dee703c702 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Thu, 4 May 2023 15:18:36 +0200 Subject: [PATCH] dynamite: support generics for TypeResult Signed-off-by: Nikolas Rimikis --- packages/dynamite/dynamite/.gitignore | 2 + packages/dynamite/dynamite/lib/dynamite.dart | 1 + .../dynamite/lib/src/openapi_builder.dart | 16 ++++---- .../dynamite/lib/src/type_result/list.dart | 6 +-- .../dynamite/lib/src/type_result/map.dart | 8 ++-- .../dynamite/lib/src/type_result/object.dart | 9 ++++- .../lib/src/type_result/type_result.dart | 19 ++++++++- packages/dynamite/dynamite/pubspec.yaml | 1 + .../dynamite/test/type_result_test.dart | 39 +++++++++++++++++++ 9 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 packages/dynamite/dynamite/test/type_result_test.dart diff --git a/packages/dynamite/dynamite/.gitignore b/packages/dynamite/dynamite/.gitignore index 65c34dc8..840b0cc8 100644 --- a/packages/dynamite/dynamite/.gitignore +++ b/packages/dynamite/dynamite/.gitignore @@ -8,3 +8,5 @@ build/ # Omit committing pubspec.lock for library packages; see # https://dart.dev/guides/libraries/private-files#pubspeclock. pubspec.lock + +coverage/ diff --git a/packages/dynamite/dynamite/lib/dynamite.dart b/packages/dynamite/dynamite/lib/dynamite.dart index c678ebf1..c5397acb 100644 --- a/packages/dynamite/dynamite/lib/dynamite.dart +++ b/packages/dynamite/dynamite/lib/dynamite.dart @@ -9,6 +9,7 @@ import 'package:dynamite/src/models/open_api.dart'; import 'package:dynamite/src/models/parameter.dart' as spec_parameter; import 'package:dynamite/src/models/path_item.dart'; import 'package:dynamite/src/models/schema.dart'; +import 'package:intersperse/intersperse.dart'; import 'package:path/path.dart' as p; part 'src/openapi_builder.dart'; diff --git a/packages/dynamite/dynamite/lib/src/openapi_builder.dart b/packages/dynamite/dynamite/lib/src/openapi_builder.dart index 8e8663af..3b34a890 100644 --- a/packages/dynamite/dynamite/lib/src/openapi_builder.dart +++ b/packages/dynamite/dynamite/lib/src/openapi_builder.dart @@ -1671,7 +1671,7 @@ TypeResult resolveType( result = TypeResultObject('${state.prefix}$identifier'); } else if (schema.isContentString) { - result = resolveType( + final subResult = resolveType( spec, state, identifier, @@ -1679,7 +1679,7 @@ TypeResult resolveType( ); state.hasContentString = true; - result = TypeResultObject('ContentString<${result.name}>'); + result = TypeResultObject('ContentString', generics: [subResult]); } else { switch (schema.type) { case 'boolean': @@ -1709,12 +1709,12 @@ TypeResult resolveType( schema.items!, ); result = TypeResultList( - 'BuiltList<${subResult.name}>', + 'BuiltList', subResult, ); } else { result = TypeResultList( - 'BuiltList', + 'BuiltList', TypeResultBase('JsonObject'), ); } @@ -1724,7 +1724,7 @@ TypeResult resolveType( if (schema.additionalProperties != null) { if (schema.additionalProperties is EmptySchema) { result = TypeResultMap( - 'BuiltMap', + 'BuiltMap', TypeResultBase('JsonObject'), ); } else { @@ -1735,8 +1735,8 @@ TypeResult resolveType( schema.additionalProperties!, ); result = TypeResultMap( - 'BuiltMap', - TypeResultBase('JsonObject'), + 'BuiltMap', + subResult, ); } break; @@ -1746,7 +1746,7 @@ TypeResult resolveType( } if (schema.properties!.isEmpty) { result = TypeResultMap( - 'BuiltMap', + 'BuiltMap', TypeResultBase('JsonObject'), ); break; diff --git a/packages/dynamite/dynamite/lib/src/type_result/list.dart b/packages/dynamite/dynamite/lib/src/type_result/list.dart index 3cc4f3fd..a674f32d 100644 --- a/packages/dynamite/dynamite/lib/src/type_result/list.dart +++ b/packages/dynamite/dynamite/lib/src/type_result/list.dart @@ -3,10 +3,10 @@ part of '../../dynamite.dart'; class TypeResultList extends TypeResult { TypeResultList( super.name, - this.subType, - ); + final TypeResult subType, + ) : super(generics: [subType]); - final TypeResult subType; + TypeResult get subType => generics.first; @override String serialize(final String object) => '$object.map((final e) => ${subType.serialize('e')})'; diff --git a/packages/dynamite/dynamite/lib/src/type_result/map.dart b/packages/dynamite/dynamite/lib/src/type_result/map.dart index 65f99eb0..802d00d1 100644 --- a/packages/dynamite/dynamite/lib/src/type_result/map.dart +++ b/packages/dynamite/dynamite/lib/src/type_result/map.dart @@ -3,10 +3,10 @@ part of '../../dynamite.dart'; class TypeResultMap extends TypeResult { TypeResultMap( super.name, - this.subType, - ); + final TypeResult subType, + ) : super(generics: [TypeResultBase('String'), subType]); - final TypeResult subType; + TypeResult get subType => generics[1]; @override String serialize(final String object) => object; @@ -29,7 +29,7 @@ class TypeResultMap extends TypeResult { @override String deserialize(final String object, {final bool toBuilder = false}) => - '($object as BuiltMap)${toBuilder ? '.toBuilder()' : ''}'; + '($object as $className)${toBuilder ? '.toBuilder()' : ''}'; @override String decode(final String object) => 'json.decode($object as String)'; diff --git a/packages/dynamite/dynamite/lib/src/type_result/object.dart b/packages/dynamite/dynamite/lib/src/type_result/object.dart index 0df93ecb..f61184f4 100644 --- a/packages/dynamite/dynamite/lib/src/type_result/object.dart +++ b/packages/dynamite/dynamite/lib/src/type_result/object.dart @@ -1,8 +1,13 @@ part of '../../dynamite.dart'; class TypeResultObject extends TypeResult { - TypeResultObject(super.name) - : assert(name != 'JsonObject' && name != 'Object' && name != 'dynamic', 'Use TypeResultBase instead'); + TypeResultObject( + super.className, { + super.generics, + }) : assert( + className != 'JsonObject' && className != 'Object' && className != 'dynamic', + 'Use TypeResultBase instead', + ); @override String serialize(final String object) => '$object.toJson()'; diff --git a/packages/dynamite/dynamite/lib/src/type_result/type_result.dart b/packages/dynamite/dynamite/lib/src/type_result/type_result.dart index 33cdbd74..83fdc9c5 100644 --- a/packages/dynamite/dynamite/lib/src/type_result/type_result.dart +++ b/packages/dynamite/dynamite/lib/src/type_result/type_result.dart @@ -1,9 +1,24 @@ part of '../../dynamite.dart'; abstract class TypeResult { - TypeResult(this.name); + TypeResult( + this.className, { + this.generics = const [], + }) : assert(!className.contains('<'), 'Specifiy generics in the generics parameter.'), + assert(!className.contains('?'), 'Nullability should not be specified in the type.'); - final String name; + final String className; + final List generics; + String get name { + if (generics.isNotEmpty) { + final buffer = StringBuffer('$className<') + ..writeAll(generics.map((final c) => c.name).intersperse(', ')) + ..write('>'); + return buffer.toString(); + } + + return className; + } String serialize(final String object); diff --git a/packages/dynamite/dynamite/pubspec.yaml b/packages/dynamite/dynamite/pubspec.yaml index 97815b27..f8781950 100644 --- a/packages/dynamite/dynamite/pubspec.yaml +++ b/packages/dynamite/dynamite/pubspec.yaml @@ -9,6 +9,7 @@ dependencies: built_value: ^8.5.0 code_builder: ^4.4.0 dart_style: ^2.3.1 + intersperse: ^2.0.0 json_annotation: ^4.8.1 path: ^1.8.3 diff --git a/packages/dynamite/dynamite/test/type_result_test.dart b/packages/dynamite/dynamite/test/type_result_test.dart new file mode 100644 index 00000000..286ec0ee --- /dev/null +++ b/packages/dynamite/dynamite/test/type_result_test.dart @@ -0,0 +1,39 @@ +import 'package:dynamite/dynamite.dart'; +import 'package:test/test.dart'; + +void main() { + group(TypeResultList, () { + test('name', () { + final subType = TypeResultBase('String'); + final listType = TypeResultList('BuiltList', subType); + + expect(listType.name, 'BuiltList'); + }); + }); + + group(TypeResultMap, () { + test('name', () { + final subType = TypeResultBase('int'); + final listType = TypeResultMap('BuiltMap', subType); + + expect(listType.name, 'BuiltMap'); + }); + }); + + group(TypeResultObject, () { + test('name', () { + final subType = TypeResultBase('String'); + final listType = TypeResultObject('CustomType', generics: [subType]); + + expect(listType.name, 'CustomType'); + }); + }); + + group(TypeResultBase, () { + test('name', () { + final type = TypeResultBase('String'); + + expect(type.name, 'String'); + }); + }); +}