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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Data collected by the dump-info task.
6 library compiler.src.lib.info;
7
8 // Note: this file intentionally doesn't import anything from the compiler. That
9 // should make it easier for tools to depend on this library. The idea is that
10 // by using this library, tools can consume the information in the same way it
11 // is produced by the compiler.
12 // TODO(sigmund): make this a proper public API (export this explicitly at the
13 // lib folder level.)
14
15 /// Common interface to many pieces of information generated by the compiler.
16 abstract class Info {
17 /// An identifier for the kind of information.
18 InfoKind get kind;
19
20 /// Name of the element associated with this info.
21 String name;
22
23 /// An id to uniquely identify this info among infos of the same [kind].
24 int get id;
25
26 /// A globally unique id combining [kind] and [id] together.
27 String get serializedId;
28
29 /// Id used by the compiler when instrumenting code for code coverage.
30 // TODO(sigmund): It would be nice if we could use the same id for
31 // serialization and for coverage. Could we unify them?
32 String coverageId;
33
34 /// Bytes used in the generated code for the corresponding element.
35 int size;
36
37 /// Info of the enclosing element.
38 Info parent;
39
40 /// Serializes the information into a JSON format.
41 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2
42 // different serializer/deserializers at once.
43 Map toJson();
44
45 void accept(InfoVisitor visitor);
46 }
47
48 /// Common information used for most kind of elements.
49 // TODO(sigmund): add more:
50 // - inputSize: bytes used in the Dart source program
51 abstract class BasicInfo implements Info {
52 final InfoKind kind;
53 final int id;
54 String coverageId;
55 int size;
56 Info parent;
57
58 String get serializedId => '${_kindToString(kind)}/$id';
59
60 String name;
61
62 /// If using deferred libraries, where the element associated with this info
63 /// is generated.
64 OutputUnitInfo outputUnit;
65
66 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size,
67 this.coverageId);
68
69 BasicInfo._fromId(String serializedId)
70 : kind = _kindFromSerializedId(serializedId),
71 id = _idFromSerializedId(serializedId);
72
73 Map toJson() {
74 var res = {
75 'id': serializedId,
76 'kind': _kindToString(kind),
77 'name': name,
78 'size': size,
79 };
80 // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in
81 // the main output unit by default).
82 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId;
83 if (coverageId != null) res['coverageId'] = coverageId;
84 if (parent != null) res['parent'] = parent.serializedId;
85 return res;
86 }
87
88 String toString() => '$serializedId $name [$size]';
89 }
90
91 /// Info associated with elements containing executable code (like fields and
92 /// methods)
93 abstract class CodeInfo implements Info {
94 /// How does this function or field depend on others.
95 final List<DependencyInfo> uses = <DependencyInfo>[];
96 }
97
98
99 /// The entire information produced while compiling a program.
100 class AllInfo {
101 /// Summary information about the program.
102 ProgramInfo program;
103
104 /// Information about each library processed by the compiler.
105 List<LibraryInfo> libraries = <LibraryInfo>[];
106
107 /// Information about each function (includes methods and getters in any
108 /// library)
109 List<FunctionInfo> functions = <FunctionInfo>[];
110
111 /// Information about type defs in the program.
112 List<TypedefInfo> typedefs = <TypedefInfo>[];
113
114 /// Information about each class (in any library).
115 List<ClassInfo> classes = <ClassInfo>[];
116
117 /// Information about fields (in any class).
118 List<FieldInfo> fields = <FieldInfo>[];
119
120 /// Information about output units (should be just one entry if not using
121 /// deferred loading).
122 List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[];
123
124 /// Details about all deferred imports and what files would be loaded when the
125 /// import is resolved.
126 // TODO(sigmund): use a different format for dump-info. This currently emits
127 // the same map that is created for the `--deferred-map` flag.
128 Map<String, Map<String, dynamic>> deferredFiles;
129
130 /// A new representation of dependencies form one info to another. An entry in
131 /// this map indicates that an Info depends on another (e.g. a function
132 /// invokes another). Please note that the data in this field might not be
133 /// accurate yet (this is work in progress).
134 Map<Info, List<Info>> dependencies = {};
135
136 /// Major version indicating breaking changes in the format. A new version
137 /// means that an old deserialization algorithm will not work with the new
138 /// format.
139 final int version = 3;
140
141 /// Minor version indicating non-breaking changes in the format. A change in
142 /// this version number means that the json parsing in this library from a
143 /// previous will continue to work after the change. This is typically
144 /// increased when adding new entries to the file format.
145 // Note: the dump-info.viewer app was written using a json parser version 3.2.
146 final int minorVersion = 5;
147
148 AllInfo();
149
150 static AllInfo parseFromJson(Map map) => new _ParseHelper().parseAll(map);
151
152 Map _listAsJsonMap(List<Info> list) {
153 var map = <String, Map>{};
154 for (var info in list) {
155 map['${info.id}'] = info.toJson();
156 }
157 return map;
158 }
159
160 Map _extractHoldingInfo() {
161 var map = <String, List>{};
162 void helper(CodeInfo info) {
163 if (info.uses.isEmpty) return;
164 map[info.serializedId] = info.uses.map((u) => u.toJson()).toList();
165 }
166 functions.forEach(helper);
167 fields.forEach(helper);
168 return map;
169 }
170
171 Map _extractDependencies() {
172 var map = <String, List>{};
173 dependencies.forEach((k, v) {
174 map[k.serializedId] = v.map((i) => i.serializedId).toList();
175 });
176 return map;
177 }
178
179 Map toJson() => {
180 'elements': {
181 'library': _listAsJsonMap(libraries),
182 'class': _listAsJsonMap(classes),
183 'function': _listAsJsonMap(functions),
184 'typedef': _listAsJsonMap(typedefs),
185 'field': _listAsJsonMap(fields),
186 },
187 'holding': _extractHoldingInfo(),
188 'dependencies': _extractDependencies(),
189 'outputUnits': outputUnits.map((u) => u.toJson()).toList(),
190 'dump_version': version,
191 'deferredFiles': deferredFiles,
192 'dump_minor_version': '$minorVersion',
193 // TODO(sigmund): change viewer to accept an int?
194 'program': program.toJson(),
195 };
196
197 void accept(InfoVisitor visitor) => visitor.visitAll(this);
198 }
199
200 class ProgramInfo {
201 int size;
202 String dart2jsVersion;
203 DateTime compilationMoment;
204 Duration compilationDuration;
205 // TODO(sigmund): use Duration.
206 int toJsonDuration;
207 int dumpInfoDuration;
208 bool noSuchMethodEnabled;
209 bool minified;
210
211 ProgramInfo(
212 {this.size,
213 this.dart2jsVersion,
214 this.compilationMoment,
215 this.compilationDuration,
216 this.toJsonDuration,
217 this.dumpInfoDuration,
218 this.noSuchMethodEnabled,
219 this.minified});
220
221 Map toJson() => {
222 'size': size,
223 'dart2jsVersion': dart2jsVersion,
224 'compilationMoment': '$compilationMoment',
225 'compilationDuration': '${compilationDuration}',
226 'toJsonDuration': toJsonDuration,
227 'dumpInfoDuration': '$dumpInfoDuration',
228 'noSuchMethodEnabled': noSuchMethodEnabled,
229 'minified': minified,
230 };
231
232 void accept(InfoVisitor visitor) => visitor.visitProgram(this);
233 }
234
235 // TODO(sigmund): add unit tests.
236 class _ParseHelper {
237 Map<String, Info> registry = {};
238
239 AllInfo parseAll(Map json) {
240 var result = new AllInfo();
241 var elements = json['elements'];
242 result.libraries.addAll(elements['library'].values.map(parseLibrary));
243 result.classes.addAll(elements['class'].values.map(parseClass));
244 result.functions.addAll(elements['function'].values.map(parseFunction));
245 result.fields.addAll(elements['field'].values.map(parseField));
246 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef));
247
248 var idMap = {};
249 for (var f in result.functions) {
250 idMap[f.serializedId] = f;
251 }
252 for (var f in result.fields) {
253 idMap[f.serializedId] = f;
254 }
255
256 json['holding'].forEach((k, deps) {
257 var src = idMap[k];
258 assert (src != null);
259 for (var dep in deps) {
260 var target = idMap[dep['id']];
261 assert (target != null);
262 src.uses.add(new DependencyInfo(target, dep['mask']));
263 }
264 });
265
266 json['dependencies']?.forEach((k, deps) {
267 result.dependencies[idMap[k]] = deps.map((d) => idMap[d]).toList();
268 });
269
270 result.program = parseProgram(json['program']);
271 // todo: version, etc
272 return result;
273 }
274
275 LibraryInfo parseLibrary(Map json) {
276 LibraryInfo result = parseId(json['id']);
277 result..name = json['name']
278 ..uri = Uri.parse(json['canonicalUri'])
279 ..outputUnit = parseId(json['outputUnit'])
280 ..size = json['size'];
281 for (var child in json['children'].map(parseId)) {
282 if (child is FunctionInfo) {
283 result.topLevelFunctions.add(child);
284 } else if (child is FieldInfo) {
285 result.topLevelVariables.add(child);
286 } else if (child is ClassInfo) {
287 result.classes.add(child);
288 } else {
289 assert(child is TypedefInfo);
290 result.typedefs.add(child);
291 }
292 }
293 return result;
294 }
295
296 ClassInfo parseClass(Map json) {
297 ClassInfo result = parseId(json['id']);
298 result..name = json['name']
299 ..parent = parseId(json['parent'])
300 ..outputUnit = parseId(json['outputUnit'])
301 ..size = json['size']
302 ..isAbstract = json['modifiers']['abstract'] == true;
303 assert(result is ClassInfo);
304 for (var child in json['children'].map(parseId)) {
305 if (child is FunctionInfo) {
306 result.functions.add(child);
307 } else {
308 assert(child is FieldInfo);
309 result.fields.add(child);
310 }
311 }
312 return result;
313 }
314
315 FieldInfo parseField(Map json) {
316 FieldInfo result = parseId(json['id']);
317 return result..name = json['name']
318 ..parent = parseId(json['parent'])
319 ..coverageId = json['coverageId']
320 ..outputUnit = parseId(json['outputUnit'])
321 ..size = json['size']
322 ..type = json['type']
323 ..inferredType = json['inferredType']
324 ..code = json['code']
325 ..closures = json['children'].map(parseId).toList();
326 }
327
328 TypedefInfo parseTypedef(Map json) {
329 TypedefInfo result = parseId(json['id']);
330 return result..name = json['name']
331 ..parent = parseId(json['parent'])
332 ..type = json['type']
333 ..size = 0;
334 }
335
336 ProgramInfo parseProgram(Map json) =>
337 new ProgramInfo()..size = json['size'];
338
339 FunctionInfo parseFunction(Map json) {
340 FunctionInfo result = parseId(json['id']);
341 return result..name = json['name']
342 ..parent = parseId(json['parent'])
343 ..coverageId = json['coverageId']
344 ..outputUnit = parseId(json['outputUnit'])
345 ..size = json['size']
346 ..type = json['type']
347 ..returnType = json['returnType']
348 ..inferredReturnType = json['inferredReturnType']
349 ..parameters = json['parameters'].map(parseParameter).toList()
350 ..code = json['code']
351 ..sideEffects = json['sideEffects']
352 ..modifiers = parseModifiers(json['modifiers'])
353 ..closures = json['children'].map(parseId).toList();
354 }
355
356 ParameterInfo parseParameter(Map json) =>
357 new ParameterInfo(json['name'], json['type'], json['declaredType']);
358
359 FunctionModifiers parseModifiers(Map<String, bool> json) {
360 return new FunctionModifiers(
361 isStatic: json['static'] == true,
362 isConst: json['const'] == true,
363 isFactory: json['factory'] == true,
364 isExternal: json['external'] == true);
365 }
366
367 Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () {
368 if (serializedId == null) {
369 return null;
370 } else if (serializedId.startsWith('function/')) {
371 return new FunctionInfo._(serializedId);
372 } else if (serializedId.startsWith('library/')) {
373 return new LibraryInfo._(serializedId);
374 } else if (serializedId.startsWith('class/')) {
375 return new ClassInfo._(serializedId);
376 } else if (serializedId.startsWith('field/')) {
377 return new FieldInfo._(serializedId);
378 } else if (serializedId.startsWith('typedef/')) {
379 return new TypedefInfo._(serializedId);
380 } else if (serializedId.startsWith('outputUnit/')) {
381 return new OutputUnitInfo._(serializedId);
382 }
383 assert(false);
384 });
385 }
386
387 /// Info associated with a library element.
388 class LibraryInfo extends BasicInfo {
389 /// Canonical uri that identifies the library.
390 Uri uri;
391
392 /// Top level functions defined within the library.
393 final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];
394
395 /// Top level fields defined within the library.
396 final List<FieldInfo> topLevelVariables = <FieldInfo>[];
397
398 /// Classes defined within the library.
399 final List<ClassInfo> classes = <ClassInfo>[];
400
401 /// Typedefs defined within the library.
402 final List<TypedefInfo> typedefs = <TypedefInfo>[];
403
404 static int _id = 0;
405
406 /// Whether there is any information recorded for this library.
407 bool get isEmpty =>
408 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;
409
410 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
411 : super(InfoKind.library, _id++, name, outputUnit, size, null);
412
413 LibraryInfo._(String serializedId) : super._fromId(serializedId);
414
415 Map toJson() => super.toJson()
416 ..addAll({
417 'children': []
418 ..addAll(topLevelFunctions.map((f) => f.serializedId))
419 ..addAll(topLevelVariables.map((v) => v.serializedId))
420 ..addAll(classes.map((c) => c.serializedId))
421 ..addAll(typedefs.map((t) => t.serializedId)),
422 'canonicalUri': '$uri',
423 });
424
425 void accept(InfoVisitor visitor) => visitor.visitLibrary(this);
426 }
427
428 /// Information about an output unit. Normally there is just one for the entire
429 /// program unless the application uses deferred imports, in which case there
430 /// would be an additional output unit per deferred chunk.
431 class OutputUnitInfo extends BasicInfo {
432 static int _ids = 0;
433 OutputUnitInfo(String name, int size)
434 : super(InfoKind.outputUnit, _ids++, name, null, size, null);
435
436 OutputUnitInfo._(String serializedId) : super._fromId(serializedId);
437
438 void accept(InfoVisitor visitor) => visitor.visitOutput(this);
439 }
440
441 /// Information about a class element.
442 class ClassInfo extends BasicInfo {
443 /// Whether the class is abstract.
444 bool isAbstract;
445
446 // TODO(sigmund): split static vs instance vs closures
447 /// Functions (static or instance) defined in the class.
448 final List<FunctionInfo> functions = <FunctionInfo>[];
449
450 /// Fields defined in the class.
451 // TODO(sigmund): currently appears to only be populated with instance fields,
452 // but this should be fixed.
453 final List<FieldInfo> fields = <FieldInfo>[];
454 static int _ids = 0;
455
456 ClassInfo(
457 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
458 : super(InfoKind.clazz, _ids++, name, outputUnit, size, null);
459
460 ClassInfo._(String serializedId) : super._fromId(serializedId);
461
462 Map toJson() => super.toJson()
463 ..addAll({
464 // TODO(sigmund): change format, include only when abstract is true.
465 'modifiers': {'abstract': isAbstract},
466 'children': []
467 ..addAll(fields.map((f) => f.serializedId))
468 ..addAll(functions.map((m) => m.serializedId))
469 });
470
471 void accept(InfoVisitor visitor) => visitor.visitClass(this);
472 }
473
474 /// Information about a field element.
475 class FieldInfo extends BasicInfo with CodeInfo {
476 /// The type of the field.
477 String type;
478
479 /// The type inferred by dart2js's whole program analysis
480 String inferredType;
481
482 /// Nested closures seen in the field initializer.
483 List<FunctionInfo> closures;
484
485 /// The actual generated code for the field.
486 String code;
487
488 static int _ids = 0;
489 FieldInfo(
490 {String name,
491 String coverageId,
492 int size: 0,
493 this.type,
494 this.inferredType,
495 this.closures,
496 this.code,
497 OutputUnitInfo outputUnit})
498 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId);
499
500 FieldInfo._(String serializedId) : super._fromId(serializedId);
501
502 Map toJson() => super.toJson()
503 ..addAll({
504 'children': closures.map((i) => i.serializedId).toList(),
505 'inferredType': inferredType,
506 'code': code,
507 'type': type,
508 });
509
510 void accept(InfoVisitor visitor) => visitor.visitField(this);
511 }
512
513 /// Information about a typedef declaration.
514 class TypedefInfo extends BasicInfo {
515 /// The declared type.
516 String type;
517
518 static int _ids = 0;
519 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
520 : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null);
521
522 TypedefInfo._(String serializedId) : super._fromId(serializedId);
523
524 Map toJson() => super.toJson()..['type'] = '$type';
525
526 void accept(InfoVisitor visitor) => visitor.visitTypedef(this);
527 }
528
529 /// Information about a function or method.
530 class FunctionInfo extends BasicInfo with CodeInfo {
531 static const int TOP_LEVEL_FUNCTION_KIND = 0;
532 static const int CLOSURE_FUNCTION_KIND = 1;
533 static const int METHOD_FUNCTION_KIND = 2;
534 static const int CONSTRUCTOR_FUNCTION_KIND = 3;
535 static int _ids = 0;
536
537 /// Kind of function (top-level function, closure, method, or constructor).
538 int functionKind;
539
540 /// Modifiers applied to this function.
541 FunctionModifiers modifiers;
542
543 /// Nested closures that appear within the body of this function.
544 List<FunctionInfo> closures;
545
546 /// The type of this function.
547 String type;
548
549 /// The declared return type.
550 String returnType;
551
552 /// The inferred return type.
553 String inferredReturnType;
554
555 /// Name and type information for each parameter.
556 List<ParameterInfo> parameters;
557
558 /// Side-effects.
559 // TODO(sigmund): serialize more precisely, not just a string representation.
560 String sideEffects;
561
562 /// How many function calls were inlined into this function.
563 int inlinedCount;
564
565 /// The actual generated code.
566 String code;
567
568 FunctionInfo(
569 {String name,
570 String coverageId,
571 OutputUnitInfo outputUnit,
572 int size: 0,
573 this.functionKind,
574 this.modifiers,
575 this.closures,
576 this.type,
577 this.returnType,
578 this.inferredReturnType,
579 this.parameters,
580 this.sideEffects,
581 this.inlinedCount,
582 this.code})
583 : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId);
584
585 FunctionInfo._(String serializedId) : super._fromId(serializedId);
586
587 Map toJson() => super.toJson()
588 ..addAll({
589 'children': closures.map((i) => i.serializedId).toList(),
590 'modifiers': modifiers.toJson(),
591 'returnType': returnType,
592 'inferredReturnType': inferredReturnType,
593 'parameters': parameters.map((p) => p.toJson()).toList(),
594 'sideEffects': sideEffects,
595 'inlinedCount': inlinedCount,
596 'code': code,
597 'type': type,
598 // Note: version 3.2 of dump-info serializes `uses` in a section called
599 // `holding` at the top-level.
600 });
601
602 void accept(InfoVisitor visitor) => visitor.visitFunction(this);
603 }
604
605 /// Information about how a dependency is used.
606 class DependencyInfo {
607 /// The dependency, either a FunctionInfo or FieldInfo.
608 final Info target;
609
610 /// Either a selector mask indicating how this is used, or 'inlined'.
611 // TODO(sigmund): split mask into an enum or something more precise to really
612 // describe the dependencies in detail.
613 final String mask;
614
615 DependencyInfo(this.target, this.mask);
616
617 Map toJson() => {'id': target.serializedId, 'mask': mask};
618 }
619
620 /// Name and type information about a function parameter.
621 class ParameterInfo {
622 final String name;
623 final String type;
624 final String declaredType;
625
626 ParameterInfo(this.name, this.type, this.declaredType);
627
628 Map toJson() => {'name': name, 'type': type, 'declaredType': declaredType};
629 }
630
631 /// Modifiers that may apply to methods.
632 class FunctionModifiers {
633 final bool isStatic;
634 final bool isConst;
635 final bool isFactory;
636 final bool isExternal;
637
638 FunctionModifiers(
639 {this.isStatic: false,
640 this.isConst: false,
641 this.isFactory: false,
642 this.isExternal: false});
643
644 // TODO(sigmund): exclude false values (requires bumping the format version):
645 // Map toJson() {
646 // var res = <String, bool>{};
647 // if (isStatic) res['static'] = true;
648 // if (isConst) res['const'] = true;
649 // if (isFactory) res['factory'] = true;
650 // if (isExternal) res['external'] = true;
651 // return res;
652 // }
653 Map toJson() => {
654 'static': isStatic,
655 'const': isConst,
656 'factory': isFactory,
657 'external': isExternal,
658 };
659 }
660
661 /// Possible values of the `kind` field in the serialied infos.
662 enum InfoKind {
663 library,
664 clazz,
665 function,
666 field,
667 outputUnit,
668 typedef,
669 }
670
671 String _kindToString(InfoKind kind) {
672 switch(kind) {
673 case InfoKind.library: return 'library';
674 case InfoKind.clazz: return 'class';
675 case InfoKind.function: return 'function';
676 case InfoKind.field: return 'field';
677 case InfoKind.outputUnit: return 'outputUnit';
678 case InfoKind.typedef: return 'typedef';
679 default: return null;
680 }
681 }
682
683 int _idFromSerializedId(String serializedId) =>
684 int.parse(serializedId.substring(serializedId.indexOf('/') + 1));
685
686 InfoKind _kindFromSerializedId(String serializedId) =>
687 _kindFromString(serializedId.substring(0, serializedId.indexOf('/')));
688
689 InfoKind _kindFromString(String kind) {
690 switch(kind) {
691 case 'library': return InfoKind.library;
692 case 'class': return InfoKind.clazz;
693 case 'function': return InfoKind.function;
694 case 'field': return InfoKind.field;
695 case 'outputUnit': return InfoKind.outputUnit;
696 case 'typedef': return InfoKind.typedef;
697 default: return null;
698 }
699 }
700
701 /// A simple visitor for information produced by the dart2js compiler.
702 class InfoVisitor {
703 visitAll(AllInfo info) {}
704 visitProgram(ProgramInfo info) {}
705 visitLibrary(LibraryInfo info) {}
706 visitClass(ClassInfo info) {}
707 visitField(FieldInfo info) {}
708 visitFunction(FunctionInfo info) {}
709 visitTypedef(TypedefInfo info) {}
710 visitOutput(OutputUnitInfo info) {}
711 }
712
713 /// A visitor that recursively walks each portion of the program. Because the
714 /// info representation is redundant, this visitor only walks the structure of
715 /// the program and skips some redundant links. For example, even though
716 /// visitAll contains references to functions, this visitor only recurses to
717 /// visit libraries, then from each library we visit functions and classes, and
718 /// so on.
719 class RecursiveInfoVisitor extends InfoVisitor {
720 visitAll(AllInfo info) {
721 // Note: we don't visit functions, fields, classes, and typedefs because
722 // they are reachable from the library info.
723 info.libraries.forEach(visitLibrary);
724 }
725
726 visitLibrary(LibraryInfo info) {
727 info.topLevelFunctions.forEach(visitFunction);
728 info.topLevelVariables.forEach(visitField);
729 info.classes.forEach(visitClass);
730 info.typedefs.forEach(visitTypedef);
731 }
732
733 visitClass(ClassInfo info) {
734 info.functions.forEach(visitFunction);
735 info.fields.forEach(visitField);
736 }
737
738 visitField(FieldInfo info) {
739 info.closures.forEach(visitFunction);
740 }
741
742 visitFunction(FunctionInfo info) {
743 info.closures.forEach(visitFunction);
744 }
745 }
OLDNEW
« 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