Skip to content

Breaking changes #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion json_serializable/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
## 0.2.6
## 0.3.0

* **BREAKING** `UnsupportedTypeError` added a new required constructor argument:
`reason`.

* **BREAKING** The deprecated `annotations.dart` library has been removed.
Use `package:json_annotation` instead.

* Make `null` field handling smarter. If a field is classified as not
`nullable`, then use this knowledge when generating serialization code – even
Expand Down
8 changes: 0 additions & 8 deletions json_serializable/lib/annotations.dart

This file was deleted.

38 changes: 20 additions & 18 deletions json_serializable/lib/src/json_serializable_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,7 @@ void $toJsonMapHelperName(String key, dynamic value) {
return _serialize(
field.type, accessOverride, _nullable(field, classIncludeNullable));
} on UnsupportedTypeError catch (e) {
var extra = (field.type != e.type) ? ' because of type `${e.type}`' : '';

var message = 'Could not generate `toJson` code for '
'`${friendlyNameForElement(field)}`$extra.';

throw new InvalidGenerationSourceError(message,
todo: 'Make sure all of the types are serializable.');
throw _createInvalidGenerationError('toJson', field, e);
}
}

Expand All @@ -360,8 +354,8 @@ void $toJsonMapHelperName(String key, dynamic value) {
_allHelpers
.map((h) => h.serialize(targetType, expression, nullable, _serialize))
.firstWhere((r) => r != null,
orElse: () =>
throw new UnsupportedTypeError(targetType, expression));
orElse: () => throw new UnsupportedTypeError(
targetType, expression, _notSupportedWithTypeHelpersMsg));

String _deserializeForField(FieldElement field, bool classSupportNullable,
{ParameterElement ctorParam}) {
Expand All @@ -373,13 +367,7 @@ void $toJsonMapHelperName(String key, dynamic value) {
return _deserialize(
targetType, 'json[$jsonKey]', _nullable(field, classSupportNullable));
} on UnsupportedTypeError catch (e) {
var extra = (field.type != e.type) ? ' because of type `${e.type}`' : '';

var message = 'Could not generate `fromJson` code for '
'`${friendlyNameForElement(field)}`$extra.';

throw new InvalidGenerationSourceError(message,
todo: 'Make sure all of the types are serializable.');
throw _createInvalidGenerationError('fromJson', field, e);
}
}

Expand All @@ -388,8 +376,8 @@ void $toJsonMapHelperName(String key, dynamic value) {
.map((th) =>
th.deserialize(targetType, expression, nullable, _deserialize))
.firstWhere((r) => r != null,
orElse: () =>
throw new UnsupportedTypeError(targetType, expression));
orElse: () => throw new UnsupportedTypeError(
targetType, expression, _notSupportedWithTypeHelpersMsg));
}

String _safeNameAccess(FieldElement field) {
Expand Down Expand Up @@ -457,3 +445,17 @@ int _offsetFor(FieldElement e) {
}
return e.nameOffset;
}

final _notSupportedWithTypeHelpersMsg =
'None of the provided `TypeHelper` instances support the defined type.';

