// 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.

// To run this, from the root of the Flutter repository:
//   bin/cache/dart-sdk/bin/dart --enable-asserts dev/bots/analyze_snippet_code.dart

// In general, please prefer using full inline examples in API docs.
//
// For documentation on creating sample code, see ../../examples/api/README.md
// See also our style guide's discussion on documentation and sample code:
// https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#documentation-dartdocs-javadocs-etc
//
// This tool is used to analyze smaller snippets of code in the API docs.
// Such snippets are wrapped in ```dart ... ``` blocks, which may themselves
// be wrapped in {@tool snippet} ... {@endtool} blocks to set them apart
// in the rendered output.
//
// Such snippets:
//
//  * If they start with `import` are treated as full application samples; avoid
//    doing this in general, it's better to use samples as described above. (One
//    exception might be in dart:ui where the sample code would end up in a
//    different repository which would be awkward.)
//
//  * If they start with a comment that says `// continuing from previous example...`,
//    they automatically import the previous test's file.
//
//  * If they start with a comment that says `// (e.g. in a stateful widget)`,
//    are analyzed after being inserted into a class that inherits from State.
//
//  * If they start with what looks like a getter, function declaration, or
//    other top-level keyword (`class`, `typedef`, etc), or if they start with
//    the keyword `final`, they are analyzed directly.
//
//  * If they end with a trailing semicolon or have a line starting with a
//    statement keyword like `while` or `try`, are analyzed after being inserted
//    into a function body.
//
//  * If they start with the word `static`, are placed in a class body before
//    analysis.
//
//  * Otherwise, are used as an initializer for a global variable for the
//    purposes of analysis; in this case, any leading label (`foo:`)
//    and any trailing comma are removed.
//
// In particular, these rules imply that starting an example with `const` means
// it is an _expression_, not a top-level declaration. This is because mostly
// `const` indicates a Widget.
//
// A line that contains just a comment with an ellipsis (`// ...`) adds an ignore
// for the `non_abstract_class_inherits_abstract_member` error for the snippet.
// This is useful when you're writing an example that extends an abstract class
// with lots of members, but you only care to show one.
//
// At the top of a file you can say `// Examples can assume:` and then list some
// commented-out declarations that will be included in the analysis for snippets
// in that file.
//
// Snippets generally import all the main Flutter packages (including material
// and flutter_test), as well as most core Dart packages with the usual prefixes.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:watcher/watcher.dart';

