// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:meta/meta.dart';

import 'basic_types.dart';
import 'constants.dart';
import 'diagnostics.dart';
import 'print.dart';
import 'stack_frame.dart';

// Examples can assume:
// late String runtimeType;
// late bool draconisAlive;
// late bool draconisAmulet;
// late Diagnosticable draconis;
// void methodThatMayThrow() { }

/// Signature for [FlutterError.onError] handler.
typedef FlutterExceptionHandler = void Function(FlutterErrorDetails details);

/// Signature for [DiagnosticPropertiesBuilder] transformer.
typedef DiagnosticPropertiesTransformer = Iterable<DiagnosticsNode> Function(Iterable<DiagnosticsNode> properties);

/// Signature for [FlutterErrorDetails.informationCollector] callback
/// and other callbacks that collect information describing an error.
typedef InformationCollector = Iterable<DiagnosticsNode> Function();

/// Signature for a function that demangles [StackTrace] objects into a format
/// that can be parsed by [StackFrame].
///
/// See also:
///
///   * [FlutterError.demangleStackTrace], which shows an example implementation.
typedef StackTraceDemangler = StackTrace Function(StackTrace details);

/// Partial information from a stack frame for stack filtering purposes.
///
/// See also:
///
///  * [RepetitiveStackFrameFilter], which uses this class to compare against [StackFrame]s.
@immutable
class PartialStackFrame {
  /// Creates a new [PartialStackFrame] instance. All arguments are required and
  /// must not be null.
  const PartialStackFrame({
    required this.package,
    required this.className,
    required this.method,
  }) : assert(className != null),
       assert(method != null),
       assert(package != null);

  /// An `<asynchronous suspension>` line in a stack trace.
  static const PartialStackFrame asynchronousSuspension = PartialStackFrame(
    package: '',
    className: '',
    method: 'asynchronous suspension',
  );

  /// The package to match, e.g. `package:flutter/src/foundation/assertions.dart`,
  /// or `dart:ui/window.dart`.
  final Pattern package;

  /// The class name for the method.
  ///
  /// On web, this is ignored, since class names are not available.
  ///
  /// On all platforms, top level methods should use the empty string.
  final String className;

  /// The method name for this frame line.
  ///
  /// On web, private methods are wrapped with `[]`.
  final String method;

  /// Tests whether the [StackFrame] matches the information in this
  /// [PartialStackFrame].
  bool matches(StackFrame stackFrame) {
    final String stackFramePackage = '${stackFrame.packageScheme}:${stackFrame.package}/${stackFrame.packagePath}';
    // Ideally this wouldn't be necessary.
    // TODO(dnfield): https://github.com/dart-lang/sdk/issues/40117
    if (kIsWeb) {
      return package.allMatches(stackFramePackage).isNotEmpty
          && stackFrame.method == (method.startsWith('_') ? '[$method]' : method);
    }
    return package.allMatches(stackFramePackage).isNotEmpty
        && stackFrame.method == method
        && stackFrame.className == className;
  }
}

/// A class that filters stack frames for additional filtering on
/// [FlutterError.defaultStackFilter].
abstract class StackFilter {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const StackFilter();

  /// Filters the list of [StackFrame]s by updating corresponding indices in
  /// `reasons`.
  ///
  /// To elide a frame or number of frames, set the string.
  void filter(List<StackFrame> stackFrames, List<String?> reasons);
}


/// A [StackFilter] that filters based on repeating lists of
/// [PartialStackFrame]s.
///
/// See also:
///
///   * [FlutterError.addDefaultStackFilter], a method to register additional
///     stack filters for [FlutterError.defaultStackFilter].
///   * [StackFrame], a class that can help with parsing stack frames.
///   * [PartialStackFrame], a class that helps match partial method information
///     to a stack frame.
class RepetitiveStackFrameFilter extends StackFilter {
  /// Creates a new RepetitiveStackFrameFilter. All parameters are required and must not be
  /// null.
  const RepetitiveStackFrameFilter({
    required this.frames,
    required this.replacement,
  }) : assert(frames != null),
       assert(replacement != null);

  /// The shape of this repetitive stack pattern.
  final List<PartialStackFrame> frames;

  /// The number of frames in this pattern.
  int get numFrames => frames.length;

  /// The string to replace the frames with.
  ///
  /// If the same replacement string is used multiple times in a row, the
  /// [FlutterError.defaultStackFilter] will simply update a counter after this
  /// line rather than repeating it.
  final String replacement;

  List<String> get _replacements => List<String>.filled(numFrames, replacement);

  @override
  void filter(List<StackFrame> stackFrames, List<String?> reasons) {
    for (int index = 0; index < stackFrames.length - numFrames; index += 1) {
      if (_matchesFrames(stackFrames.skip(index).take(numFrames).toList())) {
        reasons.setRange(index, index + numFrames, _replacements);
        index += numFrames - 1;
      }
    }
  }

  bool _matchesFrames(List<StackFrame> stackFrames) {
    if (stackFrames.length < numFrames) {
      return false;
    }
    for (int index = 0; index < stackFrames.length; index++) {
      if (!frames[index].matches(stackFrames[index])) {
        return false;
      }
    }
    return true;
  }
}

abstract class _ErrorDiagnostic extends DiagnosticsProperty<List<Object>> {
  /// This constructor provides a reliable hook for a kernel transformer to find
  /// error messages that need to be rewritten to include object references for
  /// interactive display of errors.
  _ErrorDiagnostic(
    String message, {
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.flat,
    DiagnosticLevel level = DiagnosticLevel.info,
  }) : assert(message != null),
       super(
         null,
         <Object>[message],
         showName: false,
         showSeparator: false,
         defaultValue: null,
         style: style,
         level: level,
       );

