foldFrames method Null safety
Returns a new Trace based on this where multiple stack frames matching
predicate
are folded together.
This means that whenever there are multiple frames in a row that match
predicate
, only the last one is kept. This is useful for limiting the
amount of library code that appears in a stack trace by only showing user
code and code that's called by user code.
If terse
is true, this will also fold together frames from the core
library or from this package, simplify core library frames, and
potentially remove the outermost frame as in Trace.terse.
Implementation
Trace foldFrames(bool Function(Frame) predicate, {bool terse = false}) {
if (terse) {
var oldPredicate = predicate;
predicate = (frame) {
if (oldPredicate(frame)) return true;
if (frame.isCore) return true;
if (frame.package == 'stack_trace') return true;
// Ignore async stack frames without any line or column information.
// These come from the VM's async/await implementation and represent
// internal frames. They only ever show up in stack chains and are
// always surrounded by other traces that are actually useful, so we can
// just get rid of them.
// TODO(nweiz): Get rid of this logic some time after issue 22009 is
// fixed.
if (!frame.member!.contains('<async>')) return false;
return frame.line == null;
};
}
var newFrames = <Frame>[];
for (var frame in frames.reversed) {
if (frame is UnparsedFrame || !predicate(frame)) {
newFrames.add(frame);
} else if (newFrames.isEmpty || !predicate(newFrames.last)) {
newFrames.add(Frame(frame.uri, frame.line, frame.column, frame.member));
}
}
if (terse) {
newFrames = newFrames.map((frame) {
if (frame is UnparsedFrame || !predicate(frame)) return frame;
var library = frame.library.replaceAll(_terseRegExp, '');
return Frame(Uri.parse(library), null, null, frame.member);
}).toList();
if (newFrames.length > 1 && predicate(newFrames.first)) {
newFrames.removeAt(0);
}
}
return Trace(newFrames.reversed, original: original.toString());
}