final String _flutterRoot = path.dirname(path.dirname(path.dirname(path.fromUri(Platform.script))));
final String _defaultFlutterPackage = path.join(_flutterRoot, 'packages', 'flutter', 'lib');
final String _defaultDartUiLocation = path.join(_flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui');
final String _flutter = path.join(_flutterRoot, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');

Future<void> main(List<String> arguments) async {
  bool asserts = false;
  assert(() { asserts = true; return true; }());
  if (!asserts) {
    print('You must run this script with asserts enabled.');
    exit(1);
  }
  int width;
  try {
    width = stdout.terminalColumns;
  } on StdoutException {
    width = 80;
  }
  final ArgParser argParser = ArgParser(usageLineLength: width);
  argParser.addOption(
    'temp',
    valueHelp: 'path',
    help: 'A location where temporary files may be written. Defaults to a '
          'directory in the system temp folder. If specified, will not be '
          'automatically removed at the end of execution.',
  );
  argParser.addFlag(
    'verbose',
    negatable: false,
    help: 'Print verbose output for the analysis process.',
  );
  argParser.addOption(
    'dart-ui-location',
    defaultsTo: _defaultDartUiLocation,
    valueHelp: 'path',
    help: 'A location where the dart:ui dart files are to be found. Defaults to '
          'the sky_engine directory installed in this flutter repo. This '
          'is typically the engine/src/flutter/lib/ui directory in an engine dev setup. '
          'Implies --include-dart-ui.',
  );
  argParser.addFlag(
    'include-dart-ui',
    defaultsTo: true,
    help: 'Includes the dart:ui code supplied by the engine in the analysis.',
  );
  argParser.addFlag(
    'help',
    negatable: false,
    help: 'Print help for this command.',
  );
  argParser.addOption(
    'interactive',
    abbr: 'i',
    valueHelp: 'file',
    help: 'Analyzes the snippet code in a specified file interactively.',
  );

  final ArgResults parsedArguments;
  try {
    parsedArguments = argParser.parse(arguments);
  } on FormatException catch (e) {
    print(e.message);
    print('dart --enable-asserts analyze_snippet_code.dart [options]');
    print(argParser.usage);
    exit(1);
  }

  if (parsedArguments['help'] as bool) {
    print('dart --enable-asserts analyze_snippet_code.dart [options]');
    print(argParser.usage);
    exit(0);
  }

  Directory flutterPackage;
  if (parsedArguments.rest.length == 1) {
    // Used for testing.
    flutterPackage = Directory(parsedArguments.rest.single);
  } else {
    flutterPackage = Directory(_defaultFlutterPackage);
  }

  final bool includeDartUi = parsedArguments.wasParsed('dart-ui-location') || parsedArguments['include-dart-ui'] as bool;
  late Directory dartUiLocation;
  if (((parsedArguments['dart-ui-location'] ?? '') as String).isNotEmpty) {
    dartUiLocation = Directory(
        path.absolute(parsedArguments['dart-ui-location'] as String));
  } else {
    dartUiLocation = Directory(_defaultDartUiLocation);
  }
  if (!dartUiLocation.existsSync()) {
    stderr.writeln('Unable to find dart:ui directory ${dartUiLocation.path}');
    exit(1);
  }

  if (parsedArguments['interactive'] != null) {
    await _runInteractive(
      flutterPackage: flutterPackage,
      tempDirectory: parsedArguments['temp'] as String?,
      filePath: parsedArguments['interactive'] as String,
      dartUiLocation: includeDartUi ? dartUiLocation : null,
    );
  } else {
    if (await _SnippetChecker(
        flutterPackage,
        tempDirectory: parsedArguments['temp'] as String?,
        verbose: parsedArguments['verbose'] as bool,
        dartUiLocation: includeDartUi ? dartUiLocation : null,
      ).checkSnippets()) {
      stderr.writeln('See the documentation at the top of dev/bots/analyze_snippet_code.dart for details.');
      exit(1);
    }
  }
}

/// A class to represent a line of input code.
@immutable
class _Line {
  const _Line({this.code = '', this.line = -1, this.indent = 0})
      : generated = false;
  const _Line.generated({this.code = ''})
      : line = -1,
        indent = 0,
        generated = true;

  final int line;
  final int indent;
  final String code;
  final bool generated;

  String asLocation(String filename, int column) {
    return '$filename:$line:${column + indent}';
  }

  @override
  String toString() => code;

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is _Line
        && other.line == line
        && other.indent == indent
        && other.code == code
        && other.generated == generated;
  }

  @override
  int get hashCode => Object.hash(line, indent, code, generated);
}

@immutable
class _ErrorBase implements Comparable<Object> {
  const _ErrorBase({this.file, this.line, this.column});
  final String? file;
  final int? line;
  final int? column;

  @override
  int compareTo(Object other) {
    if (other is _ErrorBase) {
      if (other.file != file) {
        if (other.file == null) {
          return -1;
        }
        if (file == null) {
          return 1;
        }
        return file!.compareTo(other.file!);
      }
      if (other.line != line) {
        if (other.line == null) {
          return -1;
        }
        if (line == null) {
          return 1;
        }
        return line!.compareTo(other.line!);
      }
      if (other.column != column) {
        if (other.column == null) {
          return -1;
        }
        if (column == null) {
          return 1;
        }
        return column!.compareTo(other.column!);
      }
    }
    return toString().compareTo(other.toString());
  }
}

@immutable
class _SnippetCheckerException extends _ErrorBase implements Exception {
  const _SnippetCheckerException(this.message, {super.file, super.line});
  final String message;

  @override
  String toString() {
    if (file != null || line != null) {
      final String fileStr = file == null ? '' : '$file:';
      final String lineStr = line == null ? '' : '$line:';
      return '$fileStr$lineStr $message';
    } else {
      return message;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is _SnippetCheckerException
        && other.message == message
        && other.file == file
        && other.line == line;
  }

  @override
  int get hashCode => Object.hash(message, file, line);
}

/// A class representing an analysis error along with the context of the error.
///
/// Changes how it converts to a string based on the source of the error.
@immutable
class _AnalysisError extends _ErrorBase {
  const _AnalysisError(
    String file,
    int line,
    int column,
    this.message,
    this.errorCode,
    this.source,
  ) : super(file: file, line: line, column: column);

  final String message;
  final String errorCode;
  final _Line source;

  @override
  String toString() {
    return '${source.asLocation(file!, column!)}: $message ($errorCode)';
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is _AnalysisError
        && other.file == file
        && other.line == line
        && other.column == column
        && other.message == message
        && other.errorCode == errorCode
        && other.source == source;
  }

  @override
  int get hashCode => Object.hash(file, line, column, message, errorCode, source);
}

/// Checks code snippets for analysis errors.
///
/// Extracts dartdoc content from flutter package source code, identifies code
/// sections, and writes them to a temporary directory, where 'flutter analyze'
/// is used to analyze the sources for problems. If problems are found, the
/// error output from the analyzer is parsed for details, and the problem
/// locations are translated back to the source location.
class _SnippetChecker {
  /// Creates a [_SnippetChecker].
  ///
  /// The positional argument is the path to the package directory for the
  /// flutter package within the Flutter root dir.
  ///
  /// The optional `tempDirectory` argument supplies the location for the
  /// temporary files to be written and analyzed. If not supplied, it defaults
  /// to a system generated temp directory.
  ///
  /// The optional `verbose` argument indicates whether or not status output
  /// should be emitted while doing the check.
  ///
  /// The optional `dartUiLocation` argument indicates the location of the
  /// `dart:ui` code to be analyzed along with the framework code. If not
  /// supplied, the default location of the `dart:ui` code in the Flutter
  /// repository is used (i.e. "<flutter repo>/bin/cache/pkg/sky_engine/lib/ui").
  _SnippetChecker(
    this._flutterPackage, {
    String? tempDirectory,
    this.verbose = false,
    Directory? dartUiLocation,
  }) : _tempDirectory = _createTempDirectory(tempDirectory),
       _keepTmp = tempDirectory != null,
       _dartUiLocation = dartUiLocation;

  /// The prefix of each comment line
  static const String _dartDocPrefix = '///';

  /// The prefix of each comment line with a space appended.
  static const String _dartDocPrefixWithSpace = '$_dartDocPrefix ';

  /// A RegExp that matches the beginning of a dartdoc snippet.
  static final RegExp _dartDocSnippetBeginRegex = RegExp(r'{@tool ([^ }]+)(?:| ([^}]*))}');

  /// A RegExp that matches the end of a dartdoc snippet.
  static final RegExp _dartDocSnippetEndRegex = RegExp(r'{@end-tool}');

  /// A RegExp that matches the start of a code block within dartdoc.
  static final RegExp _codeBlockStartRegex = RegExp(r'^ */// *```dart$');

  /// A RegExp that matches the start of a code block within a regular comment.
  /// Such blocks are not analyzed. They can be used to give sample code for
  /// internal (private) APIs where visibilty would make analyzing the sample
  /// code problematic.
  static final RegExp _uncheckedCodeBlockStartRegex = RegExp(r'^ *// *```dart$');

  /// A RegExp that matches the end of a code block within dartdoc.
  static final RegExp _codeBlockEndRegex = RegExp(r'^ */// *``` *$');

  /// A RegExp that matches a line starting with a comment or annotation
  static final RegExp _nonCodeRegExp = RegExp(r'^ *(//|@)');

  /// A RegExp that matches things that look like a function declaration.
  static final RegExp _maybeFunctionDeclarationRegExp = RegExp(r'^([A-Z][A-Za-z0-9_<>, ?]*|int|double|num|bool|void)\?? (_?[a-z][A-Za-z0-9_<>]*)\(.*');

  /// A RegExp that matches things that look like a getter.
  static final RegExp _maybeGetterDeclarationRegExp = RegExp(r'^([A-Z][A-Za-z0-9_<>?]*|int|double|num|bool)\?? get (_?[a-z][A-Za-z0-9_<>]*) (?:=>|{).*');

  /// A RegExp that matches an identifier followed by a colon, potentially with two spaces of indent.
  static final RegExp _namedArgumentRegExp = RegExp(r'^(?:  )?([a-zA-Z0-9_]+): ');

  /// A RegExp that matches things that look unambiguously like top-level declarations.
  static final RegExp _topLevelDeclarationRegExp = RegExp(r'^(abstract|class|mixin|enum|typedef|final|extension) ');

  /// A RegExp that matches things that look unambiguously like statements.
  static final RegExp _statementRegExp = RegExp(r'^(if|while|for|try) ');

  /// A RegExp that matches things that look unambiguously like declarations that must be in a class.
  static final RegExp _classDeclarationRegExp = RegExp(r'^(static) ');

  /// A RegExp that matches a line that ends with a comma (and maybe a comment)
  static final RegExp _trailingCommaRegExp = RegExp(r'^(.*),(| *//.*)$');

  /// A RegExp that matches a line that ends with a semicolon (and maybe a comment)
  static final RegExp _trailingSemicolonRegExp = RegExp(r'^(.*);(| *//.*)$');

  /// A RegExp that matches a line that ends with a closing blace (and maybe a comment)
  static final RegExp _trailingCloseBraceRegExp = RegExp(r'^(.*)}(| *//.*)$');

  /// A RegExp that matches a line that only contains a commented-out ellipsis
  /// (and maybe whitespace). Has three groups: before, ellipsis, after.
  static final RegExp _ellipsisRegExp = RegExp(r'^( *)(// \.\.\.)( *)$');

  /// Whether or not to print verbose output.
  final bool verbose;

  /// Whether or not to keep the temp directory around after running.
  ///
  /// Defaults to false.
  final bool _keepTmp;

  /// The temporary directory where all output is written. This will be deleted
  /// automatically if there are no errors unless _keepTmp is true.
  final Directory _tempDirectory;

  /// The package directory for the flutter package within the flutter root dir.
  final Directory _flutterPackage;

  /// The directory for the dart:ui code to be analyzed with the flutter code.
  ///
  /// If this is null, then no dart:ui code is included in the analysis. It
  /// defaults to the location inside of the flutter bin/cache directory that
  /// contains the dart:ui code supplied by the engine.
  final Directory? _dartUiLocation;

  static List<File> _listDartFiles(Directory directory, {bool recursive = false}) {
    return directory.listSync(recursive: recursive, followLinks: false).whereType<File>().where((File file) => path.extension(file.path) == '.dart').toList();
  }

  static const List<String> ignoresDirectives = <String>[
    '// ignore_for_file: duplicate_ignore',
    '// ignore_for_file: directives_ordering',
    '// ignore_for_file: prefer_final_locals',
    '// ignore_for_file: unnecessary_import',
    '// ignore_for_file: unused_element',
    '// ignore_for_file: unused_local_variable',
  ];

  /// Computes the headers needed for each snippet file.
  List<_Line> get headersWithoutImports {
    return _headersWithoutImports ??= ignoresDirectives.map<_Line>((String code) => _Line.generated(code: code)).toList();
  }
  List<_Line>? _headersWithoutImports;

  /// Computes the headers needed for each snippet file.
  List<_Line> get headersWithImports {
    return _headersWithImports ??= <String>[
      ...ignoresDirectives,
      '// ignore_for_file: unused_import',
      "import 'dart:async';",
      "import 'dart:convert';",
      "import 'dart:io';",
      "import 'dart:math' as math;",
      "import 'dart:typed_data';",
      "import 'dart:ui' as ui;",
      "import 'package:flutter_test/flutter_test.dart';",
      for (final File file in _listDartFiles(Directory(_defaultFlutterPackage)))
        "import 'package:flutter/${path.basename(file.path)}';",
    ].map<_Line>((String code) => _Line.generated(code: code)).toList();
  }
  List<_Line>? _headersWithImports;

  /// Checks all the snippets in the Dart files in [_flutterPackage] for errors.
  /// Returns true if any errors are found, false otherwise.
  Future<bool> checkSnippets() async {
    final Map<String, _SnippetFile> snippets = <String, _SnippetFile>{};
    if (_dartUiLocation != null && !_dartUiLocation!.existsSync()) {
      stderr.writeln('Unable to analyze engine dart snippets at ${_dartUiLocation!.path}.');
    }
    final List<File> filesToAnalyze = <File>[
      ..._listDartFiles(_flutterPackage, recursive: true),
      if (_dartUiLocation != null && _dartUiLocation!.existsSync())
        ..._listDartFiles(_dartUiLocation!, recursive: true),
    ];
    final Set<Object> errors = <Object>{};
    errors.addAll(await _extractSnippets(filesToAnalyze, snippetMap: snippets));
    errors.addAll(_analyze(snippets));
    (errors.toList()..sort()).map(_stringify).forEach(stderr.writeln);
    stderr.writeln('Found ${errors.length} snippet code errors.');
    cleanupTempDirectory();
    return errors.isNotEmpty;
  }

  static Directory _createTempDirectory(String? tempArg) {
    if (tempArg != null) {
      final Directory tempDirectory = Directory(path.join(Directory.systemTemp.absolute.path, path.basename(tempArg)));
      if (path.basename(tempArg) != tempArg) {
        stderr.writeln('Supplied temporary directory name should be a name, not a path. Using ${tempDirectory.absolute.path} instead.');
      }
      print('Leaving temporary output in ${tempDirectory.absolute.path}.');
      // Make sure that any directory left around from a previous run is cleared out.
      if (tempDirectory.existsSync()) {
        tempDirectory.deleteSync(recursive: true);
      }
      tempDirectory.createSync();
      return tempDirectory;
    }
    return Directory.systemTemp.createTempSync('flutter_analyze_snippet_code.');
  }

  void recreateTempDirectory() {
    _tempDirectory.deleteSync(recursive: true);
    _tempDirectory.createSync();
  }

  void cleanupTempDirectory() {
    if (_keepTmp) {
      print('Leaving temporary directory ${_tempDirectory.path} around for your perusal.');
    } else {
      try {
        _tempDirectory.deleteSync(recursive: true);
      } on FileSystemException catch (e) {
        stderr.writeln('Failed to delete ${_tempDirectory.path}: $e');
      }
    }
  }

  /// Creates a name for the snippets tool to use for the snippet ID from a
  /// filename and starting line number.
  String _createNameFromSource(String prefix, String filename, int start) {
    String snippetId = path.split(filename).join('.');
    snippetId = path.basenameWithoutExtension(snippetId);
    snippetId = '$prefix.$snippetId.$start';
    return snippetId;
  }

  /// Extracts the snippets from the Dart files in [files], writes them
  /// to disk, and adds them to the [snippetMap].
  Future<List<Object>> _extractSnippets(
    List<File> files, {
    required Map<String, _SnippetFile> snippetMap,
  }) async {
    final List<Object> errors = <Object>[];
    _SnippetFile? lastExample;
    for (final File file in files) {
      try {
        final String relativeFilePath = path.relative(file.path, from: _flutterRoot);
        final List<String> fileLines = file.readAsLinesSync();
        final List<_Line> ignorePreambleLinesOnly = <_Line>[];
        final List<_Line> preambleLines = <_Line>[];
        bool inExamplesCanAssumePreamble = false; // Whether or not we're in the file-wide preamble section ("Examples can assume").
        bool inToolSection = false; // Whether or not we're in a code snippet
        bool inDartSection = false; // Whether or not we're in a '```dart' segment.
        bool inOtherBlock = false; // Whether we're in some other '```' segment.
        int lineNumber = 0;
        final List<String> block = <String>[];
        late _Line startLine;
        for (final String line in fileLines) {
          lineNumber += 1;
          final String trimmedLine = line.trim();
          if (inExamplesCanAssumePreamble) {
            if (line.isEmpty) {
              // end of preamble
              inExamplesCanAssumePreamble = false;
            } else if (!line.startsWith('// ')) {
              throw _SnippetCheckerException('Unexpected content in snippet code preamble.', file: relativeFilePath, line: lineNumber);
            } else {
              final _Line newLine = _Line(line: lineNumber, indent: 3, code: line.substring(3));
              preambleLines.add(newLine);
              if (line.startsWith('// // ignore_for_file: ')) {
                ignorePreambleLinesOnly.add(newLine);
              }
            }
          } else if (trimmedLine.startsWith(_dartDocSnippetEndRegex)) {
            if (!inToolSection) {
              throw _SnippetCheckerException('{@tool-end} marker detected without matching {@tool}.', file: relativeFilePath, line: lineNumber);
            }
            if (inDartSection) {
              throw _SnippetCheckerException("Dart section didn't terminate before end of snippet", file: relativeFilePath, line: lineNumber);
            }
            inToolSection = false;
          } else if (inDartSection) {
            final RegExpMatch? snippetMatch = _dartDocSnippetBeginRegex.firstMatch(trimmedLine);
            if (snippetMatch != null) {
              throw _SnippetCheckerException('{@tool} found inside Dart section', file: relativeFilePath, line: lineNumber);
            }
            if (trimmedLine.startsWith(_codeBlockEndRegex)) {
              inDartSection = false;
              final _SnippetFile snippet = _processBlock(startLine, block, preambleLines, ignorePreambleLinesOnly, relativeFilePath, lastExample);
              final String path = _writeSnippetFile(snippet).path;
              assert(!snippetMap.containsKey(path));
              snippetMap[path] = snippet;
              block.clear();
              lastExample = snippet;
            } else if (trimmedLine == _dartDocPrefix) {
              block.add('');
            } else {
              final int index = line.indexOf(_dartDocPrefixWithSpace);
              if (index < 0) {
                throw _SnippetCheckerException(
                  'Dart section inexplicably did not contain "$_dartDocPrefixWithSpace" prefix.',
                  file: relativeFilePath,
                  line: lineNumber,
                );
              }
              block.add(line.substring(index + 4));
            }
          } else if (trimmedLine.startsWith(_codeBlockStartRegex)) {
            if (inOtherBlock) {
              throw _SnippetCheckerException(
                'Found "```dart" section in another "```" section.',
                file: relativeFilePath,
                line: lineNumber,
              );
            }
            assert(block.isEmpty);
            startLine = _Line(
              line: lineNumber + 1,
              indent: line.indexOf(_dartDocPrefixWithSpace) + _dartDocPrefixWithSpace.length,
            );
            inDartSection = true;
          } else if (line.contains('```')) {
            if (inOtherBlock) {
              inOtherBlock = false;
            } else if (line.contains('```yaml') ||
                       line.contains('```ascii') ||
                       line.contains('```java') ||
                       line.contains('```objectivec') ||
                       line.contains('```kotlin') ||
                       line.contains('```swift') ||
                       line.contains('```glsl') ||
                       line.contains('```csv')) {
              inOtherBlock = true;
            } else if (line.startsWith(_uncheckedCodeBlockStartRegex)) {
              // this is an intentionally-unchecked block that doesn't appear in the API docs.
              inOtherBlock = true;
            } else {
              throw _SnippetCheckerException(
                'Found "```" in code but it did not match $_codeBlockStartRegex so something is wrong. Line was: "$line"',
                file: relativeFilePath,
                line: lineNumber,
              );
            }
          } else if (!inToolSection) {
            final RegExpMatch? snippetMatch = _dartDocSnippetBeginRegex.firstMatch(trimmedLine);
            if (snippetMatch != null) {
              inToolSection = true;
            } else if (line == '// Examples can assume:') {
              if (inToolSection || inDartSection) {
                throw _SnippetCheckerException(
                  '"// Examples can assume:" sections must come before all sample code.',
                  file: relativeFilePath,
                  line: lineNumber,
                );
              }
              inExamplesCanAssumePreamble = true;
            }
          }
        }
      } on _SnippetCheckerException catch (e) {
        errors.add(e);
      }
    }
    return errors;
  }

  /// Process one block of snippet code (the part inside of "```" markers). Uses
  /// a primitive heuristic to make snippet blocks into valid Dart code.
  ///
  /// `block` argument will get mutated, but is copied before this function returns.
  _SnippetFile _processBlock(_Line startingLine, List<String> block, List<_Line> assumptions, List<_Line> ignoreAssumptionsOnly, String filename, _SnippetFile? lastExample) {
    if (block.isEmpty) {
      throw _SnippetCheckerException('${startingLine.asLocation(filename, 0)}: Empty ```dart block in snippet code.');
    }
    bool hasEllipsis = false;
    for (int index = 0; index < block.length; index += 1) {
      final Match? match = _ellipsisRegExp.matchAsPrefix(block[index]);
      if (match != null) {
        hasEllipsis = true; // in case the "..." is implying some overridden members, add an ignore to silence relevant warnings
        break;
      }
    }
    bool hasStatefulWidgetComment = false;
    bool importPreviousExample = false;
    int index = startingLine.line;
    for (final String line in block) {
      if (line == '// (e.g. in a stateful widget)') {
        if (hasStatefulWidgetComment) {
          throw _SnippetCheckerException('Example says it is in a stateful widget twice.', file: filename, line: index);
        }
        hasStatefulWidgetComment = true;
      } else if (line == '// continuing from previous example...') {
        if (importPreviousExample) {
          throw _SnippetCheckerException('Example says it continues from the previous example twice.', file: filename, line: index);
        }
        if (lastExample == null) {
          throw _SnippetCheckerException('Example says it continues from the previous example but it is the first example in the file.', file: filename, line: index);
        }
        importPreviousExample = true;
      } else {
        break;
      }
      index += 1;
    }
    final List<_Line> preamble;
    if (importPreviousExample) {
      preamble = <_Line>[
        ...lastExample!.code, // includes assumptions
        if (hasEllipsis || hasStatefulWidgetComment)
          const _Line.generated(code: '// ignore_for_file: non_abstract_class_inherits_abstract_member'),
      ];
    } else {
      preamble = <_Line>[
        if (hasEllipsis || hasStatefulWidgetComment)
          const _Line.generated(code: '// ignore_for_file: non_abstract_class_inherits_abstract_member'),
        ...assumptions,
      ];
    }
    final String firstCodeLine = block.firstWhere((String line) => !line.startsWith(_nonCodeRegExp)).trim();
    final String lastCodeLine = block.lastWhere((String line) => !line.startsWith(_nonCodeRegExp)).trim();
    if (firstCodeLine.startsWith('import ')) {
      // probably an entire program
      if (importPreviousExample) {
        throw _SnippetCheckerException('An example cannot both be self-contained (with its own imports) and say it wants to import the previous example.', file: filename, line: startingLine.line);
      }
      if (hasStatefulWidgetComment) {
        throw _SnippetCheckerException('An example cannot both be self-contained (with its own imports) and say it is in a stateful widget.', file: filename, line: startingLine.line);
      }
      return _SnippetFile.fromStrings(
        startingLine,
        block.toList(),
        importPreviousExample ? <_Line>[] : headersWithoutImports,
        <_Line>[
          ...ignoreAssumptionsOnly,
          if (hasEllipsis)
            const _Line.generated(code: '// ignore_for_file: non_abstract_class_inherits_abstract_member'),
        ],
        'self-contained program',
        filename,
      );
    } else if (hasStatefulWidgetComment) {
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'class _State extends State<StatefulWidget> {',
        block.toList(),
        postfix: '}',
        importPreviousExample ? <_Line>[] : headersWithImports,
        preamble,
        'stateful widget',
        filename,
      );
    } else if (firstCodeLine.startsWith(_maybeGetterDeclarationRegExp) ||
               (firstCodeLine.startsWith(_maybeFunctionDeclarationRegExp) && lastCodeLine.startsWith(_trailingCloseBraceRegExp)) ||
               block.any((String line) => line.startsWith(_topLevelDeclarationRegExp))) {
      // probably a top-level declaration
      return _SnippetFile.fromStrings(
        startingLine,
        block.toList(),
        importPreviousExample ? <_Line>[] : headersWithImports,
        preamble,
        'top-level declaration',
        filename,
      );
    } else if (lastCodeLine.startsWith(_trailingSemicolonRegExp) ||
               block.any((String line) => line.startsWith(_statementRegExp))) {
      // probably a statement
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'Future<void> function() async {',
        block.toList(),
        postfix: '}',
        importPreviousExample ? <_Line>[] : headersWithImports,
        preamble,
        'statement',
        filename,
      );
    } else if (firstCodeLine.startsWith(_classDeclarationRegExp)) {
      // probably a static method
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'class Class {',
        block.toList(),
        postfix: '}',
        importPreviousExample ? <_Line>[] : headersWithImports,
        <_Line>[
          ...preamble,
          const _Line.generated(code: '// ignore_for_file: avoid_classes_with_only_static_members'),
        ],
        'class declaration',
        filename,
      );
    } else {
      // probably an expression
      if (firstCodeLine.startsWith(_namedArgumentRegExp)) {
        // This is for snippets like:
        //
        // ```dart
        // // bla bla
        // foo: 2,
        // ```
        //
        // This section removes the label.
        for (int index = 0; index < block.length; index += 1) {
          final Match? prefix = _namedArgumentRegExp.matchAsPrefix(block[index]);
          if (prefix != null) {
            block[index] = block[index].substring(prefix.group(0)!.length);
            break;
          }
        }
      }
      // strip trailing comma, if any
      for (int index = block.length - 1; index >= 0; index -= 1) {
        if (!block[index].startsWith(_nonCodeRegExp)) {
          final Match? lastLine = _trailingCommaRegExp.matchAsPrefix(block[index]);
          if (lastLine != null) {
            block[index] = lastLine.group(1)! + lastLine.group(2)!;
          }
          break;
        }
      }
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'dynamic expression = ',
        block.toList(),
        postfix: ';',
        importPreviousExample ? <_Line>[] : headersWithImports,
        preamble,
        'expression',
        filename,
      );
    }
  }

  /// Creates the configuration files necessary for the analyzer to consider
  /// the temporary directory a package, and sets which lint rules to enforce.
  void _createConfigurationFiles() {
    final File targetPubSpec = File(path.join(_tempDirectory.path, 'pubspec.yaml'));
    if (!targetPubSpec.existsSync()) {
      // Copying pubspec.yaml from examples/api into temp directory.
      final File sourcePubSpec = File(path.join(_flutterRoot, 'examples', 'api', 'pubspec.yaml'));
      if (!sourcePubSpec.existsSync()) {
        throw 'Cannot find pubspec.yaml at ${sourcePubSpec.path}, which is also used to analyze code snippets.';
      }
      sourcePubSpec.copySync(targetPubSpec.path);
    }
    final File targetAnalysisOptions = File(path.join(_tempDirectory.path, 'analysis_options.yaml'));
    if (!targetAnalysisOptions.existsSync()) {
      // Use the same analysis_options.yaml configuration that's used for examples/api.
      final File sourceAnalysisOptions = File(path.join(_flutterRoot, 'examples', 'api', 'analysis_options.yaml'));
      if (!sourceAnalysisOptions.existsSync()) {
        throw 'Cannot find analysis_options.yaml at ${sourceAnalysisOptions.path}, which is also used to analyze code snippets.';
      }
      targetAnalysisOptions
        ..createSync(recursive: true)
        ..writeAsStringSync('include: ${sourceAnalysisOptions.absolute.path}');
    }
  }

  /// Writes out a snippet section to the disk and returns the file.
  File _writeSnippetFile(_SnippetFile snippetFile) {
    final String snippetFileId = _createNameFromSource('snippet', snippetFile.filename, snippetFile.indexLine);
    final File outputFile = File(path.join(_tempDirectory.path, '$snippetFileId.dart'))..createSync(recursive: true);
    final String contents = snippetFile.code.map<String>((_Line line) => line.code).join('\n').trimRight();
    outputFile.writeAsStringSync('$contents\n');
    return outputFile;
  }

  /// Starts the analysis phase of checking the snippets by invoking the analyzer
  /// and parsing its output. Returns the errors, if any.
  List<Object> _analyze(Map<String, _SnippetFile> snippets) {
    final List<String> analyzerOutput = _runAnalyzer();
    final List<Object> errors = <Object>[];
    final String kBullet = Platform.isWindows ? ' - ' : ' • ';
    // RegExp to match an error output line of the analyzer.
    final RegExp errorPattern = RegExp(
      '^ *(?<type>[a-z]+)'
      '$kBullet(?<description>.+)'
      '$kBullet(?<file>.+):(?<line>[0-9]+):(?<column>[0-9]+)'
      '$kBullet(?<code>[-a-z_]+)\$',
      caseSensitive: false,
    );

    for (final String error in analyzerOutput) {
      final RegExpMatch? match = errorPattern.firstMatch(error);
      if (match == null) {
        errors.add(_SnippetCheckerException('Could not parse analyzer output: $error'));
        continue;
      }
      final String message = match.namedGroup('description')!;
      final File file = File(path.join(_tempDirectory.path, match.namedGroup('file')));
      final List<String> fileContents = file.readAsLinesSync();
      final String lineString = match.namedGroup('line')!;
      final String columnString = match.namedGroup('column')!;
      final String errorCode = match.namedGroup('code')!;
      final int lineNumber = int.parse(lineString, radix: 10);
      final int columnNumber = int.parse(columnString, radix: 10);

      if (lineNumber < 1 || lineNumber > fileContents.length + 1) {
        errors.add(_AnalysisError(
          file.path,
          lineNumber,
          columnNumber,
          message,
          errorCode,
          _Line(line: lineNumber),
        ));
        errors.add(_SnippetCheckerException('Error message points to non-existent line number: $error', file: file.path, line: lineNumber));
        continue;
      }

      final _SnippetFile snippet = snippets[file.path]!;
      if (snippet == null) {
        errors.add(_SnippetCheckerException(
          "Unknown section for ${file.path}. Maybe the temporary directory wasn't empty?",
          file: file.path,
          line: lineNumber,
        ));
        continue;
      }
      if (fileContents.length != snippet.code.length) {
        errors.add(_SnippetCheckerException(
          'Unexpected file contents for ${file.path}. File has ${fileContents.length} lines but we generated ${snippet.code.length} lines:\n${snippet.code.join("\n")}',
          file: file.path,
          line: lineNumber,
        ));
        continue;
      }

      late final _Line actualSource;
      late final int actualLine;
      late final int actualColumn;
      late final String actualMessage;
      int delta = 0;
      while (true) {
        // find the nearest non-generated line to the error
        if ((lineNumber - delta > 0) && (lineNumber - delta <= snippet.code.length) && !snippet.code[lineNumber - delta - 1].generated) {
          actualSource = snippet.code[lineNumber - delta - 1];
          actualLine = actualSource.line;
          actualColumn = delta == 0 ? columnNumber : actualSource.code.length + 1;
          actualMessage = delta == 0 ? message : '$message -- in later generated code';
          break;
        }
        if ((lineNumber + delta < snippet.code.length) && (lineNumber + delta >= 0) && !snippet.code[lineNumber + delta].generated) {
          actualSource = snippet.code[lineNumber + delta];
          actualLine = actualSource.line;
          actualColumn = 1;
          actualMessage = '$message -- in earlier generated code';
          break;
        }
        delta += 1;
        assert((lineNumber - delta > 0) || (lineNumber + delta < snippet.code.length));
      }
      errors.add(_AnalysisError(
        snippet.filename,
        actualLine,
        actualColumn,
        '$actualMessage (${snippet.generatorComment})',
        errorCode,
        actualSource,
      ));
    }
    return errors;
  }

  /// Invokes the analyzer on the given [directory] and returns the stdout (with some lines filtered).
  List<String> _runAnalyzer() {
    _createConfigurationFiles();
    // Run pub get to avoid output from getting dependencies in the analyzer
    // output.
    Process.runSync(
      _flutter,
      <String>['pub', 'get'],
      workingDirectory: _tempDirectory.absolute.path,
    );
    final ProcessResult result = Process.runSync(
      _flutter,
      <String>['--no-wrap', 'analyze', '--no-preamble', '--no-congratulate', '.'],
      workingDirectory: _tempDirectory.absolute.path,
    );
    final List<String> stderr = result.stderr.toString().trim().split('\n');
    final List<String> stdout = result.stdout.toString().trim().split('\n');
    // Remove output from building the flutter tool.
    stderr.removeWhere((String line) {
      return line.startsWith('Building flutter tool...')
          || line.startsWith('Waiting for another flutter command to release the startup lock...')
          || line.startsWith('Flutter assets will be downloaded from ');
    });
    // Check out the stderr to see if the analyzer had it's own issues.
    if (stderr.isNotEmpty && stderr.first.contains(RegExp(r' issues? found\. \(ran in '))) {
      stderr.removeAt(0);
      if (stderr.isNotEmpty && stderr.last.isEmpty) {
        stderr.removeLast();
      }
    }
    if (stderr.isNotEmpty && stderr.any((String line) => line.isNotEmpty)) {
      throw _SnippetCheckerException('Cannot analyze dartdocs; unexpected error output:\n$stderr');
    }
    if (stdout.isNotEmpty && stdout.first == 'Building flutter tool...') {
      stdout.removeAt(0);
    }
    if (stdout.isNotEmpty && stdout.first.isEmpty) {
      stdout.removeAt(0);
    }
    return stdout;
  }
}

