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); }); });