  /// In debug builds, a kernel transformer rewrites calls to the default
  /// constructors for [ErrorSummary], [ErrorDescription], and [ErrorHint] to use
  /// this constructor.
  //
  // ```dart
  // _ErrorDiagnostic('Element $element must be $color')
  // ```
  // Desugars to:
  // ```dart
  // _ErrorDiagnostic.fromParts(<Object>['Element ', element, ' must be ', color])
  // ```
  //
  // Slightly more complex case:
  // ```dart
  // _ErrorDiagnostic('Element ${element.runtimeType} must be $color')
  // ```
  // Desugars to:
  //```dart
  // _ErrorDiagnostic.fromParts(<Object>[
  //   'Element ',
  //   DiagnosticsProperty(null, element, description: element.runtimeType?.toString()),
  //   ' must be ',
  //   color,
  // ])
  // ```
  _ErrorDiagnostic._fromParts(
    List<Object> messageParts, {
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.flat,
    DiagnosticLevel level = DiagnosticLevel.info,
  }) : assert(messageParts != null),
       super(
         null,
         messageParts,
         showName: false,
         showSeparator: false,
         defaultValue: null,
         style: style,
         level: level,
       );


  @override
  List<Object> get value => super.value!;

  @override
  String valueToString({ TextTreeConfiguration? parentConfiguration }) {
    return value.join();
  }
}

/// An explanation of the problem and its cause, any information that may help
/// track down the problem, background information, etc.
///
/// Use [ErrorDescription] for any part of an error message where neither
/// [ErrorSummary] or [ErrorHint] is appropriate.
///
/// In debug builds, values interpolated into the `message` are
/// expanded and placed into [value], which is of type [List<Object>].
/// This allows IDEs to examine values interpolated into error messages.
///
/// See also:
///
///  * [ErrorSummary], which provides a short (one line) description of the
///    problem that was detected.
///  * [ErrorHint], which provides specific, non-obvious advice that may be
///    applicable.
///  * [ErrorSpacer], which renders as a blank line.
///  * [FlutterError], which is the most common place to use an
///    [ErrorDescription].
class ErrorDescription extends _ErrorDiagnostic {
  /// A lint enforces that this constructor can only be called with a string
  /// literal to match the limitations of the Dart Kernel transformer that
  /// optionally extracts out objects referenced using string interpolation in
  /// the message passed in.
  ///
  /// The message will display with the same text regardless of whether the
  /// kernel transformer is used. The kernel transformer is required so that
  /// debugging tools can provide interactive displays of objects described by
  /// the error.
  ErrorDescription(String message) : super(message, level: DiagnosticLevel.info);

  /// Calls to the default constructor may be rewritten to use this constructor
  /// in debug mode using a kernel transformer.
  // ignore: unused_element
  ErrorDescription._fromParts(List<Object> messageParts) : super._fromParts(messageParts, level: DiagnosticLevel.info);
}

/// A short (one line) description of the problem that was detected.
///
/// Error summaries from the same source location should have little variance,
/// so that they can be recognized as related. For example, they shouldn't
/// include hash codes.
///
/// A [FlutterError] must start with an [ErrorSummary] and may not contain
/// multiple summaries.
///
/// In debug builds, values interpolated into the `message` are
/// expanded and placed into [value], which is of type [List<Object>].
/// This allows IDEs to examine values interpolated into error messages.
///
/// See also:
///
///  * [ErrorDescription], which provides an explanation of the problem and its
///    cause, any information that may help track down the problem, background
///    information, etc.
///  * [ErrorHint], which provides specific, non-obvious advice that may be
///    applicable.
///  * [FlutterError], which is the most common place to use an [ErrorSummary].
class ErrorSummary extends _ErrorDiagnostic {
  /// A lint enforces that this constructor can only be called with a string
  /// literal to match the limitations of the Dart Kernel transformer that
  /// optionally extracts out objects referenced using string interpolation in
  /// the message passed in.
  ///
  /// The message will display with the same text regardless of whether the
  /// kernel transformer is used. The kernel transformer is required so that
  /// debugging tools can provide interactive displays of objects described by
  /// the error.
  ErrorSummary(String message) : super(message, level: DiagnosticLevel.summary);

  /// Calls to the default constructor may be rewritten to use this constructor
  /// in debug mode using a kernel transformer.
  // ignore: unused_element
  ErrorSummary._fromParts(List<Object> messageParts) : super._fromParts(messageParts, level: DiagnosticLevel.summary);
}

/// An [ErrorHint] provides specific, non-obvious advice that may be applicable.
///
/// If your message provides obvious advice that is always applicable, it is an
/// [ErrorDescription] not a hint.
///
/// In debug builds, values interpolated into the `message` are
/// expanded and placed into [value], which is of type [List<Object>].
/// This allows IDEs to examine values interpolated into error messages.
///
/// See also:
///
///  * [ErrorSummary], which provides a short (one line) description of the
///    problem that was detected.
///  * [ErrorDescription], which provides an explanation of the problem and its
///    cause, any information that may help track down the problem, background
///    information, etc.
///  * [ErrorSpacer], which renders as a blank line.
///  * [FlutterError], which is the most common place to use an [ErrorHint].
class ErrorHint extends _ErrorDiagnostic {
  /// A lint enforces that this constructor can only be called with a string
  /// literal to match the limitations of the Dart Kernel transformer that
  /// optionally extracts out objects referenced using string interpolation in
  /// the message passed in.
  ///
  /// The message will display with the same text regardless of whether the
  /// kernel transformer is used. The kernel transformer is required so that
  /// debugging tools can provide interactive displays of objects described by
  /// the error.
  ErrorHint(String message) : super(message, level:DiagnosticLevel.hint);

  /// Calls to the default constructor may be rewritten to use this constructor
  /// in debug mode using a kernel transformer.
  // ignore: unused_element
  ErrorHint._fromParts(List<Object> messageParts) : super._fromParts(messageParts, level:DiagnosticLevel.hint);
}

