Skip to content

General cleanup #65

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 5 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
28 changes: 15 additions & 13 deletions json_serializable/lib/src/json_serializable_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,7 @@ class JsonSerializableGenerator

// Sort these in the order in which they appear in the class
// Sadly, `classElement.fields` puts properties after fields
fieldsList.sort((FieldElement a, FieldElement b) {
int offsetFor(FieldElement e) {
if (e.getter != null && e.getter.nameOffset != e.nameOffset) {
assert(e.nameOffset == -1);
return e.getter.nameOffset;
}
return e.nameOffset;
}

return offsetFor(a).compareTo(offsetFor(b));
});
fieldsList.sort((a, b) => _offsetFor(a).compareTo(_offsetFor(b)));

// Explicitly using `LinkedHashMap` – we want these ordered.
var fields = new LinkedHashMap<String, FieldElement>.fromIterable(
Expand Down Expand Up @@ -134,10 +124,12 @@ class JsonSerializableGenerator
});

if (classAnnotation.createToJson) {
var mixClassName = '${prefix}SerializerMixin';

//
// Generate the mixin class
//
buffer.writeln('abstract class ${prefix}SerializerMixin {');
buffer.writeln('abstract class $mixClassName {');

// write copies of the fields - this allows the toJson method to access
// the fields of the target class
Expand All @@ -157,7 +149,7 @@ class JsonSerializableGenerator
}

// end of the mixin class
buffer.write('}');
buffer.writeln('}');
}

return buffer.toString();
Expand Down Expand Up @@ -437,3 +429,13 @@ JsonSerializable _valueForAnnotation(ConstantReader annotation) =>
final _jsonKeyExpando = new Expando<JsonKey>();

final _jsonKeyChecker = new TypeChecker.fromRuntime(JsonKey);

/// Returns the offset of given field/property in its source file – with a
/// preference for the getter if it's defined.
int _offsetFor(FieldElement e) {
if (e.getter != null && e.getter.nameOffset != e.nameOffset) {
assert(e.nameOffset == -1);
return e.getter.nameOffset;
}
return e.nameOffset;
}
2 changes: 1 addition & 1 deletion json_serializable/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: json_serializable
version: 0.2.5
version: 0.2.6-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 Down
4 changes: 2 additions & 2 deletions json_serializable/test/json_serializable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,15 @@ abstract class _$OrderSerializerMixin {
expect(output, contains("..height = json['h']"));
});

