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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/helpers/trace.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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) 2014, 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 part of dart2js.helpers;
6
7 /// Function signature for [trace].
8 typedef void Trace(String message,
9 {bool condition(String stackTrace),
10 int limit,
11 bool throwOnPrint});
12
13 /**
14 * Helper method for printing stack traces for debugging.
15 *
16 * [message] is printed as the header of the stack trace.
17 *
18 * If [condition] is provided, the stack trace is only printed if [condition]
19 * returns [:true:] on the stack trace text. This can be used to filter the
20 * printed stack traces based on their content. For instance only print stack
21 * traces that contain specific paths.
22 *
23 * If [limit] is provided, the stack trace is limited to [limit] entries.
24 *
25 * If [throwOnPrint] is `true`, [message] will be thrown after the stack trace
26 * has been printed. Together with [condition] this can be used to discover
27 * unknown call-sites in tests by filtering known call-sites and throwning
28 * otherwise.
29 */
30 Trace get trace {
31 enableDebugMode();
32 return _trace;
33 }
34
35 void _trace(String message, {bool condition(String stackTrace), int limit,
36 bool throwOnPrint: false}) {
37 try {
38 throw '';
39 } catch (e, s) {
40 String stackTrace;
41 try {
42 stackTrace = prettifyStackTrace(
43 s, rangeStart: 1, rangeEnd: limit, filePrefix: stackTraceFilePrefix);
44 } catch (e) {
45 print(e);
46 stackTrace = '$s';
47 }
48 if (condition != null) {
49 if (!condition(stackTrace)) return;
50 }
51 print('$message\n$stackTrace');
52 if (throwOnPrint) throw message;
53 }
54 }
55
56 /// Function signature of [traceAndReport].
57 typedef void TraceAndReport(Compiler compiler, Spannable node, String message,
58 {bool condition(String stackTrace), int limit,
59 bool throwOnPrint});
60
61 /// Calls [reportHere] and [trace] with the same message.
62 TraceAndReport get traceAndReport {
63 enableDebugMode();
64 return _traceAndReport;
65 }
66
67 /// Calls [reportHere] and [trace] with the same message.
68 TraceAndReport get reportAndTrace => traceAndReport;
69
70 /// Implementation of [traceAndReport].
71 void _traceAndReport(Compiler compiler, Spannable node, String message,
72 {bool condition(String stackTrace), int limit,
73 bool throwOnPrint: false}) {
74
75 trace(message, limit: limit, throwOnPrint: throwOnPrint,
76 condition: (String stackTrace) {
77 bool result = condition != null ? condition(stackTrace) : true;
78 if (result) {
79 reportHere(compiler, node, message);
80 }
81 return result;
82 });
83 }
84
85 /// Returns the [StackTraceLines] for the current call stack.
86 ///
87 /// Use [offset] to discard the first [offset] calls of the call stack. Defaults
88 /// to `1`, that is, discard the call to [stackTrace] itself. Use [limit] to
89 /// limit the length of the stack trace lines.
90 StackTraceLines stackTrace({int offset: 1,
91 int limit: null}) {
92 int rangeStart = offset;
93 int rangeEnd = limit == null ? null : rangeStart + limit;
94 try {
95 throw '';
96 } catch (_, stackTrace) {
97 return new StackTraceLines.fromTrace(stackTrace,
98 rangeStart: offset, rangeEnd: rangeEnd,
99 filePrefix: stackTraceFilePrefix);
100 }
101 return null;
102 }
103
104 /// A stack trace as a sequence of [StackTraceLine]s.
105 class StackTraceLines {
106 final List<StackTraceLine> lines;
107 final int maxFileLength;
108 final int maxLineNoLength;
109 final int maxColumnNoLength;
110
111 factory StackTraceLines.fromTrace(StackTrace s,
112 {int rangeStart,
113 int rangeEnd,
114 String filePrefix,
115 String lambda: r'?'}) {
116 final RegExp indexPattern = new RegExp(r'#\d+\s*');
117 int index = -1;
118 int maxFileLength = 0;
119 int maxLineNoLength = 0;
120 int maxColumnNoLength = 0;
121
122 String stackTrace = '$s';
123 List<StackTraceLine> lines = <StackTraceLine>[];
124 // Parse each line in the stack trace. The supported line formats from the
125 // Dart VM are:
126 // #n <method-name> (<uri>:<line-no>:<column-no>)
127 // #n <method-name> (<uri>:<line-no>)
128 // in which '<anonymous closure>' is the name used for an (unnamed) function
129 // expression.
130 for (String line in stackTrace.split('\n')) {
131 try {
132 index++;
133 if (rangeStart != null && index < rangeStart) continue;
134 if (rangeEnd != null && index > rangeEnd) break;
135 if (line.isEmpty) continue;
136
137 // Strip index.
138 line = line.replaceFirst(indexPattern, '');
139
140 int leftParenPos = line.indexOf('(');
141 int rightParenPos = line.indexOf(')', leftParenPos);
142 int lastColon = line.lastIndexOf(':', rightParenPos);
143 int nextToLastColon = line.lastIndexOf(':', lastColon-1);
144
145 String lineNo;
146 String columnNo;
147 if (nextToLastColon != -1) {
148 lineNo = line.substring(nextToLastColon+1, lastColon);
149 columnNo = line.substring(lastColon+1, rightParenPos);
150 try {
151 int.parse(lineNo);
152 } on FormatException catch (e) {
153 lineNo = columnNo;
154 columnNo = '';
155 nextToLastColon = lastColon;
156 }
157 } else {
158 lineNo = line.substring(lastColon+1, rightParenPos);
159 columnNo = '';
160 nextToLastColon = lastColon;
161 }
162
163 if (lineNo.length > maxLineNoLength) {
164 maxLineNoLength = lineNo.length;
165 }
166 if (columnNo.length > maxColumnNoLength) {
167 maxColumnNoLength = columnNo.length;
168 }
169
170 String file = line.substring(leftParenPos+1, nextToLastColon);
171 if (filePrefix != null && file.startsWith(filePrefix)) {
172 file = file.substring(filePrefix.length);
173 }
174 if (file.length > maxFileLength) {
175 maxFileLength = file.length;
176 }
177 String method = line.substring(0, leftParenPos-1);
178 if (lambda != null) {
179 method = method.replaceAll('<anonymous closure>', lambda);
180 }
181 lines.add(new StackTraceLine(index, file, lineNo, columnNo, method));
182 } catch (e) {
183 throw 'Error prettifying "$line": $e';
184 }
185 }
186 return new StackTraceLines.fromLines(
187 lines, maxFileLength, maxLineNoLength, maxColumnNoLength);
188 }
189
190 StackTraceLines.fromLines(this.lines,
191 this.maxFileLength,
192 this.maxLineNoLength,
193 this.maxColumnNoLength);
194
195 StackTraceLines subtrace(int offset) {
196 return new StackTraceLines.fromLines(
197 lines.sublist(offset),
198 maxFileLength,
199 maxLineNoLength,
200 maxColumnNoLength);
201 }
202
203 String prettify({bool showColumnNo: false,
204 bool showDots: true}) {
205 StringBuffer sb = new StringBuffer();
206 bool dots = true;
207 for (StackTraceLine line in lines) {
208 sb.write(' ');
209 line.printOn(sb,
210 fileLength: maxFileLength,
211 padding: showDots && dots ? ' .' : ' ',
212 lineNoLength: maxLineNoLength,
213 showColumnNo: showColumnNo,
214 columnNoLength: maxColumnNoLength);
215
216 dots = !dots;
217 }
218 return sb.toString();
219 }
220
221 String toString() {
222 return prettify();
223 }
224 }
225
226 /// A parsed line from a stack trace.
227 class StackTraceLine {
228 final int index;
229 final String file;
230 final String lineNo;
231 final String columnNo;
232 final String method;
233
234 StackTraceLine(this.index, this.file, this.lineNo,
235 this.columnNo, this.method);
236
237 void printOn(StringBuffer sb,
238 {String padding: ' ',
239 int fileLength,
240 int lineNoLength,
241 int columnNoLength,
242 bool showColumnNo: false}) {
243 String fileText = '${file} ';
244 if (fileLength != null) {
245 fileText = pad(fileText, fileLength, dots: padding);
246 }
247 String lineNoText = lineNo;
248 if (lineNoLength != null) {
249 lineNoText = pad(lineNoText, lineNoLength, padLeft: true);
250 }
251 String columnNoText = showColumnNo ? '': columnNo;
252 if (columnNoLength != null) {
253 columnNoText = ':${pad(columnNoText, columnNoLength)}';
254 }
255 sb.write('$fileText $lineNoText$columnNoText $method\n');
256 }
257
258 int get hashCode {
259 return 13 * index +
260 17 * file.hashCode +
261 19 * lineNo.hashCode +
262 23 * columnNo.hashCode +
263 29 * method.hashCode;
264 }
265
266 bool operator ==(other) {
267 if (identical(this, other)) return true;
268 if (other is! StackTraceLine) return false;
269 return index == other.index &&
270 file == other.file &&
271 lineNo == other.lineNo &&
272 columnNo == other.columnNo &&
273 method == other.method;
274 }
275
276 String toString() => "$method @ $file [$lineNo:$columnNo]";
277 }
278
279 // TODO(johnniwinther): Use this format for --throw-on-error.
280 /**
281 * Converts the normal VM stack trace into a more compact and readable format.
282 *
283 * The output format is [: <file> . . . <lineNo>:<columnNo> <method> :] where
284 * [: <file> :] is file name, [: <lineNo> :] is the line number,
285 * [: <columnNo> :] is the column number, and [: <method> :] is the method name.
286 *
287 * If [rangeStart] and/or [rangeEnd] are provided, only the lines within the
288 * range are included.
289 * If [showColumnNo] is [:false:], the [: :<columnNo> :] part is omitted.
290 * If [showDots] is [:true:], the space between [: <file> :] and [: <lineNo> :]
291 * is padded with dots on every other line.
292 * If [filePrefix] is provided, then for every file name thats starts with
293 * [filePrefix] only the remainder is printed.
294 * If [lambda] is non-null, anonymous closures are printed as [lambda].
295 */
296 String prettifyStackTrace(StackTrace stackTrace,
297 {int rangeStart,
298 int rangeEnd,
299 bool showColumnNo: false,
300 bool showDots: true,
301 String filePrefix,
302 String lambda: r'?'}) {
303 return new StackTraceLines.fromTrace(stackTrace,
304 rangeStart: rangeStart, rangeEnd: rangeEnd,
305 filePrefix: filePrefix, lambda: lambda)
306 .prettify(showColumnNo: showColumnNo, showDots: showDots);
307 }
308
309 /**
310 * Pads (or truncates) [text] to the [intendedLength].
311 *
312 * If [padLeft] is [:true:] the text is padding inserted to the left of [text].
313 * A repetition of the [dots] text is used for padding.
314 */
315 String pad(String text, int intendedLength,
316 {bool padLeft: false, String dots: ' '}) {
317 if (text.length == intendedLength) return text;
318 if (text.length > intendedLength) return text.substring(0, intendedLength);
319 if (dots == null || dots.isEmpty) dots = ' ';
320 int dotsLength = dots.length;
321 StringBuffer sb = new StringBuffer();
322 if (!padLeft) {
323 sb.write(text);
324 }
325 for (int index = text.length ; index < intendedLength ; index ++) {
326 int dotsIndex = index % dotsLength;
327 sb.write(dots.substring(dotsIndex, dotsIndex + 1));
328 }
329 if (padLeft) {
330 sb.write(text);
331 }
332 return sb.toString();
333 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698