dart2js_info: enable and fix lints, validate analysis on CI

Also updated dependencies and dropped publish information

Change-Id: Ie5d8ca907599c5e504c747d97413d32ef9e329e3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/217061
Auto-Submit: Kevin Moore <kevmoo@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Kevin Moore <kevmoo@google.com>
This commit is contained in:
Kevin Moore 2021-10-17 06:25:00 +00:00 committed by commit-bot@chromium.org
parent 189aeead47
commit cc40080d96
41 changed files with 538 additions and 393 deletions

View file

@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
"generated": "2021-10-13T14:43:47.733371",
"generated": "2021-10-15T13:46:59.969883",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@ -208,7 +208,7 @@
"name": "dart2js_info",
"rootUri": "../pkg/dart2js_info",
"packageUri": "lib/",
"languageVersion": "2.3"
"languageVersion": "2.11"
},
{
"name": "dart2js_runtime_metrics",

View file

@ -0,0 +1,6 @@
include: package:lints/recommended.yaml
analyzer:
errors:
# Until the protobuf package generates the right code - or the right ignores
constant_identifier_names: ignore

View file

@ -37,16 +37,20 @@ import 'package:dart2js_info/src/util.dart';
import 'usage_exception.dart';
class CodeDepsCommand extends Command<void> with PrintUsageException {
@override
final String name = "code_deps";
@override
final String description = "";
CodeDepsCommand() {
addSubcommand(new _SomePathQuery());
addSubcommand(_SomePathQuery());
}
}
class _SomePathQuery extends Command<void> with PrintUsageException {
@override
final String name = "some_path";
@override
final String description = "find a call-graph path between two elements.";
@override
@ -62,9 +66,9 @@ class _SomePathQuery extends Command<void> with PrintUsageException {
var graph = graphFromInfo(info);
var source = info.functions
.firstWhere(_longNameMatcher(new RegExp(args[1])), orElse: () => null);
.firstWhere(_longNameMatcher(RegExp(args[1])), orElse: () => null);
var target = info.functions
.firstWhere(_longNameMatcher(new RegExp(args[2])), orElse: () => null);
.firstWhere(_longNameMatcher(RegExp(args[2])), orElse: () => null);
print('query: some_path');
if (source == null) {
usageException("source '${args[1]}' not found in '${args[0]}'");
@ -74,7 +78,7 @@ class _SomePathQuery extends Command<void> with PrintUsageException {
usageException("target '${args[2]}' not found in '${args[0]}'");
}
print('target: ${longName(target)}');
var path = new SomePathQuery(source, target).run(graph);
var path = SomePathQuery(source, target).run(graph);
if (path.isEmpty) {
print('result: no path found');
} else {
@ -103,12 +107,12 @@ class SomePathQuery {
List<Info> run(Graph<Info> graph) {
var seen = <Info, Info>{source: null};
var queue = new Queue<Info>();
var queue = Queue<Info>();
queue.addLast(source);
while (queue.isNotEmpty) {
var node = queue.removeFirst();
if (identical(node, target)) {
var result = new Queue<Info>();
var result = Queue<Info>();
while (node != null) {
result.addFirst(node);
node = seen[node];
@ -125,7 +129,7 @@ class SomePathQuery {
}
}
typedef bool LongNameMatcher(FunctionInfo info);
typedef LongNameMatcher = bool Function(FunctionInfo info);
LongNameMatcher _longNameMatcher(RegExp regexp) =>
(e) => regexp.hasMatch(longName(e));

View file

@ -11,13 +11,15 @@ import 'usage_exception.dart';
/// This tool reports how code is divided among deferred chunks.
class ConvertCommand extends Command<void> with PrintUsageException {
@override
final String name = "convert";
@override
final String description = "Convert between info formats.";
ConvertCommand() {
_addSubcommand(new ToJsonCommand());
_addSubcommand(new ToBinaryCommand());
_addSubcommand(new ToProtoCommand());
_addSubcommand(ToJsonCommand());
_addSubcommand(ToBinaryCommand());
_addSubcommand(ToProtoCommand());
}
_addSubcommand(Command<void> command) {

View file

@ -31,7 +31,9 @@ import 'package:shelf/shelf_io.dart' as shelf;
import 'usage_exception.dart';
class CoverageLogServerCommand extends Command<void> with PrintUsageException {
@override
final String name = 'coverage_server';
@override
final String description = 'Server to gather code coverage data';
CoverageLogServerCommand() {
@ -46,30 +48,29 @@ class CoverageLogServerCommand extends Command<void> with PrintUsageException {
' into the .js file',
defaultsTo: '')
..addOption('out',
abbr: 'o',
help: 'output log file',
defaultsTo: _DEFAULT_OUT_TEMPLATE);
abbr: 'o', help: 'output log file', defaultsTo: _defaultOutTemplate);
}
@override
void run() async {
if (argResults.rest.isEmpty) {
usageException('Missing arguments: <dart2js-out-file> [<html-file>]');
}
var jsPath = argResults.rest[0];
var htmlPath = null;
String htmlPath;
if (argResults.rest.length > 1) {
htmlPath = argResults.rest[1];
}
var outPath = argResults['out'];
if (outPath == _DEFAULT_OUT_TEMPLATE) outPath = '$jsPath.coverage.json';
var server = new _Server(argResults['host'], int.parse(argResults['port']),
if (outPath == _defaultOutTemplate) outPath = '$jsPath.coverage.json';
var server = _Server(argResults['host'], int.parse(argResults['port']),
jsPath, htmlPath, outPath, argResults['uri-prefix']);
await server.run();
}
}
const _DEFAULT_OUT_TEMPLATE = '<dart2js-out-file>.coverage.json';
const _defaultOutTemplate = '<dart2js-out-file>.coverage.json';
class _Server {
/// Server hostname, typically `localhost`, but can be `0.0.0.0`.
@ -102,12 +103,11 @@ class _Server {
/// against dump-info data.
Map data = {};
String get _serializedData => new JsonEncoder.withIndent(' ').convert(data);
String get _serializedData => JsonEncoder.withIndent(' ').convert(data);
_Server(this.hostname, this.port, String jsPath, this.htmlPath, this.outPath,
_Server(this.hostname, this.port, this.jsPath, this.htmlPath, this.outPath,
String prefix)
: jsPath = jsPath,
jsCode = _adjustRequestUrl(new File(jsPath).readAsStringSync(), prefix),
: jsCode = _adjustRequestUrl(File(jsPath).readAsStringSync(), prefix),
prefix = _normalize(prefix);
run() async {
@ -135,29 +135,29 @@ class _Server {
urlPath == _expectedPath(baseHtmlName)) {
var contents = htmlPath == null
? '<html><script src="$baseJsName"></script>'
: await new File(htmlPath).readAsString();
return new shelf.Response.ok(contents, headers: HTML_HEADERS);
: await File(htmlPath).readAsString();
return shelf.Response.ok(contents, headers: _htmlHeaders);
}
if (urlPath == _expectedPath(baseJsName)) {
return new shelf.Response.ok(jsCode, headers: JS_HEADERS);
return shelf.Response.ok(jsCode, headers: _jsHeaders);
}
// Handle POST requests to record coverage data, and GET requests to display
// the currently coverage results.
if (urlPath == _expectedPath('coverage')) {
if (request.method == 'GET') {
return new shelf.Response.ok(_serializedData, headers: TEXT_HEADERS);
return shelf.Response.ok(_serializedData, headers: _textHeaders);
}
if (request.method == 'POST') {
_record(jsonDecode(await request.readAsString()));
return new shelf.Response.ok("Thanks!");
return shelf.Response.ok("Thanks!");
}
}
// Any other request is not supported.
return new shelf.Response.notFound('Not found: "$urlPath"');
return shelf.Response.notFound('Not found: "$urlPath"');
}
_record(List entries) {
@ -174,8 +174,8 @@ class _Server {
_enqueueSave() async {
if (!_savePending) {
_savePending = true;
await new Future.delayed(new Duration(seconds: 3));
await new File(outPath).writeAsString(_serializedData);
await Future.delayed(Duration(seconds: 3));
await File(outPath).writeAsString(_serializedData);
var diff = data.length - _total;
print(diff == 0
? ' - no new element covered'
@ -215,6 +215,6 @@ _adjustRequestUrl(String code, String prefix) {
return '$hook$code';
}
const HTML_HEADERS = const {'content-type': 'text/html'};
const JS_HEADERS = const {'content-type': 'text/javascript'};
const TEXT_HEADERS = const {'content-type': 'text/plain'};
const _htmlHeaders = {'content-type': 'text/html'};
const _jsHeaders = {'content-type': 'text/javascript'};
const _textHeaders = {'content-type': 'text/plain'};

View file

@ -7,7 +7,6 @@
library dart2js_info.bin.debug_info;
import 'package:args/command_runner.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/graph.dart';
import 'package:dart2js_info/src/io.dart';
@ -16,7 +15,9 @@ import 'package:dart2js_info/src/util.dart';
import 'usage_exception.dart';
class DebugCommand extends Command<void> with PrintUsageException {
@override
final String name = "debug";
@override
final String description = "Dart2js-team diagnostics on a dump-info file.";
DebugCommand() {
@ -24,9 +25,10 @@ class DebugCommand extends Command<void> with PrintUsageException {
help: "Show detailed data for a library with the given name");
}
@override
void run() async {
var args = argResults.rest;
if (args.length < 1) {
if (args.isEmpty) {
usageException('Missing argument: info.data');
}
@ -43,24 +45,22 @@ class DebugCommand extends Command<void> with PrintUsageException {
/// Validates that codesize of elements adds up to total codesize.
validateSize(AllInfo info, String debugLibName) {
// Gather data from visiting all info elements.
var tracker = new _SizeTracker(debugLibName);
var tracker = _SizeTracker(debugLibName);
info.accept(tracker);
// Validate that listed elements include elements of each library.
Set<Info> listed = new Set()
..addAll(info.functions)
..addAll(info.fields);
final listed = {...info.functions, ...info.fields};
// For our sanity we do some validation of dump-info invariants
var diff1 = listed.difference(tracker.discovered);
var diff2 = tracker.discovered.difference(listed);
if (diff1.length == 0 || diff2.length == 0) {
if (diff1.isEmpty || diff2.isEmpty) {
_pass('all fields and functions are covered');
} else {
if (diff1.length > 0) {
if (diff1.isNotEmpty) {
_fail("some elements where listed globally that weren't part of any "
"library (non-zero ${diff1.where((f) => f.size > 0).length})");
}
if (diff2.length > 0) {
if (diff2.isNotEmpty) {
_fail("some elements found in libraries weren't part of the global list"
" (non-zero ${diff2.where((f) => f.size > 0).length})");
}
@ -87,7 +87,7 @@ validateSize(AllInfo info, String debugLibName) {
/// Validates that every element in the model has a parent (except libraries).
validateParents(AllInfo info) {
final parentlessInfos = new Set<Info>();
final parentlessInfos = <Info>{};
failIfNoParents(List<Info> infos) {
for (var info in infos) {
@ -118,7 +118,7 @@ class _SizeTracker extends RecursiveInfoVisitor {
/// [FunctionInfo]s and [FieldInfo]s transitively reachable from [LibraryInfo]
/// elements.
final Set<Info> discovered = new Set<Info>();
final Set<Info> discovered = <Info>{};
/// Total number of bytes missing if you look at the reported size compared
/// to the sum of the nested infos (e.g. if a class size is smaller than the
@ -131,13 +131,13 @@ class _SizeTracker extends RecursiveInfoVisitor {
final List unused = [];
/// Tracks the current state of this visitor.
List<_State> stack = [new _State()];
List<_State> stack = [_State()];
/// Code discovered for a [LibraryInfo], only used for debugging.
final StringBuffer _debugCode = new StringBuffer();
final StringBuffer _debugCode = StringBuffer();
int _indent = 2;
void _push() => stack.add(new _State());
void _push() => stack.add(_State());
void _pop(info) {
var last = stack.removeLast();
@ -158,6 +158,7 @@ class _SizeTracker extends RecursiveInfoVisitor {
}
bool _debug = false;
@override
visitLibrary(LibraryInfo info) {
if (_debugLibName != null) _debug = info.name.contains(_debugLibName);
_push();
@ -189,7 +190,7 @@ class _SizeTracker extends RecursiveInfoVisitor {
_debugCode.write('...\n');
}
print('$info ${isClosureClass} \n${info.code}');
print('$info $isClosureClass \n${info.code}');
_debugCode.write(' ' * _indent);
var endsInNewLine = code.endsWith('\n');
if (endsInNewLine) code = code.substring(0, code.length - 1);
@ -206,22 +207,26 @@ class _SizeTracker extends RecursiveInfoVisitor {
stack.last._count++;
}
@override
visitField(FieldInfo info) {
_handleCodeInfo(info);
super.visitField(info);
}
@override
visitFunction(FunctionInfo info) {
_handleCodeInfo(info);
super.visitFunction(info);
}
@override
visitTypedef(TypedefInfo info) {
if (_debug) print('$info');
stack.last._totalSize += info.size;
super.visitTypedef(info);
}
@override
visitClass(ClassInfo info) {
if (_debug) {
print('$info');
@ -239,6 +244,7 @@ class _SizeTracker extends RecursiveInfoVisitor {
}
}
@override
visitClassType(ClassTypeInfo info) {
if (_debug) {
print('$info');
@ -265,8 +271,8 @@ class _State {
/// Validates that both forms of dependency information match.
void compareGraphs(AllInfo info) {
var g1 = new EdgeListGraph<Info>();
var g2 = new EdgeListGraph<Info>();
var g1 = EdgeListGraph<Info>();
var g2 = EdgeListGraph<Info>();
for (var f in info.functions) {
g1.addNode(f);
for (var g in f.uses) {
@ -320,11 +326,9 @@ void compareGraphs(AllInfo info) {
verifyDeps(AllInfo info) {
var graph = graphFromInfo(info);
var entrypoint = info.program.entrypoint;
var reachables = new Set.from(graph.preOrder(entrypoint));
var reachables = Set.from(graph.preOrder(entrypoint));
var functionsAndFields = []
..addAll(info.functions)
..addAll(info.fields);
var functionsAndFields = <BasicInfo>[...info.functions, ...info.fields];
var unreachables =
functionsAndFields.where((func) => !reachables.contains(func));
if (unreachables.isNotEmpty) {

View file

@ -47,10 +47,13 @@ import 'usage_exception.dart';
/// A command that computes the diff between two info files.
class DeferredLibraryCheck extends Command<void> with PrintUsageException {
@override
final String name = "deferred_check";
@override
final String description =
"Verify that deferred libraries are split as expected";
@override
void run() async {
var args = argResults.rest;
if (args.length < 2) {
@ -66,6 +69,6 @@ class DeferredLibraryCheck extends Command<void> with PrintUsageException {
}
Future manifestFromFile(String fileName) async {
var file = await new File(fileName).readAsString();
var file = await File(fileName).readAsString();
return loadYaml(file);
}

View file

@ -8,7 +8,6 @@ library dart2js_info.bin.deferred_library_layout;
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/io.dart';
@ -16,12 +15,15 @@ import 'usage_exception.dart';
/// This tool reports how code is divided among deferred chunks.
class DeferredLibraryLayout extends Command<void> with PrintUsageException {
@override
final String name = "deferred_layout";
@override
final String description = "Show how code is divided among deferred parts.";
@override
void run() async {
var args = argResults.rest;
if (args.length < 1) {
if (args.isEmpty) {
usageException('Missing argument: info.data');
}
await _showLayout(args.first);
@ -37,7 +39,7 @@ _showLayout(String file) async {
var unit = info.outputUnit;
var lib = _libOf(info);
if (lib == null) return;
libToHunks.putIfAbsent(lib, () => new Set()).add(unit);
libToHunks.putIfAbsent(lib, () => <OutputUnitInfo>{}).add(unit);
hunkMembers
.putIfAbsent(unit, () => {})
.putIfAbsent(lib, () => [])

View file

@ -16,12 +16,15 @@ import 'usage_exception.dart';
/// This tool gives a breakdown of code size by deferred part in the program.
class DeferredLibrarySize extends Command<void> with PrintUsageException {
@override
final String name = "deferred_size";
@override
final String description = "Show breakdown of codesize by deferred part.";
@override
void run() async {
var args = argResults.rest;
if (args.length < 1) {
if (args.isEmpty) {
usageException('Missing argument: info.data');
}
// TODO(het): Would be faster to only parse the 'outputUnits' part
@ -37,6 +40,7 @@ class ImportSize {
const ImportSize(this.import, this.size);
@override
String toString() {
return '$import: $size';
}
@ -45,14 +49,14 @@ class ImportSize {
void printSizes(Map<String, int> sizeByImport, int programSize) {
var importSizes = <ImportSize>[];
sizeByImport.forEach((import, size) {
importSizes.add(new ImportSize(import, size));
importSizes.add(ImportSize(import, size));
});
// Sort by size, largest first.
importSizes.sort((a, b) => b.size - a.size);
int longest = importSizes.fold('Percent of code deferred'.length,
(longest, importSize) => max(longest, importSize.import.length));
_printRow(label, data, {int width: 15}) {
_printRow(label, data, {int width = 15}) {
print('${label.toString().padRight(longest + 1)}'
'${data.toString().padLeft(width)}');
}

View file

@ -13,7 +13,9 @@ import 'usage_exception.dart';
/// A command that computes the diff between two info files.
class DiffCommand extends Command<void> with PrintUsageException {
@override
final String name = "diff";
@override
final String description =
"See code size differences between two dump-info files.";
@ -23,6 +25,7 @@ class DiffCommand extends Command<void> with PrintUsageException {
help: "Show only a summary and hide details of each library");
}
@override
void run() async {
var args = argResults.rest;
if (args.length < 2) {

View file

@ -8,7 +8,6 @@ library compiler.tool.function_size_analysis;
import 'dart:math' as math;
import 'package:args/command_runner.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/graph.dart';
import 'package:dart2js_info/src/io.dart';
@ -18,12 +17,15 @@ import 'usage_exception.dart';
/// Command presenting how much each function contributes to the total code.
class FunctionSizeCommand extends Command<void> with PrintUsageException {
@override
final String name = "function_size";
@override
final String description = "See breakdown of code size by function.";
@override
void run() async {
var args = argResults.rest;
if (args.length < 1) {
if (args.isEmpty) {
usageException('Missing argument: info.data');
}
var info = await infoFromFile(args.first);
@ -32,12 +34,13 @@ class FunctionSizeCommand extends Command<void> with PrintUsageException {
}
showCodeDistribution(AllInfo info,
{bool filter(Info info), bool showLibrarySizes: false}) {
{bool Function(Info info) filter, bool showLibrarySizes = false}) {
var realTotal = info.program.size;
if (filter == null) filter = (i) => true;
var reported = <BasicInfo>[]
..addAll(info.functions.where(filter))
..addAll(info.fields.where(filter));
filter ??= (i) => true;
var reported = <BasicInfo>[
...info.functions.where(filter),
...info.fields.where(filter)
];
// Compute a graph from the dependencies in [info].
Graph<Info> graph = graphFromInfo(info);
@ -51,7 +54,7 @@ showCodeDistribution(AllInfo info,
var minS = totalCount;
var nodeData = {};
for (var scc in components) {
var sccData = new _SccData();
var sccData = _SccData();
maxS = math.max(maxS, scc.length);
minS = math.min(minS, scc.length);
for (var f in scc) {
@ -85,7 +88,9 @@ showCodeDistribution(AllInfo info,
}
helper(mainMethod);
reported.forEach((n) => dominatedSize.putIfAbsent(n, () => n.size));
for (var n in reported) {
dominatedSize.putIfAbsent(n, () => n.size);
}
reported.sort((a, b) =>
(dominatedSize[b] + nodeData[b].maxSize) -
(dominatedSize[a] + nodeData[a].maxSize));
@ -94,7 +99,7 @@ showCodeDistribution(AllInfo info,
print(' --- Results per library ---');
var totals = <LibraryInfo, int>{};
var longest = 0;
reported.forEach((info) {
for (var info in reported) {
var size = info.size;
while (info != null && info is! LibraryInfo) {
info = info.parent;
@ -104,31 +109,31 @@ showCodeDistribution(AllInfo info,
totals.putIfAbsent(lib, () => 0);
totals[lib] += size;
longest = math.max(longest, '${lib.uri}'.length);
});
}
_showLibHeader(longest + 1);
var reportedByLibrary = totals.keys.toList();
reportedByLibrary.sort((a, b) => totals[b] - totals[a]);
reportedByLibrary.forEach((info) {
for (var info in reportedByLibrary) {
_showLib('${info.uri}', totals[info], realTotal, longest + 1);
});
}
}
print('\n --- Results per element (field or function) ---');
_showElementHeader();
reported.forEach((info) {
for (var info in reported) {
var size = info.size;
var min = dominatedSize[info];
var max = nodeData[info].maxSize;
_showElement(
longName(info, useLibraryUri: true), size, min, max, realTotal);
});
}
}
/// Data associated with an SCC. Used to compute the reachable code size.
class _SccData {
int size = 0;
Set deps = new Set();
Set deps = {};
_SccData();
int _maxSize;
@ -140,7 +145,7 @@ class _SccData {
void compute() {
if (_maxSize != null) return;
var max = 0;
var seen = new Set();
var seen = <dynamic>{};
helper(n) {
if (!seen.add(n)) return;
max += n.size;

View file

@ -14,22 +14,28 @@ import 'package:dart2js_info/info.dart';
void injectText(AllInfo info) {
// 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));
});
for (var f in info.functions) {
for (var span in f.code) {
_fillSpan(span, f.outputUnit);
}
}
for (var f in info.fields) {
for (var span in f.code) {
_fillSpan(span, f.outputUnit);
}
}
for (var c in info.constants) {
for (var span in c.code) {
_fillSpan(span, c.outputUnit);
}
}
}
Map<String, String> _cache = {};
_getContents(OutputUnitInfo unit) => _cache.putIfAbsent(unit.filename, () {
var uri = Uri.base.resolve(unit.filename);
return new File.fromUri(uri).readAsStringSync();
return File.fromUri(uri).readAsStringSync();
});
_fillSpan(CodeSpan span, OutputUnitInfo unit) {

View file

@ -72,7 +72,9 @@ import 'usage_exception.dart';
/// Command presenting how much each library contributes to the total code.
class LibrarySizeCommand extends Command<void> with PrintUsageException {
@override
final String name = "library_size";
@override
final String description = "See breakdown of code size by library.";
LibrarySizeCommand() {
@ -80,9 +82,10 @@ class LibrarySizeCommand extends Command<void> with PrintUsageException {
help: 'YAML file specifying how libraries should be grouped.');
}
@override
void run() async {
var args = argResults.rest;
if (args.length < 1) {
if (args.isEmpty) {
usageException('Missing argument: info.data');
print('usage: dart tool/library_size_split.dart '
'path-to-info.json [grouping.yaml]');
@ -93,29 +96,29 @@ class LibrarySizeCommand extends Command<void> with PrintUsageException {
var groupingFile = argResults['grouping'];
var groupingText = groupingFile != null
? new File(groupingFile).readAsStringSync()
? File(groupingFile).readAsStringSync()
: defaultGrouping;
var groupingYaml = loadYaml(groupingText);
var groups = [];
for (var group in groupingYaml['groups']) {
groups.add(new _Group(
group['name'], new RegExp(group['regexp']), group['cluster'] ?? 0));
groups.add(_Group(
group['name'], RegExp(group['regexp']), group['cluster'] ?? 0));
}
var sizes = {};
var allLibs = 0;
for (LibraryInfo lib in info.libraries) {
allLibs += lib.size;
groups.forEach((group) {
for (var group in groups) {
var match = group.matcher.firstMatch('${lib.uri}');
if (match != null) {
var name = group.name;
if (name == null && match.groupCount > 0) name = match.group(1);
if (name == null) name = match.group(0);
sizes.putIfAbsent(name, () => new _SizeEntry(name, group.cluster));
name ??= match.group(0);
sizes.putIfAbsent(name, () => _SizeEntry(name, group.cluster));
sizes[name].size += lib.size;
}
});
}
}
var allConstants = 0;
@ -129,7 +132,7 @@ class LibrarySizeCommand extends Command<void> with PrintUsageException {
var longest = 0;
var rows = <_Row>[];
_addRow(String label, int value) {
rows.add(new _Row(label, value));
rows.add(_Row(label, value));
longest = max(longest, label.length);
}
@ -204,7 +207,7 @@ class _Divider extends _Row {
const _Divider() : super('', 0);
}
_pad(value, n, {bool right: false}) {
_pad(value, n, {bool right = false}) {
var s = '$value';
if (s.length >= n) return s;
var pad = ' ' * (n - s.length);

View file

@ -47,7 +47,9 @@ import 'function_size_analysis.dart';
import 'usage_exception.dart';
class LiveCodeAnalysisCommand extends Command<void> with PrintUsageException {
@override
final String name = "coverage_analysis";
@override
final String description = "Analyze coverage data collected via the"
" 'coverage_server' command";
@ -56,6 +58,7 @@ class LiveCodeAnalysisCommand extends Command<void> with PrintUsageException {
abbr: 'v', negatable: false, help: 'Show verbose details.');
}
@override
void run() async {
var args = argResults.rest;
if (args.length < 2) {
@ -67,7 +70,7 @@ class LiveCodeAnalysisCommand extends Command<void> with PrintUsageException {
_liveCodeAnalysis(infoFile, coverageFile, bool verbose) async {
var info = await infoFromFile(infoFile);
var coverage = jsonDecode(new File(coverageFile).readAsStringSync());
var coverage = jsonDecode(File(coverageFile).readAsStringSync());
int realTotal = info.program.size;
int totalLib = info.libraries.fold(0, (n, lib) => n + lib.size);

View file

@ -15,7 +15,9 @@ import 'package:dart2js_info/src/io.dart';
import 'usage_exception.dart';
class ShowInferredTypesCommand extends Command<void> with PrintUsageException {
@override
final String name = "show_inferred";
@override
final String description = "Show data inferred by dart2js global inference";
ShowInferredTypesCommand() {
@ -23,6 +25,7 @@ class ShowInferredTypesCommand extends Command<void> with PrintUsageException {
abbr: 'l', negatable: false, help: 'Show long qualified names.');
}
@override
void run() async {
var args = argResults.rest;
if (args.length < 2) {
@ -35,7 +38,7 @@ class ShowInferredTypesCommand extends Command<void> with PrintUsageException {
_showInferredTypes(String infoFile, String pattern, bool showLongName) async {
var info = await infoFromFile(infoFile);
var nameRegExp = new RegExp(pattern);
var nameRegExp = RegExp(pattern);
matches(e) => nameRegExp.hasMatch(longName(e));
bool noResults = true;

View file

@ -3,18 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:args/command_runner.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/util.dart';
import 'package:dart2js_info/src/io.dart';
import 'package:dart2js_info/src/util.dart';
import 'inject_text.dart';
import 'usage_exception.dart';
/// Shows the contents of an info file as text.
class ShowCommand extends Command<void> with PrintUsageException {
@override
final String name = "show";
@override
final String description = "Show a text representation of the info file.";
ShowCommand() {
@ -28,8 +30,9 @@ class ShowCommand extends Command<void> with PrintUsageException {
'option can be used to embed the text directly in the output.');
}
@override
void run() async {
if (argResults.rest.length < 1) {
if (argResults.rest.isEmpty) {
usageException('Missing argument: <input-info>');
}
@ -37,13 +40,13 @@ class ShowCommand extends Command<void> with PrintUsageException {
AllInfo info = await infoFromFile(filename);
if (argResults['inject-text']) injectText(info);
var buffer = new StringBuffer();
info.accept(new TextPrinter(buffer, argResults['inject-text']));
var buffer = StringBuffer();
info.accept(TextPrinter(buffer, argResults['inject-text']));
var outputPath = argResults['out'];
if (outputPath == null) {
print(buffer);
} else {
new File(outputPath).writeAsStringSync('$buffer');
File(outputPath).writeAsStringSync('$buffer');
}
}
}
@ -65,13 +68,14 @@ class TextPrinter implements InfoVisitor<void> {
buffer.writeln(s.replaceAll('\n', '\n$_textIndent'));
}
void _writeBlock(String s, void f()) {
_writeIndented("$s");
void _writeBlock(String s, void Function() f) {
_writeIndented(s);
_indent++;
f();
_indent--;
}
@override
void visitAll(AllInfo info) {
_writeBlock("Summary data", () => visitProgram(info.program));
buffer.writeln();
@ -87,6 +91,7 @@ class TextPrinter implements InfoVisitor<void> {
_writeBlock("Output units", () => info.outputUnits.forEach(visitOutput));
}
@override
void visitProgram(ProgramInfo info) {
_writeIndented('main: ${longName(info.entrypoint, useLibraryUri: true)}');
_writeIndented('size: ${info.size}');
@ -109,6 +114,7 @@ class TextPrinter implements InfoVisitor<void> {
return "${(size / (1024 * 1024)).toStringAsFixed(2)} Mb ($size b)";
}
@override
void visitLibrary(LibraryInfo info) {
_writeBlock('${info.uri}: ${_size(info.size)}', () {
if (info.topLevelFunctions.isNotEmpty) {
@ -135,6 +141,7 @@ class TextPrinter implements InfoVisitor<void> {
});
}
@override
void visitClass(ClassInfo info) {
_writeBlock(
'${info.name}: ${_size(info.size)} [${info.outputUnit.filename}]', () {
@ -148,12 +155,14 @@ class TextPrinter implements InfoVisitor<void> {
});
}
@override
void visitClassType(ClassTypeInfo info) {
_writeBlock(
'${info.name}: ${_size(info.size)} [${info.outputUnit.filename}]',
() {});
}
@override
void visitField(FieldInfo info) {
_writeBlock('${info.type} ${info.name}: ${_size(info.size)}', () {
_writeIndented('inferred type: ${info.inferredType}');
@ -167,6 +176,7 @@ class TextPrinter implements InfoVisitor<void> {
});
}
@override
void visitFunction(FunctionInfo info) {
var outputUnitFile = '';
if (info.functionKind == FunctionInfo.TOP_LEVEL_FUNCTION_KIND) {
@ -177,7 +187,7 @@ class TextPrinter implements InfoVisitor<void> {
_writeBlock(
'${info.returnType} ${info.name}($params): ${_size(info.size)}$outputUnitFile',
() {
String params = info.parameters.map((p) => "${p.type}").join(', ');
String params = info.parameters.map((p) => p.type).join(', ');
_writeIndented('declared type: ${info.type}');
_writeIndented(
'inferred type: ${info.inferredReturnType} Function($params)');
@ -197,14 +207,17 @@ class TextPrinter implements InfoVisitor<void> {
_writeIndented('- ${longName(info.target, useLibraryUri: true)} $mask');
}
@override
void visitTypedef(TypedefInfo info) {
_writeIndented('${info.name}: ${info.type}');
}
@override
void visitClosure(ClosureInfo info) {
_writeBlock('${info.name}', () => visitFunction(info.function));
_writeBlock(info.name, () => visitFunction(info.function));
}
@override
void visitConstant(ConstantInfo info) {
_writeBlock('${_size(info.size)}:', () => _writeCode(info.code));
}
@ -213,6 +226,7 @@ class TextPrinter implements InfoVisitor<void> {
_writeIndented(code.map((c) => c.text).join('\n'));
}
@override
void visitOutput(OutputUnitInfo info) {
_writeIndented('${info.filename}: ${_size(info.size)}');
}

View file

@ -15,11 +15,14 @@ import 'usage_exception.dart';
/// Converts a dump-info file emitted by dart2js in JSON to binary format.
class ToBinaryCommand extends Command<void> with PrintUsageException {
@override
final String name = "to_binary";
@override
final String description = "Convert any info file to binary format.";
@override
void run() async {
if (argResults.rest.length < 1) {
if (argResults.rest.isEmpty) {
usageException('Missing argument: <input-info>');
exit(1);
}
@ -28,7 +31,7 @@ class ToBinaryCommand extends Command<void> with PrintUsageException {
AllInfo info = await infoFromFile(filename);
if (argResults['inject-text']) injectText(info);
String outputFilename = argResults['out'] ?? '$filename.data';
var outstream = new File(outputFilename).openWrite();
var outstream = File(outputFilename).openWrite();
binary.encode(info, outstream);
await outstream.done;
}

View file

@ -16,7 +16,9 @@ import 'usage_exception.dart';
/// Converts a dump-info file emitted by dart2js in binary format to JSON.
class ToJsonCommand extends Command<void> with PrintUsageException {
@override
final String name = "to_json";
@override
final String description = "Convert any info file to JSON format.";
ToJsonCommand() {
@ -32,8 +34,9 @@ class ToJsonCommand extends Command<void> with PrintUsageException {
'available in the input file.');
}
@override
void run() async {
if (argResults.rest.length < 1) {
if (argResults.rest.isEmpty) {
usageException('Missing argument: <input-info>');
}
@ -45,10 +48,10 @@ class ToJsonCommand extends Command<void> with PrintUsageException {
injectText(info);
}
var json = new AllInfoJsonCodec(isBackwardCompatible: isBackwardCompatible)
var json = AllInfoJsonCodec(isBackwardCompatible: isBackwardCompatible)
.encode(info);
String outputFilename = argResults['out'] ?? '$filename.json';
new File(outputFilename)
File(outputFilename)
.writeAsStringSync(const JsonEncoder.withIndent(" ").convert(json));
}
}

View file

@ -17,11 +17,14 @@ import 'usage_exception.dart';
/// Converts a dump-info file emitted by dart2js to the proto format
class ToProtoCommand extends Command<void> with PrintUsageException {
@override
final String name = "to_proto";
@override
final String description = "Convert any info file to proto format.";
@override
void run() async {
if (argResults.rest.length < 1) {
if (argResults.rest.isEmpty) {
usageException('Missing argument: <input-info>');
exit(1);
}
@ -29,9 +32,9 @@ class ToProtoCommand extends Command<void> with PrintUsageException {
String filename = argResults.rest[0];
final info = await infoFromFile(filename);
if (argResults['inject-text']) injectText(info);
final proto = new AllInfoProtoCodec().encode(info);
final proto = AllInfoProtoCodec().encode(info);
String outputFilename = argResults['out'] ?? '$filename.pb';
final outputFile = new File(outputFilename);
final outputFile = File(outputFilename);
await outputFile.writeAsBytes(proto.writeToBuffer(), mode: FileMode.write);
}
}

View file

@ -8,6 +8,7 @@ import 'package:args/command_runner.dart';
abstract class PrintUsageException implements Command<void> {
// TODO(rnystrom): Use "Never" for the return type when this package is
// migrated to null safety.
@override
usageException(String message) {
print(message);
printUsage();

View file

@ -20,20 +20,20 @@ import 'src/text_print.dart';
/// Entrypoint to run all dart2js_info tools.
void main(args) {
var commandRunner = new CommandRunner("dart2js_info",
var commandRunner = CommandRunner("dart2js_info",
"collection of tools to digest the output of dart2js's --dump-info")
..addCommand(new CodeDepsCommand())
..addCommand(new CoverageLogServerCommand())
..addCommand(new DebugCommand())
..addCommand(new DiffCommand())
..addCommand(new DeferredLibraryCheck())
..addCommand(new DeferredLibrarySize())
..addCommand(new DeferredLibraryLayout())
..addCommand(new ConvertCommand())
..addCommand(new FunctionSizeCommand())
..addCommand(new LibrarySizeCommand())
..addCommand(new LiveCodeAnalysisCommand())
..addCommand(new ShowInferredTypesCommand())
..addCommand(new ShowCommand());
..addCommand(CodeDepsCommand())
..addCommand(CoverageLogServerCommand())
..addCommand(DebugCommand())
..addCommand(DiffCommand())
..addCommand(DeferredLibraryCheck())
..addCommand(DeferredLibrarySize())
..addCommand(DeferredLibraryLayout())
..addCommand(ConvertCommand())
..addCommand(FunctionSizeCommand())
..addCommand(LibrarySizeCommand())
..addCommand(LiveCodeAnalysisCommand())
..addCommand(ShowInferredTypesCommand())
..addCommand(ShowCommand());
commandRunner.run(args);
}

View file

@ -13,11 +13,11 @@ import 'src/binary/source.dart';
import 'info.dart';
void encode(AllInfo info, Sink<List<int>> sink) {
new BinaryPrinter(new BinarySink(sink)).visitAll(info);
BinaryPrinter(BinarySink(sink)).visitAll(info);
}
AllInfo decode(List<int> data) {
return new BinaryReader(new BinarySource(data)).readAll();
return BinaryReader(BinarySource(data)).readAll();
}
class BinaryPrinter implements InfoVisitor<void> {
@ -38,6 +38,7 @@ class BinaryPrinter implements InfoVisitor<void> {
info.accept(this);
}
@override
void visitAll(AllInfo info) {
sink.writeInt(info.version);
sink.writeInt(info.minorVersion);
@ -70,6 +71,7 @@ class BinaryPrinter implements InfoVisitor<void> {
sink.close();
}
@override
void visitProgram(ProgramInfo info) {
visitFunction(info.entrypoint);
sink.writeInt(info.size);
@ -94,6 +96,7 @@ class BinaryPrinter implements InfoVisitor<void> {
// Note: parent-pointers are not serialized, they get deduced during deserialization.
}
@override
void visitLibrary(LibraryInfo library) {
sink.writeCached(library, (LibraryInfo info) {
sink.writeUri(info.uri);
@ -106,6 +109,7 @@ class BinaryPrinter implements InfoVisitor<void> {
});
}
@override
void visitClass(ClassInfo cls) {
sink.writeCached(cls, (ClassInfo info) {
_visitBasicInfo(info);
@ -115,12 +119,14 @@ class BinaryPrinter implements InfoVisitor<void> {
});
}
@override
void visitClassType(ClassTypeInfo cls) {
sink.writeCached(cls, (ClassTypeInfo info) {
_visitBasicInfo(info);
});
}
@override
void visitField(FieldInfo field) {
sink.writeCached(field, (FieldInfo info) {
_visitBasicInfo(info);
@ -148,6 +154,7 @@ class BinaryPrinter implements InfoVisitor<void> {
}
}
@override
void visitConstant(ConstantInfo constant) {
sink.writeCached(constant, (ConstantInfo info) {
_visitBasicInfo(info);
@ -170,6 +177,7 @@ class BinaryPrinter implements InfoVisitor<void> {
sink.writeString(info.declaredType);
}
@override
void visitFunction(FunctionInfo function) {
sink.writeCached(function, (FunctionInfo info) {
_visitBasicInfo(info);
@ -190,6 +198,7 @@ class BinaryPrinter implements InfoVisitor<void> {
sink.writeStringOrNull(info.mask);
}
@override
void visitClosure(ClosureInfo closure) {
sink.writeCached(closure, (ClosureInfo info) {
_visitBasicInfo(info);
@ -197,6 +206,7 @@ class BinaryPrinter implements InfoVisitor<void> {
});
}
@override
void visitTypedef(TypedefInfo typedef) {
sink.writeCached(typedef, (TypedefInfo info) {
_visitBasicInfo(info);
@ -211,6 +221,7 @@ class BinaryPrinter implements InfoVisitor<void> {
}
}
@override
void visitOutput(OutputUnitInfo output) {
sink.writeCached(output, (OutputUnitInfo info) {
_visitBasicInfo(info);
@ -229,7 +240,7 @@ class BinaryReader {
}
Duration readDuration() {
return new Duration(microseconds: source.readInt());
return Duration(microseconds: source.readInt());
}
Info readInfoWithKind() {
@ -258,7 +269,7 @@ class BinaryReader {
}
AllInfo readAll() {
var info = new AllInfo();
var info = AllInfo();
int version = source.readInt();
int minorVersion = source.readInt();
if (info.version != version || info.minorVersion != minorVersion) {
@ -311,13 +322,13 @@ class BinaryReader {
}
ProgramInfo readProgram() {
var info = new ProgramInfo();
var info = ProgramInfo();
info.entrypoint = readFunction();
info.size = source.readInt();
info.dart2jsVersion = source.readStringOrNull();
info.compilationMoment = readDate();
info.compilationDuration = readDuration();
info.toJsonDuration = new Duration(microseconds: 0);
info.toJsonDuration = Duration(microseconds: 0);
info.dumpInfoDuration = readDuration();
info.noSuchMethodEnabled = source.readBool();
info.isRuntimeTypeUsed = source.readBool();
@ -337,7 +348,7 @@ class BinaryReader {
}
LibraryInfo readLibrary() => source.readCached<LibraryInfo>(() {
LibraryInfo info = new LibraryInfo.internal();
LibraryInfo info = LibraryInfo.internal();
info.uri = source.readUri();
_readBasicInfo(info);
info.topLevelFunctions = source.readList(readFunction);
@ -356,7 +367,7 @@ class BinaryReader {
});
ClassInfo readClass() => source.readCached<ClassInfo>(() {
ClassInfo info = new ClassInfo.internal();
ClassInfo info = ClassInfo.internal();
_readBasicInfo(info);
info.isAbstract = source.readBool();
info.fields = source.readList(readField);
@ -375,7 +386,7 @@ class BinaryReader {
});
FieldInfo readField() => source.readCached<FieldInfo>(() {
FieldInfo info = new FieldInfo.internal();
FieldInfo info = FieldInfo.internal();
_readBasicInfo(info);
info.closures = source.readList(readClosure);
info.inferredType = source.readString();
@ -385,12 +396,14 @@ class BinaryReader {
if (info.isConst) {
info.initializer = _readConstantOrNull();
}
info.closures.forEach((c) => c.parent = info);
for (var c in info.closures) {
c.parent = info;
}
return info;
});
CodeSpan _readCodeSpan() {
return new CodeSpan()
return CodeSpan()
..start = source.readIntOrNull()
..end = source.readIntOrNull()
..text = source.readStringOrNull();
@ -403,7 +416,7 @@ class BinaryReader {
}
ConstantInfo readConstant() => source.readCached<ConstantInfo>(() {
ConstantInfo info = new ConstantInfo.internal();
ConstantInfo info = ConstantInfo.internal();
_readBasicInfo(info);
info.code = source.readList(_readCodeSpan);
return info;
@ -411,7 +424,7 @@ class BinaryReader {
FunctionModifiers _readFunctionModifiers() {
int value = source.readInt();
return new FunctionModifiers(
return FunctionModifiers(
isStatic: value & _staticMask != 0,
isConst: value & _constMask != 0,
isFactory: value & _factoryMask != 0,
@ -419,12 +432,12 @@ class BinaryReader {
}
ParameterInfo _readParameterInfo() {
return new ParameterInfo(
return ParameterInfo(
source.readString(), source.readString(), source.readString());
}
FunctionInfo readFunction() => source.readCached<FunctionInfo>(() {
FunctionInfo info = new FunctionInfo.internal();
FunctionInfo info = FunctionInfo.internal();
_readBasicInfo(info);
info.closures = source.readList(readClosure);
info.modifiers = _readFunctionModifiers();
@ -435,15 +448,17 @@ class BinaryReader {
info.inlinedCount = source.readIntOrNull();
info.code = source.readList(_readCodeSpan);
info.type = source.readString();
info.closures.forEach((c) => c.parent = info);
for (var c in info.closures) {
c.parent = info;
}
return info;
});
DependencyInfo _readDependencyInfo() =>
new DependencyInfo(readInfoWithKind(), source.readStringOrNull());
DependencyInfo(readInfoWithKind(), source.readStringOrNull());
ClosureInfo readClosure() => source.readCached<ClosureInfo>(() {
ClosureInfo info = new ClosureInfo.internal();
ClosureInfo info = ClosureInfo.internal();
_readBasicInfo(info);
info.function = readFunction();
info.function.parent = info;
@ -451,7 +466,7 @@ class BinaryReader {
});
TypedefInfo readTypedef() => source.readCached<TypedefInfo>(() {
TypedefInfo info = new TypedefInfo.internal();
TypedefInfo info = TypedefInfo.internal();
_readBasicInfo(info);
info.type = source.readString();
return info;
@ -464,7 +479,7 @@ class BinaryReader {
}
OutputUnitInfo readOutput() => source.readCached<OutputUnitInfo>(() {
OutputUnitInfo info = new OutputUnitInfo.internal();
OutputUnitInfo info = OutputUnitInfo.internal();
_readBasicInfo(info);
info.filename = source.readStringOrNull();
info.imports = source.readList(source.readString);

View file

@ -42,8 +42,8 @@ import 'info.dart';
List<ManifestComplianceFailure> checkDeferredLibraryManifest(
AllInfo info, Map manifest) {
var includedPackages = new Map<String, Set<String>>();
var excludedPackages = new Map<String, Set<String>>();
var includedPackages = <String, Set<String>>{};
var excludedPackages = <String, Set<String>>{};
for (var part in manifest.keys) {
for (var package in manifest[part]['include'] ?? []) {
(includedPackages[part] ??= {}).add(package);
@ -59,16 +59,20 @@ List<ManifestComplianceFailure> checkDeferredLibraryManifest(
// the outputUnits whose list of 'imports' contains a single import. If the
// part is shared, it will have more than one import since it will include the
// imports of all the top-level deferred parts that will load the shared part.
List<String> validParts = ['main']..addAll(info.outputUnits
.where((unit) => unit.imports.length == 1)
.map((unit) => unit.imports.single));
List<String> mentionedParts = []
..addAll(includedPackages.keys)
..addAll(excludedPackages.keys);
List<String> validParts = [
'main',
...info.outputUnits
.where((unit) => unit.imports.length == 1)
.map((unit) => unit.imports.single)
];
List<String> mentionedParts = [
...includedPackages.keys,
...excludedPackages.keys
];
var partNameFailures = <_InvalidPartName>[];
for (var part in mentionedParts) {
if (!validParts.contains(part)) {
partNameFailures.add(new _InvalidPartName(part, validParts));
partNameFailures.add(_InvalidPartName(part, validParts));
}
}
if (partNameFailures.isNotEmpty) {
@ -79,7 +83,7 @@ List<ManifestComplianceFailure> checkDeferredLibraryManifest(
for (var values in includedPackages.values) ...values,
for (var values in excludedPackages.values) ...values
};
var actualIncludedPackages = new Map<String, Set<String>>();
var actualIncludedPackages = <String, Set<String>>{};
var failures = <ManifestComplianceFailure>[];
@ -98,8 +102,7 @@ List<ManifestComplianceFailure> checkDeferredLibraryManifest(
for (var part in containingParts) {
(actualIncludedPackages[part] ??= {}).add(packageName);
if (excludedPackages[part].contains(packageName)) {
failures
.add(new _PartContainedExcludedPackage(part, packageName, info));
failures.add(_PartContainedExcludedPackage(part, packageName, info));
}
}
}
@ -112,7 +115,7 @@ List<ManifestComplianceFailure> checkDeferredLibraryManifest(
for (var package in packages) {
if (!actualIncludedPackages.containsKey(part) ||
!actualIncludedPackages[part].contains(package)) {
failures.add(new _PartDidNotContainPackage(part, package));
failures.add(_PartDidNotContainPackage(part, package));
}
}
});
@ -146,6 +149,7 @@ class _InvalidPartName extends ManifestComplianceFailure {
final List<String> validPartNames;
const _InvalidPartName(this.part, this.validPartNames);
@override
String toString() {
return 'Manifest file declares invalid part "$part". '
'Valid part names are: $validPartNames';
@ -158,6 +162,7 @@ class _PartContainedExcludedPackage extends ManifestComplianceFailure {
final BasicInfo info;
const _PartContainedExcludedPackage(this.part, this.package, this.info);
@override
String toString() {
return 'Part "$part" was specified to exclude package "$package" but it '
'actually contains ${kindToString(info.kind)} "${info.name}" which '
@ -170,6 +175,7 @@ class _PartDidNotContainPackage extends ManifestComplianceFailure {
final String package;
const _PartDidNotContainPackage(this.part, this.package);
@override
String toString() {
return 'Part "$part" was specified to include package "$package" but it '
'does not contain any elements from that package.';

View file

@ -33,12 +33,17 @@ abstract class Info {
// TODO(sigmund): add more:
// - inputSize: bytes used in the Dart source program
abstract class BasicInfo implements Info {
@override
final InfoKind kind;
@override
String coverageId;
@override
int size;
@override
Info parent;
@override
String name;
/// If using deferred libraries, where the element associated with this info
@ -49,6 +54,7 @@ abstract class BasicInfo implements Info {
BasicInfo.internal(this.kind);
@override
String toString() => '$kind $name [$size]';
}
@ -205,6 +211,7 @@ class LibraryInfo extends BasicInfo {
LibraryInfo.internal() : super.internal(InfoKind.library);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitLibrary(this);
}
@ -222,6 +229,7 @@ class OutputUnitInfo extends BasicInfo {
OutputUnitInfo.internal() : super.internal(InfoKind.outputUnit);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitOutput(this);
}
@ -240,11 +248,12 @@ class ClassInfo extends BasicInfo {
List<FieldInfo> fields = <FieldInfo>[];
ClassInfo(
{String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
{String name, this.isAbstract, OutputUnitInfo outputUnit, int size = 0})
: super(InfoKind.clazz, name, outputUnit, size, null);
ClassInfo.internal() : super.internal(InfoKind.clazz);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitClass(this);
}
@ -252,11 +261,12 @@ class ClassInfo extends BasicInfo {
/// [ClassInfo] because a class and its type may end up in different output
/// units.
class ClassTypeInfo extends BasicInfo {
ClassTypeInfo({String name, OutputUnitInfo outputUnit, int size: 0})
ClassTypeInfo({String name, OutputUnitInfo outputUnit, int size = 0})
: super(InfoKind.classType, name, outputUnit, size, null);
ClassTypeInfo.internal() : super.internal(InfoKind.classType);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitClassType(this);
}
@ -284,11 +294,12 @@ class ConstantInfo extends BasicInfo {
List<CodeSpan> code;
// TODO(sigmund): Add coverage support to constants?
ConstantInfo({int size: 0, this.code, OutputUnitInfo outputUnit})
ConstantInfo({int size = 0, this.code, OutputUnitInfo outputUnit})
: super(InfoKind.constant, null, outputUnit, size, null);
ConstantInfo.internal() : super.internal(InfoKind.constant);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitConstant(this);
}
@ -315,7 +326,7 @@ class FieldInfo extends BasicInfo with CodeInfo {
FieldInfo(
{String name,
String coverageId,
int size: 0,
int size = 0,
this.type,
this.inferredType,
this.closures,
@ -326,6 +337,7 @@ class FieldInfo extends BasicInfo with CodeInfo {
FieldInfo.internal() : super.internal(InfoKind.field);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitField(this);
}
@ -339,6 +351,7 @@ class TypedefInfo extends BasicInfo {
TypedefInfo.internal() : super.internal(InfoKind.typedef);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitTypedef(this);
}
@ -384,7 +397,7 @@ class FunctionInfo extends BasicInfo with CodeInfo {
{String name,
String coverageId,
OutputUnitInfo outputUnit,
int size: 0,
int size = 0,
this.functionKind,
this.modifiers,
this.closures,
@ -399,6 +412,7 @@ class FunctionInfo extends BasicInfo with CodeInfo {
FunctionInfo.internal() : super.internal(InfoKind.function);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitFunction(this);
}
@ -408,11 +422,12 @@ class ClosureInfo extends BasicInfo {
FunctionInfo function;
ClosureInfo(
{String name, OutputUnitInfo outputUnit, int size: 0, this.function})
{String name, OutputUnitInfo outputUnit, int size = 0, this.function})
: super(InfoKind.closure, name, outputUnit, size, null);
ClosureInfo.internal() : super.internal(InfoKind.closure);
@override
T accept<T>(InfoVisitor<T> visitor) => visitor.visitClosure(this);
}
@ -446,10 +461,10 @@ class FunctionModifiers {
final bool isExternal;
FunctionModifiers(
{this.isStatic: false,
this.isConst: false,
this.isFactory: false,
this.isExternal: false});
{this.isStatic = false,
this.isConst = false,
this.isFactory = false,
this.isExternal = false});
}
/// Possible values of the `kind` field in the serialized infos.
@ -536,7 +551,8 @@ abstract class InfoVisitor<T> {
/// visitAll contains references to functions, this visitor only recurses to
/// visit libraries, then from each library we visit functions and classes, and
/// so on.
class RecursiveInfoVisitor extends InfoVisitor<Null> {
class RecursiveInfoVisitor extends InfoVisitor<void> {
@override
visitAll(AllInfo info) {
// Note: we don't visit functions, fields, classes, and typedefs because
// they are reachable from the library info.
@ -544,8 +560,10 @@ class RecursiveInfoVisitor extends InfoVisitor<Null> {
info.constants.forEach(visitConstant);
}
@override
visitProgram(ProgramInfo info) {}
@override
visitLibrary(LibraryInfo info) {
info.topLevelFunctions.forEach(visitFunction);
info.topLevelVariables.forEach(visitField);
@ -554,25 +572,33 @@ class RecursiveInfoVisitor extends InfoVisitor<Null> {
info.typedefs.forEach(visitTypedef);
}
@override
visitClass(ClassInfo info) {
info.functions.forEach(visitFunction);
info.fields.forEach(visitField);
}
@override
visitClassType(ClassTypeInfo info) {}
@override
visitField(FieldInfo info) {
info.closures.forEach(visitClosure);
}
@override
visitConstant(ConstantInfo info) {}
@override
visitFunction(FunctionInfo info) {
info.closures.forEach(visitClosure);
}
@override
visitTypedef(TypedefInfo info) {}
@override
visitOutput(OutputUnitInfo info) {}
@override
visitClosure(ClosureInfo info) {
visitFunction(info.function);
}

View file

@ -3,13 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
/// Converters and codecs for converting between JSON and [Info] classes.
import 'dart:collection';
import 'dart:convert';
import 'package:collection/collection.dart';
import 'src/util.dart';
import 'info.dart';
import 'src/util.dart';
List<String> _toSortedSerializedIds(
Iterable<Info> infos, Id Function(Info) getId) =>
@ -18,13 +18,14 @@ List<String> _toSortedSerializedIds(
// TODO(sigmund): add unit tests.
class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
// Using `MashMap` here because it's faster than the default `LinkedHashMap`.
final Map<String, Info> registry = new HashMap<String, Info>();
final Map<String, Info> registry = HashMap<String, Info>();
AllInfo convert(Map<String, dynamic> json) {
@override
AllInfo convert(Map<String, dynamic> input) {
registry.clear();
var result = new AllInfo();
var elements = json['elements'];
var result = AllInfo();
var elements = input['elements'];
// TODO(srawlins): Since only the Map values are being extracted below,
// replace `as` with `cast` when `cast` becomes available in Dart 2.0:
//
@ -50,29 +51,29 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
result.constants.addAll(
(elements['constant'] as Map).values.map((c) => parseConstant(c)));
json['holding'].forEach((k, deps) {
input['holding'].forEach((k, deps) {
CodeInfo src = registry[k];
assert(src != null);
for (var dep in deps) {
var target = registry[dep['id']];
assert(target != null);
src.uses.add(new DependencyInfo(target, dep['mask']));
src.uses.add(DependencyInfo(target, dep['mask']));
}
});
json['dependencies']?.forEach((String k, dependencies) {
input['dependencies']?.forEach((String k, dependencies) {
List<String> deps = dependencies;
result.dependencies[registry[k]] = deps.map((d) => registry[d]).toList();
});
result.outputUnits
.addAll((json['outputUnits'] as List).map((o) => parseOutputUnit(o)));
.addAll((input['outputUnits'] as List).map((o) => parseOutputUnit(o)));
result.program = parseProgram(json['program']);
result.program = parseProgram(input['program']);
if (json['deferredFiles'] != null) {
if (input['deferredFiles'] != null) {
final deferredFilesMap =
(json['deferredFiles'] as Map).cast<String, Map<String, dynamic>>();
(input['deferredFiles'] as Map).cast<String, Map<String, dynamic>>();
for (final library in deferredFilesMap.values) {
if (library['imports'] != null) {
// The importMap needs to be typed as <String, List<String>>, but the
@ -192,7 +193,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
}
ProgramInfo parseProgram(Map json) {
var programInfo = new ProgramInfo()
var programInfo = ProgramInfo()
..entrypoint = parseId(json['entrypoint'])
..size = json['size']
..compilationMoment = DateTime.parse(json['compilationMoment'])
@ -211,7 +212,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
} else {
assert(compilationDuration is int);
programInfo.compilationDuration =
new Duration(microseconds: compilationDuration);
Duration(microseconds: compilationDuration);
}
var toJsonDuration = json['toJsonDuration'];
@ -219,7 +220,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
programInfo.toJsonDuration = _parseDuration(toJsonDuration);
} else {
assert(toJsonDuration is int);
programInfo.toJsonDuration = new Duration(microseconds: toJsonDuration);
programInfo.toJsonDuration = Duration(microseconds: toJsonDuration);
}
var dumpInfoDuration = json['dumpInfoDuration'];
@ -227,8 +228,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
programInfo.dumpInfoDuration = _parseDuration(dumpInfoDuration);
} else {
assert(dumpInfoDuration is int);
programInfo.dumpInfoDuration =
new Duration(microseconds: dumpInfoDuration);
programInfo.dumpInfoDuration = Duration(microseconds: dumpInfoDuration);
}
return programInfo;
@ -237,7 +237,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
/// Parse a string formatted as "XX:YY:ZZ.ZZZZZ" into a [Duration].
Duration _parseDuration(String duration) {
if (!duration.contains(':')) {
return new Duration(milliseconds: int.parse(duration));
return Duration(milliseconds: int.parse(duration));
}
var parts = duration.split(':');
var hours = double.parse(parts[0]);
@ -249,7 +249,7 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
var totalMillis = secondsInMillis * seconds +
minutesInMillis * minutes +
hoursInMillis * hours;
return new Duration(milliseconds: totalMillis.round());
return Duration(milliseconds: totalMillis.round());
}
FunctionInfo parseFunction(Map json) {
@ -268,18 +268,17 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
..code = parseCode(json['code'])
..sideEffects = json['sideEffects']
..inlinedCount = json['inlinedCount']
..modifiers =
parseModifiers(new Map<String, bool>.from(json['modifiers']))
..modifiers = parseModifiers(Map<String, bool>.from(json['modifiers']))
..closures = (json['children'] as List)
.map<ClosureInfo>((c) => parseId(c))
.toList();
}
ParameterInfo parseParameter(Map json) =>
new ParameterInfo(json['name'], json['type'], json['declaredType']);
ParameterInfo(json['name'], json['type'], json['declaredType']);
FunctionModifiers parseModifiers(Map<String, bool> json) {
return new FunctionModifiers(
return FunctionModifiers(
isStatic: json['static'] == true,
isConst: json['const'] == true,
isFactory: json['factory'] == true,
@ -303,23 +302,23 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
}
return registry.putIfAbsent(serializedId, () {
if (serializedId.startsWith('function/')) {
return new FunctionInfo.internal();
return FunctionInfo.internal();
} else if (serializedId.startsWith('closure/')) {
return new ClosureInfo.internal();
return ClosureInfo.internal();
} else if (serializedId.startsWith('library/')) {
return new LibraryInfo.internal();
return LibraryInfo.internal();
} else if (serializedId.startsWith('class/')) {
return new ClassInfo.internal();
return ClassInfo.internal();
} else if (serializedId.startsWith('classType/')) {
return new ClassTypeInfo.internal();
return ClassTypeInfo.internal();
} else if (serializedId.startsWith('field/')) {
return new FieldInfo.internal();
return FieldInfo.internal();
} else if (serializedId.startsWith('constant/')) {
return new ConstantInfo.internal();
return ConstantInfo.internal();
} else if (serializedId.startsWith('typedef/')) {
return new TypedefInfo.internal();
return TypedefInfo.internal();
} else if (serializedId.startsWith('outputUnit/')) {
return new OutputUnitInfo.internal();
return OutputUnitInfo.internal();
}
assert(false);
return null;
@ -329,13 +328,13 @@ class JsonToAllInfoConverter extends Converter<Map<String, dynamic>, AllInfo> {
List<CodeSpan> parseCode(dynamic json) {
// backwards compatibility with format 5.1:
if (json is String) {
return [new CodeSpan(start: null, end: null, text: json)];
return [CodeSpan(start: null, end: null, text: json)];
}
if (json is List) {
return json.map((dynamic value) {
Map<String, dynamic> jsonCode = value;
return new CodeSpan(
return CodeSpan(
start: jsonCode['start'],
end: jsonCode['end'],
text: jsonCode['text']);
@ -350,10 +349,10 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
implements InfoVisitor<Map> {
/// Whether to generate json compatible with format 5.1
final bool isBackwardCompatible;
final Map<Info, Id> ids = new HashMap<Info, Id>();
final Set<int> usedIds = new Set<int>();
final Map<Info, Id> ids = HashMap<Info, Id>();
final Set<int> usedIds = <int>{};
AllInfoToJsonConverter({this.isBackwardCompatible: false});
AllInfoToJsonConverter({this.isBackwardCompatible = false});
Id idFor(Info info) {
var serializedId = ids[info];
@ -381,17 +380,18 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
while (!usedIds.add(id)) {
id++;
}
serializedId = new Id(info.kind, '$id');
serializedId = Id(info.kind, '$id');
return ids[info] = serializedId;
}
Map convert(AllInfo info) => info.accept(this);
@override
Map convert(AllInfo input) => input.accept(this);
Map _visitList(List<Info> infos) {
// Using SplayTree to maintain a consistent order of keys
var map = new SplayTreeMap<String, Map>(compareNatural);
var map = SplayTreeMap<String, Map>(compareNatural);
for (var info in infos) {
map['${idFor(info).id}'] = info.accept(this);
map[idFor(info).id] = info.accept(this);
}
return map;
}
@ -421,7 +421,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
{'id': idFor(info.target).serializedId, 'mask': info.mask};
Map _visitAllInfoHolding(AllInfo allInfo) {
var map = new SplayTreeMap<String, List>(compareNatural);
var map = SplayTreeMap<String, List>(compareNatural);
void helper(CodeInfo info) {
if (info.uses.isEmpty) return;
map[idFor(info).serializedId] = info.uses
@ -436,13 +436,14 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
}
Map _visitAllInfoDependencies(AllInfo allInfo) {
var map = new SplayTreeMap<String, List>(compareNatural);
var map = SplayTreeMap<String, List>(compareNatural);
allInfo.dependencies.forEach((k, v) {
map[idFor(k).serializedId] = _toSortedSerializedIds(v, idFor);
});
return map;
}
@override
Map visitAll(AllInfo info) {
var elements = _visitAllInfoElements(info);
var jsonHolding = _visitAllInfoHolding(info);
@ -459,6 +460,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
};
}
@override
Map visitProgram(ProgramInfo info) {
return {
'entrypoint': idFor(info.entrypoint).serializedId,
@ -494,6 +496,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
return res;
}
@override
Map visitLibrary(LibraryInfo info) {
return _visitBasicInfo(info)
..addAll(<String, Object>{
@ -510,6 +513,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
});
}
@override
Map visitClass(ClassInfo info) {
return _visitBasicInfo(info)
..addAll(<String, Object>{
@ -520,10 +524,12 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
});
}
@override
Map visitClassType(ClassTypeInfo info) {
return _visitBasicInfo(info);
}
@override
Map visitField(FieldInfo info) {
var result = _visitBasicInfo(info)
..addAll(<String, Object>{
@ -541,6 +547,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
return result;
}
@override
Map visitConstant(ConstantInfo info) => _visitBasicInfo(info)
..addAll(<String, Object>{'code': _serializeCode(info.code)});
@ -561,6 +568,7 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
Map _visitParameterInfo(ParameterInfo info) =>
{'name': info.name, 'type': info.type, 'declaredType': info.declaredType};
@override
Map visitFunction(FunctionInfo info) {
return _visitBasicInfo(info)
..addAll(<String, Object>{
@ -579,13 +587,16 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
});
}
@override
Map visitClosure(ClosureInfo info) {
return _visitBasicInfo(info)
..addAll(<String, Object>{'function': idFor(info.function).serializedId});
}
@override
visitTypedef(TypedefInfo info) => _visitBasicInfo(info)..['type'] = info.type;
@override
visitOutput(OutputUnitInfo info) => _visitBasicInfo(info)
..['filename'] = info.filename
..['imports'] = info.imports;
@ -605,12 +616,14 @@ class AllInfoToJsonConverter extends Converter<AllInfo, Map>
}
class AllInfoJsonCodec extends Codec<AllInfo, Map> {
@override
final Converter<AllInfo, Map> encoder;
final Converter<Map, AllInfo> decoder = new JsonToAllInfoConverter();
@override
final Converter<Map, AllInfo> decoder = JsonToAllInfoConverter();
AllInfoJsonCodec({bool isBackwardCompatible: false})
: encoder = new AllInfoToJsonConverter(
isBackwardCompatible: isBackwardCompatible);
AllInfoJsonCodec({bool isBackwardCompatible = false})
: encoder =
AllInfoToJsonConverter(isBackwardCompatible: isBackwardCompatible);
}
class Id {

View file

@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
/// Converters and codecs for converting between Protobuf and [Info] classes.
import 'dart:convert';
import 'package:fixnum/fixnum.dart';
import 'info.dart';
@ -14,18 +14,19 @@ import 'src/util.dart';
export 'src/proto/info.pb.dart';
class ProtoToAllInfoConverter extends Converter<AllInfoPB, AllInfo> {
AllInfo convert(AllInfoPB info) {
@override
AllInfo convert(AllInfoPB input) {
// TODO(lorenvs): Implement this conversion. It is unlikely to to be used
// by production code since the goal of the proto codec is to consume this
// information from other languages. However, it is useful for roundtrip
// testing, so we should support it.
throw new UnimplementedError('ProtoToAllInfoConverter is not implemented');
throw UnimplementedError('ProtoToAllInfoConverter is not implemented');
}
}
class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
final Map<Info, Id> ids = {};
final Set<int> usedIds = new Set<int>();
final Set<int> usedIds = <int>{};
Id idFor(Info info) {
if (info == null) return null;
@ -51,14 +52,15 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
while (!usedIds.add(id)) {
id++;
}
serializedId = new Id(info.kind, id);
serializedId = Id(info.kind, id);
return ids[info] = serializedId;
}
AllInfoPB convert(AllInfo info) => _convertToAllInfoPB(info);
@override
AllInfoPB convert(AllInfo input) => _convertToAllInfoPB(input);
DependencyInfoPB _convertToDependencyInfoPB(DependencyInfo info) {
var result = new DependencyInfoPB()
var result = DependencyInfoPB()
..targetId = idFor(info.target)?.serializedId;
if (info.mask != null) {
result.mask = info.mask;
@ -67,14 +69,14 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
static ParameterInfoPB _convertToParameterInfoPB(ParameterInfo info) {
return new ParameterInfoPB()
return ParameterInfoPB()
..name = info.name
..type = info.type
..declaredType = info.declaredType;
}
LibraryInfoPB _convertToLibraryInfoPB(LibraryInfo info) {
final proto = new LibraryInfoPB()..uri = info.uri.toString();
final proto = LibraryInfoPB()..uri = info.uri.toString();
proto.childrenIds
.addAll(info.topLevelFunctions.map((func) => idFor(func).serializedId));
@ -91,7 +93,7 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
ClassInfoPB _convertToClassInfoPB(ClassInfo info) {
final proto = new ClassInfoPB()..isAbstract = info.isAbstract;
final proto = ClassInfoPB()..isAbstract = info.isAbstract;
proto.childrenIds
.addAll(info.functions.map((func) => idFor(func).serializedId));
@ -107,7 +109,7 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
static FunctionModifiersPB _convertToFunctionModifiers(
FunctionModifiers modifiers) {
return new FunctionModifiersPB()
return FunctionModifiersPB()
..isStatic = modifiers.isStatic
..isConst = modifiers.isConst
..isFactory = modifiers.isFactory
@ -115,7 +117,7 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
FunctionInfoPB _convertToFunctionInfoPB(FunctionInfo info) {
final proto = new FunctionInfoPB()
final proto = FunctionInfoPB()
..functionModifiers = _convertToFunctionModifiers(info.modifiers)
..inlinedCount = info.inlinedCount ?? 0;
@ -143,7 +145,7 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
FieldInfoPB _convertToFieldInfoPB(FieldInfo info) {
final proto = new FieldInfoPB()
final proto = FieldInfoPB()
..type = info.type
..inferredType = info.inferredType
..isConst = info.isConst;
@ -163,25 +165,25 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
static ConstantInfoPB _convertToConstantInfoPB(ConstantInfo info) {
return new ConstantInfoPB()..code = info.code.map((c) => c.text).join('\n');
return ConstantInfoPB()..code = info.code.map((c) => c.text).join('\n');
}
static OutputUnitInfoPB _convertToOutputUnitInfoPB(OutputUnitInfo info) {
final proto = new OutputUnitInfoPB();
final proto = OutputUnitInfoPB();
proto.imports.addAll(info.imports.where((import) => import != null));
return proto;
}
static TypedefInfoPB _convertToTypedefInfoPB(TypedefInfo info) {
return new TypedefInfoPB()..type = info.type;
return TypedefInfoPB()..type = info.type;
}
ClosureInfoPB _convertToClosureInfoPB(ClosureInfo info) {
return new ClosureInfoPB()..functionId = idFor(info.function).serializedId;
return ClosureInfoPB()..functionId = idFor(info.function).serializedId;
}
InfoPB _convertToInfoPB(Info info) {
final proto = new InfoPB()
final proto = InfoPB()
..id = idFor(info).id
..serializedId = idFor(info).serializedId
..size = info.size;
@ -233,14 +235,13 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
ProgramInfoPB _convertToProgramInfoPB(ProgramInfo info) {
var result = new ProgramInfoPB()
var result = ProgramInfoPB()
..entrypointId = idFor(info.entrypoint).serializedId
..size = info.size
..compilationMoment =
new Int64(info.compilationMoment.microsecondsSinceEpoch)
..compilationDuration = new Int64(info.compilationDuration.inMicroseconds)
..toProtoDuration = new Int64(info.toJsonDuration.inMicroseconds)
..dumpInfoDuration = new Int64(info.dumpInfoDuration.inMicroseconds)
..compilationMoment = Int64(info.compilationMoment.microsecondsSinceEpoch)
..compilationDuration = Int64(info.compilationDuration.inMicroseconds)
..toProtoDuration = Int64(info.toJsonDuration.inMicroseconds)
..dumpInfoDuration = Int64(info.dumpInfoDuration.inMicroseconds)
..noSuchMethodEnabled = info.noSuchMethodEnabled ?? false
..isRuntimeTypeUsed = info.isRuntimeTypeUsed ?? false
..isIsolateUsed = info.isIsolateInUse ?? false
@ -265,13 +266,13 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
static LibraryDeferredImportsPB _convertToLibraryDeferredImportsPB(
String libraryUri, Map<String, dynamic> fields) {
final proto = new LibraryDeferredImportsPB()
final proto = LibraryDeferredImportsPB()
..libraryUri = libraryUri
..libraryName = fields['name'] ?? '<unnamed>';
Map<String, List<String>> imports = fields['imports'];
imports.forEach((prefix, files) {
final import = new DeferredImportPB()..prefix = prefix;
final import = DeferredImportPB()..prefix = prefix;
import.files.addAll(files);
proto.imports.add(import);
});
@ -280,8 +281,7 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
}
AllInfoPB _convertToAllInfoPB(AllInfo info) {
final proto = new AllInfoPB()
..program = _convertToProgramInfoPB(info.program);
final proto = AllInfoPB()..program = _convertToProgramInfoPB(info.program);
proto.allInfos.addEntries(_convertToAllInfosEntries(info.libraries));
proto.allInfos.addEntries(_convertToAllInfosEntries(info.classes));
@ -307,8 +307,10 @@ class AllInfoToProtoConverter extends Converter<AllInfo, AllInfoPB> {
/// This codec is still experimental, and will likely crash on certain output
/// from dart2js.
class AllInfoProtoCodec extends Codec<AllInfo, AllInfoPB> {
final Converter<AllInfo, AllInfoPB> encoder = new AllInfoToProtoConverter();
final Converter<AllInfoPB, AllInfo> decoder = new ProtoToAllInfoConverter();
@override
final Converter<AllInfo, AllInfoPB> encoder = AllInfoToProtoConverter();
@override
final Converter<AllInfoPB, AllInfo> decoder = ProtoToAllInfoConverter();
}
class Id {

View file

@ -20,22 +20,22 @@ abstract class DataSink {
/// Writes a reference to [value] to this data sink. If [value] has not yet
/// been serialized, [f] is called to serialize the value itself.
void writeCached<E>(E value, void f(E value));
void writeCached<E>(E value, void Function(E value) f);
/// Writes the potentially `null` [value] to this data sink. If [value] is
/// non-null [f] is called to write the non-null value to the data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readValueOrNull].
void writeValueOrNull<E>(E value, void f(E value));
void writeValueOrNull<E>(E value, void Function(E value) f);
/// Writes the [values] to this data sink calling [f] to write each value to
/// the data sink. If [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readList].
void writeList<E>(Iterable<E> values, void f(E value),
{bool allowNull: false});
void writeList<E>(Iterable<E> values, void Function(E value) f,
{bool allowNull = false});
/// Writes the boolean [value] to this data sink.
void writeBool(bool value);
@ -63,7 +63,7 @@ abstract class DataSink {
///
/// This is a convenience method to be used together with
/// [DataSource.readStrings].
void writeStrings(Iterable<String> values, {bool allowNull: false});
void writeStrings(Iterable<String> values, {bool allowNull = false});
/// Writes the [map] from string to [V] values to this data sink, calling [f]
/// to write each value to the data sink. If [allowNull] is `true`, [map] is
@ -71,8 +71,8 @@ abstract class DataSink {
///
/// This is a convenience method to be used together with
/// [DataSource.readStringMap].
void writeStringMap<V>(Map<String, V> map, void f(V value),
{bool allowNull: false});
void writeStringMap<V>(Map<String, V> map, void Function(V value) f,
{bool allowNull = false});
/// Writes the enum value [value] to this data sink.
// TODO(johnniwinther): Change the signature to
@ -103,7 +103,7 @@ abstract class DataSinkMixin implements DataSink {
}
@override
void writeStrings(Iterable<String> values, {bool allowNull: false}) {
void writeStrings(Iterable<String> values, {bool allowNull = false}) {
if (values == null) {
assert(allowNull);
writeInt(0);
@ -116,8 +116,8 @@ abstract class DataSinkMixin implements DataSink {
}
@override
void writeStringMap<V>(Map<String, V> map, void f(V value),
{bool allowNull: false}) {
void writeStringMap<V>(Map<String, V> map, void Function(V value) f,
{bool allowNull = false}) {
if (map == null) {
assert(allowNull);
writeInt(0);
@ -131,8 +131,8 @@ abstract class DataSinkMixin implements DataSink {
}
@override
void writeList<E>(Iterable<E> values, void f(E value),
{bool allowNull: false}) {
void writeList<E>(Iterable<E> values, void Function(E value) f,
{bool allowNull = false}) {
if (values == null) {
assert(allowNull);
writeInt(0);
@ -143,7 +143,7 @@ abstract class DataSinkMixin implements DataSink {
}
@override
void writeValueOrNull<E>(E value, void f(E value)) {
void writeValueOrNull<E>(E value, void Function(E value) f) {
writeBool(value != null);
if (value != null) {
f(value);
@ -162,7 +162,7 @@ class IndexedSink<E> {
///
/// If [value] has not been canonicalized yet, [writeValue] is called to
/// serialize the [value] itself.
void write(E value, void writeValue(E value)) {
void write(E value, void Function(E value) writeValue) {
int index = _cache[value];
if (index == null) {
index = _cache.length;
@ -180,17 +180,16 @@ class IndexedSink<E> {
abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
IndexedSink<String> _stringIndex;
IndexedSink<Uri> _uriIndex;
Map<Type, IndexedSink> _generalCaches = {};
final Map<Type, IndexedSink> _generalCaches = {};
AbstractDataSink() {
_stringIndex = new IndexedSink<String>(_writeIntInternal);
_uriIndex = new IndexedSink<Uri>(_writeIntInternal);
_stringIndex = IndexedSink<String>(_writeIntInternal);
_uriIndex = IndexedSink<Uri>(_writeIntInternal);
}
@override
void writeCached<E>(E value, void f(E value)) {
IndexedSink sink =
_generalCaches[E] ??= new IndexedSink<E>(_writeIntInternal);
void writeCached<E>(E value, void Function(E value) f) {
IndexedSink sink = _generalCaches[E] ??= IndexedSink<E>(_writeIntInternal);
sink.write(value, (v) => f(v));
}
@ -254,7 +253,7 @@ class BinarySink extends AbstractDataSink {
BufferedSink _bufferedSink;
int _length = 0;
BinarySink(this.sink) : _bufferedSink = new BufferedSink(sink);
BinarySink(this.sink) : _bufferedSink = BufferedSink(sink);
@override
void _writeUriInternal(Uri value) {
@ -290,6 +289,7 @@ class BinarySink extends AbstractDataSink {
_writeIntInternal(value.index);
}
@override
void close() {
_bufferedSink.flushAndDestroy();
_bufferedSink = null;
@ -297,6 +297,7 @@ class BinarySink extends AbstractDataSink {
}
/// Returns the number of bytes written to this data sink.
@override
int get length => _length;
}
@ -304,15 +305,15 @@ class BinarySink extends AbstractDataSink {
// TODO(sigmund): share with the implementation in
// package:kernel/binary/ast_to_binary.dart
class BufferedSink {
static const int SIZE = 100000;
static const int SAFE_SIZE = SIZE - 5;
static const int SMALL = 10000;
static const int _size = 100000;
static const int _safeSize = _size - 5;
static const int _small = 10000;
final Sink<List<int>> _sink;
Uint8List _buffer = new Uint8List(SIZE);
Uint8List _buffer = Uint8List(_size);
int length = 0;
int flushedLength = 0;
Float64List _doubleBuffer = new Float64List(1);
final Float64List _doubleBuffer = Float64List(1);
Uint8List _doubleBufferUint8;
int get offset => length + flushedLength;
@ -330,16 +331,16 @@ class BufferedSink {
void addByte(int byte) {
_buffer[length++] = byte;
if (length == SIZE) {
if (length == _size) {
_sink.add(_buffer);
_buffer = new Uint8List(SIZE);
_buffer = Uint8List(_size);
length = 0;
flushedLength += SIZE;
flushedLength += _size;
}
}
void addByte2(int byte1, int byte2) {
if (length < SAFE_SIZE) {
if (length < _safeSize) {
_buffer[length++] = byte1;
_buffer[length++] = byte2;
} else {
@ -349,7 +350,7 @@ class BufferedSink {
}
void addByte4(int byte1, int byte2, int byte3, int byte4) {
if (length < SAFE_SIZE) {
if (length < _safeSize) {
_buffer[length++] = byte1;
_buffer[length++] = byte2;
_buffer[length++] = byte3;
@ -365,22 +366,22 @@ class BufferedSink {
void addBytes(List<int> bytes) {
// Avoid copying a large buffer into the another large buffer. Also, if
// the bytes buffer is too large to fit in our own buffer, just emit both.
if (length + bytes.length < SIZE &&
(bytes.length < SMALL || length < SMALL)) {
if (length + bytes.length < _size &&
(bytes.length < _small || length < _small)) {
_buffer.setRange(length, length + bytes.length, bytes);
length += bytes.length;
} else if (bytes.length < SMALL) {
} else if (bytes.length < _small) {
// Flush as much as we can in the current buffer.
_buffer.setRange(length, SIZE, bytes);
_buffer.setRange(length, _size, bytes);
_sink.add(_buffer);
// Copy over the remainder into a new buffer. It is guaranteed to fit
// because the input byte array is small.
int alreadyEmitted = SIZE - length;
int alreadyEmitted = _size - length;
int remainder = bytes.length - alreadyEmitted;
_buffer = new Uint8List(SIZE);
_buffer = Uint8List(_size);
_buffer.setRange(0, remainder, bytes, alreadyEmitted);
length = remainder;
flushedLength += SIZE;
flushedLength += _size;
} else {
flush();
_sink.add(bytes);
@ -390,7 +391,7 @@ class BufferedSink {
void flush() {
_sink.add(_buffer.sublist(0, length));
_buffer = new Uint8List(SIZE);
_buffer = Uint8List(_size);
flushedLength += length;
length = 0;
}

View file

@ -2,29 +2,29 @@
// 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:typed_data';
import 'dart:convert';
import 'dart:typed_data';
/// Interface for deserialization.
// TODO(sigmund): share this with pkg:compiler/src/serialization/*
abstract class DataSource {
/// Reads a reference to an [E] value from this data source. If the value has
/// not yet been deserialized, [f] is called to deserialize the value itself.
E readCached<E>(E f());
E readCached<E>(E Function() f);
/// Reads a potentially `null` [E] value from this data source, calling [f] to
/// read the non-null value from the data source.
///
/// This is a convenience method to be used together with
/// [DataSink.writeValueOrNull].
E readValueOrNull<E>(E f());
E readValueOrNull<E>(E Function() f);
/// Reads a list of [E] values from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeList].
List<E> readList<E>(E f(), {bool emptyAsNull: false});
List<E> readList<E>(E Function() f, {bool emptyAsNull = false});
/// Reads a boolean value from this data source.
bool readBool();
@ -53,7 +53,7 @@ abstract class DataSource {
///
/// This is a convenience method to be used together with
/// [DataSink.writeStrings].
List<String> readStrings({bool emptyAsNull: false});
List<String> readStrings({bool emptyAsNull = false});
/// Reads a map from string values to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
@ -61,7 +61,7 @@ abstract class DataSource {
///
/// This is a convenience method to be used together with
/// [DataSink.writeStringMap].
Map<String, V> readStringMap<V>(V f(), {bool emptyAsNull: false});
Map<String, V> readStringMap<V>(V Function() f, {bool emptyAsNull = false});
/// Reads an enum value from the list of enum [values] from this data source.
///
@ -81,7 +81,7 @@ abstract class DataSource {
/// Mixin that implements all convenience methods of [DataSource].
abstract class DataSourceMixin implements DataSource {
@override
E readValueOrNull<E>(E f()) {
E readValueOrNull<E>(E Function() f) {
bool hasValue = readBool();
if (hasValue) {
return f();
@ -90,14 +90,10 @@ abstract class DataSourceMixin implements DataSource {
}
@override
List<E> readList<E>(E f(), {bool emptyAsNull: false}) {
List<E> readList<E>(E Function() f, {bool emptyAsNull = false}) {
int count = readInt();
if (count == 0 && emptyAsNull) return null;
List<E> list = new List<E>(count);
for (int i = 0; i < count; i++) {
list[i] = f();
}
return list;
return List.generate(count, (i) => f());
}
@override
@ -119,18 +115,14 @@ abstract class DataSourceMixin implements DataSource {
}
@override
List<String> readStrings({bool emptyAsNull: false}) {
List<String> readStrings({bool emptyAsNull = false}) {
int count = readInt();
if (count == 0 && emptyAsNull) return null;
List<String> list = new List<String>(count);
for (int i = 0; i < count; i++) {
list[i] = readString();
}
return list;
return List.generate(count, (index) => readString());
}
@override
Map<String, V> readStringMap<V>(V f(), {bool emptyAsNull: false}) {
Map<String, V> readStringMap<V>(V Function() f, {bool emptyAsNull = false}) {
int count = readInt();
if (count == 0 && emptyAsNull) return null;
Map<String, V> map = {};
@ -147,7 +139,7 @@ abstract class DataSourceMixin implements DataSource {
class IndexedSource<E> {
final int Function() _readInt;
final List<E> _cache = [];
final Set<int> _pending = new Set();
final Set<int> _pending = {};
IndexedSource(this._readInt);
@ -155,7 +147,7 @@ class IndexedSource<E> {
///
/// If the value hasn't yet been read, [readValue] is called to deserialize
/// the value itself.
E read(E readValue()) {
E read(E Function() readValue) {
int index = _readInt();
if (_pending.contains(index)) throw "serialization cycles not supported";
if (index >= _cache.length) {
@ -177,17 +169,17 @@ abstract class AbstractDataSource extends DataSourceMixin
implements DataSource {
IndexedSource<String> _stringIndex;
IndexedSource<Uri> _uriIndex;
Map<Type, IndexedSource> _generalCaches = {};
final Map<Type, IndexedSource> _generalCaches = {};
AbstractDataSource() {
_stringIndex = new IndexedSource<String>(_readIntInternal);
_uriIndex = new IndexedSource<Uri>(_readIntInternal);
_stringIndex = IndexedSource<String>(_readIntInternal);
_uriIndex = IndexedSource<Uri>(_readIntInternal);
}
@override
E readCached<E>(E f()) {
E readCached<E>(E Function() f) {
IndexedSource source =
_generalCaches[E] ??= new IndexedSource<E>(_readIntInternal);
_generalCaches[E] ??= IndexedSource<E>(_readIntInternal);
return source.read(f);
}
@ -254,7 +246,7 @@ class BinarySource extends AbstractDataSource {
@override
String _readStringInternal() {
int length = _readIntInternal();
List<int> bytes = new Uint8List(length);
List<int> bytes = Uint8List(length);
bytes.setRange(0, bytes.length, _bytes, _byteOffset);
_byteOffset += bytes.length;
return utf8.decode(bytes);

View file

@ -29,12 +29,12 @@ class DeferredStatusDiff extends Diff {
}
List<Diff> diff(AllInfo oldInfo, AllInfo newInfo) {
var differ = new _InfoDiffer(oldInfo, newInfo);
var differ = _InfoDiffer(oldInfo, newInfo);
differ.diff();
return differ.diffs;
}
class _InfoDiffer extends InfoVisitor<Null> {
class _InfoDiffer extends InfoVisitor<void> {
final AllInfo _old;
final AllInfo _new;
@ -50,23 +50,23 @@ class _InfoDiffer extends InfoVisitor<Null> {
@override
visitAll(AllInfo info) {
throw new StateError('should not diff AllInfo');
throw StateError('should not diff AllInfo');
}
@override
visitProgram(ProgramInfo info) {
throw new StateError('should not diff ProgramInfo');
throw StateError('should not diff ProgramInfo');
}
@override
visitOutput(OutputUnitInfo info) {
throw new StateError('should not diff OutputUnitInfo');
throw StateError('should not diff OutputUnitInfo');
}
// TODO(het): diff constants
@override
visitConstant(ConstantInfo info) {
throw new StateError('should not diff ConstantInfo');
throw StateError('should not diff ConstantInfo');
}
@override
@ -127,7 +127,7 @@ class _InfoDiffer extends InfoVisitor<Null> {
void _checkSize(BasicInfo info, BasicInfo other) {
if (info.size != other.size) {
diffs.add(new SizeDiff(info, other.size - info.size));
diffs.add(SizeDiff(info, other.size - info.size));
}
}
@ -135,7 +135,7 @@ class _InfoDiffer extends InfoVisitor<Null> {
var oldIsDeferred = _isDeferred(oldInfo);
var newIsDeferred = _isDeferred(newInfo);
if (oldIsDeferred != newIsDeferred) {
diffs.add(new DeferredStatusDiff(oldInfo, oldIsDeferred));
diffs.add(DeferredStatusDiff(oldInfo, oldIsDeferred));
}
}
@ -157,7 +157,7 @@ class _InfoDiffer extends InfoVisitor<Null> {
}
for (var oldName in oldNames.keys) {
if (newNames[oldName] == null) {
diffs.add(new RemoveDiff(oldNames[oldName]));
diffs.add(RemoveDiff(oldNames[oldName]));
} else {
_other = newNames[oldName];
oldNames[oldName].accept(this);
@ -165,7 +165,7 @@ class _InfoDiffer extends InfoVisitor<Null> {
}
for (var newName in newNames.keys) {
if (oldNames[newName] == null) {
diffs.add(new AddDiff(newNames[newName]));
diffs.add(AddDiff(newNames[newName]));
}
}
}

View file

@ -25,13 +25,13 @@ abstract class Graph<N> {
/// of nodes. The nodes in each strongly connected components only have edges
/// that point to nodes in the same component or earlier components.
List<List<N>> computeTopologicalSort() {
_SccFinder<N> finder = new _SccFinder<N>(this);
_SccFinder<N> finder = _SccFinder<N>(this);
return finder.computeTopologicalSort();
}
/// Whether [source] can transitively reach [target].
bool containsPath(N source, N target) {
Set<N> seen = new Set<N>();
Set<N> seen = <N>{};
bool helper(N node) {
if (identical(node, target)) return true;
if (!seen.add(node)) return false;
@ -43,7 +43,7 @@ abstract class Graph<N> {
/// Returns all nodes reachable from [root] in post order.
Iterable<N> postOrder(N root) sync* {
var seen = new Set<N>();
var seen = <N>{};
Iterable<N> helper(N n) sync* {
if (!seen.add(n)) return;
for (var x in targetsOf(n)) {
@ -57,7 +57,7 @@ abstract class Graph<N> {
/// Returns an iterable of all nodes reachable from [root] in preorder.
Iterable<N> preOrder(N root) sync* {
var seen = new Set<N>();
var seen = <N>{};
var stack = <N>[root];
while (stack.isNotEmpty) {
var next = stack.removeLast();
@ -74,7 +74,7 @@ abstract class Graph<N> {
/// the node itself will be returned.
List<N> findCycleContaining(N node) {
assert(node != null);
_SccFinder<N> finder = new _SccFinder<N>(this);
_SccFinder<N> finder = _SccFinder<N>(this);
return finder._componentContaining(node);
}
@ -103,8 +103,8 @@ abstract class Graph<N> {
/// Internally we compute dominators using (Cooper, Harvey, and Kennedy's
/// algorithm)[http://www.cs.rice.edu/~keith/EMBED/dom.pdf].
Graph<N> dominatorTree(N root) {
var iDom = (new _DominatorFinder(this)..run(root)).immediateDominators;
var graph = new EdgeListGraph<N>();
var iDom = (_DominatorFinder(this)..run(root)).immediateDominators;
var graph = EdgeListGraph<N>();
for (N node in iDom.keys) {
if (node != root) graph.addEdge(iDom[node], node);
}
@ -114,18 +114,23 @@ abstract class Graph<N> {
class EdgeListGraph<N> extends Graph<N> {
/// Edges in the graph.
Map<N, Set<N>> _edges = new Map<N, Set<N>>();
final Map<N, Set<N>> _edges = <N, Set<N>>{};
/// The reverse of _edges.
Map<N, Set<N>> _revEdges = new Map<N, Set<N>>();
final Map<N, Set<N>> _revEdges = <N, Set<N>>{};
@override
Iterable<N> get nodes => _edges.keys;
@override
bool get isEmpty => _edges.isEmpty;
@override
int get nodeCount => _edges.length;
final _empty = new Set<N>();
final _empty = <N>{};
@override
Iterable<N> targetsOf(N source) => _edges[source] ?? _empty;
@override
Iterable<N> sourcesOf(N source) => _revEdges[source] ?? _empty;
void addEdge(N source, N target) {
@ -139,8 +144,8 @@ class EdgeListGraph<N> extends Graph<N> {
void addNode(N node) {
assert(node != null);
_edges.putIfAbsent(node, () => new Set<N>());
_revEdges.putIfAbsent(node, () => new Set<N>());
_edges.putIfAbsent(node, () => <N>{});
_revEdges.putIfAbsent(node, () => <N>{});
}
/// Remove the edge from the given [source] node to the given [target] node.
@ -200,15 +205,15 @@ class _SccFinder<N> {
int _index = 0;
/// Nodes that are being visited in order to identify components.
List<N> _stack = new List<N>();
final List<N> _stack = <N>[];
/// Information associated with each node.
Map<N, _NodeInfo<N>> _info = <N, _NodeInfo<N>>{};
final Map<N, _NodeInfo<N>> _info = <N, _NodeInfo<N>>{};
/// All strongly connected components found, in topological sort order (each
/// node in a strongly connected component only has edges that point to nodes
/// in the same component or earlier components).
List<List<N>> _allComponents = new List<List<N>>();
final List<List<N>> _allComponents = <List<N>>[];
_SccFinder(this._graph);
@ -246,7 +251,7 @@ class _SccFinder<N> {
/// component.
_NodeInfo<N> _strongConnect(N v) {
// Set the depth index for v to the smallest unused index
var vInfo = new _NodeInfo<N>(_index++);
var vInfo = _NodeInfo<N>(_index++);
_info[v] = vInfo;
_push(v);
@ -264,7 +269,7 @@ class _SccFinder<N> {
// If v is a root node, pop the stack and generate an SCC
if (vInfo.lowlink == vInfo.index) {
var component = new List<N>();
var component = <N>[];
N w;
do {
w = _pop();

View file

@ -6,9 +6,9 @@ import 'package:dart2js_info/json_info_codec.dart';
import 'package:dart2js_info/binary_serialization.dart' as binary;
Future<AllInfo> infoFromFile(String fileName) async {
var file = new File(fileName);
var file = File(fileName);
if (fileName.endsWith('.json')) {
return new AllInfoJsonCodec().decode(jsonDecode(await file.readAsString()));
return AllInfoJsonCodec().decode(jsonDecode(await file.readAsString()));
} else {
return binary.decode(file.readAsBytesSync());
}

View file

@ -18,12 +18,12 @@ class StringEditBuffer {
StringEditBuffer(this.original);
bool get hasEdits => _edits.length > 0;
bool get hasEdits => _edits.isNotEmpty;
/// Edit the original text, replacing text on the range [begin] and
/// exclusive [end] with the [replacement] string.
void replace(int begin, int end, String replacement, [int sortId]) {
_edits.add(new _StringEdit(begin, end, replacement, sortId));
_edits.add(_StringEdit(begin, end, replacement, sortId));
}
/// Insert [string] at [offset].
@ -43,9 +43,10 @@ class StringEditBuffer {
///
/// Throws [UnsupportedError] if the edits were overlapping. If no edits were
/// made, the original string will be returned.
@override
String toString() {
var sb = new StringBuffer();
if (_edits.length == 0) return original;
var sb = StringBuffer();
if (_edits.isEmpty) return original;
// Sort edits by start location.
_edits.sort();
@ -53,7 +54,7 @@ class StringEditBuffer {
int consumed = 0;
for (var edit in _edits) {
if (consumed > edit.begin) {
sb = new StringBuffer();
sb = StringBuffer();
sb.write('overlapping edits. Insert at offset ');
sb.write(edit.begin);
sb.write(' but have consumed ');
@ -63,7 +64,7 @@ class StringEditBuffer {
sb.write('\n ');
sb.write(e);
}
throw new UnsupportedError(sb.toString());
throw UnsupportedError(sb.toString());
}
// Add characters from the original string between this edit and the last
@ -94,14 +95,15 @@ class _StringEdit implements Comparable<_StringEdit> {
// String to insert
final String string;
_StringEdit(int begin, this.end, this.string, [int sortId])
: begin = begin,
sortId = sortId == null ? begin : sortId;
_StringEdit(this.begin, this.end, this.string, [int sortId])
: sortId = sortId ?? begin;
int get length => end - begin;
@override
String toString() => '(Edit @ $begin,$end: "$string")';
@override
int compareTo(_StringEdit other) {
int diff = begin - other.begin;
if (diff != 0) return diff;

View file

@ -28,7 +28,7 @@ class Table {
List<List> rows = [];
/// Columns to skip, for example, if they are all zero entries.
List<bool> _skipped = <bool>[];
final List<bool> _skipped = <bool>[];
/// Whether we started adding entries. Indicates that no more columns can be
/// added.
@ -39,14 +39,16 @@ class Table {
/// Add a column with the given [name].
void declareColumn(String name,
{bool abbreviate: false, String color: _NO_COLOR}) {
{bool abbreviate = false, String color = _noColor}) {
assert(!_sealed);
var headerName = name;
if (abbreviate) {
// abbreviate the header by using only the initials of each word
headerName =
name.split(' ').map((s) => s.substring(0, 1).toUpperCase()).join('');
while (abbreviations[headerName] != null) headerName = "$headerName'";
while (abbreviations[headerName] != null) {
headerName = "$headerName'";
}
abbreviations[headerName] = name;
}
widths.add(max(5, headerName.length + 1));
@ -94,11 +96,12 @@ class Table {
/// Generates a string representation of the table to print on a terminal.
// TODO(sigmund): add also a .csv format
@override
String toString() {
var sb = new StringBuffer();
var sb = StringBuffer();
sb.write('\n');
for (var row in rows) {
var lastColor = _NO_COLOR;
var lastColor = _noColor;
for (int i = 0; i < _totalColumns; i++) {
if (_skipped[i]) continue;
var entry = row[i];
@ -111,7 +114,7 @@ class Table {
sb.write(
i == 0 ? entry.padRight(widths[i]) : entry.padLeft(widths[i] + 1));
}
if (lastColor != _NO_COLOR) sb.write(_NO_COLOR);
if (lastColor != _noColor) sb.write(_noColor);
sb.write('\n');
}
sb.write('\nWhere:\n');
@ -123,4 +126,4 @@ class Table {
}
}
const _NO_COLOR = "\x1b[0m";
const _noColor = "\x1b[0m";

View file

@ -18,7 +18,7 @@ Graph<Info> graphFromInfo(AllInfo info) {
// of them.
// TODO(sigmund): create a concrete implementation of InfoGraph, instead of
// using the EdgeListGraph.
var graph = new EdgeListGraph<Info>();
var graph = EdgeListGraph<Info>();
for (var f in info.functions) {
graph.addNode(f);
for (var g in f.uses) {
@ -48,13 +48,13 @@ Graph<Info> graphFromInfo(AllInfo info) {
/// Provide a unique long name associated with [info].
// TODO(sigmund): guarantee that the name is actually unique.
String longName(Info info, {bool useLibraryUri: false, bool forId: false}) {
String longName(Info info, {bool useLibraryUri = false, bool forId = false}) {
var infoPath = [];
while (info != null) {
infoPath.add(info);
info = info.parent;
}
var sb = new StringBuffer();
var sb = StringBuffer();
var first = true;
for (var segment in infoPath.reversed) {
if (!first) sb.write('.');
@ -91,7 +91,7 @@ String longName(Info info, {bool useLibraryUri: false, bool forId: false}) {
}
/// Produce a string containing [value] padded with white space up to [n] chars.
pad(value, n, {bool right: false}) {
pad(value, n, {bool right = false}) {
var s = '$value';
if (s.length >= n) return s;
var pad = ' ' * (n - s.length);

View file

@ -1,24 +1,24 @@
name: dart2js_info
version: 0.6.5
publish_to: none
description: >-
Libraries and tools to process data produced when running dart2js with
--dump-info.
homepage: https://github.com/dart-lang/dart2js_info/
environment:
sdk: '>=2.3.0 <3.0.0'
sdk: '>=2.11.99 <3.0.0'
dependencies:
args: ^1.4.3
args: ^2.3.0
collection: ^1.10.1
fixnum: '>=0.10.5 <2.0.0'
path: ^1.3.6
protobuf: '>=1.0.1 <3.0.0'
shelf: ^0.7.3
yaml: ^2.1.0
shelf: ^1.2.0
yaml: ^3.1.0
dev_dependencies:
lints: ^1.0.0
test: ^1.2.0
executables:

View file

@ -12,15 +12,17 @@ import 'package:test/test.dart';
class ByteSink implements Sink<List<int>> {
BytesBuilder builder = BytesBuilder();
@override
add(List<int> data) => builder.add(data);
@override
close() {}
}
main() {
group('json to proto conversion with deferred files', () {
test('hello_world_deferred', () {
var uri = Platform.script.resolve(
'hello_world_deferred/hello_world_deferred.js.info.json');
var uri = Platform.script
.resolve('hello_world_deferred/hello_world_deferred.js.info.json');
var helloWorld = File.fromUri(uri);
var contents = helloWorld.readAsStringSync();
var json = jsonDecode(contents);

View file

@ -60,7 +60,7 @@ main() {
/// C
/// ```
Graph<String> makeTestGraph() {
var graph = new EdgeListGraph<String>();
var graph = EdgeListGraph<String>();
graph.addEdge('A', 'B');
graph.addEdge('A', 'D');
graph.addEdge('A', 'E');

View file

@ -12,8 +12,8 @@ import 'package:test/test.dart';
main() {
group('json to proto conversion with deferred files', () {
test('hello_world_deferred', () {
var uri = Platform.script.resolve(
'hello_world_deferred/hello_world_deferred.js.info.json');
var uri = Platform.script
.resolve('hello_world_deferred/hello_world_deferred.js.info.json');
final helloWorld = File.fromUri(uri);
final json = jsonDecode(helloWorld.readAsStringSync());
final decoded = AllInfoJsonCodec().decode(json);

View file

@ -13,8 +13,7 @@ import 'package:test/test.dart';
main() {
group('json to proto conversion', () {
test('hello_world', () {
var uri = Platform.script.resolve(
'hello_world/hello_world.js.info.json');
var uri = Platform.script.resolve('hello_world/hello_world.js.info.json');
final helloWorld = File.fromUri(uri);
final json = jsonDecode(helloWorld.readAsStringSync());
final decoded = AllInfoJsonCodec().decode(json);
@ -33,8 +32,7 @@ main() {
});
test('has proper id format', () {
var uri = Platform.script.resolve(
'hello_world/hello_world.js.info.json');
var uri = Platform.script.resolve('hello_world/hello_world.js.info.json');
final helloWorld = File.fromUri(uri);
final json = jsonDecode(helloWorld.readAsStringSync());
final decoded = AllInfoJsonCodec().decode(json);
@ -54,8 +52,8 @@ main() {
expect(
value.serializedId, startsWith(expectedPrefixes[InfoKind.clazz]));
} else if (value.hasClassTypeInfo()) {
expect(
value.serializedId, startsWith(expectedPrefixes[InfoKind.classType]));
expect(value.serializedId,
startsWith(expectedPrefixes[InfoKind.classType]));
} else if (value.hasFunctionInfo()) {
expect(value.serializedId,
startsWith(expectedPrefixes[InfoKind.function]));

View file

@ -11,8 +11,7 @@ import 'package:test/test.dart';
main() {
group('parse', () {
test('hello_world', () {
var uri =
Platform.script.resolve('hello_world/hello_world.js.info.json');
var uri = Platform.script.resolve('hello_world/hello_world.js.info.json');
var helloWorld = File.fromUri(uri);
var json = jsonDecode(helloWorld.readAsStringSync());
var decoded = AllInfoJsonCodec().decode(json);
@ -24,9 +23,9 @@ main() {
expect(program.size, 94182);
expect(program.compilationMoment,
DateTime.parse("2021-09-27 15:32:00.380236"));
expect(program.compilationDuration, new Duration(microseconds: 2848001));
expect(program.toJsonDuration, new Duration(milliseconds: 3));
expect(program.dumpInfoDuration, new Duration(seconds: 0));
expect(program.compilationDuration, Duration(microseconds: 2848001));
expect(program.toJsonDuration, Duration(milliseconds: 3));
expect(program.dumpInfoDuration, Duration(seconds: 0));
expect(program.noSuchMethodEnabled, false);
expect(program.minified, false);
});

View file

@ -3247,6 +3247,15 @@
"pkg/dartdev"
]
},
{
"name": "analyze pkg/dart2js_info",
"script": "out/ReleaseX64/dart-sdk/bin/dart",
"arguments": [
"analyze",
"--fatal-infos",
"pkg/dart2js_info"
]
},
{
"name": "analyze pkg/dart2js_tools",
"script": "out/ReleaseX64/dart-sdk/bin/dart",