test('works to change the name of a field', () async {
test('fails if name duplicates existing field', () async {
expect(
() => _runForElementNamed('KeyDupesField'),
throwsInvalidGenerationSourceError(
'More than one field has the JSON key `str`.',
'Check the `JsonKey` annotations on fields.'));
});

test('works to change the name of a field', () async {
test('fails if two names collide', () async {
expect(
() => _runForElementNamed('DupeKeys'),
throwsInvalidGenerationSourceError(
Expand Down
15 changes: 6 additions & 9 deletions json_serializable/test/kitchen_sink_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:test/test.dart';
import 'package:json_serializable/src/utils.dart';

import 'test_files/kitchen_sink.dart';
import 'test_files/kitchen_sink.non_nullable.dart';
import 'test_files/kitchen_sink.non_nullable.dart' as nn;
import 'test_utils.dart';

void main() {
Expand Down Expand Up @@ -78,17 +78,14 @@ void main() {
(j) => new KitchenSink.fromJson(j));
});

group('BathTub', () {
group('KitchenSink - non-nullable', () {
test('with null values fails serialization', () {
expect(
() =>
(new KitchenSinkNonNullable()..stringDateTimeMap = null).toJson(),
expect(() => (new nn.KitchenSink()..stringDateTimeMap = null).toJson(),
throwsNoSuchMethodError);
});

test('with empty json fails deserialization', () {
expect(() => new KitchenSinkNonNullable.fromJson({}),
throwsNoSuchMethodError);
expect(() => new nn.KitchenSink.fromJson({}), throwsNoSuchMethodError);
});

_sharedTests(
Expand All @@ -98,13 +95,13 @@ void main() {
Iterable<Object> objectIterable,
Iterable<int> intIterable,
Iterable<DateTime> dateTimeIterable}) =>
new KitchenSinkNonNullable(
new nn.KitchenSink(
iterable: iterable,
dynamicIterable: dynamicIterable,
objectIterable: objectIterable,
intIterable: intIterable,
dateTimeIterable: dateTimeIterable),
(j) => new KitchenSinkNonNullable.fromJson(j));
(j) => new nn.KitchenSink.fromJson(j));
});
}

Expand Down
18 changes: 9 additions & 9 deletions json_serializable/test/test_files/kitchen_sink.non_nullable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// Generator: Test Boilerplate generator
// Generator: _NonNullableGenerator
// **************************************************************************

// ignore_for_file: annotate_overrides, hash_and_equals
library json_serializable.test.kitchen_sink_nullable;
library json_serializable.test.kitchen_sink_non_nullable;

import 'package:json_annotation/json_annotation.dart';

import 'kitchen_sink.dart';
import 'kitchen_sink.dart' as k;
import 'test_files_util.dart';

part 'kitchen_sink.non_nullable.g.dart';
Expand All @@ -22,9 +22,9 @@ List<T> _defaultList<T>() => <T>[];
Map _defaultMap() => {};

@JsonSerializable(nullable: false)
class KitchenSinkNonNullable extends Object
with _$KitchenSinkNonNullableSerializerMixin
implements KitchenSink {
class KitchenSink extends Object
with _$KitchenSinkSerializerMixin
implements k.KitchenSink {
// To ensure static members are not considered for serialization.
static const answer = 42;
static final reason = 42;
Expand All @@ -38,7 +38,7 @@ class KitchenSinkNonNullable extends Object
final Iterable<int> _intIterable;
final Iterable<DateTime> _dateTimeIterable;

KitchenSinkNonNullable(
KitchenSink(
{Iterable iterable,
Iterable<dynamic> dynamicIterable,
Iterable<Object> objectIterable,
Expand All @@ -50,8 +50,8 @@ class KitchenSinkNonNullable extends Object
_intIterable = intIterable?.toList() ?? _defaultList(),
_dateTimeIterable = dateTimeIterable?.toList() ?? _defaultList();

factory KitchenSinkNonNullable.fromJson(Map<String, Object> json) =>
_$KitchenSinkNonNullableFromJson(json);
factory KitchenSink.fromJson(Map<String, Object> json) =>
_$KitchenSinkFromJson(json);

@JsonKey(includeIfNull: false)
DateTime dateTime = new DateTime(1981, 6, 5);
Expand Down
73 changes: 35 additions & 38 deletions json_serializable/test/test_files/kitchen_sink.non_nullable.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,47 @@

// GENERATED CODE - DO NOT MODIFY BY HAND

part of json_serializable.test.kitchen_sink_nullable;
part of json_serializable.test.kitchen_sink_non_nullable;

// **************************************************************************
// Generator: JsonSerializableGenerator
// **************************************************************************

KitchenSinkNonNullable _$KitchenSinkNonNullableFromJson(
Map<String, dynamic> json) =>
new KitchenSinkNonNullable(
iterable: json['iterable'] as List,
dynamicIterable: json['dynamicIterable'] as List,
objectIterable: json['objectIterable'] as List,
intIterable: (json['intIterable'] as List).map((e) => e as int),
dateTimeIterable: (json['datetime-iterable'] as List)
.map((e) => DateTime.parse(e as String)))
..dateTime = DateTime.parse(json['dateTime'] as String)
..list = json['list'] as List
..dynamicList = json['dynamicList'] as List
..objectList = json['objectList'] as List
..intList = (json['intList'] as List).map((e) => e as int).toList()
..dateTimeList = (json['dateTimeList'] as List)
.map((e) => DateTime.parse(e as String))
.toList()
..map = json['map'] as Map<String, dynamic>
..stringStringMap =
new Map<String, String>.from(json['stringStringMap'] as Map)
..stringIntMap = new Map<String, int>.from(json['stringIntMap'] as Map)
..stringDateTimeMap = new Map<String, DateTime>.fromIterables(
(json['stringDateTimeMap'] as Map<String, dynamic>).keys,
(json['stringDateTimeMap'] as Map)
.values
.map((e) => DateTime.parse(e as String)))
..crazyComplex = (json['crazyComplex'] as List)
.map((e) => new Map<String, Map<String, List<List<DateTime>>>>.fromIterables(
(e as Map<String, dynamic>).keys,
(e as Map)
.values
.map((e) => new Map<String, List<List<DateTime>>>.fromIterables((e as Map<String, dynamic>).keys, (e as Map).values.map((e) => (e as List).map((e) => (e as List).map((e) => DateTime.parse(e as String)).toList()).toList())))))
.toList()
..val = new Map<String, bool>.from(json['val'] as Map)
..writeNotNull = json['writeNotNull'] as bool
..string = json[r'$string'] as String;
KitchenSink _$KitchenSinkFromJson(Map<String, dynamic> json) => new KitchenSink(
iterable: json['iterable'] as List,
dynamicIterable: json['dynamicIterable'] as List,
objectIterable: json['objectIterable'] as List,
intIterable: (json['intIterable'] as List).map((e) => e as int),
dateTimeIterable: (json['datetime-iterable'] as List)
.map((e) => DateTime.parse(e as String)))
..dateTime = DateTime.parse(json['dateTime'] as String)
..list = json['list'] as List
..dynamicList = json['dynamicList'] as List
..objectList = json['objectList'] as List
..intList = (json['intList'] as List).map((e) => e as int).toList()
..dateTimeList = (json['dateTimeList'] as List)
.map((e) => DateTime.parse(e as String))
.toList()
..map = json['map'] as Map<String, dynamic>
..stringStringMap =
new Map<String, String>.from(json['stringStringMap'] as Map)
..stringIntMap = new Map<String, int>.from(json['stringIntMap'] as Map)
..stringDateTimeMap = new Map<String, DateTime>.fromIterables(
(json['stringDateTimeMap'] as Map<String, dynamic>).keys,
(json['stringDateTimeMap'] as Map)
.values
.map((e) => DateTime.parse(e as String)))
..crazyComplex = (json['crazyComplex'] as List)
.map((e) => new Map<String, Map<String, List<List<DateTime>>>>.fromIterables(
(e as Map<String, dynamic>).keys,
(e as Map).values.map((e) =>
new Map<String, List<List<DateTime>>>.fromIterables((e as Map<String, dynamic>).keys, (e as Map).values.map((e) => (e as List).map((e) => (e as List).map((e) => DateTime.parse(e as String)).toList()).toList())))))
.toList()
..val = new Map<String, bool>.from(json['val'] as Map)
..writeNotNull = json['writeNotNull'] as bool
..string = json[r'$string'] as String;

abstract class _$KitchenSinkNonNullableSerializerMixin {
abstract class _$KitchenSinkSerializerMixin {
DateTime get dateTime;
Iterable<dynamic> get iterable;
Iterable<dynamic> get dynamicIterable;
Expand Down
81 changes: 34 additions & 47 deletions json_serializable/tool/build_actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ import 'package:source_gen/source_gen.dart';

final List<BuildAction> buildActions = [
new BuildAction(
new LibraryBuilder(
new _TestBoilerplateGenerator('test/test_files/kitchen_sink.dart'),
generatedExtension: '.non_nullable.dart',
additionalOutputExtensions: _TestBoilerplateGenerator.extensions,
header: _copyrightHeader),
new LibraryBuilder(new _NonNullableGenerator(),
generatedExtension: '.non_nullable.dart', header: _copyrightHeader),
'json_serializable',
inputs: const ['test/test_files/*.dart']),
inputs: const ['test/test_files/kitchen_sink.dart']),
new BuildAction(
new PartBuilder(
const [const JsonSerializableGenerator(), const JsonLiteralGenerator()],
header: _copyrightHeader),
'json_serializable',
inputs: const ['example/*.dart', 'test/test_files/*.dart'],
inputs: const [
'example/*.dart',
'test/test_files/json_literal.dart',
'test/test_files/json_test_example.dart',
'test/test_files/kitchen_sink.dart',
'test/test_files/kitchen_sink.non_nullable.dart'
],
)
];

Expand All @@ -37,50 +40,37 @@ final _copyrightContent =

final _copyrightHeader = '$_copyrightContent\n$defaultFileHeader';

class _TestBoilerplateGenerator extends Generator {
static final extensions = const ['.nullable.dart'];
final String path;
final String _baseFileName;

_TestBoilerplateGenerator(this.path)
: _baseFileName = p.basenameWithoutExtension(path) {
assert(p.extension(path) == '.dart');
assert(!_baseFileName.contains('.'));
}

class _NonNullableGenerator extends Generator {
@override
FutureOr<String> generate(LibraryReader library, BuildStep buildStep) async {
if (buildStep.inputId.path != path) {
return null;
}
final path = buildStep.inputId.path;
final baseName = p.basenameWithoutExtension(path);

// 1) - source file
final f1Content = await buildStep.readAsString(buildStep.inputId);
final f1LibraryDirective =
'library ${buildStep.inputId.package}.test.$_baseFileName';
assert(f1Content.contains(f1LibraryDirective));
final f1PartDirective = "part '${_baseFileName}.g.dart";
assert(f1Content.contains(f1PartDirective));

var replacements = <Replacement>[
new Replacement(_copyrightContent, ''),
new Replacement(f1LibraryDirective,
'library ${buildStep.inputId.package}.test.${_baseFileName}_nullable'),
new Replacement(
'library ${buildStep.inputId.package}.test.$baseName';
final f1PartDirective = "part '${baseName}.g.dart";

var replacements = <_Replacement>[
new _Replacement(_copyrightContent, ''),
new _Replacement(f1LibraryDirective,
'library ${buildStep.inputId.package}.test.${baseName}_non_nullable'),
new _Replacement(
f1PartDirective,
"part '${_baseFileName}.non_nullable.g.dart",
"part '${baseName}.non_nullable.g.dart",
),
new Replacement("import 'test_files_util.dart';",
"import 'kitchen_sink.dart';\nimport 'test_files_util.dart';"),
new Replacement('List<T> _defaultList<T>() => null;',
new _Replacement("import 'test_files_util.dart';",
"import 'kitchen_sink.dart' as k;\nimport 'test_files_util.dart';"),
new _Replacement('List<T> _defaultList<T>() => null;',
'List<T> _defaultList<T>() => <T>[];'),
new Replacement('Map _defaultMap() => null;', 'Map _defaultMap() => {};'),
new Replacement(
new _Replacement(
'Map _defaultMap() => null;', 'Map _defaultMap() => {};'),
new _Replacement(
'@JsonSerializable()', '@JsonSerializable(nullable: false)'),
new Replacement('KitchenSink', 'KitchenSinkNonNullable', false),
new Replacement(r'with _$KitchenSinkNonNullableSerializerMixin {',
r'with _$KitchenSinkNonNullableSerializerMixin implements KitchenSink {'),
new Replacement(
new _Replacement(r'with _$KitchenSinkSerializerMixin {',
r'with _$KitchenSinkSerializerMixin implements k.KitchenSink {'),
new _Replacement(
'DateTime dateTime;', 'DateTime dateTime = new DateTime(1981, 6, 5);')
];

Expand All @@ -98,15 +88,12 @@ class _TestBoilerplateGenerator extends Generator {

return f2Content;
}

@override
String toString() => 'Test Boilerplate generator';
}

class Replacement {
final String existing;
class _Replacement {
final Pattern existing;
final String replacement;
final bool single;

Replacement(this.existing, this.replacement, [this.single = true]);
_Replacement(this.existing, this.replacement, [this.single = true]);
}