Support parsing empty stack chains.
Closes dart-lang/stack_trace#4
R=rnystrom@google.com
Review URL: https://codereview.chromium.org//1171873002.
diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md
index d4696ec..8615187 100644
--- a/pkgs/stack_trace/CHANGELOG.md
+++ b/pkgs/stack_trace/CHANGELOG.md
@@ -4,6 +4,8 @@
nested `Chain.capture()` blocks, substitute the inner block's chain rather
than the outer block's.
+* Add support for empty chains and chains of empty traces to `Chain.parse()`.
+
## 1.3.2
* Don't crash when running `Trace.terse` on empty stack traces.
diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart
index 87cc6be..3e2100e 100644
--- a/pkgs/stack_trace/lib/src/chain.dart
+++ b/pkgs/stack_trace/lib/src/chain.dart
@@ -127,8 +127,11 @@
/// Parses a string representation of a stack chain.
///
/// Specifically, this parses the output of [Chain.toString].
- factory Chain.parse(String chain) =>
- new Chain(chain.split(_gap).map((trace) => new Trace.parseFriendly(trace)));
+ factory Chain.parse(String chain) {
+ if (chain.isEmpty) return new Chain([]);
+ return new Chain(
+ chain.split(_gap).map((trace) => new Trace.parseFriendly(trace)));
+ }
/// Returns a new [Chain] comprised of [traces].
Chain(Iterable<Trace> traces)
diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart
index 84a19ef..418c4ab 100644
--- a/pkgs/stack_trace/lib/src/trace.dart
+++ b/pkgs/stack_trace/lib/src/trace.dart
@@ -188,10 +188,12 @@
/// This also parses string representations of [Chain]s. They parse to the
/// same trace that [Chain.toTrace] would return.
Trace.parseFriendly(String trace)
- : this(trace.trim().split("\n")
- // Filter out asynchronous gaps from [Chain]s.
- .where((line) => !line.startsWith('====='))
- .map((line) => new Frame.parseFriendly(line)));
+ : this(trace.isEmpty
+ ? []
+ : trace.trim().split("\n")
+ // Filter out asynchronous gaps from [Chain]s.
+ .where((line) => !line.startsWith('====='))
+ .map((line) => new Frame.parseFriendly(line)));
/// Returns a new [Trace] comprised of [frames].
Trace(Iterable<Frame> frames)
diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart
index bfe322c..0b6f36e 100644
--- a/pkgs/stack_trace/test/chain_test.dart
+++ b/pkgs/stack_trace/test/chain_test.dart
@@ -472,10 +472,28 @@
equals(new Trace.from(trace).toString()));
});
- test('Chain.parse() parses a real Chain', () {
- return captureFuture(() => inMicrotask(() => throw 'error')).then((chain) {
- expect(new Chain.parse(chain.toString()).toString(),
- equals(chain.toString()));
+ group('Chain.parse()', () {
+ test('parses a real Chain', () {
+ return captureFuture(() => inMicrotask(() => throw 'error'))
+ .then((chain) {
+ expect(new Chain.parse(chain.toString()).toString(),
+ equals(chain.toString()));
+ });
+ });
+
+ test('parses an empty string', () {
+ var chain = new Chain.parse('');
+ expect(chain.traces, isEmpty);
+ });
+
+ test('parses a chain containing empty traces', () {
+ var chain = new Chain.parse(
+ '===== asynchronous gap ===========================\n'
+ '===== asynchronous gap ===========================\n');
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces[0].frames, isEmpty);
+ expect(chain.traces[1].frames, isEmpty);
+ expect(chain.traces[2].frames, isEmpty);
});
});