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

Side by Side Diff: pkg/stack_trace/lib/src/trace.dart

Issue 13102003: Add a library for manipulating stack traces. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
(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 library trace;
6
7 import 'dart:uri';
8
9 import 'frame.dart';
10
11 /// A stack trace, comprised of a list of stack frames.
12 class Trace implements StackTrace {
13 // TODO(nweiz): make this read-only once issue 8321 is fixed.
14 /// The stack frames that comprise this stack trace.
15 final List<Frame> frames;
16
17 /// Returns a human-readable representation of [stackTrace]. If [terse] is
18 /// set, this folds together multiple stack frames from the Dart core
19 /// libraries, so that only the core library method directly called from user
20 /// code is visible (see [Trace.terse]).
21 static String format(StackTrace stackTrace, {bool terse: true}) {
22 var trace = new Trace.from(stackTrace);
23 if (terse) trace = trace.terse;
24 return trace.toString();
25 }
26
27 /// Returns the current stack trace.
28 ///
29 /// By default, the first frame of this trace will be the line where
30 /// [Trace.current] is called. If [level] is passed, the trace will start that
31 /// many frames up instead.
32 factory Trace.current([int level=0]) {
33 if (level < 0) {
34 throw new ArgumentError("Argument [level] must be greater than or equal "
35 "to 0.");
36 }
37
38 try {
39 throw '';
40 } catch (_, nativeTrace) {
41 var trace = new Trace.from(nativeTrace);
42 return new Trace(trace.frames.skip(level + 1));
43 }
44 }
45
46 /// Returns a new stack trace containing the same data as [trace].
47 ///
48 /// If [trace] is a native [StackTrace], its data will be parsed out; if it's
49 /// a [Trace], it will be returned as-is.
50 factory Trace.from(StackTrace trace) {
51 if (trace is Trace) return trace;
52 return new Trace.parse(trace.fullStackTrace);
53 }
54
55 /// Parses a string representation of a stack trace.
56 ///
57 /// [trace] should be formatted in the same way as native stack traces.
58 Trace.parse(String trace)
59 : this(trace.trim().split("\n").map((line) => new Frame.parse(line)));
60
61 /// Returns a new [Trace] comprised of [frames].
62 Trace(Iterable<Frame> frames)
63 : frames = frames.toList();
64
65 // TODO(nweiz): Keep track of which [Frame]s are part of the partial stack
66 // trace and only print them.
67 /// Returns a string representation of this stack trace.
68 ///
69 /// This is identical to [toString]. It will not be formatted in the manner of
70 /// native stack traces.
71 String get stackTrace => toString();
72
73 /// Returns a string representation of this stack trace.
74 ///
75 /// This is identical to [toString]. It will not be formatted in the manner of
76 /// native stack traces.
77 String get fullStackTrace => toString();
78
79 /// Returns a terser version of [this]. This is accomplished by folding
80 /// together multiple stack frames from the core library. If multiple such
81 /// frames appear in a row, only the last (the one directly called by user
82 /// code) is kept. Core library patches are also renamed to remove their
83 /// `-patch` suffix.
84 Trace get terse {
85 return new Trace(frames.reversed.reduce(<Frame>[], (newFrames, frame) {
86 if (!frame.isCore) {
87 newFrames.add(frame);
Bob Nystrom 2013/03/27 00:46:44 Given that you are imperatively building up a resu
nweiz 2013/03/27 21:15:46 Done.
88 } else if (newFrames.isEmpty || !newFrames.last.isCore) {
89 var library = frame.library.replaceAll(new RegExp(r"-patch$"), '');
Bob Nystrom 2013/03/27 00:46:44 Hoist this regex out to a top level final variable
nweiz 2013/03/27 21:15:46 I really hate that we have to do this for every re
90 newFrames.add(new Frame(
91 Uri.parse(library), frame.line, frame.column, frame.member));
92 }
93
94 return newFrames;
95 }).reversed);
96 }
97
98 /// Returns a human-readable string representation of [this].
99 String toString() {
100 if (frames.length == '') return '';
101
102 // Figure out the longest path so we know how much to pad.
103 var longest = frames.map((frame) => frame.location.length).max();
104
105 // Print out the stack trace nicely formatted.
106 return frames.map((frame) {
107 return '${_padRight(frame.location, longest)} ${frame.member}\n';
108 }).join();
109 }
110
111 /// Returns [string] with enough spaces added to the end to make it [length]
112 /// characters long.
113 String _padRight(String string, int length) {
Bob Nystrom 2013/03/27 00:46:44 Make a top-level function? It doesn't access any i
nweiz 2013/03/27 21:15:46 Done.
114 if (string.length >= length) return string;
115
116 var result = new StringBuffer();
117 result.write(string);
118 for (var i = 0; i < length - string.length; i++) {
119 result.write(' ');
120 }
121
122 return result.toString();
123 }
124 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698