// 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 { 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;