OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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 library stack_trace.chain; | 5 library stack_trace.chain; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'frame.dart'; | 10 import 'frame.dart'; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 new Chain(chain.split(_GAP).map((trace) => new Trace.parseFriendly(trace))); | 129 new Chain(chain.split(_GAP).map((trace) => new Trace.parseFriendly(trace))); |
130 | 130 |
131 /// Returns a new [Chain] comprised of [traces]. | 131 /// Returns a new [Chain] comprised of [traces]. |
132 Chain(Iterable<Trace> traces) | 132 Chain(Iterable<Trace> traces) |
133 : traces = new UnmodifiableListView<Trace>(traces.toList()); | 133 : traces = new UnmodifiableListView<Trace>(traces.toList()); |
134 | 134 |
135 /// Returns a terser version of [this]. | 135 /// Returns a terser version of [this]. |
136 /// | 136 /// |
137 /// This calls [Trace.terse] on every trace in [traces], and discards any | 137 /// This calls [Trace.terse] on every trace in [traces], and discards any |
138 /// trace that contain only internal frames. | 138 /// trace that contain only internal frames. |
139 Chain get terse { | 139 Chain get terse => foldFrames((_) => false, terse: true); |
140 var terseTraces = traces.map((trace) => trace.terse); | |
141 var nonEmptyTraces = terseTraces.where((trace) { | |
142 // Ignore traces that contain only internal processing. | |
143 return trace.frames.length > 1; | |
144 }); | |
145 | |
146 // If all the traces contain only internal processing, preserve the last | |
147 // (top-most) one so that the chain isn't empty. | |
148 if (nonEmptyTraces.isEmpty && terseTraces.isNotEmpty) { | |
149 return new Chain([terseTraces.last]); | |
150 } | |
151 | |
152 return new Chain(nonEmptyTraces); | |
153 } | |
154 | 140 |
155 /// Returns a new [Chain] based on [this] where multiple stack frames matching | 141 /// Returns a new [Chain] based on [this] where multiple stack frames matching |
156 /// [predicate] are folded together. | 142 /// [predicate] are folded together. |
157 /// | 143 /// |
158 /// This means that whenever there are multiple frames in a row that match | 144 /// This means that whenever there are multiple frames in a row that match |
159 /// [predicate], only the last one is kept. In addition, traces that are | 145 /// [predicate], only the last one is kept. In addition, traces that are |
160 /// composed entirely of frames matching [predicate] are omitted. | 146 /// composed entirely of frames matching [predicate] are omitted. |
161 /// | 147 /// |
162 /// This is useful for limiting the amount of library code that appears in a | 148 /// This is useful for limiting the amount of library code that appears in a |
163 /// stack trace by only showing user code and code that's called by user code. | 149 /// stack trace by only showing user code and code that's called by user code. |
164 Chain foldFrames(bool predicate(Frame frame)) { | 150 /// |
165 var foldedTraces = traces.map((trace) => trace.foldFrames(predicate)); | 151 /// If [terse] is true, this will also fold together frames from the core |
| 152 /// library or from this package, and simplify core library frames as in |
| 153 /// [Trace.terse]. |
| 154 Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) { |
| 155 var foldedTraces = traces.map( |
| 156 (trace) => trace.foldFrames(predicate, terse: terse)); |
166 var nonEmptyTraces = foldedTraces.where((trace) { | 157 var nonEmptyTraces = foldedTraces.where((trace) { |
167 // Ignore traces that contain only folded frames. These traces will be | 158 // Ignore traces that contain only folded frames. These traces will be |
168 // folded into a single frame each. | 159 // folded into a single frame each. |
169 return trace.frames.length > 1; | 160 return trace.frames.length > 1; |
170 }); | 161 }); |
171 | 162 |
172 // If all the traces contain only internal processing, preserve the last | 163 // If all the traces contain only internal processing, preserve the last |
173 // (top-most) one so that the chain isn't empty. | 164 // (top-most) one so that the chain isn't empty. |
174 if (nonEmptyTraces.isEmpty && foldedTraces.isNotEmpty) { | 165 if (nonEmptyTraces.isEmpty && foldedTraces.isNotEmpty) { |
175 return new Chain([foldedTraces.last]); | 166 return new Chain([foldedTraces.last]); |
176 } | 167 } |
177 | 168 |
178 return new Chain(nonEmptyTraces); | 169 return new Chain(nonEmptyTraces); |
179 } | 170 } |
180 | 171 |
181 /// Converts [this] to a [Trace]. | 172 /// Converts [this] to a [Trace]. |
182 /// | 173 /// |
183 /// The trace version of a chain is just the concatenation of all the traces | 174 /// The trace version of a chain is just the concatenation of all the traces |
184 /// in the chain. | 175 /// in the chain. |
185 Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames))); | 176 Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames))); |
186 | 177 |
187 String toString() => traces.join(_GAP); | 178 String toString() => traces.join(_GAP); |
188 } | 179 } |
OLD | NEW |