| 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 utils; | 5 library utils; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:stack_trace/stack_trace.dart'; | 9 import 'package:stack_trace/stack_trace.dart'; |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 int get hashCode => first.hashCode ^ last.hashCode; | 25 int get hashCode => first.hashCode ^ last.hashCode; |
| 26 } | 26 } |
| 27 | 27 |
| 28 /// Configures [future] so that its result (success or exception) is passed on | 28 /// Configures [future] so that its result (success or exception) is passed on |
| 29 /// to [completer]. | 29 /// to [completer]. |
| 30 void chainToCompleter(Future future, Completer completer) { | 30 void chainToCompleter(Future future, Completer completer) { |
| 31 future.then(completer.complete, onError: completer.completeError); | 31 future.then(completer.complete, onError: completer.completeError); |
| 32 } | 32 } |
| 33 | 33 |
| 34 /// Like [Future.sync], but wraps the Future in [Chain.track] as well. |
| 35 Future syncFuture(callback()) => Chain.track(new Future.sync(callback)); |
| 36 |
| 34 /// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the | 37 /// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the |
| 35 /// first line is prefixed with that instead. | 38 /// first line is prefixed with that instead. |
| 36 String prefixLines(String text, {String prefix: '| ', String firstPrefix}) { | 39 String prefixLines(String text, {String prefix: '| ', String firstPrefix}) { |
| 37 var lines = text.split('\n'); | 40 var lines = text.split('\n'); |
| 38 if (firstPrefix == null) { | 41 if (firstPrefix == null) { |
| 39 return lines.map((line) => '$prefix$line').join('\n'); | 42 return lines.map((line) => '$prefix$line').join('\n'); |
| 40 } | 43 } |
| 41 | 44 |
| 42 var firstLine = "$firstPrefix${lines.first}"; | 45 var firstLine = "$firstPrefix${lines.first}"; |
| 43 lines = lines.skip(1).map((line) => '$prefix$line').toList(); | 46 lines = lines.skip(1).map((line) => '$prefix$line').toList(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 65 | 68 |
| 66 while (true) { | 69 while (true) { |
| 67 var hasNext1 = iter1.moveNext(); | 70 var hasNext1 = iter1.moveNext(); |
| 68 var hasNext2 = iter2.moveNext(); | 71 var hasNext2 = iter2.moveNext(); |
| 69 if (hasNext1 != hasNext2) return false; | 72 if (hasNext1 != hasNext2) return false; |
| 70 if (!hasNext1) return true; | 73 if (!hasNext1) return true; |
| 71 if (iter1.current != iter2.current) return false; | 74 if (iter1.current != iter2.current) return false; |
| 72 } | 75 } |
| 73 } | 76 } |
| 74 | 77 |
| 75 // TODO(nweiz): remove this when issue 8731 is fixed. | |
| 76 /// Returns a [Stream] that will immediately emit [error] and then close. | |
| 77 Stream errorStream(error) => new Future.error(error).asStream(); | |
| 78 | |
| 79 /// Returns a buffered stream that will emit the same values as the stream | 78 /// Returns a buffered stream that will emit the same values as the stream |
| 80 /// returned by [future] once [future] completes. | 79 /// returned by [future] once [future] completes. |
| 81 /// | 80 /// |
| 82 /// If [future] completes to an error, the return value will emit that error and | 81 /// If [future] completes to an error, the return value will emit that error and |
| 83 /// then close. | 82 /// then close. |
| 84 /// | 83 /// |
| 85 /// If [broadcast] is true, a broadcast stream is returned. This assumes that | 84 /// If [broadcast] is true, a broadcast stream is returned. This assumes that |
| 86 /// the stream returned by [future] will be a broadcast stream as well. | 85 /// the stream returned by [future] will be a broadcast stream as well. |
| 87 /// [broadcast] defaults to false. | 86 /// [broadcast] defaults to false. |
| 88 Stream futureStream(Future<Stream> future, {bool broadcast: false}) { | 87 Stream futureStream(Future<Stream> future, {bool broadcast: false}) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 controller = new StreamController( | 119 controller = new StreamController( |
| 121 sync: true, onListen: onListen, onCancel: onCancel); | 120 sync: true, onListen: onListen, onCancel: onCancel); |
| 122 } | 121 } |
| 123 return controller.stream; | 122 return controller.stream; |
| 124 } | 123 } |
| 125 | 124 |
| 126 /// Returns the first element of a [StreamIterator]. | 125 /// Returns the first element of a [StreamIterator]. |
| 127 /// | 126 /// |
| 128 /// If the [StreamIterator] has no elements, the result is a state error. | 127 /// If the [StreamIterator] has no elements, the result is a state error. |
| 129 Future<String> streamIteratorFirst(StreamIterator<String> streamIterator) { | 128 Future<String> streamIteratorFirst(StreamIterator<String> streamIterator) { |
| 130 StackTrace stackTrace = new Trace.current(); | |
| 131 return streamIterator.moveNext().then((hasNext) { | 129 return streamIterator.moveNext().then((hasNext) { |
| 132 if (hasNext) { | 130 if (hasNext) { |
| 133 return streamIterator.current; | 131 return streamIterator.current; |
| 134 } else { | 132 } else { |
| 135 return new Future.error(new StateError("No elements"), stackTrace); | 133 throw new StateError("No elements"); |
| 136 } | 134 } |
| 137 }); | 135 }); |
| 138 } | 136 } |
| 139 | 137 |
| 140 /// Collects all remaining lines from a [StreamIterator] of lines. | 138 /// Collects all remaining lines from a [StreamIterator] of lines. |
| 141 /// | 139 /// |
| 142 /// Returns the concatenation of the collected lines joined by newlines. | 140 /// Returns the concatenation of the collected lines joined by newlines. |
| 143 Future<String> concatRest(StreamIterator<String> streamIterator) { | 141 Future<String> concatRest(StreamIterator<String> streamIterator) { |
| 144 var completer = new Completer<String>(); | 142 var completer = new Completer<String>(); |
| 145 var buffer = new StringBuffer(); | 143 var buffer = new StringBuffer(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 /// Returns whether [pattern] matches all of [string]. | 224 /// Returns whether [pattern] matches all of [string]. |
| 227 bool fullMatch(String string, Pattern pattern) { | 225 bool fullMatch(String string, Pattern pattern) { |
| 228 var matches = pattern.allMatches(string); | 226 var matches = pattern.allMatches(string); |
| 229 if (matches.isEmpty) return false; | 227 if (matches.isEmpty) return false; |
| 230 return matches.first.start == 0 && matches.first.end == string.length; | 228 return matches.first.start == 0 && matches.first.end == string.length; |
| 231 } | 229 } |
| 232 | 230 |
| 233 /// Returns a string representation of [trace] that has the core and test frames | 231 /// Returns a string representation of [trace] that has the core and test frames |
| 234 /// folded together. | 232 /// folded together. |
| 235 String terseTraceString(StackTrace trace) { | 233 String terseTraceString(StackTrace trace) { |
| 236 return new Trace.from(trace).terse.foldFrames((frame) { | 234 return new Chain(new Chain.forTrace(trace).traces.map((trace) { |
| 237 return frame.package == 'scheduled_test' || frame.package == 'unittest' || | 235 return trace.foldFrames((frame) { |
| 238 frame.isCore; | 236 return frame.package == 'scheduled_test' || |
| 239 }).toString().trim(); | 237 frame.package == 'unittest' || |
| 238 frame.package == 'stack_trace' || |
| 239 frame.isCore; |
| 240 }); |
| 241 })).terse.toString().trim(); |
| 240 } | 242 } |
| OLD | NEW |