/// An [ErrorSpacer] creates an empty [DiagnosticsNode], that can be used to
/// tune the spacing between other [DiagnosticsNode] objects.
class ErrorSpacer extends DiagnosticsProperty<void> {
  /// Creates an empty space to insert into a list of [DiagnosticsNode] objects
  /// typically within a [FlutterError] object.
  ErrorSpacer() : super(
    '',
    null,
    description: '',
    showName: false,
  );
}

/// Class for information provided to [FlutterExceptionHandler] callbacks.
///
/// {@tool snippet}
/// This is an example of using [FlutterErrorDetails] when calling
/// [FlutterError.reportError].
///
/// ```dart
/// void main() {
///   try {
///     // Try to do something!
///   } catch (error) {
///     // Catch & report error.
///     FlutterError.reportError(FlutterErrorDetails(
///       exception: error,
///       library: 'Flutter test framework',
///       context: ErrorSummary('while running async test code'),
///     ));
///   }
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///   * [FlutterError.onError], which is called whenever the Flutter framework
///     catches an error.
class FlutterErrorDetails with Diagnosticable {
  /// Creates a [FlutterErrorDetails] object with the given arguments setting
  /// the object's properties.
  ///
  /// The framework calls this constructor when catching an exception that will
  /// subsequently be reported using [FlutterError.onError].
  ///
  /// The [exception] must not be null; other arguments can be left to
  /// their default values. (`throw null` results in a
  /// [NullThrownError] exception.)
  const FlutterErrorDetails({
    required this.exception,
    this.stack,
    this.library = 'Flutter framework',
    this.context,
    this.stackFilter,
    this.informationCollector,
    this.silent = false,
  }) : assert(exception != null);

  /// Creates a copy of the error details but with the given fields replaced
  /// with new values.
  FlutterErrorDetails copyWith({
    DiagnosticsNode? context,
    Object? exception,
    InformationCollector? informationCollector,
    String? library,
    bool? silent,
    StackTrace? stack,
    IterableFilter<String>? stackFilter,
  }) {
    return FlutterErrorDetails(
      context: context ?? this.context,
      exception: exception ?? this.exception,
      informationCollector: informationCollector ?? this.informationCollector,
      library: library ?? this.library,
      silent: silent ?? this.silent,
      stack: stack ?? this.stack,
      stackFilter: stackFilter ?? this.stackFilter,
    );
  }

  /// Transformers to transform [DiagnosticsNode] in [DiagnosticPropertiesBuilder]
  /// into a more descriptive form.
  ///
  /// There are layers that attach certain [DiagnosticsNode] into
  /// [FlutterErrorDetails] that require knowledge from other layers to parse.
  /// To correctly interpret those [DiagnosticsNode], register transformers in
  /// the layers that possess the knowledge.
  ///
  /// See also:
  ///
  ///  * [WidgetsBinding.initInstances], which registers its transformer.
  static final List<DiagnosticPropertiesTransformer> propertiesTransformers =
    <DiagnosticPropertiesTransformer>[];

  /// The exception. Often this will be an [AssertionError], maybe specifically
  /// a [FlutterError]. However, this could be any value at all.
  final Object exception;

  /// The stack trace from where the [exception] was thrown (as opposed to where
  /// it was caught).
  ///
  /// StackTrace objects are opaque except for their [toString] function.
  ///
  /// If this field is not null, then the [stackFilter] callback, if any, will
  /// be called with the result of calling [toString] on this object and
  /// splitting that result on line breaks. If there's no [stackFilter]
  /// callback, then [FlutterError.defaultStackFilter] is used instead. That
  /// function expects the stack to be in the format used by
  /// [StackTrace.toString].
  final StackTrace? stack;

  /// A human-readable brief name describing the library that caught the error
  /// message. This is used by the default error handler in the header dumped to
  /// the console.
  final String? library;

  /// A [DiagnosticsNode] that provides a human-readable description of where
  /// the error was caught (as opposed to where it was thrown).
  ///
  /// The node, e.g. an [ErrorDescription], should be in a form that will make
  /// sense in English when following the word "thrown", as in "thrown while
  /// obtaining the image from the network" (for the context "while obtaining
  /// the image from the network").
  ///
  /// {@tool snippet}
  /// This is an example of using and [ErrorDescription] as the
  /// [FlutterErrorDetails.context] when calling [FlutterError.reportError].
  ///
  /// ```dart
  /// void maybeDoSomething() {
  ///   try {
  ///     // Try to do something!
  ///   } catch (error) {
  ///     // Catch & report error.
  ///     FlutterError.reportError(FlutterErrorDetails(
  ///       exception: error,
  ///       library: 'Flutter test framework',
  ///       context: ErrorDescription('while dispatching notifications for $runtimeType'),
  ///     ));
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [ErrorDescription], which provides an explanation of the problem and
  ///    its cause, any information that may help track down the problem,
  ///    background information, etc.
  ///  * [ErrorSummary], which provides a short (one line) description of the
  ///    problem that was detected.
  ///  * [ErrorHint], which provides specific, non-obvious advice that may be
  ///    applicable.
  ///  * [FlutterError], which is the most common place to use
  ///    [FlutterErrorDetails].
  final DiagnosticsNode? context;

  /// A callback which filters the [stack] trace. Receives an iterable of
  /// strings representing the frames encoded in the way that
  /// [StackTrace.toString()] provides. Should return an iterable of lines to
  /// output for the stack.
  ///
  /// If this is not provided, then [FlutterError.dumpErrorToConsole] will use
  /// [FlutterError.defaultStackFilter] instead.
  ///
  /// If the [FlutterError.defaultStackFilter] behavior is desired, then the
  /// callback should manually call that function. That function expects the
  /// incoming list to be in the [StackTrace.toString()] format. The output of
  /// that function, however, does not always follow this format.
  ///
  /// This won't be called if [stack] is null.
  final IterableFilter<String>? stackFilter;

