Skip to content

Commit

Permalink
Merge pull request #1319 from nextcloud/fix/dynamite/int-enums-leptopoda
Browse files Browse the repository at this point in the history
fix(dynamite): Allow int enums
  • Loading branch information
Leptopoda committed Dec 21, 2023
2 parents 2e014fa + 967c888 commit 4b3407d
Show file tree
Hide file tree
Showing 62 changed files with 6,372 additions and 3,137 deletions.
38 changes: 0 additions & 38 deletions packages/dynamite/dynamite/lib/src/builder/imports.dart

This file was deleted.

300 changes: 217 additions & 83 deletions packages/dynamite/dynamite/lib/src/builder/resolve_enum.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:convert';

import 'package:code_builder/code_builder.dart';
import 'package:dynamite/src/builder/resolve_type.dart';
import 'package:dynamite/src/builder/state.dart';
import 'package:dynamite/src/helpers/built_value.dart';
import 'package:dynamite/src/helpers/dart_helpers.dart';
import 'package:dynamite/src/helpers/type_result.dart';
import 'package:dynamite/src/models/openapi.dart' as openapi;
import 'package:dynamite/src/models/type_result.dart';

Expand All @@ -16,92 +16,226 @@ TypeResult resolveEnum(
final bool nullable = false,
}) {
if (state.resolvedTypes.add(TypeResultEnum(identifier, subResult))) {
state.output.add(
Class(
(final b) => b
..name = identifier
..extend = refer('EnumClass')
..constructors.add(
Constructor(
(final b) => b
..name = '_'
..constant = true
..requiredParameters.add(
Parameter(
(final b) => b
..name = 'name'
..toSuper = true,
),
final values = <({String dartName, Object? value, String name})>[];
for (final enumValue in schema.$enum!) {
final name = enumValue.toString();
final dartName = toDartName(name);
var value = jsonEncode(enumValue.value);
if (enumValue.isString) {
value = 'r$value';
}

values.add((dartName: dartName, value: value, name: name));
}

final $class = Class(
(final b) => b
..name = identifier
..extend = refer('EnumClass')
..constructors.add(
Constructor(
(final b) => b
..name = '_'
..constant = true
..requiredParameters.add(
Parameter(
(final b) => b
..name = 'name'
..toSuper = true,
),
),
)
..fields.addAll(
schema.$enum!.map(
(final value) => Field(
(final b) {
final result = resolveType(
spec,
state,
'$identifier${toDartName(value, uppercaseFirstCharacter: true)}',
schema,
ignoreEnum: true,
),
),
)
..fields.addAll(
values.map(
(final enumValue) => Field(
(final b) {
b
..name = enumValue.dartName
..static = true
..modifier = FieldModifier.constant
..type = refer(identifier)
..assignment = Code(
'_\$${toCamelCase('$identifier${enumValue.dartName.capitalize()}')}',
);
b
..name = toDartName(value)
..static = true
..modifier = FieldModifier.constant
..type = refer(identifier)
..assignment = Code(
'_\$${toCamelCase(identifier)}${toDartName(value, uppercaseFirstCharacter: true)}',
);

if (toDartName(value) != value) {
if (result.name != 'String' && result.name != 'int') {
throw Exception(
'Sorry enum values are a bit broken. '
'See https://github.com/google/json_serializable.dart/issues/616. '
'Please remove the enum values on $identifier.',
);
}
b.annotations.add(
refer('BuiltValueEnumConst').call([], {
'wireName': refer(valueToEscapedValue(result, value)),
}),
);
}
},
),
),
)
..methods.addAll([
Method(
(final b) => b
..name = 'values'
..returns = refer('BuiltSet<$identifier>')
..lambda = true
..static = true
..body = Code('_\$${toCamelCase(identifier)}Values')
..type = MethodType.getter,
),
Method(
(final b) => b
..name = 'valueOf'
..returns = refer(identifier)
..lambda = true
..static = true
..requiredParameters.add(
Parameter(
(final b) => b
..name = 'name'
..type = refer(subResult.name),
),
)
..body = Code('_\$valueOf$identifier(name)'),
if (enumValue.name != enumValue.dartName) {
b.annotations.add(
refer('BuiltValueEnumConst').call([], {
'wireName': refer("r'${enumValue.name}'"),
}),
);
}
},
),
buildSerializer(identifier),
]),
),
),
)
..methods.addAll([
Method(
(final b) => b
..name = 'values'
..returns = refer('BuiltSet<$identifier>')
..lambda = true
..static = true
..body = Code('_\$${toCamelCase(identifier)}Values')
..type = MethodType.getter,
),
Method(
(final b) => b
..name = 'valueOf'
..returns = refer(identifier)
..lambda = true
..static = true
..requiredParameters.add(
Parameter(
(final b) => b
..name = 'name'
..type = refer('String'),
),
)
..body = Code('_\$valueOf$identifier(name)'),
),
Method(
(final b) => b
..returns = refer(subResult.dartType.className)
..name = 'value'
..type = MethodType.getter
..lambda = true
..body = Code('jsonSerializers.serializeWith(serializer, this)! as ${subResult.dartType.className}'),
),
buildSerializer(identifier, isCustom: true),
]),
);

final serializer = Class(
(final b) => b
..name = '_\$${identifier}Serializer'
..implements.add(refer('PrimitiveSerializer<$identifier>'))
..constructors.add(
Constructor(
(final b) => b..constant = true,
),
)
..fields.addAll([
Field((final b) {
b
..static = true
..modifier = FieldModifier.constant
..type = refer('Map<$identifier, Object>')
..name = '_toWire';
final buffer = StringBuffer()
..writeln('<$identifier, Object>{')
..writeAll(
values.map((final enumValue) => '$identifier.${enumValue.dartName}: ${enumValue.value}'),
',\n',
)
..writeln(',')
..write('}');

b.assignment = Code(buffer.toString());
}),
Field((final b) {
b
..static = true
..modifier = FieldModifier.constant
..type = refer('Map<Object, $identifier>')
..name = '_fromWire';
final buffer = StringBuffer()
..writeln('<Object, $identifier>{')
..writeAll(
values.map((final enumValue) => '${enumValue.value}: $identifier.${enumValue.dartName}'),
',\n',
)
..writeln(',')
..write('}');

b.assignment = Code(buffer.toString());
}),
])
..methods.addAll([
Method(
(final b) => b
..name = 'types'
..lambda = true
..type = MethodType.getter
..returns = refer('Iterable<Type>')
..annotations.add(refer('override'))
..body = Code('const [$identifier]'),
),
Method(
(final b) => b
..name = 'wireName'
..lambda = true
..type = MethodType.getter
..returns = refer('String')
..annotations.add(refer('override'))
..body = Code("r'$identifier'"),
),
Method((final b) {
b
..name = 'serialize'
..returns = refer('Object')
..annotations.add(refer('override'))
..lambda = true
..requiredParameters.addAll([
Parameter(
(final b) => b
..name = 'serializers'
..type = refer('Serializers'),
),
Parameter(
(final b) => b
..name = 'object'
..type = refer(identifier),
),
])
..optionalParameters.add(
Parameter(
(final b) => b
..name = 'specifiedType'
..type = refer('FullType')
..named = true
..defaultTo = const Code('FullType.unspecified'),
),
)
..body = const Code('_toWire[object]!');
}),
Method((final b) {
b
..name = 'deserialize'
..returns = refer(identifier)
..annotations.add(refer('override'))
..lambda = true
..requiredParameters.addAll([
Parameter(
(final b) => b
..name = 'serializers'
..type = refer('Serializers'),
),
Parameter(
(final b) => b
..name = 'serialized'
..type = refer('Object'),
),
])
..optionalParameters.add(
Parameter(
(final b) => b
..name = 'specifiedType'
..type = refer('FullType')
..named = true
..defaultTo = const Code('FullType.unspecified'),
),
)
..body = const Code('_fromWire[serialized]!');
}),
]),
);

state.output.addAll([
$class,
serializer,
]);
}
return TypeResultEnum(
identifier,
Expand Down
3 changes: 1 addition & 2 deletions packages/dynamite/dynamite/lib/src/builder/resolve_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ TypeResult resolveType(
final State state,
final String identifier,
final openapi.Schema schema, {
final bool ignoreEnum = false,
final bool nullable = false,
}) {
TypeResult? result;
Expand Down Expand Up @@ -178,7 +177,7 @@ TypeResult resolveType(
}

if (result != null) {
if (!ignoreEnum && schema.$enum != null) {
if (schema.$enum != null) {
result = resolveEnum(
spec,
state,
Expand Down
Loading

0 comments on commit 4b3407d

Please sign in to comment.