Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: pkg/compiler/lib/src/info/info.dart

Issue 1298553002: dart2js: switch to use dart2js_info/info.dart (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/dump_info.dart ('k') | pkg/compiler/pubspec.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/info/info.dart
diff --git a/pkg/compiler/lib/src/info/info.dart b/pkg/compiler/lib/src/info/info.dart
deleted file mode 100644
index 6a6f747ef7947daccbb3a15331eb78799c800353..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/info/info.dart
+++ /dev/null
@@ -1,745 +0,0 @@
-// Copyright (c) 2015, 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.
-
-/// Data collected by the dump-info task.
-library compiler.src.lib.info;
-
-// Note: this file intentionally doesn't import anything from the compiler. That
-// should make it easier for tools to depend on this library. The idea is that
-// by using this library, tools can consume the information in the same way it
-// is produced by the compiler.
-// TODO(sigmund): make this a proper public API (export this explicitly at the
-// lib folder level.)
-
-/// Common interface to many pieces of information generated by the compiler.
-abstract class Info {
- /// An identifier for the kind of information.
- InfoKind get kind;
-
- /// Name of the element associated with this info.
- String name;
-
- /// An id to uniquely identify this info among infos of the same [kind].
- int get id;
-
- /// A globally unique id combining [kind] and [id] together.
- String get serializedId;
-
- /// Id used by the compiler when instrumenting code for code coverage.
- // TODO(sigmund): It would be nice if we could use the same id for
- // serialization and for coverage. Could we unify them?
- String coverageId;
-
- /// Bytes used in the generated code for the corresponding element.
- int size;
-
- /// Info of the enclosing element.
- Info parent;
-
- /// Serializes the information into a JSON format.
- // TODO(sigmund): refactor and put toJson outside the class, so we can have 2
- // different serializer/deserializers at once.
- Map toJson();
-
- void accept(InfoVisitor visitor);
-}
-
-/// Common information used for most kind of elements.
-// TODO(sigmund): add more:
-// - inputSize: bytes used in the Dart source program
-abstract class BasicInfo implements Info {
- final InfoKind kind;
- final int id;
- String coverageId;
- int size;
- Info parent;
-
- String get serializedId => '${_kindToString(kind)}/$id';
-
- String name;
-
- /// If using deferred libraries, where the element associated with this info
- /// is generated.
- OutputUnitInfo outputUnit;
-
- BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size,
- this.coverageId);
-
- BasicInfo._fromId(String serializedId)
- : kind = _kindFromSerializedId(serializedId),
- id = _idFromSerializedId(serializedId);
-
- Map toJson() {
- var res = {
- 'id': serializedId,
- 'kind': _kindToString(kind),
- 'name': name,
- 'size': size,
- };
- // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in
- // the main output unit by default).
- if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId;
- if (coverageId != null) res['coverageId'] = coverageId;
- if (parent != null) res['parent'] = parent.serializedId;
- return res;
- }
-
- String toString() => '$serializedId $name [$size]';
-}
-
-/// Info associated with elements containing executable code (like fields and
-/// methods)
-abstract class CodeInfo implements Info {
- /// How does this function or field depend on others.
- final List<DependencyInfo> uses = <DependencyInfo>[];
-}
-
-
-/// The entire information produced while compiling a program.
-class AllInfo {
- /// Summary information about the program.
- ProgramInfo program;
-
- /// Information about each library processed by the compiler.
- List<LibraryInfo> libraries = <LibraryInfo>[];
-
- /// Information about each function (includes methods and getters in any
- /// library)
- List<FunctionInfo> functions = <FunctionInfo>[];
-
- /// Information about type defs in the program.
- List<TypedefInfo> typedefs = <TypedefInfo>[];
-
- /// Information about each class (in any library).
- List<ClassInfo> classes = <ClassInfo>[];
-
- /// Information about fields (in any class).
- List<FieldInfo> fields = <FieldInfo>[];
-
- /// Information about output units (should be just one entry if not using
- /// deferred loading).
- List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[];
-
- /// Details about all deferred imports and what files would be loaded when the
- /// import is resolved.
- // TODO(sigmund): use a different format for dump-info. This currently emits
- // the same map that is created for the `--deferred-map` flag.
- Map<String, Map<String, dynamic>> deferredFiles;
-
- /// A new representation of dependencies form one info to another. An entry in
- /// this map indicates that an Info depends on another (e.g. a function
- /// invokes another). Please note that the data in this field might not be
- /// accurate yet (this is work in progress).
- Map<Info, List<Info>> dependencies = {};
-
- /// Major version indicating breaking changes in the format. A new version
- /// means that an old deserialization algorithm will not work with the new
- /// format.
- final int version = 3;
-
- /// Minor version indicating non-breaking changes in the format. A change in
- /// this version number means that the json parsing in this library from a
- /// previous will continue to work after the change. This is typically
- /// increased when adding new entries to the file format.
- // Note: the dump-info.viewer app was written using a json parser version 3.2.
- final int minorVersion = 5;
-
- AllInfo();
-
- static AllInfo parseFromJson(Map map) => new _ParseHelper().parseAll(map);
-
- Map _listAsJsonMap(List<Info> list) {
- var map = <String, Map>{};
- for (var info in list) {
- map['${info.id}'] = info.toJson();
- }
- return map;
- }
-
- Map _extractHoldingInfo() {
- var map = <String, List>{};
- void helper(CodeInfo info) {
- if (info.uses.isEmpty) return;
- map[info.serializedId] = info.uses.map((u) => u.toJson()).toList();
- }
- functions.forEach(helper);
- fields.forEach(helper);
- return map;
- }
-
- Map _extractDependencies() {
- var map = <String, List>{};
- dependencies.forEach((k, v) {
- map[k.serializedId] = v.map((i) => i.serializedId).toList();
- });
- return map;
- }
-
- Map toJson() => {
- 'elements': {
- 'library': _listAsJsonMap(libraries),
- 'class': _listAsJsonMap(classes),
- 'function': _listAsJsonMap(functions),
- 'typedef': _listAsJsonMap(typedefs),
- 'field': _listAsJsonMap(fields),
- },
- 'holding': _extractHoldingInfo(),
- 'dependencies': _extractDependencies(),
- 'outputUnits': outputUnits.map((u) => u.toJson()).toList(),
- 'dump_version': version,
- 'deferredFiles': deferredFiles,
- 'dump_minor_version': '$minorVersion',
- // TODO(sigmund): change viewer to accept an int?
- 'program': program.toJson(),
- };
-
- void accept(InfoVisitor visitor) => visitor.visitAll(this);
-}
-
-class ProgramInfo {
- int size;
- String dart2jsVersion;
- DateTime compilationMoment;
- Duration compilationDuration;
- // TODO(sigmund): use Duration.
- int toJsonDuration;
- int dumpInfoDuration;
- bool noSuchMethodEnabled;
- bool minified;
-
- ProgramInfo(
- {this.size,
- this.dart2jsVersion,
- this.compilationMoment,
- this.compilationDuration,
- this.toJsonDuration,
- this.dumpInfoDuration,
- this.noSuchMethodEnabled,
- this.minified});
-
- Map toJson() => {
- 'size': size,
- 'dart2jsVersion': dart2jsVersion,
- 'compilationMoment': '$compilationMoment',
- 'compilationDuration': '${compilationDuration}',
- 'toJsonDuration': toJsonDuration,
- 'dumpInfoDuration': '$dumpInfoDuration',
- 'noSuchMethodEnabled': noSuchMethodEnabled,
- 'minified': minified,
- };
-
- void accept(InfoVisitor visitor) => visitor.visitProgram(this);
-}
-
-// TODO(sigmund): add unit tests.
-class _ParseHelper {
- Map<String, Info> registry = {};
-
- AllInfo parseAll(Map json) {
- var result = new AllInfo();
- var elements = json['elements'];
- result.libraries.addAll(elements['library'].values.map(parseLibrary));
- result.classes.addAll(elements['class'].values.map(parseClass));
- result.functions.addAll(elements['function'].values.map(parseFunction));
- result.fields.addAll(elements['field'].values.map(parseField));
- result.typedefs.addAll(elements['typedef'].values.map(parseTypedef));
-
- var idMap = {};
- for (var f in result.functions) {
- idMap[f.serializedId] = f;
- }
- for (var f in result.fields) {
- idMap[f.serializedId] = f;
- }
-
- json['holding'].forEach((k, deps) {
- var src = idMap[k];
- assert (src != null);
- for (var dep in deps) {
- var target = idMap[dep['id']];
- assert (target != null);
- src.uses.add(new DependencyInfo(target, dep['mask']));
- }
- });
-
- json['dependencies']?.forEach((k, deps) {
- result.dependencies[idMap[k]] = deps.map((d) => idMap[d]).toList();
- });
-
- result.program = parseProgram(json['program']);
- // todo: version, etc
- return result;
- }
-
- LibraryInfo parseLibrary(Map json) {
- LibraryInfo result = parseId(json['id']);
- result..name = json['name']
- ..uri = Uri.parse(json['canonicalUri'])
- ..outputUnit = parseId(json['outputUnit'])
- ..size = json['size'];
- for (var child in json['children'].map(parseId)) {
- if (child is FunctionInfo) {
- result.topLevelFunctions.add(child);
- } else if (child is FieldInfo) {
- result.topLevelVariables.add(child);
- } else if (child is ClassInfo) {
- result.classes.add(child);
- } else {
- assert(child is TypedefInfo);
- result.typedefs.add(child);
- }
- }
- return result;
- }
-
- ClassInfo parseClass(Map json) {
- ClassInfo result = parseId(json['id']);
- result..name = json['name']
- ..parent = parseId(json['parent'])
- ..outputUnit = parseId(json['outputUnit'])
- ..size = json['size']
- ..isAbstract = json['modifiers']['abstract'] == true;
- assert(result is ClassInfo);
- for (var child in json['children'].map(parseId)) {
- if (child is FunctionInfo) {
- result.functions.add(child);
- } else {
- assert(child is FieldInfo);
- result.fields.add(child);
- }
- }
- return result;
- }
-
- FieldInfo parseField(Map json) {
- FieldInfo result = parseId(json['id']);
- return result..name = json['name']
- ..parent = parseId(json['parent'])
- ..coverageId = json['coverageId']
- ..outputUnit = parseId(json['outputUnit'])
- ..size = json['size']
- ..type = json['type']
- ..inferredType = json['inferredType']
- ..code = json['code']
- ..closures = json['children'].map(parseId).toList();
- }
-
- TypedefInfo parseTypedef(Map json) {
- TypedefInfo result = parseId(json['id']);
- return result..name = json['name']
- ..parent = parseId(json['parent'])
- ..type = json['type']
- ..size = 0;
- }
-
- ProgramInfo parseProgram(Map json) =>
- new ProgramInfo()..size = json['size'];
-
- FunctionInfo parseFunction(Map json) {
- FunctionInfo result = parseId(json['id']);
- return result..name = json['name']
- ..parent = parseId(json['parent'])
- ..coverageId = json['coverageId']
- ..outputUnit = parseId(json['outputUnit'])
- ..size = json['size']
- ..type = json['type']
- ..returnType = json['returnType']
- ..inferredReturnType = json['inferredReturnType']
- ..parameters = json['parameters'].map(parseParameter).toList()
- ..code = json['code']
- ..sideEffects = json['sideEffects']
- ..modifiers = parseModifiers(json['modifiers'])
- ..closures = json['children'].map(parseId).toList();
- }
-
- ParameterInfo parseParameter(Map json) =>
- new ParameterInfo(json['name'], json['type'], json['declaredType']);
-
- FunctionModifiers parseModifiers(Map<String, bool> json) {
- return new FunctionModifiers(
- isStatic: json['static'] == true,
- isConst: json['const'] == true,
- isFactory: json['factory'] == true,
- isExternal: json['external'] == true);
- }
-
- Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () {
- if (serializedId == null) {
- return null;
- } else if (serializedId.startsWith('function/')) {
- return new FunctionInfo._(serializedId);
- } else if (serializedId.startsWith('library/')) {
- return new LibraryInfo._(serializedId);
- } else if (serializedId.startsWith('class/')) {
- return new ClassInfo._(serializedId);
- } else if (serializedId.startsWith('field/')) {
- return new FieldInfo._(serializedId);
- } else if (serializedId.startsWith('typedef/')) {
- return new TypedefInfo._(serializedId);
- } else if (serializedId.startsWith('outputUnit/')) {
- return new OutputUnitInfo._(serializedId);
- }
- assert(false);
- });
-}
-
-/// Info associated with a library element.
-class LibraryInfo extends BasicInfo {
- /// Canonical uri that identifies the library.
- Uri uri;
-
- /// Top level functions defined within the library.
- final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];
-
- /// Top level fields defined within the library.
- final List<FieldInfo> topLevelVariables = <FieldInfo>[];
-
- /// Classes defined within the library.
- final List<ClassInfo> classes = <ClassInfo>[];
-
- /// Typedefs defined within the library.
- final List<TypedefInfo> typedefs = <TypedefInfo>[];
-
- static int _id = 0;
-
- /// Whether there is any information recorded for this library.
- bool get isEmpty =>
- topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;
-
- LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
- : super(InfoKind.library, _id++, name, outputUnit, size, null);
-
- LibraryInfo._(String serializedId) : super._fromId(serializedId);
-
- Map toJson() => super.toJson()
- ..addAll({
- 'children': []
- ..addAll(topLevelFunctions.map((f) => f.serializedId))
- ..addAll(topLevelVariables.map((v) => v.serializedId))
- ..addAll(classes.map((c) => c.serializedId))
- ..addAll(typedefs.map((t) => t.serializedId)),
- 'canonicalUri': '$uri',
- });
-
- void accept(InfoVisitor visitor) => visitor.visitLibrary(this);
-}
-
-/// Information about an output unit. Normally there is just one for the entire
-/// program unless the application uses deferred imports, in which case there
-/// would be an additional output unit per deferred chunk.
-class OutputUnitInfo extends BasicInfo {
- static int _ids = 0;
- OutputUnitInfo(String name, int size)
- : super(InfoKind.outputUnit, _ids++, name, null, size, null);
-
- OutputUnitInfo._(String serializedId) : super._fromId(serializedId);
-
- void accept(InfoVisitor visitor) => visitor.visitOutput(this);
-}
-
-/// Information about a class element.
-class ClassInfo extends BasicInfo {
- /// Whether the class is abstract.
- bool isAbstract;
-
- // TODO(sigmund): split static vs instance vs closures
- /// Functions (static or instance) defined in the class.
- final List<FunctionInfo> functions = <FunctionInfo>[];
-
- /// Fields defined in the class.
- // TODO(sigmund): currently appears to only be populated with instance fields,
- // but this should be fixed.
- final List<FieldInfo> fields = <FieldInfo>[];
- static int _ids = 0;
-
- ClassInfo(
- {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
- : super(InfoKind.clazz, _ids++, name, outputUnit, size, null);
-
- ClassInfo._(String serializedId) : super._fromId(serializedId);
-
- Map toJson() => super.toJson()
- ..addAll({
- // TODO(sigmund): change format, include only when abstract is true.
- 'modifiers': {'abstract': isAbstract},
- 'children': []
- ..addAll(fields.map((f) => f.serializedId))
- ..addAll(functions.map((m) => m.serializedId))
- });
-
- void accept(InfoVisitor visitor) => visitor.visitClass(this);
-}
-
-/// Information about a field element.
-class FieldInfo extends BasicInfo with CodeInfo {
- /// The type of the field.
- String type;
-
- /// The type inferred by dart2js's whole program analysis
- String inferredType;
-
- /// Nested closures seen in the field initializer.
- List<FunctionInfo> closures;
-
- /// The actual generated code for the field.
- String code;
-
- static int _ids = 0;
- FieldInfo(
- {String name,
- String coverageId,
- int size: 0,
- this.type,
- this.inferredType,
- this.closures,
- this.code,
- OutputUnitInfo outputUnit})
- : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId);
-
- FieldInfo._(String serializedId) : super._fromId(serializedId);
-
- Map toJson() => super.toJson()
- ..addAll({
- 'children': closures.map((i) => i.serializedId).toList(),
- 'inferredType': inferredType,
- 'code': code,
- 'type': type,
- });
-
- void accept(InfoVisitor visitor) => visitor.visitField(this);
-}
-
-/// Information about a typedef declaration.
-class TypedefInfo extends BasicInfo {
- /// The declared type.
- String type;
-
- static int _ids = 0;
- TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
- : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null);
-
- TypedefInfo._(String serializedId) : super._fromId(serializedId);
-
- Map toJson() => super.toJson()..['type'] = '$type';
-
- void accept(InfoVisitor visitor) => visitor.visitTypedef(this);
-}
-
-/// Information about a function or method.
-class FunctionInfo extends BasicInfo with CodeInfo {
- static const int TOP_LEVEL_FUNCTION_KIND = 0;
- static const int CLOSURE_FUNCTION_KIND = 1;
- static const int METHOD_FUNCTION_KIND = 2;
- static const int CONSTRUCTOR_FUNCTION_KIND = 3;
- static int _ids = 0;
-
- /// Kind of function (top-level function, closure, method, or constructor).
- int functionKind;
-
- /// Modifiers applied to this function.
- FunctionModifiers modifiers;
-
- /// Nested closures that appear within the body of this function.
- List<FunctionInfo> closures;
-
- /// The type of this function.
- String type;
-
- /// The declared return type.
- String returnType;
-
- /// The inferred return type.
- String inferredReturnType;
-
- /// Name and type information for each parameter.
- List<ParameterInfo> parameters;
-
- /// Side-effects.
- // TODO(sigmund): serialize more precisely, not just a string representation.
- String sideEffects;
-
- /// How many function calls were inlined into this function.
- int inlinedCount;
-
- /// The actual generated code.
- String code;
-
- FunctionInfo(
- {String name,
- String coverageId,
- OutputUnitInfo outputUnit,
- int size: 0,
- this.functionKind,
- this.modifiers,
- this.closures,
- this.type,
- this.returnType,
- this.inferredReturnType,
- this.parameters,
- this.sideEffects,
- this.inlinedCount,
- this.code})
- : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId);
-
- FunctionInfo._(String serializedId) : super._fromId(serializedId);
-
- Map toJson() => super.toJson()
- ..addAll({
- 'children': closures.map((i) => i.serializedId).toList(),
- 'modifiers': modifiers.toJson(),
- 'returnType': returnType,
- 'inferredReturnType': inferredReturnType,
- 'parameters': parameters.map((p) => p.toJson()).toList(),
- 'sideEffects': sideEffects,
- 'inlinedCount': inlinedCount,
- 'code': code,
- 'type': type,
- // Note: version 3.2 of dump-info serializes `uses` in a section called
- // `holding` at the top-level.
- });
-
- void accept(InfoVisitor visitor) => visitor.visitFunction(this);
-}
-
-/// Information about how a dependency is used.
-class DependencyInfo {
- /// The dependency, either a FunctionInfo or FieldInfo.
- final Info target;
-
- /// Either a selector mask indicating how this is used, or 'inlined'.
- // TODO(sigmund): split mask into an enum or something more precise to really
- // describe the dependencies in detail.
- final String mask;
-
- DependencyInfo(this.target, this.mask);
-
- Map toJson() => {'id': target.serializedId, 'mask': mask};
-}
-
-/// Name and type information about a function parameter.
-class ParameterInfo {
- final String name;
- final String type;
- final String declaredType;
-
- ParameterInfo(this.name, this.type, this.declaredType);
-
- Map toJson() => {'name': name, 'type': type, 'declaredType': declaredType};
-}
-
-/// Modifiers that may apply to methods.
-class FunctionModifiers {
- final bool isStatic;
- final bool isConst;
- final bool isFactory;
- final bool isExternal;
-
- FunctionModifiers(
- {this.isStatic: false,
- this.isConst: false,
- this.isFactory: false,
- this.isExternal: false});
-
- // TODO(sigmund): exclude false values (requires bumping the format version):
- // Map toJson() {
- // var res = <String, bool>{};
- // if (isStatic) res['static'] = true;
- // if (isConst) res['const'] = true;
- // if (isFactory) res['factory'] = true;
- // if (isExternal) res['external'] = true;
- // return res;
- // }
- Map toJson() => {
- 'static': isStatic,
- 'const': isConst,
- 'factory': isFactory,
- 'external': isExternal,
- };
-}
-
-/// Possible values of the `kind` field in the serialied infos.
-enum InfoKind {
- library,
- clazz,
- function,
- field,
- outputUnit,
- typedef,
-}
-
-String _kindToString(InfoKind kind) {
- switch(kind) {
- case InfoKind.library: return 'library';
- case InfoKind.clazz: return 'class';
- case InfoKind.function: return 'function';
- case InfoKind.field: return 'field';
- case InfoKind.outputUnit: return 'outputUnit';
- case InfoKind.typedef: return 'typedef';
- default: return null;
- }
-}
-
-int _idFromSerializedId(String serializedId) =>
- int.parse(serializedId.substring(serializedId.indexOf('/') + 1));
-
-InfoKind _kindFromSerializedId(String serializedId) =>
- _kindFromString(serializedId.substring(0, serializedId.indexOf('/')));
-
-InfoKind _kindFromString(String kind) {
- switch(kind) {
- case 'library': return InfoKind.library;
- case 'class': return InfoKind.clazz;
- case 'function': return InfoKind.function;
- case 'field': return InfoKind.field;
- case 'outputUnit': return InfoKind.outputUnit;
- case 'typedef': return InfoKind.typedef;
- default: return null;
- }
-}
-
-/// A simple visitor for information produced by the dart2js compiler.
-class InfoVisitor {
- visitAll(AllInfo info) {}
- visitProgram(ProgramInfo info) {}
- visitLibrary(LibraryInfo info) {}
- visitClass(ClassInfo info) {}
- visitField(FieldInfo info) {}
- visitFunction(FunctionInfo info) {}
- visitTypedef(TypedefInfo info) {}
- visitOutput(OutputUnitInfo info) {}
-}
-
-/// A visitor that recursively walks each portion of the program. Because the
-/// info representation is redundant, this visitor only walks the structure of
-/// the program and skips some redundant links. For example, even though
-/// 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 {
- visitAll(AllInfo info) {
- // Note: we don't visit functions, fields, classes, and typedefs because
- // they are reachable from the library info.
- info.libraries.forEach(visitLibrary);
- }
-
- visitLibrary(LibraryInfo info) {
- info.topLevelFunctions.forEach(visitFunction);
- info.topLevelVariables.forEach(visitField);
- info.classes.forEach(visitClass);
- info.typedefs.forEach(visitTypedef);
- }
-
- visitClass(ClassInfo info) {
- info.functions.forEach(visitFunction);
- info.fields.forEach(visitField);
- }
-
- visitField(FieldInfo info) {
- info.closures.forEach(visitFunction);
- }
-
- visitFunction(FunctionInfo info) {
- info.closures.forEach(visitFunction);
- }
-}
« no previous file with comments | « pkg/compiler/lib/src/dump_info.dart ('k') | pkg/compiler/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698