  /// A callback which will provide information that could help with debugging
  /// the problem.
  ///
  /// Information collector callbacks can be expensive, so the generated
  /// information should be cached by the caller, rather than the callback being
  /// called multiple times.
  ///
  /// The callback is expected to return an iterable of [DiagnosticsNode] objects,
  /// typically implemented using `sync*` and `yield`.
  ///
  /// {@tool snippet}
  /// In this example, the information collector returns two pieces of information,
  /// one broadly-applicable statement regarding how the error happened, and one
  /// giving a specific piece of information that may be useful in some cases but
  /// may also be irrelevant most of the time (an argument to the method).
  ///
  /// ```dart
  /// void climbElevator(int pid) {
  ///   try {
  ///     // ...
  ///   } catch (error, stack) {
  ///     FlutterError.reportError(FlutterErrorDetails(
  ///       exception: error,
  ///       stack: stack,
  ///       informationCollector: () => <DiagnosticsNode>[
  ///         ErrorDescription('This happened while climbing the space elevator.'),
  ///         ErrorHint('The process ID is: $pid'),
  ///       ],
  ///     ));
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// The following classes may be of particular use:
  ///
  ///  * [ErrorDescription], for information that is broadly applicable to the
  ///    situation being described.
  ///  * [ErrorHint], for specific information that may not always be applicable
  ///    but can be helpful in certain situations.
  ///  * [DiagnosticsStackTrace], for reporting stack traces.
  ///  * [ErrorSpacer], for adding spaces (a blank line) between other items.
  ///
  /// For objects that implement [Diagnosticable] one may consider providing
  /// additional information by yielding the output of the object's
  /// [Diagnosticable.toDiagnosticsNode] method.
  final InformationCollector? informationCollector;

  /// Whether this error should be ignored by the default error reporting
  /// behavior in release mode.
  ///
  /// If this is false, the default, then the default error handler will always
  /// dump this error to the console.
  ///
  /// If this is true, then the default error handler would only dump this error
  /// to the console in debug mode. In release mode, the error is ignored.
  ///
  /// This is used by certain exception handlers that catch errors that could be
  /// triggered by environmental conditions (as opposed to logic errors). For
  /// example, the HTTP library sets this flag so as to not report every 404
  /// error to the console on end-user devices, while still allowing a custom
  /// error handler to see the errors even in release builds.
  final bool silent;

  /// Converts the [exception] to a string.
  ///
  /// This applies some additional logic to make [AssertionError] exceptions
  /// prettier, to handle exceptions that stringify to empty strings, to handle
  /// objects that don't inherit from [Exception] or [Error], and so forth.
  String exceptionAsString() {
    String? longMessage;
    if (exception is AssertionError) {
      // Regular _AssertionErrors thrown by assert() put the message last, after
      // some code snippets. This leads to ugly messages. To avoid this, we move
      // the assertion message up to before the code snippets, separated by a
      // newline, if we recognize that format is being used.
      final Object? message = (exception as AssertionError).message;
      final String fullMessage = exception.toString();
      if (message is String && message != fullMessage) {
        if (fullMessage.length > message.length) {
          final int position = fullMessage.lastIndexOf(message);
          if (position == fullMessage.length - message.length &&
              position > 2 &&
              fullMessage.substring(position - 2, position) == ': ') {
            // Add a linebreak so that the filename at the start of the
            // assertion message is always on its own line.
            String body = fullMessage.substring(0, position - 2);
            final int splitPoint = body.indexOf(' Failed assertion:');
            if (splitPoint >= 0) {
              body = '${body.substring(0, splitPoint)}\n${body.substring(splitPoint + 1)}';
            }
            longMessage = '${message.trimRight()}\n$body';
          }
        }
      }
      longMessage ??= fullMessage;
    } else if (exception is String) {
      longMessage = exception as String;
    } else if (exception is Error || exception is Exception) {
      longMessage = exception.toString();
    } else {
      longMessage = '  ${exception.toString()}';
    }
    longMessage = longMessage.trimRight();
    if (longMessage.isEmpty)
      longMessage = '  <no message available>';
    return longMessage;
  }

  Diagnosticable? _exceptionToDiagnosticable() {
    final Object exception = this.exception;
    if (exception is FlutterError) {
      return exception;
    }
    if (exception is AssertionError && exception.message is FlutterError) {
      return exception.message! as FlutterError;
    }
    return null;
  }

