@@ -214,6 +214,8 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
214214 indent.writeln ('$datatype ${field .name };' );
215215 indent.newln ();
216216 }
217+ _writeToList (indent, classDefinition);
218+ indent.newln ();
217219 writeClassEncode (
218220 generatorOptions,
219221 root,
@@ -229,6 +231,14 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
229231 classDefinition,
230232 dartPackageName: dartPackageName,
231233 );
234+ indent.newln ();
235+ writeClassEquality (
236+ generatorOptions,
237+ root,
238+ indent,
239+ classDefinition,
240+ dartPackageName: dartPackageName,
241+ );
232242 });
233243 }
234244
@@ -248,6 +258,17 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
248258 });
249259 }
250260
261+ void _writeToList (Indent indent, Class classDefinition) {
262+ indent.writeScoped ('List<Object?> _toList() {' , '}' , () {
263+ indent.writeScoped ('return <Object?>[' , '];' , () {
264+ for (final NamedType field
265+ in getFieldsInSerializationOrder (classDefinition)) {
266+ indent.writeln ('${field .name },' );
267+ }
268+ });
269+ });
270+ }
271+
251272 @override
252273 void writeClassEncode (
253274 InternalDartOptions generatorOptions,
@@ -259,14 +280,8 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
259280 indent.write ('Object encode() ' );
260281 indent.addScoped ('{' , '}' , () {
261282 indent.write (
262- 'return <Object?> ' ,
283+ 'return _toList(); ' ,
263284 );
264- indent.addScoped ('[' , '];' , () {
265- for (final NamedType field
266- in getFieldsInSerializationOrder (classDefinition)) {
267- indent.writeln ('${field .name },' );
268- }
269- });
270285 });
271286 }
272287
@@ -317,6 +332,48 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {
317332 });
318333 }
319334
335+ @override
336+ void writeClassEquality (
337+ InternalDartOptions generatorOptions,
338+ Root root,
339+ Indent indent,
340+ Class classDefinition, {
341+ required String dartPackageName,
342+ }) {
343+ indent.writeln ('@override' );
344+ indent.writeln ('// ignore: avoid_equals_and_hash_code_on_mutable_classes' );
345+ indent.writeScoped ('bool operator ==(Object other) {' , '}' , () {
346+ indent.writeScoped (
347+ 'if (other is! ${classDefinition .name } || other.runtimeType != runtimeType) {' ,
348+ '}' , () {
349+ indent.writeln ('return false;' );
350+ });
351+ indent.writeScoped ('if (identical(this, other)) {' , '}' , () {
352+ indent.writeln ('return true;' );
353+ });
354+ indent.writeScoped ('return ' , '' , () {
355+ indent.format (
356+ classDefinition.fields
357+ .map ((NamedType field) => field.type.baseName == 'List' ||
358+ field.type.baseName == 'Float64List' ||
359+ field.type.baseName == 'Int32List' ||
360+ field.type.baseName == 'Int64List' ||
361+ field.type.baseName == 'Uint8List' ||
362+ field.type.baseName == 'Map'
363+ ? '_deepEquals(${field .name }, other.${field .name })'
364+ : '${field .name } == other.${field .name }' )
365+ .join ('\n && ' ),
366+ trailingNewline: false );
367+ indent.addln (';' );
368+ }, addTrailingNewline: false );
369+ });
370+ indent.newln ();
371+ indent.writeln ('@override' );
372+ indent.writeln ('// ignore: avoid_equals_and_hash_code_on_mutable_classes' );
373+ indent.writeln ('int get hashCode => Object.hashAll(_toList())' );
374+ indent.addln (';' );
375+ }
376+
320377 @override
321378 void writeGeneralCodec (
322379 InternalDartOptions generatorOptions,
@@ -1031,6 +1088,13 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger;
10311088 generatorOptions.testOut != null ) {
10321089 _writeWrapResponse (generatorOptions, root, indent);
10331090 }
1091+ if (root.classes.isNotEmpty &&
1092+ root.classes.any ((Class dataClass) => dataClass.fields.any (
1093+ (NamedType field) =>
1094+ field.type.baseName.startsWith ('List' ) ||
1095+ field.type.baseName.startsWith ('Map' )))) {
1096+ _writeDeepEquals (indent);
1097+ }
10341098 }
10351099
10361100 /// Writes [wrapResponse] method.
@@ -1050,6 +1114,25 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger;
10501114 });
10511115 }
10521116
1117+ void _writeDeepEquals (Indent indent) {
1118+ indent.format (r'''
1119+ bool _deepEquals(Object? a, Object? b) {
1120+ if (a is List && b is List) {
1121+ return a.length == b.length &&
1122+ a.indexed
1123+ .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
1124+ }
1125+ if (a is Map && b is Map) {
1126+ final Iterable<Object?> keys = (a as Map<Object?, Object?>).keys;
1127+ return a.length == b.length && keys.every((Object? key) =>
1128+ (b as Map<Object?, Object?>).containsKey(key) &&
1129+ _deepEquals(a[key], b[key]));
1130+ }
1131+ return a == b;
1132+ }
1133+ ''' );
1134+ }
1135+
10531136 void _writeCreateConnectionError (Indent indent) {
10541137 indent.newln ();
10551138 indent.format ('''
0 commit comments