diff --git a/CHANGELOG.md b/CHANGELOG.md index cd2daf45..ccbe35ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,19 @@ `package:json_serializable`. * Removed `lib/builder.dart`. Import through `source_gen.dart` instead. * Removed `OutputFormatter` typedef. + * Add `LibraryReader.allElements` - a utility to iterate across all `Element` instances contained in Dart library. * Add `LibraryReader.element` to get back to the `LibraryElement` instance. +* Add `ConstantReader.peek` to read a value that returns `null` if not found: + +```dart +// Tries to read the field "token" first, then "_token". +findTokenField(DartObject o) { + final reader = new ConstantReader(o); + final token = o.peek('token') ?? o.read('_token'); +} +``` ## 0.6.1+1 diff --git a/lib/src/constants.dart b/lib/src/constants.dart index 0dac0b2b..dac7d9cc 100644 --- a/lib/src/constants.dart +++ b/lib/src/constants.dart @@ -152,6 +152,11 @@ abstract class ConstantReader { /// [FormatException]. ConstantReader read(String field); + /// Reads [field] from the constant as another constant value. + /// + /// Unlike [read], returns `null` if the field is not found. + ConstantReader peek(String field); + /// Returns as a revived meta class. /// /// This is appropriate for cases where the underlying object is not a literal @@ -224,6 +229,9 @@ class _NullConstant implements ConstantReader { @override ConstantReader read(_) => throw new UnsupportedError('Null'); + @override + ConstantReader peek(_) => null; + @override Revivable revive() => throw new UnsupportedError('Null'); @@ -307,14 +315,24 @@ class _Constant implements ConstantReader { checker.isAssignableFromType(_object.type); @override - ConstantReader read(String field) { + ConstantReader peek(String field) { final constant = new ConstantReader(_getFieldRecursive(_object, field)); if (constant.isNull) { - _assertHasField(_object?.type?.element, field); + return null; } return constant; } + @override + ConstantReader read(String field) { + final reader = peek(field); + if (reader == null) { + _assertHasField(_object?.type?.element, field); + return const _NullConstant(); + } + return reader; + } + @override Revivable revive() => reviveInstance(_object); diff --git a/test/constants_test.dart b/test/constants_test.dart index e089ef5c..1dedd7ce 100644 --- a/test/constants_test.dart +++ b/test/constants_test.dart @@ -99,7 +99,7 @@ void main() { final nested = constant.read('nested'); expect(nested.isNull, isFalse, reason: '$nested'); - expect(nested.read('aString').isNull, isTrue); + expect(nested.read('aString').isNull, isTrue, reason: '$nested'); expect(nested.read('aInt').isNull, isTrue); expect(nested.read('aBool').isNull, isTrue); }); @@ -150,6 +150,12 @@ void main() { expect(() => $null.read('foo'), throwsUnsupportedError); }); + test('should not fail reading from `null` when using peek', () { + final $null = constants[3]; + expect($null.isNull, isTrue, reason: '${$null}'); + expect($null.peek('foo'), isNull); + }); + test('should fail reading a missing field', () { final $super = constants[5]; expect(() => $super.read('foo'), throwsFormatException);