| // Copyright (c) 2019, 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:io'; |
| import 'dart:convert'; |
| |
| import 'package:args/command_runner.dart'; |
| |
| import 'package:dart2js_info/info.dart'; |
| import 'package:dart2js_info/json_info_codec.dart'; |
| import 'package:dart2js_info/src/io.dart'; |
| |
| import 'usage_exception.dart'; |
| |
| /// Converts a dump-info file emitted by dart2js in binary format to JSON. |
| class ToJsonCommand extends Command<void> with PrintUsageException { |
| final String name = "to_json"; |
| final String description = "Convert any info file to JSON format."; |
| |
| ToJsonCommand() { |
| argParser.addOption('out', |
| abbr: 'o', help: 'Output file (defauts to <input>.json)'); |
| |
| argParser.addFlag('inject-text', |
| negatable: false, |
| help: 'Whether to inject output code snippets.\n\n' |
| 'By default dart2js produces code spans, but excludes the text. This\n' |
| 'option can be used to embed the text directly in the output JSON.\n' |
| 'This is implied by `--compat-mode`.'); |
| |
| argParser.addFlag('compat-mode', |
| negatable: false, |
| help: 'Whether to generate an older version of the JSON format.\n\n' |
| 'By default files are converted to the latest JSON format, but\n' |
| 'passing `--compat-mode` will produce a JSON file that may still\n' |
| 'work in the visualizer tool at:\n' |
| 'https://dart-lang.github.io/dump-info-visualizer/.\n\n' |
| 'Note, however, that files produced in this mode do not contain\n' |
| 'all the data available in the input file.'); |
| } |
| |
| void run() async { |
| if (argResults.rest.length < 1) { |
| usageException('Missing argument: <input-info>'); |
| } |
| |
| String filename = argResults.rest[0]; |
| bool isBackwardCompatible = argResults['compat-mode']; |
| AllInfo info = await infoFromFile(filename); |
| |
| if (isBackwardCompatible || argResults['inject-text']) { |
| // Fill the text of each code span. The binary form produced by dart2js |
| // produces code spans, but excludes the orignal text |
| info.functions.forEach((f) { |
| f.code.forEach((span) => _fillSpan(span, f.outputUnit)); |
| }); |
| info.fields.forEach((f) { |
| f.code.forEach((span) => _fillSpan(span, f.outputUnit)); |
| }); |
| info.constants.forEach((c) { |
| c.code.forEach((span) => _fillSpan(span, c.outputUnit)); |
| }); |
| } |
| |
| var json = new AllInfoJsonCodec(isBackwardCompatible: isBackwardCompatible) |
| .encode(info); |
| String outputFilename = argResults['out'] ?? '$filename.json'; |
| new File(outputFilename) |
| .writeAsStringSync(const JsonEncoder.withIndent(" ").convert(json)); |
| } |
| } |
| |
| Map<String, String> _cache = {}; |
| |
| _getContents(OutputUnitInfo unit) => _cache.putIfAbsent(unit.filename, () { |
| var uri = Uri.base.resolve(unit.filename); |
| return new File.fromUri(uri).readAsStringSync(); |
| }); |
| |
| _fillSpan(CodeSpan span, OutputUnitInfo unit) { |
| if (span.text == null && span.start != null && span.end != 0) { |
| var contents = _getContents(unit); |
| span.text = contents.substring(span.start, span.end); |
| } |
| } |