fromStackTraceLine static method

StackFrame? fromStackTraceLine(
  1. 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,
  );
}