trphoenix
2018-11-12 29fbfc5dd1d55d189f23eb6d32f000252f92985f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
 
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:json_annotation/json_annotation.dart';
 
/// Context information provided in calls to [TypeHelper.serialize] and
/// [TypeHelper.deserialize].
abstract class TypeHelperContext {
  /// The annotated class that code is being generated for.
  ClassElement get classElement;
 
  /// The field that code is being generated for.
  FieldElement get fieldElement;
 
  /// Returns `true` if [fieldElement] could potentially contain a `null` value.
  bool get nullable;
 
  /// [expression] may be just the name of the field or it may an expression
  /// representing the serialization of a value.
  Object serialize(DartType fieldType, String expression);
 
  /// [expression] may be just the name of the field or it may an expression
  /// representing the serialization of a value.
  Object deserialize(DartType fieldType, String expression);
 
  /// Adds [memberContent] to the set of generated, top-level members.
  void addMember(String memberContent);
}
 
/// Extended context information with includes configuration values
/// corresponding to `JsonSerializableGenerator` settings.
abstract class TypeHelperContextWithConfig extends TypeHelperContext {
  JsonSerializable get config;
}
 
abstract class TypeHelper<T extends TypeHelperContext> {
  const TypeHelper();
 
  /// Returns Dart code that serializes an [expression] representing a Dart
  /// object of type [targetType].
  ///
  /// If [targetType] is not supported, returns `null`.
  ///
  /// Let's say you want to serialize a class `Foo` as just its `id` property
  /// of type `int`.
  ///
  /// Treating [expression] as a opaque Dart expression, the [serialize]
  /// implementation could be a simple as:
  ///
  /// ```dart
  /// String serialize(DartType targetType, String expression) =>
  ///   "$expression.id";
  /// ```.
  Object serialize(DartType targetType, String expression, T context);
 
  /// Returns Dart code that deserializes an [expression] representing a JSON
  /// literal to into [targetType].
  ///
  /// If [targetType] is not supported, returns `null`.
  ///
  /// Let's say you want to deserialize a class `Foo` by taking an `int` stored
  /// in a JSON literal and calling the `Foo.fromInt` constructor.
  ///
  /// Treating [expression] as a opaque Dart expression representing a JSON
  /// literal, the [deserialize] implementation could be a simple as:
  ///
  /// ```dart
  /// String deserialize(DartType targetType, String expression) =>
  ///   "new Foo.fromInt($expression)";
  /// ```.
  ///
  /// Note that [targetType] is not used here. If you wanted to support many
  /// types of [targetType] you could write:
  ///
  /// ```dart
  /// String deserialize(DartType targetType, String expression) =>
  ///   "new ${targetType.name}.fromInt($expression)";
  /// ```.
  Object deserialize(DartType targetType, String expression, T context);
}
 
class LambdaResult {
  final String expression;
  final String lambda;
 
  LambdaResult(this.expression, this.lambda);
 
  @override
  String toString() => '$lambda($expression)';
 
  static String process(Object subField, String closureArg) =>
      (subField is LambdaResult && closureArg == subField.expression)
          ? subField.lambda
          : '($closureArg) => $subField';
}
 
class UnsupportedTypeError extends Error {
  final String expression;
  final DartType type;
  final String reason;
 
  UnsupportedTypeError(this.type, this.expression, this.reason);
}
 
Object commonNullPrefix(
        bool nullable, String expression, Object unsafeExpression) =>
    nullable
        ? '$expression == null ? null : $unsafeExpression'
        : unsafeExpression;