InvalidGenerationSourceError _createInvalidGenerationError(
String targetMember, FieldElement field, UnsupportedTypeError e) {
var extra = (field.type != e.type) ? ' because of type `${e.type}`' : '';

var message = 'Could not generate `$targetMember` code for '
'`${friendlyNameForElement(field)}`$extra.\n${e.reason}';

return new InvalidGenerationSourceError(message,
todo: 'Make sure all of the types are serializable.');
}
3 changes: 2 additions & 1 deletion json_serializable/lib/src/type_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ const simpleJsonTypeChecker = const TypeChecker.any(const [
class UnsupportedTypeError extends Error {
final String expression;
final DartType type;
final String reason;

UnsupportedTypeError(this.type, this.expression);
UnsupportedTypeError(this.type, this.expression, this.reason);
}

DartType _getImplementationType(DartType type, TypeChecker checker) {
Expand Down
36 changes: 15 additions & 21 deletions json_serializable/lib/src/type_helpers/map_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,7 @@ class MapHelper extends TypeHelper {
var keyArg = args[0];
var valueType = args[1];

// We're not going to handle converting key types at the moment
// So the only safe types for key are dynamic/Object/String
var safeKey = keyArg.isDynamic ||
keyArg.isObject ||
_stringTypeChecker.isExactlyType(keyArg);

if (!safeKey) {
// TODO: should add some logic to `UnsupportedTypeError` to allow more
// details to be provided – such as this case where the `key` in
// `targetType` is not supported.
throw new UnsupportedTypeError(targetType, expression);
}
_checkSafeKeyType(expression, keyArg);

var subFieldValue = serializeNested(valueType, _closureArg, nullable);

Expand Down Expand Up @@ -62,15 +51,7 @@ class MapHelper extends TypeHelper {
var keyArg = typeArgs.first;
var valueArg = typeArgs.last;

// We're not going to handle converting key types at the moment
// So the only safe types for key are dynamic/Object/String
var safeKey = keyArg.isDynamic ||
keyArg.isObject ||
_stringTypeChecker.isExactlyType(keyArg);

if (!safeKey) {
throw new UnsupportedTypeError(keyArg, expression);
}
_checkSafeKeyType(expression, keyArg);

// this is the trivial case. Do a runtime cast to the known type of JSON
// map values - `Map<String, dynamic>`
Expand All @@ -96,6 +77,19 @@ class MapHelper extends TypeHelper {

return commonNullPrefix(nullable, expression, result);
}

void _checkSafeKeyType(String expression, DartType keyArg) {
// We're not going to handle converting key types at the moment
// So the only safe types for key are dynamic/Object/String
var safeKey = keyArg.isDynamic ||
keyArg.isObject ||
_stringTypeChecker.isExactlyType(keyArg);

if (!safeKey) {
throw new UnsupportedTypeError(keyArg, expression,
'The type of the Map key must be `String`, `Object` or `dynamic`.');
}
}
}

final _coreMapChecker = const TypeChecker.fromUrl('dart:core#Map');
Expand Down
4 changes: 2 additions & 2 deletions json_serializable/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: json_serializable
version: 0.2.6-dev
version: 0.3.0-dev
author: Dart Team <misc@dartlang.org>
description: Generates utilities to aid in serializing to/from JSON.
homepage: https://github.com/dart-lang/json_serializable
Expand All @@ -16,7 +16,7 @@ dependencies:
path: ^1.3.2
source_gen: ^0.7.1
dev_dependencies:
build_runner: ^0.6.0
build_runner: ^0.6.0+1
build_test: ^0.9.0
collection: ^1.14.0
dart_style: ^1.0.0
Expand Down
6 changes: 2 additions & 4 deletions json_serializable/test/ensure_build_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ void main() {

test('ensure local build succeeds with no changes', () {
// 1 - get a list of modified `.g.dart` files - should be empty
//expect(_changedGeneratedFiles(), isEmpty);
expect(_changedGeneratedFiles(), isEmpty);

// 2 - run build - should be no output, since nothing should change
// TODO(kevmoo): run checked after github.com/dart-lang/build/issues/566
// is fixed
var result = _runProc('dart', ['tool/build.dart']);
var result = _runProc('dart', ['--checked', 'tool/build.dart']);
expect(result,
contains(new RegExp(r'Build: Succeeded after \S+ with \d+ outputs')));

Expand Down
22 changes: 13 additions & 9 deletions json_serializable/test/json_serializable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,37 +63,41 @@ void main() {
});

group('unserializable types', () {
final noSupportHelperFyi =
'Could not generate `toJson` code for `Stopwatch watch`.\n'
'None of the provided `TypeHelper` instances support the defined type.';

test('for toJson', () async {
expect(
_runForElementNamed('NoSerializeFieldType'),
throwsInvalidGenerationSourceError(
'Could not generate `toJson` code for `Stopwatch watch`.',
throwsInvalidGenerationSourceError(noSupportHelperFyi,
'Make sure all of the types are serializable.'));
});

test('for fromJson', () async {
expect(
_runForElementNamed('NoDeserializeFieldType'),
throwsInvalidGenerationSourceError(
'Could not generate `fromJson` code for `Stopwatch watch`.',
noSupportHelperFyi.replaceFirst('toJson', 'fromJson'),
'Make sure all of the types are serializable.'));
});

final mapKeyFyi = 'Could not generate `toJson` code for '
'`Map<int, DateTime> intDateTimeMap` because of type `int`.\n'
'The type of the Map key must be `String`, `Object` or `dynamic`.';

test('for toJson in Map key', () async {
expect(
_runForElementNamed('NoSerializeBadKey'),
throwsInvalidGenerationSourceError(
'Could not generate `toJson` code for '
'`Map<int, DateTime> intDateTimeMap`.',
'Make sure all of the types are serializable.'));
mapKeyFyi, 'Make sure all of the types are serializable.'));
});

test('for fromJson', () async {
expect(
_runForElementNamed('NoDeserializeBadKey'),
throwsInvalidGenerationSourceError(
'Could not generate `fromJson` code for '
'`Map<int, DateTime> intDateTimeMap` because of type `int`.',
mapKeyFyi.replaceFirst('toJson', 'fromJson'),
'Make sure all of the types are serializable.'));
});
});
Expand Down Expand Up @@ -270,7 +274,7 @@ Future<CompilationUnit> _getCompilationUnitForString(String projectPath) async {
CompilationUnit _compUnit;

const _testSource = r'''
import 'package:json_serializable/annotations.dart';
import 'package:json_annotation/json_annotation.dart';

@JsonSerializable()
const theAnswer = 42;
Expand Down