// 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
// ../../packages/flutter/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';
import 'package:yaml_edit/yaml_edit.dart' show YamlEditor;

const String _pubspecName = 'pubspec.yaml';

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 {
  var 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(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 pubspec = File(path.join(entity.path, _pubspecName));
      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 fileStr = file == null ? '' : '$file:';
      final 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;

  Directory get _contentDirectory {
    final directory = Directory(path.join(_tempDirectory.path, 'packages'));
    if (!directory.existsSync()) {
      directory.createSync();
    }
    return directory;
  }

  /// 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: invalid_annotation_target',
    '// ignore_for_file: no_leading_underscores_for_local_identifiers',
    '// ignore_for_file: override_on_non_overriding_member',
    '// 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 snippets = <String, _SnippetFile>{};
    if (_dartUiLocation != null && !_dartUiLocation.existsSync()) {
      stderr.writeln('Unable to analyze engine dart snippets at ${_dartUiLocation.path}.');
    }
    final filesToAnalyze = <File>[
      for (final Directory flutterPackage in _flutterPackages)
        ..._listDartFiles(flutterPackage, recursive: true),
      if (_dartUiLocation != null && _dartUiLocation.existsSync())
        ..._listDartFiles(_dartUiLocation, recursive: true),
    ];
    final 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 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 errors = <Object>[];
    _SnippetFile? lastExample;
    for (final file in files) {
      try {
        final String relativeFilePath = path.relative(file.path, from: _flutterRoot);
        final List<String> fileLines = file.readAsLinesSync();
        final ignorePreambleLinesOnly = <_Line>[];
        final preambleLines = <_Line>[];
        final customImports = <_Line>[];
        var inExamplesCanAssumePreamble =
            false; // Whether or not we're in the file-wide preamble section ("Examples can assume").
        var inToolSection = false; // Whether or not we're in a code snippet
        var inDartSection = false; // Whether or not we're in a '```dart' segment.
        var inOtherBlock = false; // Whether we're in some other '```' segment.
        var lineNumber = 0;
        final block = <String>[];
        late _Line startLine;
        for (final 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 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.',
      );
    }
    var hasEllipsis = false;
    for (var 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;
      }
    }
    var hasStatefulWidgetComment = false;
    var importPreviousExample = false;
    int index = startingLine.line;
    for (final 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 (var 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 String targetWorkspacePubspecPath = path.join(_tempDirectory.path, _pubspecName);
    _copyPubspec(targetWorkspacePubspecPath, path.join(_flutterRoot, _pubspecName));
    final targetWorkspacePubspec = File(targetWorkspacePubspecPath);
    final String pubspec = targetWorkspacePubspec.readAsStringSync();

    final yamlEditor = YamlEditor(pubspec);
    yamlEditor.update(<String>['workspace'], <String>['packages']);
    targetWorkspacePubspec.writeAsStringSync(yamlEditor.toString());

    _copyPubspec(
      path.join(_contentDirectory.path, _pubspecName),
      path.join(_flutterRoot, 'packages', 'flutter', 'examples', 'api', _pubspecName),
    );
    final targetAnalysisOptions = File(path.join(_contentDirectory.path, 'analysis_options.yaml'));
    if (!targetAnalysisOptions.existsSync()) {
      // Use the same analysis_options.yaml configuration that's used for packages/flutter/examples/api.
      final sourceAnalysisOptions = File(
        path.join(_flutterRoot, 'packages', 'flutter', '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}');
    }
  }

  void _copyPubspec(String targetPath, String sourcePath) {
    final targetPubSpec = File(targetPath);
    if (!targetPubSpec.existsSync()) {
      // Copying pubspec.yaml from packages/flutter/examples/api into temp directory.
      final sourcePubSpec = File(sourcePath);
      if (!sourcePubSpec.existsSync()) {
        throw 'Cannot find pubspec.yaml at ${sourcePubSpec.path}, which is also used to analyze code snippets.';
      }
      targetPubSpec
        ..createSync(recursive: true)
        ..writeAsStringSync(sourcePubSpec.readAsStringSync());
    }
  }

  /// 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 outputFile = File(path.join(_contentDirectory.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 errors = <Object>[];
    final kBullet = Platform.isWindows ? ' - ' : ' • ';
    // RegExp to match an error output line of the analyzer.
    final errorPattern = RegExp(
      '^ *(?<type>[a-z]+)'
      '$kBullet(?<description>.+)'
      '$kBullet(?<file>.+):(?<line>[0-9]+):(?<column>[0-9]+)'
      '$kBullet(?<code>[-a-z_]+)\$',
      caseSensitive: false,
    );

    for (final 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(path.join(_contentDirectory.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;
      var 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: _contentDirectory.absolute.path);
    final ProcessResult result = Process.runSync(_flutter, <String>[
      '--no-wrap',
      'analyze',
      '--no-congratulate',
      '.',
    ], workingDirectory: _contentDirectory.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');
    }
    // Skip the boring part of the analysis, the preface - we only want the errors.
    return stdout
        .skipWhile((String line) => !line.startsWith('Analyzing packages...'))
        .skip(1)
        .skipWhile((String line) => line.isEmpty)
        .toList();
  }
}

/// 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 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(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 checker = _SnippetChecker(flutterPackages, tempDirectory: tempDirectory)
    .._createConfigurationFiles();

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

  var busy = false;
  Future<void> rerun() async {
    assert(!busy);
    try {
      busy = true;
      print('\nAnalyzing...');
      checker.recreateTempDirectory();
      final snippets = <String, _SnippetFile>{};
      final 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:
        await rerun();
    }
  });
  Watcher(file.absolute.path).events.listen((_) => rerun());
}

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