OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Data collected by the dump-info task. | 5 /// Data collected by the dump-info task. |
6 library compiler.src.lib.info; | 6 library compiler.src.lib.info; |
7 | 7 |
8 // Note: this file intentionally doesn't import anything from the compiler. That | 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 | 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 | 10 // by using this library, tools can consume the information in the same way it |
11 // is produced by the compiler. | 11 // is produced by the compiler. |
12 // TODO(sigmund): make this a proper public API (export this explicitly at the | 12 // TODO(sigmund): make this a proper public API (export this explicitly at the |
13 // lib folder level.) | 13 // lib folder level.) |
14 | 14 |
15 /// Common interface to many pieces of information generated by the compiler. | 15 /// Common interface to many pieces of information generated by the compiler. |
16 abstract class Info { | 16 abstract class Info { |
17 /// An identifier for the kind of information. | 17 /// An identifier for the kind of information. |
18 InfoKind get kind; | 18 InfoKind get kind; |
19 | 19 |
20 /// Name of the element associated with this info. | 20 /// Name of the element associated with this info. |
21 String name; | 21 String name; |
22 | 22 |
23 /// An id to uniquely identify this info among infos of the same [kind]. | 23 /// An id to uniquely identify this info among infos of the same [kind]. |
24 int get id; | 24 int get id; |
25 | 25 |
26 /// A globally unique id combining [kind] and [id] together. | 26 /// A globally unique id combining [kind] and [id] together. |
27 String get serializedId; | 27 String get serializedId; |
28 | 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 |
29 /// Bytes used in the generated code for the corresponding element. | 34 /// Bytes used in the generated code for the corresponding element. |
30 int size; | 35 int size; |
31 | 36 |
32 /// Info of the enclosing element. | 37 /// Info of the enclosing element. |
33 Info parent; | 38 Info parent; |
34 | 39 |
35 /// Serializes the information into a JSON format. | 40 /// Serializes the information into a JSON format. |
36 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2 | 41 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2 |
37 // different serializer/deserializers at once. | 42 // different serializer/deserializers at once. |
38 Map toJson(); | 43 Map toJson(); |
39 | 44 |
40 void accept(InfoVisitor visitor); | 45 void accept(InfoVisitor visitor); |
41 } | 46 } |
42 | 47 |
43 /// Common information used for most kind of elements. | 48 /// Common information used for most kind of elements. |
44 // TODO(sigmund): add more: | 49 // TODO(sigmund): add more: |
45 // - inputSize: bytes used in the Dart source program | 50 // - inputSize: bytes used in the Dart source program |
46 abstract class BasicInfo implements Info { | 51 abstract class BasicInfo implements Info { |
47 final InfoKind kind; | 52 final InfoKind kind; |
48 final int id; | 53 final int id; |
| 54 String coverageId; |
49 int size; | 55 int size; |
50 Info parent; | 56 Info parent; |
51 | 57 |
52 String get serializedId => '${_kindToString(kind)}/$id'; | 58 String get serializedId => '${_kindToString(kind)}/$id'; |
53 | 59 |
54 String name; | 60 String name; |
55 | 61 |
56 /// If using deferred libraries, where the element associated with this info | 62 /// If using deferred libraries, where the element associated with this info |
57 /// is generated. | 63 /// is generated. |
58 OutputUnitInfo outputUnit; | 64 OutputUnitInfo outputUnit; |
59 | 65 |
60 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size); | 66 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size, |
| 67 this.coverageId); |
61 | 68 |
62 BasicInfo._fromId(String serializedId) | 69 BasicInfo._fromId(String serializedId) |
63 : kind = _kindFromSerializedId(serializedId), | 70 : kind = _kindFromSerializedId(serializedId), |
64 id = _idFromSerializedId(serializedId); | 71 id = _idFromSerializedId(serializedId); |
65 | 72 |
66 Map toJson() { | 73 Map toJson() { |
67 var res = { | 74 var res = { |
68 'id': serializedId, | 75 'id': serializedId, |
69 'kind': _kindToString(kind), | 76 'kind': _kindToString(kind), |
70 'name': name, | 77 'name': name, |
71 'size': size, | 78 'size': size, |
72 }; | 79 }; |
73 // TODO(sigmund): omit this also when outputUnit.id == 0 | 80 // TODO(sigmund): Omit this also when outputUnit.id == 0 (most code is in |
74 // (most code is by default in the main output unit) | 81 // the main output unit by default). |
75 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId; | 82 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId; |
| 83 if (coverageId != null) res['coverageId'] = coverageId; |
76 if (parent != null) res['parent'] = parent.serializedId; | 84 if (parent != null) res['parent'] = parent.serializedId; |
77 return res; | 85 return res; |
78 } | 86 } |
79 | 87 |
80 String toString() => '$serializedId $name [$size]'; | 88 String toString() => '$serializedId $name [$size]'; |
81 } | 89 } |
82 | 90 |
83 /// Info associated with elements containing executable code (like fields and | 91 /// Info associated with elements containing executable code (like fields and |
84 /// methods) | 92 /// methods) |
85 abstract class CodeInfo implements Info { | 93 abstract class CodeInfo implements Info { |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 result.fields.add(child); | 309 result.fields.add(child); |
302 } | 310 } |
303 } | 311 } |
304 return result; | 312 return result; |
305 } | 313 } |
306 | 314 |
307 FieldInfo parseField(Map json) { | 315 FieldInfo parseField(Map json) { |
308 FieldInfo result = parseId(json['id']); | 316 FieldInfo result = parseId(json['id']); |
309 return result..name = json['name'] | 317 return result..name = json['name'] |
310 ..parent = parseId(json['parent']) | 318 ..parent = parseId(json['parent']) |
| 319 ..coverageId = json['coverageId'] |
311 ..outputUnit = parseId(json['outputUnit']) | 320 ..outputUnit = parseId(json['outputUnit']) |
312 ..size = json['size'] | 321 ..size = json['size'] |
313 ..type = json['type'] | 322 ..type = json['type'] |
314 ..inferredType = json['inferredType'] | 323 ..inferredType = json['inferredType'] |
315 ..code = json['code'] | 324 ..code = json['code'] |
316 ..closures = json['children'].map(parseId).toList(); | 325 ..closures = json['children'].map(parseId).toList(); |
317 } | 326 } |
318 | 327 |
319 TypedefInfo parseTypedef(Map json) { | 328 TypedefInfo parseTypedef(Map json) { |
320 TypedefInfo result = parseId(json['id']); | 329 TypedefInfo result = parseId(json['id']); |
321 return result..name = json['name'] | 330 return result..name = json['name'] |
322 ..parent = parseId(json['parent']) | 331 ..parent = parseId(json['parent']) |
323 ..type = json['type'] | 332 ..type = json['type'] |
324 ..size = 0; | 333 ..size = 0; |
325 } | 334 } |
326 | 335 |
327 ProgramInfo parseProgram(Map json) => | 336 ProgramInfo parseProgram(Map json) => |
328 new ProgramInfo()..size = json['size']; | 337 new ProgramInfo()..size = json['size']; |
329 | 338 |
330 FunctionInfo parseFunction(Map json) { | 339 FunctionInfo parseFunction(Map json) { |
331 FunctionInfo result = parseId(json['id']); | 340 FunctionInfo result = parseId(json['id']); |
332 return result..name = json['name'] | 341 return result..name = json['name'] |
333 ..parent = parseId(json['parent']) | 342 ..parent = parseId(json['parent']) |
| 343 ..coverageId = json['coverageId'] |
334 ..outputUnit = parseId(json['outputUnit']) | 344 ..outputUnit = parseId(json['outputUnit']) |
335 ..size = json['size'] | 345 ..size = json['size'] |
336 ..type = json['type'] | 346 ..type = json['type'] |
337 ..returnType = json['returnType'] | 347 ..returnType = json['returnType'] |
338 ..inferredReturnType = json['inferredReturnType'] | 348 ..inferredReturnType = json['inferredReturnType'] |
339 ..parameters = json['parameters'].map(parseParameter).toList() | 349 ..parameters = json['parameters'].map(parseParameter).toList() |
340 ..code = json['code'] | 350 ..code = json['code'] |
341 ..sideEffects = json['sideEffects'] | 351 ..sideEffects = json['sideEffects'] |
342 ..modifiers = parseModifiers(json['modifiers']) | 352 ..modifiers = parseModifiers(json['modifiers']) |
343 ..closures = json['children'].map(parseId).toList(); | 353 ..closures = json['children'].map(parseId).toList(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 /// Typedefs defined within the library. | 401 /// Typedefs defined within the library. |
392 final List<TypedefInfo> typedefs = <TypedefInfo>[]; | 402 final List<TypedefInfo> typedefs = <TypedefInfo>[]; |
393 | 403 |
394 static int _id = 0; | 404 static int _id = 0; |
395 | 405 |
396 /// Whether there is any information recorded for this library. | 406 /// Whether there is any information recorded for this library. |
397 bool get isEmpty => | 407 bool get isEmpty => |
398 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty; | 408 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty; |
399 | 409 |
400 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size) | 410 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size) |
401 : super(InfoKind.library, _id++, name, outputUnit, size); | 411 : super(InfoKind.library, _id++, name, outputUnit, size, null); |
402 | 412 |
403 LibraryInfo._(String serializedId) : super._fromId(serializedId); | 413 LibraryInfo._(String serializedId) : super._fromId(serializedId); |
404 | 414 |
405 Map toJson() => super.toJson() | 415 Map toJson() => super.toJson() |
406 ..addAll({ | 416 ..addAll({ |
407 'children': [] | 417 'children': [] |
408 ..addAll(topLevelFunctions.map((f) => f.serializedId)) | 418 ..addAll(topLevelFunctions.map((f) => f.serializedId)) |
409 ..addAll(topLevelVariables.map((v) => v.serializedId)) | 419 ..addAll(topLevelVariables.map((v) => v.serializedId)) |
410 ..addAll(classes.map((c) => c.serializedId)) | 420 ..addAll(classes.map((c) => c.serializedId)) |
411 ..addAll(typedefs.map((t) => t.serializedId)), | 421 ..addAll(typedefs.map((t) => t.serializedId)), |
412 'canonicalUri': '$uri', | 422 'canonicalUri': '$uri', |
413 }); | 423 }); |
414 | 424 |
415 void accept(InfoVisitor visitor) => visitor.visitLibrary(this); | 425 void accept(InfoVisitor visitor) => visitor.visitLibrary(this); |
416 } | 426 } |
417 | 427 |
418 /// Information about an output unit. Normally there is just one for the entire | 428 /// Information about an output unit. Normally there is just one for the entire |
419 /// program unless the application uses deferred imports, in which case there | 429 /// program unless the application uses deferred imports, in which case there |
420 /// would be an additional output unit per deferred chunk. | 430 /// would be an additional output unit per deferred chunk. |
421 class OutputUnitInfo extends BasicInfo { | 431 class OutputUnitInfo extends BasicInfo { |
422 static int _ids = 0; | 432 static int _ids = 0; |
423 OutputUnitInfo(String name, int size) | 433 OutputUnitInfo(String name, int size) |
424 : super(InfoKind.outputUnit, _ids++, name, null, size); | 434 : super(InfoKind.outputUnit, _ids++, name, null, size, null); |
425 | 435 |
426 OutputUnitInfo._(String serializedId) : super._fromId(serializedId); | 436 OutputUnitInfo._(String serializedId) : super._fromId(serializedId); |
427 | 437 |
428 void accept(InfoVisitor visitor) => visitor.visitOutput(this); | 438 void accept(InfoVisitor visitor) => visitor.visitOutput(this); |
429 } | 439 } |
430 | 440 |
431 /// Information about a class element. | 441 /// Information about a class element. |
432 class ClassInfo extends BasicInfo { | 442 class ClassInfo extends BasicInfo { |
433 /// Whether the class is abstract. | 443 /// Whether the class is abstract. |
434 bool isAbstract; | 444 bool isAbstract; |
435 | 445 |
436 // TODO(sigmund): split static vs instance vs closures | 446 // TODO(sigmund): split static vs instance vs closures |
437 /// Functions (static or instance) defined in the class. | 447 /// Functions (static or instance) defined in the class. |
438 final List<FunctionInfo> functions = <FunctionInfo>[]; | 448 final List<FunctionInfo> functions = <FunctionInfo>[]; |
439 | 449 |
440 /// Fields defined in the class. | 450 /// Fields defined in the class. |
441 // TODO(sigmund): currently appears to only be populated with instance fields, | 451 // TODO(sigmund): currently appears to only be populated with instance fields, |
442 // but this should be fixed. | 452 // but this should be fixed. |
443 final List<FieldInfo> fields = <FieldInfo>[]; | 453 final List<FieldInfo> fields = <FieldInfo>[]; |
444 static int _ids = 0; | 454 static int _ids = 0; |
445 | 455 |
446 ClassInfo( | 456 ClassInfo( |
447 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0}) | 457 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0}) |
448 : super(InfoKind.clazz, _ids++, name, outputUnit, size); | 458 : super(InfoKind.clazz, _ids++, name, outputUnit, size, null); |
449 | 459 |
450 ClassInfo._(String serializedId) : super._fromId(serializedId); | 460 ClassInfo._(String serializedId) : super._fromId(serializedId); |
451 | 461 |
452 Map toJson() => super.toJson() | 462 Map toJson() => super.toJson() |
453 ..addAll({ | 463 ..addAll({ |
454 // TODO(sigmund): change format, include only when abstract is true. | 464 // TODO(sigmund): change format, include only when abstract is true. |
455 'modifiers': {'abstract': isAbstract}, | 465 'modifiers': {'abstract': isAbstract}, |
456 'children': [] | 466 'children': [] |
457 ..addAll(fields.map((f) => f.serializedId)) | 467 ..addAll(fields.map((f) => f.serializedId)) |
458 ..addAll(functions.map((m) => m.serializedId)) | 468 ..addAll(functions.map((m) => m.serializedId)) |
(...skipping 12 matching lines...) Expand all Loading... |
471 | 481 |
472 /// Nested closures seen in the field initializer. | 482 /// Nested closures seen in the field initializer. |
473 List<FunctionInfo> closures; | 483 List<FunctionInfo> closures; |
474 | 484 |
475 /// The actual generated code for the field. | 485 /// The actual generated code for the field. |
476 String code; | 486 String code; |
477 | 487 |
478 static int _ids = 0; | 488 static int _ids = 0; |
479 FieldInfo( | 489 FieldInfo( |
480 {String name, | 490 {String name, |
| 491 String coverageId, |
481 int size: 0, | 492 int size: 0, |
482 this.type, | 493 this.type, |
483 this.inferredType, | 494 this.inferredType, |
484 this.closures, | 495 this.closures, |
485 this.code, | 496 this.code, |
486 OutputUnitInfo outputUnit}) | 497 OutputUnitInfo outputUnit}) |
487 : super(InfoKind.field, _ids++, name, outputUnit, size); | 498 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId); |
488 | 499 |
489 FieldInfo._(String serializedId) : super._fromId(serializedId); | 500 FieldInfo._(String serializedId) : super._fromId(serializedId); |
490 | 501 |
491 Map toJson() => super.toJson() | 502 Map toJson() => super.toJson() |
492 ..addAll({ | 503 ..addAll({ |
493 'children': closures.map((i) => i.serializedId).toList(), | 504 'children': closures.map((i) => i.serializedId).toList(), |
494 'inferredType': inferredType, | 505 'inferredType': inferredType, |
495 'code': code, | 506 'code': code, |
496 'type': type, | 507 'type': type, |
497 }); | 508 }); |
498 | 509 |
499 void accept(InfoVisitor visitor) => visitor.visitField(this); | 510 void accept(InfoVisitor visitor) => visitor.visitField(this); |
500 } | 511 } |
501 | 512 |
502 /// Information about a typedef declaration. | 513 /// Information about a typedef declaration. |
503 class TypedefInfo extends BasicInfo { | 514 class TypedefInfo extends BasicInfo { |
504 /// The declared type. | 515 /// The declared type. |
505 String type; | 516 String type; |
506 | 517 |
507 static int _ids = 0; | 518 static int _ids = 0; |
508 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit) | 519 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit) |
509 : super(InfoKind.typedef, _ids++, name, outputUnit, 0); | 520 : super(InfoKind.typedef, _ids++, name, outputUnit, 0, null); |
510 | 521 |
511 TypedefInfo._(String serializedId) : super._fromId(serializedId); | 522 TypedefInfo._(String serializedId) : super._fromId(serializedId); |
512 | 523 |
513 Map toJson() => super.toJson()..['type'] = '$type'; | 524 Map toJson() => super.toJson()..['type'] = '$type'; |
514 | 525 |
515 void accept(InfoVisitor visitor) => visitor.visitTypedef(this); | 526 void accept(InfoVisitor visitor) => visitor.visitTypedef(this); |
516 } | 527 } |
517 | 528 |
518 /// Information about a function or method. | 529 /// Information about a function or method. |
519 class FunctionInfo extends BasicInfo with CodeInfo { | 530 class FunctionInfo extends BasicInfo with CodeInfo { |
(...skipping 29 matching lines...) Expand all Loading... |
549 String sideEffects; | 560 String sideEffects; |
550 | 561 |
551 /// How many function calls were inlined into this function. | 562 /// How many function calls were inlined into this function. |
552 int inlinedCount; | 563 int inlinedCount; |
553 | 564 |
554 /// The actual generated code. | 565 /// The actual generated code. |
555 String code; | 566 String code; |
556 | 567 |
557 FunctionInfo( | 568 FunctionInfo( |
558 {String name, | 569 {String name, |
| 570 String coverageId, |
559 OutputUnitInfo outputUnit, | 571 OutputUnitInfo outputUnit, |
560 int size: 0, | 572 int size: 0, |
561 this.functionKind, | 573 this.functionKind, |
562 this.modifiers, | 574 this.modifiers, |
563 this.closures, | 575 this.closures, |
564 this.type, | 576 this.type, |
565 this.returnType, | 577 this.returnType, |
566 this.inferredReturnType, | 578 this.inferredReturnType, |
567 this.parameters, | 579 this.parameters, |
568 this.sideEffects, | 580 this.sideEffects, |
569 this.inlinedCount, | 581 this.inlinedCount, |
570 this.code}) | 582 this.code}) |
571 : super(InfoKind.function, _ids++, name, outputUnit, size); | 583 : super(InfoKind.function, _ids++, name, outputUnit, size, coverageId); |
572 | 584 |
573 FunctionInfo._(String serializedId) : super._fromId(serializedId); | 585 FunctionInfo._(String serializedId) : super._fromId(serializedId); |
574 | 586 |
575 Map toJson() => super.toJson() | 587 Map toJson() => super.toJson() |
576 ..addAll({ | 588 ..addAll({ |
577 'children': closures.map((i) => i.serializedId).toList(), | 589 'children': closures.map((i) => i.serializedId).toList(), |
578 'modifiers': modifiers.toJson(), | 590 'modifiers': modifiers.toJson(), |
579 'returnType': returnType, | 591 'returnType': returnType, |
580 'inferredReturnType': inferredReturnType, | 592 'inferredReturnType': inferredReturnType, |
581 'parameters': parameters.map((p) => p.toJson()).toList(), | 593 'parameters': parameters.map((p) => p.toJson()).toList(), |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 } | 736 } |
725 | 737 |
726 visitField(FieldInfo info) { | 738 visitField(FieldInfo info) { |
727 info.closures.forEach(visitFunction); | 739 info.closures.forEach(visitFunction); |
728 } | 740 } |
729 | 741 |
730 visitFunction(FunctionInfo info) { | 742 visitFunction(FunctionInfo info) { |
731 info.closures.forEach(visitFunction); | 743 info.closures.forEach(visitFunction); |
732 } | 744 } |
733 } | 745 } |
OLD | NEW |