// 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 'dart:async'; import 'dart:convert'; import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; import 'package:path/path.dart' as p; import 'package:source_gen/source_gen.dart'; import 'package:json_annotation/json_annotation.dart'; import 'utils.dart'; class JsonLiteralGenerator extends GeneratorForAnnotation { const JsonLiteralGenerator(); @override Future generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep) async { if (p.isAbsolute(annotation.read('path').stringValue)) { throw ArgumentError( '`annotation.path` must be relative path to the source file.'); } final sourcePathDir = p.dirname(buildStep.inputId.path); final fileId = AssetId(buildStep.inputId.package, p.join(sourcePathDir, annotation.read('path').stringValue)); final content = json.decode(await buildStep.readAsString(fileId)); final asConst = annotation.read('asConst').boolValue; final thing = jsonLiteralAsDart(content).toString(); final marked = asConst ? 'const' : 'final'; return '$marked _\$${element.name}JsonLiteral = $thing;'; } } /// Returns a [String] representing a valid Dart literal for [value]. String jsonLiteralAsDart(dynamic value) { if (value == null) return 'null'; if (value is String) return escapeDartString(value); if (value is bool || value is num) return value.toString(); if (value is List) { final listItems = value.map(jsonLiteralAsDart).join(', '); return '[$listItems]'; } if (value is Map) return jsonMapAsDart(value); throw StateError( 'Should never get here – with ${value.runtimeType} - `$value`.'); } String jsonMapAsDart(Map value) { final buffer = StringBuffer(); buffer.write('{'); var first = true; value.forEach((k, v) { if (first) { first = false; } else { buffer.writeln(','); } buffer.write(escapeDartString(k as String)); buffer.write(': '); buffer.write(jsonLiteralAsDart(v)); }); buffer.write('}'); return buffer.toString(); }