Skip to content

Commit 40f6768

Browse files
committed
fix record level hooks
1 parent 1a0a529 commit 40f6768

6 files changed

Lines changed: 181 additions & 0 deletions

File tree

packages/dart_mappable/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
- Record mappers now correctly generate hooks specified on the record annotation itself, not just those on individual fields.
4+
15
# 4.6.0
26

37
- Add support for self-referencing generics (e.g. `T extends Comparable<T>`)

packages/dart_mappable/test/records/mappable_record_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:math';
2+
13
import 'package:dart_mappable/dart_mappable.dart';
24
import 'package:test/test.dart';
35

@@ -19,6 +21,22 @@ class RoundingHook extends MappingHook {
1921
}
2022
}
2123

24+
class HypotenuseHook extends MappingHook {
25+
const HypotenuseHook();
26+
27+
@override
28+
Object? beforeDecode(Object? value) {
29+
final map = (value as Map).cast<String, dynamic>();
30+
final leg1 = map['x'] as num;
31+
final leg2 = map['y'] as num;
32+
map['hypotenuse'] = sqrt(leg1 * leg1 + leg2 * leg2);
33+
return map;
34+
}
35+
}
36+
37+
@MappableRecord(hook: HypotenuseHook())
38+
typedef Hypotenuse = ({double x, double y, double hypotenuse});
39+
2240
@MappableClass()
2341
class Location with LocationMappable {
2442
final Point point;
@@ -66,5 +84,19 @@ void main() {
6684
expect(p, equals((x: 1, y: 2)));
6785
expect(encode(p), equals({'a': 1, 'y': 2}));
6886
});
87+
88+
test('can decode and encode record hook on record', () {
89+
var decode = MapperContainer.globals.fromMap;
90+
var encode = MapperContainer.globals.toMap;
91+
92+
HypotenuseMapper.ensureInitialized();
93+
94+
var h = decode<Hypotenuse>({'x': 3, 'y': 4});
95+
expect(h, equals((x: 3, y: 4, hypotenuse: sqrt(3 * 3 + 4 * 4))));
96+
expect(
97+
encode(h),
98+
equals({'x': 3, 'y': 4, 'hypotenuse': sqrt(3 * 3 + 4 * 4)}),
99+
);
100+
});
69101
});
70102
}

packages/dart_mappable/test/records/mappable_record_test.mapper.dart

Lines changed: 113 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dart_mappable_builder/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
- Record mappers now correctly generate hooks specified on the record annotation itself, not just those on individual fields.
4+
15
# 4.6.0
26

37
- Migrate to new `element2` analyzer model.

packages/dart_mappable_builder/lib/src/elements/record/record_mapper_element.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import 'package:analyzer/dart/ast/ast.dart';
12
import 'package:analyzer/dart/element/element2.dart';
23
import 'package:analyzer/dart/element/type.dart';
34
import 'package:collection/collection.dart';
45

6+
import '../../utils.dart';
57
import '../mapper_element.dart';
68

79
abstract class RecordMapperElement<T extends Element2>
@@ -48,4 +50,19 @@ abstract class RecordMapperElement<T extends Element2>
4850
String genericArgAt(int index) {
4951
return String.fromCharCode('A'.codeUnitAt(0) + index);
5052
}
53+
54+
late final String? hookForRecord = () {
55+
var hook = annotation.value?.read('hook');
56+
if (hook != null && !hook.isNull) {
57+
var node = annotation.getPropertyNode('hook');
58+
if (node != null) {
59+
var hook = node.toSource();
60+
if (node is InstanceCreationExpression) {
61+
hook = 'const $hook';
62+
}
63+
return hook;
64+
}
65+
}
66+
return null;
67+
}();
5168
}

packages/dart_mappable_builder/lib/src/generators/record_mapper_generator.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class RecordMapperGenerator extends MapperGenerator<RecordMapperElement> {
3232

3333
generateTypeFactory(output);
3434
generateApplyOverride(output);
35+
generateHook(output);
3536
generateInstantiate(output);
3637
generateStaticDecoders(output);
3738

@@ -120,4 +121,14 @@ class RecordMapperGenerator extends MapperGenerator<RecordMapperElement> {
120121
' }\n',
121122
);
122123
}
124+
125+
void generateHook(StringBuffer output) {
126+
var hook = element.hookForRecord;
127+
if (hook != null) {
128+
output.write('''
129+
@override
130+
final MappingHook hook = $hook;
131+
''');
132+
}
133+
}
123134
}

0 commit comments

Comments
 (0)