  /// Returns a short (one line) description of the problem that was detected.
  ///
  /// If the exception contains an [ErrorSummary] that summary is used,
  /// otherwise the summary is inferred from the string representation of the
  /// exception.
  ///
  /// In release mode, this always returns a [DiagnosticsNode.message] with a
  /// formatted version of the exception.
  DiagnosticsNode get summary {
    String formatException() => exceptionAsString().split('\n')[0].trimLeft();
    if (kReleaseMode) {
      return DiagnosticsNode.message(formatException());
    }
    final Diagnosticable? diagnosticable = _exceptionToDiagnosticable();
    DiagnosticsNode? summary;
    if (diagnosticable != null) {
      final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
      debugFillProperties(builder);
      summary = builder.properties.cast<DiagnosticsNode?>().firstWhere((DiagnosticsNode? node) => node!.level == DiagnosticLevel.summary, orElse: () => null);
    }
    return summary ?? ErrorSummary(formatException());
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    final DiagnosticsNode verb = ErrorDescription('thrown${ context != null ? ErrorDescription(" $context") : ""}');
    final Diagnosticable? diagnosticable = _exceptionToDiagnosticable();
    if (exception is NullThrownError) {
      properties.add(ErrorDescription('The null value was $verb.'));
    } else if (exception is num) {
      properties.add(ErrorDescription('The number $exception was $verb.'));
    } else {
      final DiagnosticsNode errorName;
      if (exception is AssertionError) {
        errorName = ErrorDescription('assertion');
      } else if (exception is String) {
        errorName = ErrorDescription('message');
      } else if (exception is Error || exception is Exception) {
        errorName = ErrorDescription('${exception.runtimeType}');
      } else {
        errorName = ErrorDescription('${exception.runtimeType} object');
      }
      properties.add(ErrorDescription('The following $errorName was $verb:'));
      if (diagnosticable != null) {
        diagnosticable.debugFillProperties(properties);
      } else {
        // Many exception classes put their type at the head of their message.
        // This is redundant with the way we display exceptions, so attempt to
        // strip out that header when we see it.
        final String prefix = '${exception.runtimeType}: ';
        String message = exceptionAsString();
        if (message.startsWith(prefix))
          message = message.substring(prefix.length);
        properties.add(ErrorSummary(message));
      }
    }

    if (stack != null) {
      if (exception is AssertionError && diagnosticable == null) {
        // After popping off any dart: stack frames, are there at least two more
        // stack frames coming from package flutter?
        //
        // If not: Error is in user code (user violated assertion in framework).
        // If so:  Error is in Framework. We either need an assertion higher up
        //         in the stack, or we've violated our own assertions.
        final List<StackFrame> stackFrames = StackFrame.fromStackTrace(FlutterError.demangleStackTrace(stack!))
                                                       .skipWhile((StackFrame frame) => frame.packageScheme == 'dart')
                                                       .toList();
        final bool ourFault =  stackFrames.length >= 2
                            && stackFrames[0].package == 'flutter'
                            && stackFrames[1].package == 'flutter';
        if (ourFault) {
          properties.add(ErrorSpacer());
          properties.add(ErrorHint(
            'Either the assertion indicates an error in the framework itself, or we should '
            'provide substantially more information in this error message to help you determine '
            'and fix the underlying cause.\n'
            'In either case, please report this assertion by filing a bug on GitHub:\n'
            '  https://github.com/flutter/flutter/issues/new?template=2_bug.md',
          ));
        }
      }
      properties.add(ErrorSpacer());
      properties.add(DiagnosticsStackTrace('When the exception was thrown, this was the stack', stack, stackFilter: stackFilter));
    }
    if (informationCollector != null) {
      properties.add(ErrorSpacer());
      informationCollector!().forEach(properties.add);
    }
  }

  @override
  String toStringShort() {
    return library != null ? 'Exception caught by $library' : 'Exception caught';
  }

  @override
  String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
    return toDiagnosticsNode(style: DiagnosticsTreeStyle.error).toStringDeep(minLevel: minLevel);
  }

  @override
  DiagnosticsNode toDiagnosticsNode({ String? name, DiagnosticsTreeStyle? style }) {
    return _FlutterErrorDetailsNode(
      name: name,
      value: this,
      style: style,
    );
  }
}

/// Error class used to report Flutter-specific assertion failures and
/// contract violations.
///
/// See also:
///
///  * <https://flutter.dev/docs/testing/errors>, more information about error
///    handling in Flutter.
class FlutterError extends Error with DiagnosticableTreeMixin implements AssertionError {
  /// Create an error message from a string.
  ///
  /// The message may have newlines in it. The first line should be a terse
  /// description of the error, e.g. "Incorrect GlobalKey usage" or "setState()
  /// or markNeedsBuild() called during build". Subsequent lines should contain
  /// substantial additional information, ideally sufficient to develop a
  /// correct solution to the problem.
  ///
  /// In some cases, when a [FlutterError] is reported to the user, only the first
  /// line is included. For example, Flutter will typically only fully report
  /// the first exception at runtime, displaying only the first line of
  /// subsequent errors.
  ///
  /// All sentences in the error should be correctly punctuated (i.e.,
  /// do end the error message with a period).
  ///
  /// This constructor defers to the [new FlutterError.fromParts] constructor.
  /// The first line is wrapped in an implied [ErrorSummary], and subsequent
  /// lines are wrapped in implied [ErrorDescription]s. Consider using the
  /// [new FlutterError.fromParts] constructor to provide more detail, e.g.
  /// using [ErrorHint]s or other [DiagnosticsNode]s.
  factory FlutterError(String message) {
    final List<String> lines = message.split('\n');
    return FlutterError.fromParts(<DiagnosticsNode>[
      ErrorSummary(lines.first),
      ...lines.skip(1).map<DiagnosticsNode>((String line) => ErrorDescription(line)),
    ]);
  }