/// A class to represent a section of snippet code, marked by "```dart ... ```", that ends up
/// in a file we then analyze (each snippet is in its own file).
class _SnippetFile {
  const _SnippetFile(this.code, this.generatorComment, this.filename, this.indexLine);

  factory _SnippetFile.fromLines(
    List<_Line> code,
    List<_Line> headers,
    List<_Line> preamble,
    String generatorComment,
    String filename,
  ) {
    while (code.isNotEmpty && code.last.code.isEmpty) {
      code.removeLast();
    }
    assert(code.isNotEmpty);
    final _Line firstLine = code.firstWhere((_Line line) => !line.generated);
    return _SnippetFile(
      <_Line>[
        ...headers,
        const _Line.generated(), // blank line
        if (preamble.isNotEmpty)
          ...preamble,
        if (preamble.isNotEmpty)
          const _Line.generated(), // blank line
        _Line.generated(code: '// From: $filename:${firstLine.line}'),
        ...code,
      ],
      generatorComment,
      filename,
      firstLine.line,
    );
  }

  factory _SnippetFile.fromStrings(
    _Line firstLine,
    List<String> code,
    List<_Line> headers,
    List<_Line> preamble,
    String generatorComment,
    String filename, {
    String? prefix, String? postfix,
  }) {
    final List<_Line> codeLines = <_Line>[
      if (prefix != null)
        _Line.generated(code: prefix),
      for (int i = 0; i < code.length; i += 1)
        _Line(code: code[i], line: firstLine.line + i, indent: firstLine.indent),
      if (postfix != null)
        _Line.generated(code: postfix),
    ];
    return _SnippetFile.fromLines(codeLines, headers, preamble, generatorComment, filename);
  }

