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