  /// Create an error message from a list of [DiagnosticsNode]s.
  ///
  /// By convention, there should be exactly one [ErrorSummary] in the list,
  /// and it should be the first entry.
  ///
  /// Other entries are typically [ErrorDescription]s (for material that is
  /// always applicable for this error) and [ErrorHint]s (for material that may
  /// be sometimes useful, but may not always apply). Other [DiagnosticsNode]
  /// subclasses, such as [DiagnosticsStackTrace], may
  /// also be used.
  ///
  /// When using an [ErrorSummary], [ErrorDescription]s, and [ErrorHint]s, in
  /// debug builds, values interpolated into the `message` arguments of those
  /// classes' constructors are expanded and placed into the
  /// [DiagnosticsProperty.value] property of those objects (which is of type
  /// [List<Object>]). This allows IDEs to examine values interpolated into
  /// error messages.
  ///
  /// Alternatively, to include a specific [Diagnosticable] object into the
  /// error message and have the object describe itself in detail (see
  /// [DiagnosticsNode.toStringDeep]), consider calling
  /// [Diagnosticable.toDiagnosticsNode] on that object and using that as one of
  /// the values passed to this constructor.
  ///
  /// {@tool snippet}
  /// In this example, an error is thrown in debug mode if certain conditions
  /// are not met. The error message includes a description of an object that
  /// implements the [Diagnosticable] interface, `draconis`.
  ///
  /// ```dart
  /// void controlDraconis() {
  ///   assert(() {
  ///     if (!draconisAlive || !draconisAmulet) {
  ///       throw FlutterError.fromParts(<DiagnosticsNode>[
  ///         ErrorSummary('Cannot control Draconis in current state.'),
  ///         ErrorDescription('Draconis can only be controlled while alive and while the amulet is wielded.'),
  ///         if (!draconisAlive)
  ///           ErrorHint('Draconis is currently not alive.'),
  ///         if (!draconisAmulet)
  ///           ErrorHint('The Amulet of Draconis is currently not wielded.'),
  ///         draconis.toDiagnosticsNode(name: 'Draconis'),
  ///       ]);
  ///     }
  ///     return true;
  ///   }());
  ///   // ...
  /// }
  /// ```
  /// {@end-tool}
  FlutterError.fromParts(this.diagnostics) : assert(diagnostics.isNotEmpty, FlutterError.fromParts(<DiagnosticsNode>[ErrorSummary('Empty FlutterError')])) {
    assert(
      diagnostics.first.level == DiagnosticLevel.summary,
      FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('FlutterError is missing a summary.'),
        ErrorDescription(
          'All FlutterError objects should start with a short (one line) '
          'summary description of the problem that was detected.',
        ),
        DiagnosticsProperty<FlutterError>('Malformed', this, expandableValue: true, showSeparator: false, style: DiagnosticsTreeStyle.whitespace),
        ErrorDescription(
          '\nThis error should still help you solve your problem, '
          'however please also report this malformed error in the '
          'framework by filing a bug on GitHub:\n'
          '  https://github.com/flutter/flutter/issues/new?template=2_bug.md',
        ),
      ]),
    );
    assert(() {
      final Iterable<DiagnosticsNode> summaries = diagnostics.where((DiagnosticsNode node) => node.level == DiagnosticLevel.summary);
      if (summaries.length > 1) {
        final List<DiagnosticsNode> message = <DiagnosticsNode>[
          ErrorSummary('FlutterError contained multiple error summaries.'),
          ErrorDescription(
            'All FlutterError objects should have only a single short '
            '(one line) summary description of the problem that was '
            'detected.',
          ),
          DiagnosticsProperty<FlutterError>('Malformed', this, expandableValue: true, showSeparator: false, style: DiagnosticsTreeStyle.whitespace),
          ErrorDescription('\nThe malformed error has ${summaries.length} summaries.'),
        ];
        int i = 1;
        for (final DiagnosticsNode summary in summaries) {
          message.add(DiagnosticsProperty<DiagnosticsNode>('Summary $i', summary, expandableValue : true));
          i += 1;
        }
        message.add(ErrorDescription(
          '\nThis error should still help you solve your problem, '
          'however please also report this malformed error in the '
          'framework by filing a bug on GitHub:\n'
          '  https://github.com/flutter/flutter/issues/new?template=2_bug.md',
        ));
        throw FlutterError.fromParts(message);
      }
      return true;
    }());
  }

  /// The information associated with this error, in structured form.
  ///
  /// The first node is typically an [ErrorSummary] giving a short description
  /// of the problem, suitable for an index of errors, a log, etc.
  ///
  /// Subsequent nodes should give information specific to this error. Typically
  /// these will be [ErrorDescription]s or [ErrorHint]s, but they could be other
  /// objects also. For instance, an error relating to a timer could include a
  /// stack trace of when the timer was scheduled using the
  /// [DiagnosticsStackTrace] class.
  final List<DiagnosticsNode> diagnostics;

  /// The message associated with this error.
  ///
  /// This is generated by serializing the [diagnostics].
  @override
  String get message => toString();

  /// Called whenever the Flutter framework catches an error.
  ///
  /// The default behavior is to call [presentError].
  ///
  /// You can set this to your own function to override this default behavior.
  /// For example, you could report all errors to your server. Consider calling
  /// [presentError] from your custom error handler in order to see the logs in
  /// the console as well.
  ///
  /// If the error handler throws an exception, it will not be caught by the
  /// Flutter framework.
  ///
  /// Set this to null to silently catch and ignore errors. This is not
  /// recommended.
  ///
  /// Do not call [onError] directly, instead, call [reportError], which
  /// forwards to [onError] if it is not null.
  ///
  /// See also:
  ///
  ///  * <https://flutter.dev/docs/testing/errors>, more information about error
  ///    handling in Flutter.
  static FlutterExceptionHandler? onError = presentError;

  /// Called by the Flutter framework before attempting to parse a [StackTrace].
  ///
  /// Some [StackTrace] implementations have a different toString format from
  /// what the framework expects, like ones from package:stack_trace. To make
  /// sure we can still parse and filter mangled [StackTrace]s, the framework
  /// first calls this function to demangle them.
  ///
  /// This should be set in any environment that could propagate a non-standard
  /// stack trace to the framework. Otherwise, the default behavior is to assume
  /// all stack traces are in a standard format.
  ///
  /// The following example demangles package:stack_trace traces by converting
  /// them into vm traces, which the framework is able to parse:
  ///
  /// ```dart
  /// FlutterError.demangleStackTrace = (StackTrace stackTrace) {
  ///   if (stack is stack_trace.Trace)
  ///     return stack.vmTrace;
  ///   if (stack is stack_trace.Chain)
  ///     return stack.toTrace().vmTrace;
  ///   return stack;
  /// };
  /// ```
  static StackTraceDemangler demangleStackTrace = _defaultStackTraceDemangler;

  static StackTrace _defaultStackTraceDemangler(StackTrace stackTrace) => stackTrace;

  /// Called whenever the Flutter framework wants to present an error to the
  /// users.
  ///
  /// The default behavior is to call [dumpErrorToConsole].
  ///
  /// Plugins can override how an error is to be presented to the user. For
  /// example, the structured errors service extension sets its own method when
  /// the extension is enabled. If you want to change how Flutter responds to an
  /// error, use [onError] instead.
  static FlutterExceptionHandler presentError = dumpErrorToConsole;

  static int _errorCount = 0;

  /// Resets the count of errors used by [dumpErrorToConsole] to decide whether
  /// to show a complete error message or an abbreviated one.
  ///
  /// After this is called, the next error message will be shown in full.
  static void resetErrorCount() {
    _errorCount = 0;
  }

  /// The width to which [dumpErrorToConsole] will wrap lines.
  ///
  /// This can be used to ensure strings will not exceed the length at which
  /// they will wrap, e.g. when placing ASCII art diagrams in messages.
  static const int wrapWidth = 100;

  /// Prints the given exception details to the console.
  ///
  /// The first time this is called, it dumps a very verbose message to the
  /// console using [debugPrint].
  ///
  /// Subsequent calls only dump the first line of the exception, unless
  /// `forceReport` is set to true (in which case it dumps the verbose message).
  ///
  /// Call [resetErrorCount] to cause this method to go back to acting as if it
  /// had not been called before (so the next message is verbose again).
  ///
  /// The default behavior for the [onError] handler is to call this function.
  static void dumpErrorToConsole(FlutterErrorDetails details, { bool forceReport = false }) {
    assert(details != null);
    assert(details.exception != null);
    bool isInDebugMode = false;
    assert(() {
      // In debug mode, we ignore the "silent" flag.
      isInDebugMode = true;
      return true;
    }());
    final bool reportError = isInDebugMode || details.silent != true; // could be null
    if (!reportError && !forceReport)
      return;
    if (_errorCount == 0 || forceReport) {
      // Diagnostics is only available in debug mode. In profile and release modes fallback to plain print.
      if (isInDebugMode) {
        debugPrint(
          TextTreeRenderer(
            wrapWidthProperties: wrapWidth,
            maxDescendentsTruncatableNode: 5,
          ).render(details.toDiagnosticsNode(style: DiagnosticsTreeStyle.error)).trimRight(),
        );
      } else {
        debugPrintStack(
          stackTrace: details.stack,
          label: details.exception.toString(),
          maxFrames: 100,
        );
      }
    } else {
      debugPrint('Another exception was thrown: ${details.summary}');
    }
    _errorCount += 1;
  }

  static final List<StackFilter> _stackFilters = <StackFilter>[];

  /// Adds a stack filtering function to [defaultStackFilter].
  ///
  /// For example, the framework adds common patterns of element building to
  /// elide tree-walking patterns in the stacktrace.
  ///
  /// Added filters are checked in order of addition. The first matching filter
  /// wins, and subsequent filters will not be checked.
  static void addDefaultStackFilter(StackFilter filter) {
    _stackFilters.add(filter);
  }

  /// Converts a stack to a string that is more readable by omitting stack
  /// frames that correspond to Dart internals.
  ///
  /// This is the default filter used by [dumpErrorToConsole] if the
  /// [FlutterErrorDetails] object has no [FlutterErrorDetails.stackFilter]
  /// callback.
  ///
  /// This function expects its input to be in the format used by
  /// [StackTrace.toString()]. The output of this function is similar to that
  /// format but the frame numbers will not be consecutive (frames are elided)
  /// and the final line may be prose rather than a stack frame.
  static Iterable<String> defaultStackFilter(Iterable<String> frames) {
    final Map<String, int> removedPackagesAndClasses = <String, int>{
      'dart:async-patch': 0,
      'dart:async': 0,
      'package:stack_trace': 0,
      'class _AssertionError': 0,
      'class _FakeAsync': 0,
      'class _FrameCallbackEntry': 0,
      'class _Timer': 0,
      'class _RawReceivePortImpl': 0,
    };
    int skipped = 0;

    final List<StackFrame> parsedFrames = StackFrame.fromStackString(frames.join('\n'));

    for (int index = 0; index < parsedFrames.length; index += 1) {
      final StackFrame frame = parsedFrames[index];
      final String className = 'class ${frame.className}';
      final String package = '${frame.packageScheme}:${frame.package}';
      if (removedPackagesAndClasses.containsKey(className)) {
        skipped += 1;
        removedPackagesAndClasses.update(className, (int value) => value + 1);
        parsedFrames.removeAt(index);
        index -= 1;
      } else if (removedPackagesAndClasses.containsKey(package)) {
        skipped += 1;
        removedPackagesAndClasses.update(package, (int value) => value + 1);
        parsedFrames.removeAt(index);
        index -= 1;
      }
    }
    final List<String?> reasons = List<String?>.filled(parsedFrames.length, null);
    for (final StackFilter filter in _stackFilters) {
      filter.filter(parsedFrames, reasons);
    }

    final List<String> result = <String>[];

    // Collapse duplicated reasons.
    for (int index = 0; index < parsedFrames.length; index += 1) {
      final int start = index;
      while (index < reasons.length - 1 && reasons[index] != null && reasons[index + 1] == reasons[index]) {
        index++;
      }
      String suffix = '';
      if (reasons[index] != null) {
        if (index != start) {
          suffix = ' (${index - start + 2} frames)';
        } else {
          suffix = ' (1 frame)';
        }
      }
      final String resultLine = '${reasons[index] ?? parsedFrames[index].source}$suffix';
      result.add(resultLine);
    }

    // Only include packages we actually elided from.
    final List<String> where = <String>[
      for (MapEntry<String, int> entry in removedPackagesAndClasses.entries)
        if (entry.value > 0)
          entry.key,
    ]..sort();
    if (skipped == 1) {
      result.add('(elided one frame from ${where.single})');
    } else if (skipped > 1) {
      if (where.length > 1)
        where[where.length - 1] = 'and ${where.last}';
      if (where.length > 2) {
        result.add('(elided $skipped frames from ${where.join(", ")})');
      } else {
        result.add('(elided $skipped frames from ${where.join(" ")})');
      }
    }
    return result;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    diagnostics.forEach(properties.add);
  }

  @override
  String toStringShort() => 'FlutterError';

  @override
  String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
    if (kReleaseMode) {
      final Iterable<_ErrorDiagnostic> errors = diagnostics.whereType<_ErrorDiagnostic>();
      return errors.isNotEmpty ? errors.first.valueToString() : toStringShort();
    }
    // Avoid wrapping lines.
    final TextTreeRenderer renderer = TextTreeRenderer(wrapWidth: 4000000000);
    return diagnostics.map((DiagnosticsNode node) => renderer.render(node).trimRight()).join('\n');
  }

  /// Calls [onError] with the given details, unless it is null.
  ///
  /// {@tool snippet}
  /// When calling this from a `catch` block consider annotating the method
  /// containing the `catch` block with
  /// `@pragma('vm:notify-debugger-on-exception')` to allow an attached debugger
  /// to treat the exception as unhandled. This means instead of executing the
  /// `catch` block, the debugger can break at the original source location from
  /// which the exception was thrown.
  ///
  /// ```dart
  /// @pragma('vm:notify-debugger-on-exception')
  /// void doSomething() {
  ///   try {
  ///     methodThatMayThrow();
  ///   } catch (exception, stack) {
  ///     FlutterError.reportError(FlutterErrorDetails(
  ///       exception: exception,
  ///       stack: stack,
  ///       library: 'example library',
  ///       context: ErrorDescription('while doing something'),
  ///     ));
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  static void reportError(FlutterErrorDetails details) {
    assert(details != null);
    assert(details.exception != null);
    onError?.call(details);
  }
}

