| Index: sdk/lib/_internal/compiler/implementation/dump_info.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/dump_info.dart b/sdk/lib/_internal/compiler/implementation/dump_info.dart
|
| deleted file mode 100644
|
| index c59ea596ab48213d27935bc65f222db80e3eed4b..0000000000000000000000000000000000000000
|
| --- a/sdk/lib/_internal/compiler/implementation/dump_info.dart
|
| +++ /dev/null
|
| @@ -1,667 +0,0 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library dump_info;
|
| -
|
| -import 'dart:convert' show
|
| - HtmlEscape,
|
| - JsonEncoder,
|
| - StringConversionSink,
|
| - ChunkedConversionSink;
|
| -
|
| -import 'elements/elements.dart';
|
| -import 'elements/visitor.dart';
|
| -import 'dart2jslib.dart' show
|
| - Backend,
|
| - CodeBuffer,
|
| - Compiler,
|
| - CompilerTask,
|
| - MessageKind;
|
| -import 'types/types.dart' show TypeMask;
|
| -import 'deferred_load.dart' show OutputUnit;
|
| -import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
| -import 'js/js.dart' as jsAst;
|
| -import 'universe/universe.dart' show Selector;
|
| -import 'util/util.dart' show NO_LOCATION_SPANNABLE;
|
| -
|
| -/// Maps objects to an id. Supports lookups in
|
| -/// both directions.
|
| -class IdMapper<T>{
|
| - Map<int, T> _idToElement = {};
|
| - Map<T, int> _elementToId = {};
|
| - int _idCounter = 0;
|
| - String name;
|
| -
|
| - IdMapper(this.name);
|
| -
|
| - Iterable<T> get elements => _elementToId.keys;
|
| -
|
| - String add(T e) {
|
| - if (_elementToId.containsKey(e)) {
|
| - return name + "/${_elementToId[e]}";
|
| - }
|
| -
|
| - _idToElement[_idCounter] = e;
|
| - _elementToId[e] = _idCounter;
|
| - _idCounter += 1;
|
| - return name + "/${_idCounter - 1}";
|
| - }
|
| -}
|
| -
|
| -class GroupedIdMapper {
|
| - // Mappers for specific kinds of elements.
|
| - IdMapper<LibraryElement> _library = new IdMapper('library');
|
| - IdMapper<TypedefElement> _typedef = new IdMapper('typedef');
|
| - IdMapper<FieldElement> _field = new IdMapper('field');
|
| - IdMapper<ClassElement> _class = new IdMapper('class');
|
| - IdMapper<FunctionElement> _function = new IdMapper('function');
|
| - IdMapper<OutputUnit> _outputUnit = new IdMapper('outputUnit');
|
| -
|
| - Iterable<Element> get functions => _function.elements;
|
| -
|
| - // Convert this database of elements into JSON for rendering
|
| - Map<String, dynamic> _toJson(ElementToJsonVisitor elementToJson) {
|
| - Map<String, dynamic> json = {};
|
| - var m = [_library, _typedef, _field, _class, _function];
|
| - for (IdMapper mapper in m) {
|
| - Map<String, dynamic> innerMapper = {};
|
| - mapper._idToElement.forEach((k, v) {
|
| - // All these elements are already cached in the
|
| - // jsonCache, so this is just an access.
|
| - var elementJson = elementToJson.process(v);
|
| - if (elementJson != null) {
|
| - innerMapper["$k"] = elementJson;
|
| - }
|
| - });
|
| - json[mapper.name] = innerMapper;
|
| - }
|
| - return json;
|
| - }
|
| -}
|
| -
|
| -class ElementToJsonVisitor extends ElementVisitor<Map<String, dynamic>> {
|
| - final GroupedIdMapper mapper = new GroupedIdMapper();
|
| - final Compiler compiler;
|
| -
|
| - final Map<Element, Map<String, dynamic>> jsonCache = {};
|
| -
|
| - int programSize;
|
| - String dart2jsVersion;
|
| -
|
| - ElementToJsonVisitor(this.compiler);
|
| -
|
| - void run() {
|
| - Backend backend = compiler.backend;
|
| - if (backend is JavaScriptBackend) {
|
| - // Add up the sizes of all output-buffers.
|
| - programSize = backend.emitter.oldEmitter.outputBuffers.values.fold(0,
|
| - (a, b) => a + b.length);
|
| - } else {
|
| - programSize = compiler.assembledCode.length;
|
| - }
|
| -
|
| - dart2jsVersion = compiler.hasBuildId ? compiler.buildId : null;
|
| -
|
| - for (var library in compiler.libraryLoader.libraries.toList()) {
|
| - library.accept(this);
|
| - }
|
| - }
|
| -
|
| - // If keeping the element is in question (like if a function has a size
|
| - // of zero), only keep it if it holds dependencies to elsewhere.
|
| - bool shouldKeep(Element element) {
|
| - return compiler.dumpInfoTask.selectorsFromElement.containsKey(element)
|
| - || compiler.dumpInfoTask.inlineCount.containsKey(element);
|
| - }
|
| -
|
| - Map<String, dynamic> toJson() {
|
| - return mapper._toJson(this);
|
| - }
|
| -
|
| - // Memoization of the JSON creating process.
|
| - Map<String, dynamic> process(Element element) {
|
| - return jsonCache.putIfAbsent(element, () => element.accept(this));
|
| - }
|
| -
|
| - // Returns the id of an [element] if it has already been processed.
|
| - // If the element has not been processed, this function does not
|
| - // process it, and simply returns null instead.
|
| - String idOf(Element element) {
|
| - if (jsonCache.containsKey(element) && jsonCache[element] != null) {
|
| - return jsonCache[element]['id'];
|
| - } else {
|
| - return null;
|
| - }
|
| - }
|
| -
|
| - Map<String, dynamic> visitElement(Element element) {
|
| - return null;
|
| - }
|
| -
|
| - Map<String, dynamic> visitConstructorBodyElement(ConstructorBodyElement e) {
|
| - return visitFunctionElement(e.constructor);
|
| - }
|
| -
|
| - Map<String, dynamic> visitLibraryElement(LibraryElement element) {
|
| - var id = mapper._library.add(element);
|
| - List<String> children = <String>[];
|
| -
|
| - String libname = element.getLibraryName();
|
| - libname = libname == "" ? "<unnamed>" : libname;
|
| -
|
| - int size = compiler.dumpInfoTask.sizeOf(element);
|
| -
|
| - LibraryElement contentsOfLibrary = element.isPatched
|
| - ? element.patch : element;
|
| - contentsOfLibrary.forEachLocalMember((Element member) {
|
| - Map<String, dynamic> childJson = this.process(member);
|
| - if (childJson == null) return;
|
| - children.add(childJson['id']);
|
| - });
|
| -
|
| - if (children.length == 0 && !shouldKeep(element)) {
|
| - return null;
|
| - }
|
| -
|
| - return {
|
| - 'kind': 'library',
|
| - 'name': libname,
|
| - 'size': size,
|
| - 'id': id,
|
| - 'children': children
|
| - };
|
| - }
|
| -
|
| - Map<String, dynamic> visitTypedefElement(TypedefElement element) {
|
| - String id = mapper._typedef.add(element);
|
| - return element.alias == null
|
| - ? null
|
| - : {
|
| - 'id': id,
|
| - 'type': element.alias.toString(),
|
| - 'kind': 'typedef',
|
| - 'name': element.name
|
| - };
|
| - }
|
| -
|
| - Map<String, dynamic> visitFieldElement(FieldElement element) {
|
| - String id = mapper._field.add(element);
|
| - List<String> children = [];
|
| - StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
|
| -
|
| - TypeMask inferredType =
|
| - compiler.typesTask.getGuaranteedTypeOfElement(element);
|
| - // If a field has an empty inferred type it is never used.
|
| - if (inferredType == null || inferredType.isEmpty || element.isConst) {
|
| - return null;
|
| - }
|
| -
|
| - int size = compiler.dumpInfoTask.sizeOf(element);
|
| - String code;
|
| -
|
| - if (emittedCode != null) {
|
| - size += emittedCode.length;
|
| - code = emittedCode.toString();
|
| - }
|
| -
|
| - for (Element closure in element.nestedClosures) {
|
| - var childJson = this.process(closure);
|
| - if (childJson != null) {
|
| - children.add(childJson['id']);
|
| - if (childJson.containsKey('size')) {
|
| - size += childJson['size'];
|
| - }
|
| - }
|
| - }
|
| -
|
| - OutputUnit outputUnit =
|
| - compiler.deferredLoadTask.outputUnitForElement(element);
|
| -
|
| - return {
|
| - 'id': id,
|
| - 'kind': 'field',
|
| - 'type': element.type.toString(),
|
| - 'inferredType': inferredType.toString(),
|
| - 'name': element.name,
|
| - 'children': children,
|
| - 'size': size,
|
| - 'code': code,
|
| - 'outputUnit': mapper._outputUnit.add(outputUnit)
|
| - };
|
| - }
|
| -
|
| - Map<String, dynamic> visitClassElement(ClassElement element) {
|
| - String id = mapper._class.add(element);
|
| - List<String> children = [];
|
| -
|
| - int size = compiler.dumpInfoTask.sizeOf(element);
|
| - JavaScriptBackend backend = compiler.backend;
|
| -
|
| - Map<String, dynamic> modifiers = { 'abstract': element.isAbstract };
|
| -
|
| - element.forEachLocalMember((Element member) {
|
| - Map<String, dynamic> childJson = this.process(member);
|
| - if (childJson != null) {
|
| - children.add(childJson['id']);
|
| -
|
| - // Closures are placed in the library namespace, but
|
| - // we want to attribute them to a function, and by
|
| - // extension, this class. Process and add the sizes
|
| - // here.
|
| - if (member is MemberElement) {
|
| - for (Element closure in member.nestedClosures) {
|
| - Map<String, dynamic> child = this.process(closure);
|
| -
|
| - // Look for the parent element of this closure which should
|
| - // be a class. If it exists, set the display name to
|
| - // the name of the class + the name of the closure function.
|
| - Element parent = closure.enclosingElement;
|
| - Map<String, dynamic> processedParent = this.process(parent);
|
| - if (processedParent != null) {
|
| - child['name'] = "${processedParent['name']}.${child['name']}";
|
| - }
|
| -
|
| - if (child != null) {
|
| - size += child['size'];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - });
|
| -
|
| - // Omit element if it is not needed.
|
| - if (!backend.emitter.neededClasses.contains(element) &&
|
| - children.length == 0) {
|
| - return null;
|
| - }
|
| -
|
| - OutputUnit outputUnit =
|
| - compiler.deferredLoadTask.outputUnitForElement(element);
|
| -
|
| - return {
|
| - 'name': element.name,
|
| - 'size': size,
|
| - 'kind': 'class',
|
| - 'modifiers': modifiers,
|
| - 'children': children,
|
| - 'id': id,
|
| - 'outputUnit': mapper._outputUnit.add(outputUnit)
|
| - };
|
| - }
|
| -
|
| - Map<String, dynamic> visitFunctionElement(FunctionElement element) {
|
| - String id = mapper._function.add(element);
|
| - String name = element.name;
|
| - String kind = "function";
|
| - List<String> children = [];
|
| - List<Map<String, dynamic>> parameters = [];
|
| - String inferredReturnType = null;
|
| - String returnType = null;
|
| - String sideEffects = null;
|
| - String code = "";
|
| -
|
| - StringBuffer emittedCode = compiler.dumpInfoTask.codeOf(element);
|
| - int size = compiler.dumpInfoTask.sizeOf(element);
|
| -
|
| - Map<String, dynamic> modifiers = {
|
| - 'static': element.isStatic,
|
| - 'const': element.isConst,
|
| - 'factory': element.isFactoryConstructor,
|
| - 'external': element.isPatched
|
| - };
|
| -
|
| - var enclosingElement = element.enclosingElement;
|
| - if (enclosingElement.isField ||
|
| - enclosingElement.isFunction ||
|
| - element.isClosure ||
|
| - enclosingElement.isConstructor) {
|
| - kind = "closure";
|
| - name = "<unnamed>";
|
| - } else if (modifiers['static']) {
|
| - kind = 'function';
|
| - } else if (enclosingElement.isClass) {
|
| - kind = 'method';
|
| - }
|
| -
|
| - if (element.isConstructor) {
|
| - name == ""
|
| - ? "${element.enclosingElement.name}"
|
| - : "${element.enclosingElement.name}.${element.name}";
|
| - kind = "constructor";
|
| - }
|
| -
|
| - if (emittedCode != null) {
|
| - FunctionSignature signature = element.functionSignature;
|
| - returnType = signature.type.returnType.toString();
|
| - signature.forEachParameter((parameter) {
|
| - parameters.add({
|
| - 'name': parameter.name,
|
| - 'type': compiler.typesTask
|
| - .getGuaranteedTypeOfElement(parameter).toString(),
|
| - 'declaredType': parameter.node.type.toString()
|
| - });
|
| - });
|
| - inferredReturnType = compiler.typesTask
|
| - .getGuaranteedReturnTypeOfElement(element).toString();
|
| - sideEffects = compiler.world.getSideEffectsOfElement(element).toString();
|
| - code = emittedCode.toString();
|
| - }
|
| -
|
| - if (element is MemberElement) {
|
| - MemberElement member = element as MemberElement;
|
| - for (Element closure in member.nestedClosures) {
|
| - Map<String, dynamic> child = this.process(closure);
|
| - if (child != null) {
|
| - child['kind'] = 'closure';
|
| - children.add(child['id']);
|
| - size += child['size'];
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (size == 0 && !shouldKeep(element)) {
|
| - return null;
|
| - }
|
| -
|
| - int inlinedCount = compiler.dumpInfoTask.inlineCount[element];
|
| - if (inlinedCount == null) {
|
| - inlinedCount = 0;
|
| - }
|
| -
|
| - OutputUnit outputUnit =
|
| - compiler.deferredLoadTask.outputUnitForElement(element);
|
| -
|
| - return {
|
| - 'kind': kind,
|
| - 'name': name,
|
| - 'id': id,
|
| - 'modifiers': modifiers,
|
| - 'children': children,
|
| - 'size': size,
|
| - 'returnType': returnType,
|
| - 'inferredReturnType': inferredReturnType,
|
| - 'parameters': parameters,
|
| - 'sideEffects': sideEffects,
|
| - 'inlinedCount': inlinedCount,
|
| - 'code': code,
|
| - 'type': element.type.toString(),
|
| - 'outputUnit': mapper._outputUnit.add(outputUnit)
|
| - };
|
| - }
|
| -}
|
| -
|
| -class Selection {
|
| - final Element selectedElement;
|
| - final Selector selector;
|
| - Selection(this.selectedElement, this.selector);
|
| -}
|
| -
|
| -class DumpInfoTask extends CompilerTask {
|
| - DumpInfoTask(Compiler compiler)
|
| - : super(compiler);
|
| -
|
| - String name = "Dump Info";
|
| -
|
| - ElementToJsonVisitor infoCollector;
|
| -
|
| - // A set of javascript AST nodes that we care about the size of.
|
| - // This set is automatically populated when registerElementAst()
|
| - // is called.
|
| - final Set<jsAst.Node> _tracking = new Set<jsAst.Node>();
|
| - // A mapping from Dart Elements to Javascript AST Nodes.
|
| - final Map<Element, List<jsAst.Node>> _elementToNodes =
|
| - <Element, List<jsAst.Node>>{};
|
| - // A mapping from Javascript AST Nodes to the size of their
|
| - // pretty-printed contents.
|
| - final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
|
| - final Map<jsAst.Node, int> _nodeBeforeSize = <jsAst.Node, int>{};
|
| - final Map<Element, int> _fieldNameToSize = <Element, int>{};
|
| -
|
| - final Map<Element, Set<Selector>> selectorsFromElement = {};
|
| - final Map<Element, int> inlineCount = <Element, int>{};
|
| - // A mapping from an element to a list of elements that are
|
| - // inlined inside of it.
|
| - final Map<Element, List<Element>> inlineMap = <Element, List<Element>>{};
|
| -
|
| - void registerInlined(Element element, Element inlinedFrom) {
|
| - inlineCount.putIfAbsent(element, () => 0);
|
| - inlineCount[element] += 1;
|
| - inlineMap.putIfAbsent(inlinedFrom, () => new List<Element>());
|
| - inlineMap[inlinedFrom].add(element);
|
| - }
|
| -
|
| - /**
|
| - * Registers that a function uses a selector in the
|
| - * function body
|
| - */
|
| - void elementUsesSelector(Element element, Selector selector) {
|
| - if (compiler.dumpInfo) {
|
| - selectorsFromElement
|
| - .putIfAbsent(element, () => new Set<Selector>())
|
| - .add(selector);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Returns an iterable of [Selection]s that are used by
|
| - * [element]. Each [Selection] contains an element that is
|
| - * used and the selector that selected the element.
|
| - */
|
| - Iterable<Selection> getRetaining(Element element) {
|
| - if (!selectorsFromElement.containsKey(element)) {
|
| - return const <Selection>[];
|
| - } else {
|
| - return selectorsFromElement[element].expand(
|
| - (selector) {
|
| - return compiler.world.allFunctions.filter(selector).map((element) {
|
| - return new Selection(element, selector);
|
| - });
|
| - });
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * A callback that can be called before a jsAst [node] is
|
| - * pretty-printed. The size of the code buffer ([aftersize])
|
| - * is also passed.
|
| - */
|
| - void enteringAst(jsAst.Node node, int beforeSize) {
|
| - if (isTracking(node)) {
|
| - _nodeBeforeSize[node] = beforeSize;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * A callback that can be called after a jsAst [node] is
|
| - * pretty-printed. The size of the code buffer ([aftersize])
|
| - * is also passed.
|
| - */
|
| - void exitingAst(jsAst.Node node, int afterSize) {
|
| - if (isTracking(node)) {
|
| - int diff = afterSize - _nodeBeforeSize[node];
|
| - recordAstSize(node, diff);
|
| - }
|
| - }
|
| -
|
| - // Returns true if we care about tracking the size of
|
| - // this node.
|
| - bool isTracking(jsAst.Node code) {
|
| - if (compiler.dumpInfo) {
|
| - return _tracking.contains(code);
|
| - } else {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - // Registers that a javascript AST node `code` was produced by the
|
| - // dart Element `element`.
|
| - void registerElementAst(Element element, jsAst.Node code) {
|
| - if (compiler.dumpInfo) {
|
| - _elementToNodes
|
| - .putIfAbsent(element, () => new List<jsAst.Node>())
|
| - .add(code);
|
| - _tracking.add(code);
|
| - }
|
| - }
|
| -
|
| - // Records the size of a dart AST node after it has been
|
| - // pretty-printed into the output buffer.
|
| - void recordAstSize(jsAst.Node code, int size) {
|
| - if (compiler.dumpInfo) {
|
| - //TODO: should I be incrementing here instead?
|
| - _nodeToSize[code] = size;
|
| - }
|
| - }
|
| -
|
| - // Field names are treated differently by the dart compiler
|
| - // so they must be recorded seperately.
|
| - void recordFieldNameSize(Element element, int size) {
|
| - _fieldNameToSize[element] = size;
|
| - }
|
| -
|
| - // Returns the size of the source code that
|
| - // was generated for an element. If no source
|
| - // code was produced, return 0.
|
| - int sizeOf(Element element) {
|
| - if (_fieldNameToSize.containsKey(element)) {
|
| - return _fieldNameToSize[element];
|
| - }
|
| - if (_elementToNodes.containsKey(element)) {
|
| - return _elementToNodes[element]
|
| - .map(sizeOfNode)
|
| - .fold(0, (a, b) => a + b);
|
| - } else {
|
| - return 0;
|
| - }
|
| - }
|
| -
|
| - int sizeOfNode(jsAst.Node node) {
|
| - if (_nodeToSize.containsKey(node)) {
|
| - return _nodeToSize[node];
|
| - } else {
|
| - return 0;
|
| - }
|
| - }
|
| -
|
| - StringBuffer codeOf(Element element) {
|
| - List<jsAst.Node> code = _elementToNodes[element];
|
| - if (code == null) return null;
|
| - // Concatenate rendered ASTs.
|
| - StringBuffer sb = new StringBuffer();
|
| - for (jsAst.Node ast in code) {
|
| - sb.writeln(jsAst.prettyPrint(ast, compiler).getText());
|
| - }
|
| - return sb;
|
| - }
|
| -
|
| - void collectInfo() {
|
| - infoCollector = new ElementToJsonVisitor(compiler)..run();
|
| - }
|
| -
|
| - void dumpInfo() {
|
| - measure(() {
|
| - if (infoCollector == null) {
|
| - collectInfo();
|
| - }
|
| -
|
| - StringBuffer jsonBuffer = new StringBuffer();
|
| - dumpInfoJson(jsonBuffer);
|
| - compiler.outputProvider('', 'info.json')
|
| - ..add(jsonBuffer.toString())
|
| - ..close();
|
| - });
|
| - }
|
| -
|
| -
|
| - void dumpInfoJson(StringSink buffer) {
|
| - JsonEncoder encoder = const JsonEncoder();
|
| - DateTime startToJsonTime = new DateTime.now();
|
| -
|
| - Map<String, List<Map<String, String>>> holding =
|
| - <String, List<Map<String, String>>>{};
|
| - for (Element fn in infoCollector.mapper.functions) {
|
| - Iterable<Selection> pulling = getRetaining(fn);
|
| - // Don't bother recording an empty list of dependencies.
|
| - if (pulling.length > 0) {
|
| - String fnId = infoCollector.idOf(fn);
|
| - // Some dart2js builtin functions are not
|
| - // recorded. Don't register these.
|
| - if (fnId != null) {
|
| - holding[fnId] = pulling
|
| - .map((selection) {
|
| - return <String, String>{
|
| - "id": infoCollector.idOf(selection.selectedElement),
|
| - "mask": selection.selector.mask.toString()
|
| - };
|
| - })
|
| - // Filter non-null ids for the same reason as above.
|
| - .where((a) => a['id'] != null)
|
| - .toList();
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Track dependencies that come from inlining.
|
| - for (Element element in inlineMap.keys) {
|
| - String keyId = infoCollector.idOf(element);
|
| - if (keyId != null) {
|
| - for (Element held in inlineMap[element]) {
|
| - String valueId = infoCollector.idOf(held);
|
| - if (valueId != null) {
|
| - holding.putIfAbsent(keyId, () => new List<Map<String, String>>())
|
| - .add(<String, String>{
|
| - "id": valueId,
|
| - "mask": "inlined"
|
| - });
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - List<Map<String, dynamic>> outputUnits =
|
| - new List<Map<String, dynamic>>();
|
| -
|
| - JavaScriptBackend backend = compiler.backend;
|
| -
|
| - for (OutputUnit outputUnit in
|
| - infoCollector.mapper._outputUnit._elementToId.keys) {
|
| - String id = infoCollector.mapper._outputUnit.add(outputUnit);
|
| - outputUnits.add(<String, dynamic> {
|
| - 'id': id,
|
| - 'name': outputUnit.name,
|
| - 'size': backend.emitter.oldEmitter.outputBuffers[outputUnit].length,
|
| - });
|
| - }
|
| -
|
| - Map<String, dynamic> outJson = {
|
| - 'elements': infoCollector.toJson(),
|
| - 'holding': holding,
|
| - 'outputUnits': outputUnits,
|
| - 'dump_version': 3,
|
| - };
|
| -
|
| - Duration toJsonDuration = new DateTime.now().difference(startToJsonTime);
|
| -
|
| - Map<String, dynamic> generalProgramInfo = <String, dynamic> {
|
| - 'size': infoCollector.programSize,
|
| - 'dart2jsVersion': infoCollector.dart2jsVersion,
|
| - 'compilationMoment': new DateTime.now().toString(),
|
| - 'compilationDuration': compiler.totalCompileTime.elapsed.toString(),
|
| - 'toJsonDuration': 0,
|
| - 'dumpInfoDuration': this.timing.toString(),
|
| - 'noSuchMethodEnabled': compiler.enabledNoSuchMethod
|
| - };
|
| -
|
| - outJson['program'] = generalProgramInfo;
|
| -
|
| - ChunkedConversionSink<Object> sink =
|
| - encoder.startChunkedConversion(
|
| - new StringConversionSink.fromStringSink(buffer));
|
| - sink.add(outJson);
|
| - compiler.reportInfo(NO_LOCATION_SPANNABLE,
|
| - const MessageKind(
|
| - "View the dumped .info.json file at "
|
| - "https://dart-lang.github.io/dump-info-visualizer"));
|
| - }
|
| -}
|
|
|