// 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 linked 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/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
//
// 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} ... {@end-tool} 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. This section may also contain explicit import statements.
//
// For files without an `// Examples can assume:` section or if that section
// contains no explicit imports, the snippets will implicitly import all the
// main Flutter packages (including material and flutter_test), as well as most
// core Dart packages with the usual prefixes.
//
// When invoked without an additional path argument, the script will analyze
// the code snippets for all packages in the "packages" subdirectory that do
// not specify "nodoc: true" in their pubspec.yaml (i.e. all packages for which
// we publish docs will have their doc code snippets analyzed).

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 _packageFlutter = 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);
  }

  final List<Directory> flutterPackages;
  if (parsedArguments.rest.length == 1) {
    // Used for testing.
    flutterPackages = <Directory>[Directory(parsedArguments.rest.single)];
  } else {
    // By default analyze snippets in all packages in the packages subdirectory
    // that do not specify "nodoc: true" in their pubspec.yaml.
    flutterPackages = <Directory>[];
    final String packagesRoot = path.join(_flutterRoot, 'packages');
    for (final FileSystemEntity entity in Directory(packagesRoot).listSync()) {
      if (entity is! Directory) {
        continue;
      }
      final File pubspec = File(path.join(entity.path, 'pubspec.yaml'));
      if (!pubspec.existsSync()) {
        throw StateError("Unexpected package '${entity.path}' found in packages directory");
      }
      if (!pubspec.readAsStringSync().contains('nodoc: true')) {
        flutterPackages.add(Directory(path.join(entity.path, 'lib')));
      }
    }
    assert(flutterPackages.length >= 4);
  }

  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(
      flutterPackages: flutterPackages,
      tempDirectory: parsedArguments['temp'] as String?,
      filePath: parsedArguments['interactive'] as String,
      dartUiLocation: includeDartUi ? dartUiLocation : null,
    );
  } else {
    if (await _SnippetChecker(
        flutterPackages,
        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._flutterPackages, {
    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 visibility 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 brace (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 directories within the flutter root dir that will be checked.
  final List<Directory> _flutterPackages;

  /// 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: directives_ordering',
    '// ignore_for_file: duplicate_ignore',
    '// ignore_for_file: no_leading_underscores_for_local_identifiers',
    '// ignore_for_file: prefer_final_locals',
    '// ignore_for_file: unnecessary_import',
    '// ignore_for_file: unreachable_from_main',
    '// ignore_for_file: unused_element',
    '// ignore_for_file: unused_element_parameter',
    '// 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(_packageFlutter)))
        "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>[
      for (final Directory flutterPackage in _flutterPackages)
        ..._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>[];
        final List<_Line> customImports = <_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));
              if (newLine.code.startsWith('import ')) {
               customImports.add(newLine);
              } else {
                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, customImports);
              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('```json') ||
                       line.contains('```csv') ||
                       line.contains('```sh')) {
              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, List<_Line> customImports) {
    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(),
        headersWithoutImports,
        <_Line>[
          ...ignoreAssumptionsOnly,
          if (hasEllipsis)
            const _Line.generated(code: '// ignore_for_file: non_abstract_class_inherits_abstract_member'),
        ],
        'self-contained program',
        filename,
      );
    }

    final List<_Line> headers = switch ((importPreviousExample, customImports.length)) {
      (true, _) => <_Line>[],
      (false, 0) => headersWithImports,
      (false, _) => <_Line>[
        ...headersWithoutImports,
        const _Line.generated(code: '// ignore_for_file: unused_import'),
        ...customImports,
      ]
    };
    if (hasStatefulWidgetComment) {
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'class _State extends State<StatefulWidget> {',
        block.toList(),
        postfix: '}',
        headers,
        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(),
        headers,
        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: '}',
        headers,
        preamble,
        'statement',
        filename,
      );
    } else if (firstCodeLine.startsWith(_classDeclarationRegExp)) {
      // probably a static method
      return _SnippetFile.fromStrings(
        startingLine,
        prefix: 'class Class {',
        block.toList(),
        postfix: '}',
        headers,
        <_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: ';',
        headers,
        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 List<Directory> flutterPackages,
  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(flutterPackages, 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' when !busy:
        rerun();
    }
  });
  Watcher(file.absolute.path).events.listen((_) => rerun());
}

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