/// Dump the stack to the console using [debugPrint] and
/// [FlutterError.defaultStackFilter].
///
/// If the `stackTrace` parameter is null, the [StackTrace.current] is used to
/// obtain the stack.
///
/// The `maxFrames` argument can be given to limit the stack to the given number
/// of lines before filtering is applied. By default, all stack lines are
/// included.
///
/// The `label` argument, if present, will be printed before the stack.
void debugPrintStack({StackTrace? stackTrace, String? label, int? maxFrames}) {
  if (label != null)
    debugPrint(label);
  if (stackTrace == null) {
    stackTrace = StackTrace.current;
  } else {
    stackTrace = FlutterError.demangleStackTrace(stackTrace);
  }
  Iterable<String> lines = stackTrace.toString().trimRight().split('\n');
  if (kIsWeb && lines.isNotEmpty) {
    // Remove extra call to StackTrace.current for web platform.
    // TODO(ferhat): remove when https://github.com/flutter/flutter/issues/37635
    // is addressed.
    lines = lines.skipWhile((String line) {
      return line.contains('StackTrace.current') ||
             line.contains('dart-sdk/lib/_internal') ||
             line.contains('dart:sdk_internal');
    });
  }
  if (maxFrames != null)
    lines = lines.take(maxFrames);
  debugPrint(FlutterError.defaultStackFilter(lines).join('\n'));
}

