diff --git a/packages/dynamite/dynamite/lib/src/helpers/docs.dart b/packages/dynamite/dynamite/lib/src/helpers/docs.dart new file mode 100644 index 00000000..87b2501b --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/helpers/docs.dart @@ -0,0 +1,9 @@ +const docsSeparator = '///'; + +Iterable descriptionToDocs(final String? description) sync* { + if (description != null && description.isNotEmpty) { + for (final line in description.split('\n')) { + yield '$docsSeparator $line'; + } + } +} diff --git a/packages/dynamite/dynamite/lib/src/models/open_api.dart b/packages/dynamite/dynamite/lib/src/models/open_api.dart index a58ac874..6795f78d 100644 --- a/packages/dynamite/dynamite/lib/src/models/open_api.dart +++ b/packages/dynamite/dynamite/lib/src/models/open_api.dart @@ -40,4 +40,12 @@ class OpenAPI { final Components? components; final Paths? paths; + + Iterable formattedTagsFor(final String? tag) sync* { + final matchedTags = tags?.where((final t) => t.name == tag); + + if (matchedTags != null && matchedTags.isNotEmpty) { + yield* matchedTags.single.formattedDescription; + } + } } diff --git a/packages/dynamite/dynamite/lib/src/models/operation.dart b/packages/dynamite/dynamite/lib/src/models/operation.dart index 95f8c57b..e7fcec64 100644 --- a/packages/dynamite/dynamite/lib/src/models/operation.dart +++ b/packages/dynamite/dynamite/lib/src/models/operation.dart @@ -1,3 +1,4 @@ +import 'package:dynamite/src/helpers/docs.dart'; import 'package:dynamite/src/models/parameter.dart'; import 'package:dynamite/src/models/request_body.dart'; import 'package:dynamite/src/models/response.dart'; @@ -43,4 +44,14 @@ class Operation { final Responses? responses; final List? security; + + Iterable get formattedDescription sync* { + yield* descriptionToDocs(summary); + + if (summary != null && description != null) { + yield docsSeparator; + } + + yield* descriptionToDocs(description); + } } diff --git a/packages/dynamite/dynamite/lib/src/models/schema.dart b/packages/dynamite/dynamite/lib/src/models/schema.dart index f168eeb9..74e191fa 100644 --- a/packages/dynamite/dynamite/lib/src/models/schema.dart +++ b/packages/dynamite/dynamite/lib/src/models/schema.dart @@ -1,3 +1,4 @@ +import 'package:dynamite/src/helpers/docs.dart'; import 'package:dynamite/src/models/discriminator.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -85,6 +86,8 @@ class Schema { final bool? nullable; bool get isContentString => type == 'string' && (contentMediaType?.isNotEmpty ?? false) && contentSchema != null; + + Iterable get formattedDescription => descriptionToDocs(description); } class EmptySchema extends Schema { diff --git a/packages/dynamite/dynamite/lib/src/models/tag.dart b/packages/dynamite/dynamite/lib/src/models/tag.dart index 7943a1b2..f6bd0b0a 100644 --- a/packages/dynamite/dynamite/lib/src/models/tag.dart +++ b/packages/dynamite/dynamite/lib/src/models/tag.dart @@ -1,3 +1,4 @@ +import 'package:dynamite/src/helpers/docs.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:meta/meta.dart'; @@ -17,4 +18,6 @@ class Tag { final String name; final String? description; + + Iterable get formattedDescription => descriptionToDocs(description); } diff --git a/packages/dynamite/dynamite/lib/src/openapi_builder.dart b/packages/dynamite/dynamite/lib/src/openapi_builder.dart index 6af6c103..4f6971a3 100644 --- a/packages/dynamite/dynamite/lib/src/openapi_builder.dart +++ b/packages/dynamite/dynamite/lib/src/openapi_builder.dart @@ -288,14 +288,9 @@ class OpenAPIBuilder implements Builder { ), ); } - final matchedTags = spec.tags?.where((final t) => t.name == tag); b ..name = '$classPrefix${isRootClient ? 'Client' : _clientName(tag)}' - ..docs.addAll( - _descriptionToDocs( - matchedTags != null && matchedTags.isNotEmpty ? matchedTags.single.description : null, - ), - ) + ..docs.addAll(spec.formattedTagsFor(tag)) ..methods.addAll( [ for (final t in tags.whereType().where( @@ -324,13 +319,7 @@ class OpenAPIBuilder implements Builder { b ..name = _toDartName(_filterMethodName(operationId, tag ?? '')) ..modifier = MethodModifier.async - ..docs.addAll([ - ..._descriptionToDocs(operation.summary), - if (operation.summary != null && operation.description != null) ...[ - '///', - ], - ..._descriptionToDocs(operation.description), - ]); + ..docs.addAll(operation.formattedDescription); if (operation.deprecated ?? false) { b.annotations.add(refer('Deprecated').call([refer("''")])); } @@ -871,14 +860,6 @@ String _toCamelCase(final String name) { return result; } -List _descriptionToDocs(final String? description) => [ - if (description != null && description.isNotEmpty) ...[ - for (final line in description.split('\n')) ...[ - '/// $line', - ], - ], - ]; - String _filterMethodName(final String operationId, final String tag) { final expandedTag = tag.split('/').toList(); final parts = operationId.split('-'); @@ -918,7 +899,7 @@ TypeResult resolveObject( (final b) { b ..name = '${state.prefix}$identifier' - ..docs.addAll(_descriptionToDocs(schema.description)) + ..docs.addAll(schema.formattedDescription) ..abstract = true ..implements.add( refer( @@ -988,7 +969,7 @@ TypeResult resolveObject( ..name = _toDartName(propertyName) ..returns = refer(result.nullableName) ..type = MethodType.getter - ..docs.addAll(_descriptionToDocs(propertySchema.description)); + ..docs.addAll(propertySchema.formattedDescription); if (_toDartName(propertyName) != propertyName) { b.annotations.add( @@ -1302,7 +1283,7 @@ TypeResult resolveType( ..name = fields[result.name] ..returns = refer(result.nullableName) ..type = MethodType.getter - ..docs.addAll(_descriptionToDocs(s.description)); + ..docs.addAll(s.formattedDescription); }, ), ],