fromStackTraceLine static method
- String line
Parses a single StackFrame from a single line of a StackTrace.
Returns null if format is not as expected.
Implementation
static StackFrame? fromStackTraceLine(String line) {
if (line == '<asynchronous suspension>') {
return asynchronousSuspension;
} else if (line == '...') {
return stackOverFlowElision;
}
assert(
line != '===== asynchronous gap ===========================',
'Got a stack frame from package:stack_trace, where a vm or web frame was expected. '
'This can happen if FlutterError.demangleStackTrace was not set in an environment '
'that propagates non-standard stack traces to the framework, such as during tests.',
);
// Web frames.
if (!line.startsWith('#')) {
return _tryParseWebFrame(line);
}
final RegExp parser = RegExp(r'^#(\d+) +(.+) \((.+?):?(\d+){0,1}:?(\d+){0,1}\)$');
Match? match = parser.firstMatch(line);
assert(match != null, 'Expected $line to match $parser.');
match = match!;
bool isConstructor = false;
String className = '';
String method = match.group(2)!.replaceAll('.<anonymous closure>', '');
if (method.startsWith('new')) {
final List<String> methodParts = method.split(' ');
// Sometimes a web frame will only read "new" and have no class name.
className = methodParts.length > 1 ? method.split(' ')[1] : '<unknown>';
method = '';
if (className.contains('.')) {
final List<String> parts = className.split('.');
className = parts[0];
method = parts[1];
}
isConstructor = true;
} else if (method.contains('.')) {
final List<String> parts = method.split('.');
className = parts[0];
method = parts[1];
}
final Uri packageUri = Uri.parse(match.group(3)!);
String package = '<unknown>';
String packagePath = packageUri.path;
if (packageUri.scheme == 'dart' || packageUri.scheme == 'package') {
package = packageUri.pathSegments[0];
packagePath = packageUri.path.replaceFirst('${packageUri.pathSegments[0]}/', '');
}
return StackFrame(
number: int.parse(match.group(1)!),
className: className,
method: method,
packageScheme: packageUri.scheme,
package: package,
packagePath: packagePath,
line: match.group(4) == null ? -1 : int.parse(match.group(4)!),
column: match.group(5) == null ? -1 : int.parse(match.group(5)!),
isConstructor: isConstructor,
source: line,
);
}