  final List<_Line> code;
  final String generatorComment;
  final String filename;
  final int indexLine;
}

Future<void> _runInteractive({
  required String? tempDirectory,
  required Directory flutterPackage,
  required String filePath,
  required Directory? dartUiLocation,
}) async {
  filePath = path.isAbsolute(filePath) ? filePath : path.join(path.current, filePath);
  final File file = File(filePath);
  if (!file.existsSync()) {
    stderr.writeln('Specified file ${file.absolute.path} does not exist or is not a file.');
    exit(1);
  }
  if (!path.isWithin(_flutterRoot, file.absolute.path) &&
      (dartUiLocation == null || !path.isWithin(dartUiLocation.path, file.absolute.path))) {
    stderr.writeln(
      'Specified file ${file.absolute.path} is not within the flutter root: '
      "$_flutterRoot${dartUiLocation != null ? ' or the dart:ui location: $dartUiLocation' : ''}"
    );
    exit(1);
  }

  print('Starting up in interactive mode on ${path.relative(filePath, from: _flutterRoot)} ...');
  print('Type "q" to quit, or "r" to force a reload.');

  final _SnippetChecker checker = _SnippetChecker(flutterPackage, tempDirectory: tempDirectory)
    .._createConfigurationFiles();

  ProcessSignal.sigint.watch().listen((_) {
    checker.cleanupTempDirectory();
    exit(0);
  });

  bool busy = false;
  Future<void> rerun() async {
    assert(!busy);
    try {
      busy = true;
      print('\nAnalyzing...');
      checker.recreateTempDirectory();
      final Map<String, _SnippetFile> snippets = <String, _SnippetFile>{};
      final Set<Object> errors = <Object>{};
      errors.addAll(await checker._extractSnippets(<File>[file], snippetMap: snippets));
      errors.addAll(checker._analyze(snippets));
      stderr.writeln('\u001B[2J\u001B[H'); // Clears the old results from the terminal.
      if (errors.isNotEmpty) {
        (errors.toList()..sort()).map(_stringify).forEach(stderr.writeln);
        stderr.writeln('Found ${errors.length} errors.');
      } else {
        stderr.writeln('No issues found.');
      }
    } finally {
      busy = false;
    }
  }
  await rerun();

  stdin.lineMode = false;
  stdin.echoMode = false;
  stdin.transform(utf8.decoder).listen((String input) async {
    switch (input.trim()) {
      case 'q':
        checker.cleanupTempDirectory();
        exit(0);
      case 'r':
        if (!busy) {
          rerun();
        }
        break;
    }
  });
  Watcher(file.absolute.path).events.listen((_) => rerun());
}

String _stringify(Object object) => object.toString();
