Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, 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 /// A library with code coverage models. | |
| 6 library runtime.coverage.model; | |
| 7 | |
| 8 import 'dart:collection' show SplayTreeMap; | |
| 9 | |
| 10 import 'package:analyzer_experimental/src/generated/source.dart' show Source, So urceRange; | |
| 11 import 'package:analyzer_experimental/src/generated/ast.dart' show ASTNode; | |
| 12 | |
| 13 import 'utils.dart'; | |
| 14 | |
| 15 | |
| 16 /// Contains information about the application. | |
| 17 class AppInfo { | |
| 18 final List<NodeInfo> nodeStack = new List<NodeInfo>(); | |
|
Bob Nystrom
2013/06/17 21:30:12
final nodeStack = <NodeInfo>[];
Ditto for other f
scheglov
2013/06/17 22:30:57
For all fields or for final fields with initialize
Bob Nystrom
2013/06/17 22:44:41
Just ones with initializers. If they aren't initia
| |
| 19 final List<UnitInfo> units = new List<UnitInfo>(); | |
| 20 final Map<String, UnitInfo> pathToFile = new Map<String, UnitInfo>(); | |
| 21 NodeInfo currentNode = null; | |
| 22 int nextId = 0; | |
| 23 | |
| 24 void enterUnit(String path, String content) { | |
| 25 var unit = new UnitInfo(this, path, content); | |
| 26 units.add(unit); | |
| 27 currentNode = unit; | |
| 28 } | |
| 29 | |
| 30 void enter(String kind, String name) { | |
| 31 nodeStack.add(currentNode); | |
| 32 currentNode = new NodeInfo(this, currentNode, kind, name); | |
| 33 } | |
| 34 | |
| 35 void leave() { | |
| 36 currentNode = nodeStack.removeLast(); | |
| 37 } | |
| 38 | |
| 39 int addNode(ASTNode node) { | |
| 40 return currentNode.addNode(node); | |
| 41 } | |
| 42 | |
| 43 void print(StringSink sink, Set<int> executedIds) { | |
|
Bob Nystrom
2013/06/17 21:30:12
Calling a method "print" is probably asking for tr
scheglov
2013/06/17 22:30:57
Ah... yes.
Renamed to 'write'.
| |
| 44 sink.writeln('{'); | |
| 45 units.asMap().forEach((int i, UnitInfo unit) { | |
| 46 if (i != 0) sink.writeln(','); | |
| 47 unit.print(sink, executedIds, ' '); | |
| 48 }); | |
| 49 sink.writeln(); | |
| 50 sink.writeln('}'); | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 /// Information about some node - unit, class, method, function. | |
| 55 class NodeInfo { | |
| 56 final AppInfo appInfo; | |
| 57 final NodeInfo parent; | |
| 58 final String kind; | |
| 59 final String name; | |
| 60 final Map<int, SourceRange> idToRange = new SplayTreeMap<int, SourceRange>(); | |
| 61 final List<NodeInfo> children = <NodeInfo> []; | |
|
Bob Nystrom
2013/06/17 21:30:12
No space between > and [
scheglov
2013/06/17 22:30:57
Done.
| |
| 62 | |
| 63 NodeInfo(this.appInfo, this.parent, this.kind, this.name) { | |
| 64 if (parent != null) { | |
| 65 parent.children.add(this); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 int addNode(ASTNode node) { | |
| 70 var id = appInfo.nextId++; | |
| 71 var range = new SourceRange(node.offset, node.length); | |
| 72 idToRange[id] = range; | |
| 73 return id; | |
| 74 } | |
| 75 | |
| 76 void print(StringSink sink, Set<int> executedIds, String prefix) { | |
| 77 sink.writeln('$prefix"$name": {'); | |
| 78 // Kind. | |
| 79 sink.writeln('$prefix "kind": "$kind",'); | |
| 80 // Print children. | |
| 81 if (children.isNotEmpty) { | |
|
Bob Nystrom
2013/06/17 21:30:12
Today I learned Iterable has isNotEmpty! :)
| |
| 82 sink.writeln('$prefix "children": {'); | |
| 83 children.asMap().forEach((int i, NodeInfo child) { | |
|
scheglov
2013/06/17 22:30:57
Is it recommended to have type annotations for clo
Bob Nystrom
2013/06/17 22:44:41
The style guide says: "AVOID annotating types on f
scheglov
2013/06/18 06:11:04
Done.
| |
| 84 if (i != 0) sink.writeln(','); | |
| 85 children[i].print(sink, executedIds, '$prefix '); | |
| 86 }); | |
|
Bob Nystrom
2013/06/17 21:30:12
Clever! You could also try:
children.fold(null, (
scheglov
2013/06/17 22:30:57
More lines of code - I have to add "return" :-(
| |
| 87 sink.writeln(); | |
| 88 sink.writeln('$prefix }'); | |
| 89 } | |
| 90 // Print source and line ranges. | |
| 91 if (children.isEmpty) { | |
| 92 sink.write('${prefix} "ranges": ['); | |
| 93 var rangePrinter = new RangePrinter(unit, sink, executedIds); | |
| 94 idToRange.forEach(rangePrinter.handle); | |
|
Bob Nystrom
2013/06/17 21:30:12
Nice.
| |
| 95 rangePrinter.printRange(); | |
| 96 sink.writeln(']'); | |
| 97 } | |
| 98 // Close this node. | |
| 99 sink.write('$prefix}'); | |
| 100 } | |
| 101 | |
| 102 UnitInfo get unit => parent.unit; | |
| 103 } | |
| 104 | |
| 105 /// Helper for printing merged source/line intervals. | |
| 106 class RangePrinter { | |
| 107 final UnitInfo unit; | |
| 108 final StringSink sink; | |
| 109 final Set<int> executedIds; | |
| 110 | |
| 111 bool first = true; | |
| 112 int startId = -1; | |
| 113 int startOffset = -1; | |
| 114 int endId = -1; | |
| 115 int endOffset = -1; | |
| 116 | |
| 117 RangePrinter(this.unit, this.sink, this.executedIds); | |
| 118 | |
| 119 handle(int id, SourceRange range) { | |
| 120 if (executedIds.contains(id)) { | |
| 121 printRange(); | |
| 122 } else { | |
| 123 if (endId == id - 1) { | |
| 124 endId = id; | |
| 125 endOffset = range.end; | |
| 126 } else { | |
| 127 startId = id; | |
| 128 endId = id; | |
| 129 startOffset = range.offset; | |
| 130 endOffset = range.end; | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 void printRange() { | |
| 136 if (endId == -1) return; | |
| 137 printSeparator(); | |
| 138 var startLine = unit.getLine(startOffset); | |
| 139 var endLine = unit.getLine(endOffset); | |
| 140 sink.write('$startOffset,$endOffset,$startLine,$endLine'); | |
| 141 startId = startOffset = startLine = -1; | |
| 142 endId = endOffset = endLine = -1; | |
| 143 } | |
| 144 | |
| 145 void printSeparator() { | |
| 146 if (first) { | |
| 147 first = false; | |
| 148 } else { | |
| 149 sink.write(', '); | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 /// Containts information about the single unit of the application. | |
|
Bob Nystrom
2013/06/17 21:30:12
Containts -> Contains.
scheglov
2013/06/17 22:30:57
Done.
| |
| 155 class UnitInfo extends NodeInfo { | |
| 156 List<int> lineOffsets; | |
| 157 | |
| 158 UnitInfo(AppInfo appInfo, String path, String content) : super(appInfo, null, 'unit', path) { | |
|
Bob Nystrom
2013/06/17 21:30:12
Move ": super..." to the next line.
scheglov
2013/06/17 22:30:57
Done.
| |
| 159 lineOffsets = getLineOffsets(content); | |
| 160 } | |
| 161 | |
| 162 UnitInfo get unit => this; | |
| 163 | |
| 164 int getLine(int offset) { | |
| 165 return binarySearch(lineOffsets, (x) => x >= offset); | |
| 166 } | |
| 167 } | |
| OLD | NEW |