/// Diagnostic with a [StackTrace] [value] suitable for displaying stack traces
/// as part of a [FlutterError] object.
class DiagnosticsStackTrace extends DiagnosticsBlock {
  /// Creates a diagnostic for a stack trace.
  ///
  /// [name] describes a name the stacktrace is given, e.g.
  /// `When the exception was thrown, this was the stack`.
  /// [stackFilter] provides an optional filter to use to filter which frames
  /// are included. If no filter is specified, [FlutterError.defaultStackFilter]
  /// is used.
  /// [showSeparator] indicates whether to include a ':' after the [name].
  DiagnosticsStackTrace(
    String name,
    StackTrace? stack, {
    IterableFilter<String>? stackFilter,
    bool showSeparator = true,
  }) : super(
    name: name,
    value: stack,
    properties: _applyStackFilter(stack, stackFilter),
    style: DiagnosticsTreeStyle.flat,
    showSeparator: showSeparator,
    allowTruncate: true,
  );

  /// Creates a diagnostic describing a single frame from a StackTrace.
  DiagnosticsStackTrace.singleFrame(
    String name, {
    required String frame,
    bool showSeparator = true,
  }) : super(
    name: name,
    properties: <DiagnosticsNode>[_createStackFrame(frame)],
    style: DiagnosticsTreeStyle.whitespace,
    showSeparator: showSeparator,
  );

  static List<DiagnosticsNode> _applyStackFilter(
    StackTrace? stack,
    IterableFilter<String>? stackFilter,
  ) {
    if (stack == null)
      return <DiagnosticsNode>[];
    final IterableFilter<String> filter = stackFilter ?? FlutterError.defaultStackFilter;
    final Iterable<String> frames = filter('${FlutterError.demangleStackTrace(stack)}'.trimRight().split('\n'));
    return frames.map<DiagnosticsNode>(_createStackFrame).toList();
  }

  static DiagnosticsNode _createStackFrame(String frame) {
    return DiagnosticsNode.message(frame, allowWrap: false);
  }

  @override
  bool get allowTruncate => false;
}

class _FlutterErrorDetailsNode extends DiagnosticableNode<FlutterErrorDetails> {
  _FlutterErrorDetailsNode({
    String? name,
    required FlutterErrorDetails value,
    required DiagnosticsTreeStyle? style,
  }) : super(
    name: name,
    value: value,
    style: style,
  );

  @override
  DiagnosticPropertiesBuilder? get builder {
    final DiagnosticPropertiesBuilder? builder = super.builder;
    if (builder == null) {
      return null;
    }
    Iterable<DiagnosticsNode> properties = builder.properties;
    for (final DiagnosticPropertiesTransformer transformer in FlutterErrorDetails.propertiesTransformers) {
      properties = transformer(properties);
    }
    return DiagnosticPropertiesBuilder.fromProperties(properties.toList());
  }
}
