| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 dart2js.util; | 5 library dart2js.util; |
| 6 | 6 |
| 7 import "dart:collection"; | 7 import "dart:collection"; |
| 8 import 'util_implementation.dart'; | 8 import 'util_implementation.dart'; |
| 9 import 'characters.dart'; | 9 import 'characters.dart'; |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 class SpannableAssertionFailure { | 33 class SpannableAssertionFailure { |
| 34 final Spannable node; | 34 final Spannable node; |
| 35 final String message; | 35 final String message; |
| 36 SpannableAssertionFailure(this.node, this.message); | 36 SpannableAssertionFailure(this.node, this.message); |
| 37 | 37 |
| 38 String toString() => 'Compiler crashed: $message.'; | 38 String toString() => 'Compiler crashed: $message.'; |
| 39 } | 39 } |
| 40 | 40 |
| 41 /** | 41 /** |
| 42 * Helper method for printing stack traces for debugging. | 42 * Helper method for printing stack traces for debugging. |
| 43 * | 43 * |
| 44 * [message] is printed as the header of the stack trace. | 44 * [message] is printed as the header of the stack trace. |
| 45 * | 45 * |
| 46 * If [condition] is provided, the stack trace is only printed if [condition] | 46 * If [condition] is provided, the stack trace is only printed if [condition] |
| 47 * returns [:true:] on the stack trace text. This can be used to filter the | 47 * returns [:true:] on the stack trace text. This can be used to filter the |
| 48 * printed stack traces based on their content. For instance only print stack | 48 * printed stack traces based on their content. For instance only print stack |
| 49 * traces that contain specific paths. | 49 * traces that contain specific paths. |
| 50 */ | 50 */ |
| 51 void trace(String message, [bool condition(String stackTrace)]) { | 51 void trace(String message, [bool condition(String stackTrace)]) { |
| 52 try { | 52 try { |
| 53 throw ''; | 53 throw ''; |
| 54 } catch (e, s) { | 54 } catch (e, s) { |
| 55 String stackTrace = prettifyStackTrace( | 55 String stackTrace = prettifyStackTrace( |
| 56 s, rangeStart: 1, filePrefix: stackTraceFilePrefix); | 56 s, rangeStart: 1, filePrefix: stackTraceFilePrefix); |
| 57 if (condition != null) { | 57 if (condition != null) { |
| 58 if (!condition(stackTrace)) return; | 58 if (!condition(stackTrace)) return; |
| 59 } | 59 } |
| 60 print('$message\n$stackTrace'); | 60 print('$message\n$stackTrace'); |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 | 63 |
| 64 /** | 64 /** |
| 65 * File name prefix used to shorten the file name in stack traces printed by | 65 * File name prefix used to shorten the file name in stack traces printed by |
| 66 * [trace]. | 66 * [trace]. |
| 67 */ | 67 */ |
| 68 String stackTraceFilePrefix = null; | 68 String stackTraceFilePrefix = null; |
| 69 | 69 |
| 70 /// Helper class for the processing of stack traces in [prettifyStackTrace]. | 70 /// Helper class for the processing of stack traces in [prettifyStackTrace]. |
| 71 class _StackTraceLine { | 71 class _StackTraceLine { |
| 72 final int index; | 72 final int index; |
| 73 final String file; | 73 final String file; |
| 74 final String lineNo; | 74 final String lineNo; |
| 75 final String columnNo; | 75 final String columnNo; |
| 76 final String method; | 76 final String method; |
| 77 | 77 |
| 78 _StackTraceLine(this.index, this.file, this.lineNo, | 78 _StackTraceLine(this.index, this.file, this.lineNo, |
| 79 this.columnNo, this.method); | 79 this.columnNo, this.method); |
| 80 } | 80 } |
| 81 | 81 |
| 82 // TODO(johnniwinther): Use this format for --throw-on-error. | 82 // TODO(johnniwinther): Use this format for --throw-on-error. |
| 83 /** | 83 /** |
| 84 * Converts the normal VM stack trace into a more compact and readable format. | 84 * Converts the normal VM stack trace into a more compact and readable format. |
| 85 * | 85 * |
| 86 * The output format is [: <file> . . . <lineNo>:<columnNo> <method> :] where | 86 * The output format is [: <file> . . . <lineNo>:<columnNo> <method> :] where |
| 87 * [: <file> :] is file name, [: <lineNo> :] is the line number, | 87 * [: <file> :] is file name, [: <lineNo> :] is the line number, |
| 88 * [: <columnNo> :] is the column number, and [: <method> :] is the method name. | 88 * [: <columnNo> :] is the column number, and [: <method> :] is the method name. |
| 89 * | 89 * |
| 90 * If [rangeStart] and/or [rangeEnd] are provided, only the lines within the | 90 * If [rangeStart] and/or [rangeEnd] are provided, only the lines within the |
| 91 * range are included. | 91 * range are included. |
| 92 * If [showColumnNo] is [:false:], the [: :<columnNo> :] part is omitted. | 92 * If [showColumnNo] is [:false:], the [: :<columnNo> :] part is omitted. |
| 93 * If [showDots] is [:true:], the space between [: <file> :] and [: <lineNo> :] | 93 * If [showDots] is [:true:], the space between [: <file> :] and [: <lineNo> :] |
| 94 * is padded with dots on every other line. | 94 * is padded with dots on every other line. |
| 95 * If [filePrefix] is provided, then for every file name thats starts with | 95 * If [filePrefix] is provided, then for every file name thats starts with |
| 96 * [filePrefix] only the remainder is printed. | 96 * [filePrefix] only the remainder is printed. |
| 97 * If [lambda] is non-null, anonymous closures are printed as [lambda]. | 97 * If [lambda] is non-null, anonymous closures are printed as [lambda]. |
| 98 */ | 98 */ |
| 99 String prettifyStackTrace(StackTrace s, | 99 String prettifyStackTrace(StackTrace s, |
| 100 {int rangeStart, | 100 {int rangeStart, |
| 101 int rangeEnd, | 101 int rangeEnd, |
| 102 bool showColumnNo: false, | 102 bool showColumnNo: false, |
| 103 bool showDots: true, | 103 bool showDots: true, |
| 104 String filePrefix, | 104 String filePrefix, |
| 105 String lambda: r'?'}) { | 105 String lambda: r'?'}) { |
| 106 int index = -1; | 106 int index = -1; |
| 107 int maxFileLength = 0; | 107 int maxFileLength = 0; |
| 108 int maxLineNoLength = 0; | 108 int maxLineNoLength = 0; |
| 109 int maxColumnNoLength = 0; | 109 int maxColumnNoLength = 0; |
| 110 | 110 |
| 111 List<_StackTraceLine> lines = <_StackTraceLine>[]; | 111 List<_StackTraceLine> lines = <_StackTraceLine>[]; |
| 112 for (String line in '$s'.split('\n')) { | 112 for (String line in '$s'.split('\n')) { |
| 113 index++; | 113 index++; |
| 114 if (rangeStart != null && index < rangeStart) continue; | 114 if (rangeStart != null && index < rangeStart) continue; |
| 115 if (rangeEnd != null && index > rangeEnd) continue; | 115 if (rangeEnd != null && index > rangeEnd) continue; |
| 116 if (line.isEmpty) continue; | 116 if (line.isEmpty) continue; |
| 117 | 117 |
| 118 // Strip index. | 118 // Strip index. |
| 119 line = line.replaceFirst(new RegExp(r'#\d+\s*'), ''); | 119 line = line.replaceFirst(new RegExp(r'#\d+\s*'), ''); |
| 120 | 120 |
| 121 int leftParenPos = line.indexOf('('); | 121 int leftParenPos = line.indexOf('('); |
| 122 int rightParenPos = line.indexOf(')', leftParenPos); | 122 int rightParenPos = line.indexOf(')', leftParenPos); |
| 123 int lastColon = line.lastIndexOf(':', rightParenPos); | 123 int lastColon = line.lastIndexOf(':', rightParenPos); |
| 124 int nextToLastColon = line.lastIndexOf(':', lastColon-1); | 124 int nextToLastColon = line.lastIndexOf(':', lastColon-1); |
| 125 | 125 |
| 126 String lineNo = line.substring(nextToLastColon+1, lastColon); | 126 String lineNo = line.substring(nextToLastColon+1, lastColon); |
| 127 if (lineNo.length > maxLineNoLength) { | 127 if (lineNo.length > maxLineNoLength) { |
| 128 maxLineNoLength = lineNo.length; | 128 maxLineNoLength = lineNo.length; |
| 129 } | 129 } |
| 130 String columnNo = line.substring(lastColon+1, rightParenPos); | 130 String columnNo = line.substring(lastColon+1, rightParenPos); |
| 131 if (columnNo.length > maxColumnNoLength) { | 131 if (columnNo.length > maxColumnNoLength) { |
| 132 maxColumnNoLength = columnNo.length; | 132 maxColumnNoLength = columnNo.length; |
| 133 } | 133 } |
| 134 String file = line.substring(leftParenPos+1, nextToLastColon); | 134 String file = line.substring(leftParenPos+1, nextToLastColon); |
| 135 if (filePrefix != null && file.startsWith(filePrefix)) { | 135 if (filePrefix != null && file.startsWith(filePrefix)) { |
| 136 file = file.substring(filePrefix.length); | 136 file = file.substring(filePrefix.length); |
| 137 } | 137 } |
| 138 if (file.length > maxFileLength) { | 138 if (file.length > maxFileLength) { |
| 139 maxFileLength = file.length; | 139 maxFileLength = file.length; |
| 140 } | 140 } |
| 141 String method = line.substring(0, leftParenPos-1); | 141 String method = line.substring(0, leftParenPos-1); |
| 142 if (lambda != null) { | 142 if (lambda != null) { |
| 143 method = method.replaceAll('<anonymous closure>', lambda); | 143 method = method.replaceAll('<anonymous closure>', lambda); |
| 144 } | 144 } |
| 145 lines.add(new _StackTraceLine(index, file, lineNo, columnNo, method)); | 145 lines.add(new _StackTraceLine(index, file, lineNo, columnNo, method)); |
| 146 } | 146 } |
| 147 | 147 |
| 148 StringBuffer sb = new StringBuffer(); | 148 StringBuffer sb = new StringBuffer(); |
| 149 bool dots = true; | 149 bool dots = true; |
| 150 for (_StackTraceLine line in lines) { | 150 for (_StackTraceLine line in lines) { |
| 151 String file = pad('${line.file} ', maxFileLength, | 151 String file = pad('${line.file} ', maxFileLength, |
| 152 dots: showDots && dots ? ' .' : ' '); | 152 dots: showDots && dots ? ' .' : ' '); |
| 153 String lineNo = pad(line.lineNo, maxLineNoLength, padLeft: true); | 153 String lineNo = pad(line.lineNo, maxLineNoLength, padLeft: true); |
| 154 String columnNo = | 154 String columnNo = |
| 155 showColumnNo ? ':${pad(line.columnNo, maxColumnNoLength)}' : ''; | 155 showColumnNo ? ':${pad(line.columnNo, maxColumnNoLength)}' : ''; |
| 156 String method = line.method; | 156 String method = line.method; |
| 157 sb.write(' $file $lineNo$columnNo $method\n'); | 157 sb.write(' $file $lineNo$columnNo $method\n'); |
| 158 dots = !dots; | 158 dots = !dots; |
| 159 } | 159 } |
| 160 | 160 |
| 161 return sb.toString(); | 161 return sb.toString(); |
| 162 } | 162 } |
| 163 | 163 |
| 164 /** | 164 /** |
| 165 * Pads (or truncates) [text] to the [intendedLength]. | 165 * Pads (or truncates) [text] to the [intendedLength]. |
| 166 * | 166 * |
| 167 * If [padLeft] is [:true:] the text is padding inserted to the left of [text]. | 167 * If [padLeft] is [:true:] the text is padding inserted to the left of [text]. |
| 168 * A repetition of the [dots] text is used for padding. | 168 * A repetition of the [dots] text is used for padding. |
| 169 */ | 169 */ |
| 170 String pad(String text, int intendedLength, | 170 String pad(String text, int intendedLength, |
| 171 {bool padLeft: false, String dots: ' '}) { | 171 {bool padLeft: false, String dots: ' '}) { |
| 172 if (text.length == intendedLength) return text; | 172 if (text.length == intendedLength) return text; |
| 173 if (text.length > intendedLength) return text.substring(0, intendedLength); | 173 if (text.length > intendedLength) return text.substring(0, intendedLength); |
| 174 if (dots == null || dots.isEmpty) dots = ' '; | 174 if (dots == null || dots.isEmpty) dots = ' '; |
| 175 int dotsLength = dots.length; | 175 int dotsLength = dots.length; |
| 176 StringBuffer sb = new StringBuffer(); | 176 StringBuffer sb = new StringBuffer(); |
| 177 if (!padLeft) { | 177 if (!padLeft) { |
| 178 sb.write(text); | 178 sb.write(text); |
| 179 } | 179 } |
| 180 for (int index = text.length ; index < intendedLength ; index ++) { | 180 for (int index = text.length ; index < intendedLength ; index ++) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 } | 259 } |
| 260 buffer.write(string); | 260 buffer.write(string); |
| 261 } | 261 } |
| 262 | 262 |
| 263 int computeHashCode(part1, [part2, part3, part4]) { | 263 int computeHashCode(part1, [part2, part3, part4]) { |
| 264 return (part1.hashCode | 264 return (part1.hashCode |
| 265 ^ part2.hashCode | 265 ^ part2.hashCode |
| 266 ^ part3.hashCode | 266 ^ part3.hashCode |
| 267 ^ part4.hashCode) & 0x3fffffff; | 267 ^ part4.hashCode) & 0x3fffffff; |
| 268 } | 268 } |
| OLD | NEW |