// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// dartdoc's dartdoc_options.yaml configuration file follows similar loading
/// semantics to that of analysis_options.yaml,
/// [documented here](https://dart.dev/guides/language/analysis-options).
/// It searches parent directories until it finds an analysis_options.yaml file,
/// and uses built-in defaults if one is not found.
///
/// The classes here manage both the dartdoc_options.yaml loading and command
/// line arguments.
library;

import 'dart:io' show exitCode, stderr, stdout;

import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:args/args.dart';
import 'package:dartdoc/src/dartdoc.dart' show dartdocVersion, programName;
import 'package:dartdoc/src/experiment_options.dart';
import 'package:dartdoc/src/failure.dart';
import 'package:dartdoc/src/generator/generator.dart';
import 'package:dartdoc/src/io_utils.dart';
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:dartdoc/src/source_linker.dart';
import 'package:dartdoc/src/tool_configuration.dart';
import 'package:dartdoc/src/warnings.dart';
import 'package:path/path.dart' as p show Context, canonicalize;
import 'package:yaml/yaml.dart';

/// Constants to help with type checking, because T is int and so forth
/// don't work in Dart.
const String _kStringVal = '';
const List<String> _kListStringVal = <String>[];
const Map<String, String> _kMapStringVal = <String, String>{};
const int _kIntVal = 0;
const double _kDoubleVal = 0.0;
const bool _kBoolVal = true;

const String compileArgsTagName = 'compile_args';

int get _usageLineLength => stdout.hasTerminal ? stdout.terminalColumns : 80;

typedef ConvertYamlToType<T> = T Function(YamlMap, String, ResourceProvider);

class DartdocOptionError extends DartdocFailure {
  DartdocOptionError(super.details);
}

class DartdocFileMissing extends DartdocOptionError {
  DartdocFileMissing(super.details);
}

/// Defines the attributes of a category in the options file, corresponding to
/// the 'categories' keyword in the options file, and populated by the
/// [CategoryConfiguration] class.
class CategoryDefinition {
  /// Internal name of the category, or null for the default category.
  final String? name;

  /// Displayed name of the category in docs, or null if there is none.
  final String? _displayName;

  /// Canonical path of the markdown file used to document this category
  /// (or null if undocumented).
  final String? documentationMarkdown;

  /// The external items defined for this category.
  final List<ExternalItem> externalItems;

  CategoryDefinition(
    this.name,
    this._displayName,
    this.documentationMarkdown, {
    this.externalItems = const [],
  });

  /// Returns the [_displayName], if available, or else simply [name].
  String get displayName => _displayName ?? name ?? '';
}

/// A configuration class that can interpret category definitions from a YAML
/// map.
class CategoryConfiguration {
  /// A map of [CategoryDefinition.name] to [CategoryDefinition] objects.
  final Map<String, CategoryDefinition> categoryDefinitions;

  CategoryConfiguration._(this.categoryDefinitions);

  static CategoryConfiguration get empty {
    return CategoryConfiguration._(const {});
  }

  static CategoryConfiguration fromYamlMap(YamlMap yamlMap,
      String canonicalYamlPath, ResourceProvider resourceProvider) {
    var newCategoryDefinitions = <String, CategoryDefinition>{};
    for (var MapEntry(:key, value: categoryMap) in yamlMap.entries) {
      var name = key.toString();
      if (categoryMap is Map) {
        var displayName = categoryMap['displayName']?.toString();
        var documentationMarkdown = categoryMap['markdown']?.toString();
        if (documentationMarkdown != null) {
          documentationMarkdown = resourceProvider.pathContext.canonicalize(
              resourceProvider.pathContext
                  .join(canonicalYamlPath, documentationMarkdown));
          if (!resourceProvider.getFile(documentationMarkdown).exists) {
            throw DartdocFileMissing(
                'In categories definition for $name, "markdown" resolves to '
                'the missing file $documentationMarkdown');
          }
        }
        final externalItems = <ExternalItem>[];
        var items = categoryMap['external'] as List?;
        if (items != null) {
          for (var item in items) {
            if (item is! Map) {
              throw DartdocOptionError("'external' field should be a map");
            } else {
              final itemName = item['name'] as String?;
              if (itemName == null) {
                throw DartdocOptionError(
                    "'external' item missing required field 'name'");
              }

              final itemUrl = item['url'] as String?;
              if (itemUrl == null) {
                throw DartdocOptionError(
                    "'external' item missing required field 'url'");
              }

              externalItems.add(ExternalItem(
                name: itemName,
                url: itemUrl,
                docs: item['docs'] as String?,
              ));
            }
          }
        }
        newCategoryDefinitions[name] = CategoryDefinition(
          name,
          displayName,
          documentationMarkdown,
          externalItems: externalItems,
        );
      }
    }
    return CategoryConfiguration._(newCategoryDefinitions);
  }
}

/// A container class to keep track of where our yaml data came from.
class _YamlFileData {
  /// The map from the yaml file.
  final Map<Object?, Object?> data;

  /// The path to the directory containing the yaml file.
  final String canonicalDirectoryPath;

  _YamlFileData(this.data, this.canonicalDirectoryPath);
}

/// An enum to specify the multiple different kinds of data an option might
/// represent.
enum OptionKind {
  /// Make no assumptions about the option data; it may be of any type or
  /// semantic.
  other,

  /// Option data references a filename or filenames with strings.
  file,

  /// Option data references a directory name or names with strings.
  dir,

  /// Option data references globs with strings that may cover many filenames
  /// and/or directories.
  glob,
}

/// Some DartdocOption subclasses need to keep track of where they
/// got the value from; this class contains those intermediate results
/// so that error messages can be more useful.
class _OptionValueWithContext<T> {
  /// The value of the option at canonicalDirectoryPath.
  final T value;

  /// A canonical path to the directory where this value came from.  May
  /// be different from [DartdocOption.valueAt]'s `dir` parameter.
  String canonicalDirectoryPath;

  /// If non-null, the basename of the configuration file the value came from.
  String? definingFile;

  /// A [p.Context] variable initialized with 'canonicalDirectoryPath'.
  p.Context pathContext;

  /// Build a _OptionValueWithContext.
  ///
  /// [path] is the path where this value came from (not required to be
  /// canonical).
  _OptionValueWithContext(this.value, String path, {this.definingFile})
      : canonicalDirectoryPath = p.canonicalize(path),
        pathContext = p.Context(current: p.canonicalize(path));

  /// Assume value is a path, and attempt to resolve it.
  ///
  /// Throws [UnsupportedError] if [T] isn't a [String] or [List<String>].
  T get resolvedValue {
    final value = this.value;
    return switch (value) {
      List<String>() => value
          .map((v) => pathContext.canonicalizeWithTilde(v))
          .cast<String>()
          .toList(growable: false) as T,
      String() => pathContext.canonicalizeWithTilde(value) as T,
      Map<String, String>() =>
        value.map<String, String>((String key, String value) {
          return MapEntry(key, pathContext.canonicalizeWithTilde(value));
        }) as T,
      _ => throw UnsupportedError('Type $T is not supported for resolvedValue')
    };
  }
}

/// An abstract class for interacting with dartdoc options.
///
/// This class and its implementations allow Dartdoc to declare options that
/// are both defined in a configuration file and specified via the command line,
/// with searching the directory tree for a proper file and overriding file
/// options with the command line built-in.  A number of sanity checks are also
/// built in to these classes so that file existence can be verified, types
/// constrained, and defaults provided.
///
/// This class caches the current working directory from the [ResourceProvider];
/// do not attempt to change it during the life of an instance.
///
/// Use via implementations [DartdocOptionSet], [DartdocOptionArgFile],
/// [DartdocOptionArgOnly], and [DartdocOptionFileOnly].
abstract class DartdocOption<T extends Object?> {
  /// This is the value returned if we couldn't find one otherwise.
  final T? defaultsTo;

  /// Text string for help passed on in command line options.
  final String help;

  /// The name of this option, not including the names of any parents.
  final String name;

  /// Set to true if this option represents the name of a directory.
  bool get isDir => optionIs == OptionKind.dir;

  /// Set to true if this option represents the name of a file.
  bool get isFile => optionIs == OptionKind.file;

  /// Set to true if this option represents a glob.
  bool get isGlob => optionIs == OptionKind.glob;

  final OptionKind optionIs;

  /// Set to true if DartdocOption subclasses should validate that the
  /// directory or file exists.  Does not imply validation of [defaultsTo],
  /// and requires that one of [isDir] or [isFile] is set.
  final bool mustExist;

  final ResourceProvider resourceProvider;

  DartdocOption(this.name, this.defaultsTo, this.help, this.optionIs,
      this.mustExist, this._convertYamlToType, this.resourceProvider) {
    if (isDir || isFile || isGlob) {
      assert(_isString || _isListString || _isMapString);
    }
    if (mustExist) {
      // Globs by definition don't have to exist.
      assert(isDir || isFile);
    }
  }

  /// Closure to convert yaml data into some other structure.
  final ConvertYamlToType<T>? _convertYamlToType;

  // The choice not to use reflection means there's some ugly type checking,
  // somewhat more ugly than we'd have to do anyway to automatically convert
  // command line arguments and yaml data to real types.
  //
  // Condense the ugly all in one place, this set of getters.
  bool get _isString => _kStringVal is T;

  bool get _isListString => _kListStringVal is T;

  bool get _isMapString => _kMapStringVal is T;

  bool get _isBool => _kBoolVal is T;

  bool get _isInt => _kIntVal is T;

  bool get _isDouble => _kDoubleVal is T;

  String get _expectedTypeForDisplay {
    if (_isString) return 'String';
    if (_isListString) return 'list of Strings';
    if (_isMapString) return 'map of String to String';
    if (_isBool) return 'boolean';
    if (_isInt) return 'int';
    if (_isDouble) return 'double';
    assert(false, 'Expecting an unknown type');
    return '<<unknown>>';
  }

  final Map<String, _YamlFileData> __yamlAtCanonicalPathCache = {};

  /// Implementation detail for [DartdocOptionFileOnly].  Make sure we use
  /// the root node's cache.
  Map<String, _YamlFileData> get _yamlAtCanonicalPathCache =>
      root.__yamlAtCanonicalPathCache;

  /// Throw [DartdocFileMissing] with a detailed error message indicating where
  /// the error came from when a file or directory option is missing.
  void _onMissing(
      _OptionValueWithContext<T> valueWithContext, String missingFilename);

  /// Call [_onMissing] for every path that does not exist.
  void _validatePaths(_OptionValueWithContext<T> valueWithContext) {
    if (!mustExist) return;
    assert(isDir || isFile);
    List<String> resolvedPaths;
    var value = valueWithContext.value;
    switch (value) {
      case String():
        resolvedPaths = [valueWithContext.resolvedValue as String];
      case List<String>():
        resolvedPaths = valueWithContext.resolvedValue as List<String>;
      case Map<String, String>():
        resolvedPaths = (valueWithContext.resolvedValue as Map<String, String>)
            .values
            .toList(growable: false);
      default:
        assert(
            false,
            'Trying to ensure existence of unsupported type '
            '${valueWithContext.value.runtimeType}');
        return;
    }
    for (var path in resolvedPaths) {
      var f = isDir
          ? resourceProvider.getFolder(path)
          : resourceProvider.getFile(path);
      if (!f.exists) {
        _onMissing(valueWithContext, path);
      }
    }
  }

  /// For a [List<String>] or [String] value, if [isDir] or [isFile] is set,
  /// resolve paths in value relative to canonicalPath.
  T? _handlePathsInContext(_OptionValueWithContext<T>? valueWithContext) {
    if (valueWithContext?.value == null || !(isDir || isFile || isGlob)) {
      return valueWithContext?.value;
    }
    _validatePaths(valueWithContext!);
    return valueWithContext.resolvedValue;
  }

  /// Call this with argv to set up the argument overrides.  Applies to all
  /// children.
  void parseArguments(List<String> arguments) =>
      root._parseArguments(arguments);

  ArgResults get _argResults => root.__argResults;

  /// To avoid accessing early, call [add] on the option's parent before
  /// looking up unless this is a [DartdocOptionRoot].
  late final DartdocOption<dynamic> parent;

  /// The [DartdocOptionRoot] containing this object.
  DartdocOptionRoot get root {
    DartdocOption<dynamic> p = this;
    while (p is! DartdocOptionRoot) {
      p = p.parent;
    }
    return p;
  }

  /// All object names starting at the root.
  Iterable<String> get keys {
    var keyList = <String>[];
    DartdocOption<dynamic> option = this;
    while (option is! DartdocOptionRoot) {
      keyList.add(option.name);
      option = option.parent;
    }
    keyList.add(option.name);
    return keyList.reversed;
  }

  /// Direct children of this node, mapped by name.
  final Map<String, DartdocOption> _children = {};

  /// Return the calculated value of this option, given the directory as
  /// context.
  ///
  /// If [isFile] or [isDir] is set, the returned value will be transformed
  /// into a canonical path relative to the current working directory
  /// (for arguments) or the config file from which the value was derived.
  ///
  /// May throw [DartdocOptionError] if a command line argument is of the wrong
  /// type.  If [mustExist] is true, will throw [DartdocFileMissing] for command
  /// line parameters and file paths in config files that don't point to
  /// corresponding files or directories.
  // TODO(jcollins-g): use of dynamic.  https://github.com/dart-lang/dartdoc/issues/2814
  dynamic valueAt(Folder dir);

  /// Calls [valueAt] with the working directory at the start of the program.
  Object? valueAtCurrent() => valueAt(_directoryCurrent);

  late final Folder _directoryCurrent =
      resourceProvider.getFolder(_directoryCurrentPath);
  late final String _directoryCurrentPath =
      resourceProvider.pathContext.current;

  /// Adds a DartdocOption to the children of this DartdocOption.
  void add(DartdocOption option) {
    if (_children.containsKey(option.name)) {
      throw DartdocOptionError(
          'Tried to add two children with the same name: ${option.name}');
    }
    _children[option.name] = option;
    // TODO(jcollins-g): Consider a stronger refactor that doesn't rely on
    // post-construction setup for [parent].
    option.parent = this;
  }

  /// This method is called when parsing options to set up the [ArgParser].
  void _addToArgParser(ArgParser argParser) {}

  /// Adds a list of dartdoc options to the children of this DartdocOption.
  void addAll(Iterable<DartdocOption> options) => options.forEach(add);

  /// Get the immediate child of this node named [name].
  DartdocOption operator [](String name) {
    return _children[name]!;
  }

  /// Get the immediate child of this node named [name] and its value at [dir].
  U getValueAs<U>(String name, Folder dir) =>
      _children[name]?.valueAt(dir) as U;

  /// Apply the function [visit] to this [DartdocOption] and all children.
  void traverse(void Function(DartdocOption option) visit) {
    visit(this);
    for (var value in _children.values) {
      value.traverse(visit);
    }
  }
}

/// A class that defaults to a value computed from a closure, but can be
/// overridden by a file.
class DartdocOptionFileSynth<T> extends DartdocOption<T>
    with DartdocSyntheticOption<T>, _DartdocFileOption<T> {
  @override
  final T Function(DartdocSyntheticOption<T>, Folder) _compute;

  DartdocOptionFileSynth(
      String name, this._compute, ResourceProvider resourceProvider,
      {String help = ''})
      : super(
            name, null, help, OptionKind.other, false, null, resourceProvider);

  @override
  bool get parentDirOverridesChild => false;

  @override
  T? valueAt(Folder dir) {
    var result = _valueAtFromFile(dir);
    if (result?.definingFile != null) {
      return _handlePathsInContext(result);
    }
    return _valueAtFromSynthetic(dir);
  }

  @override
  Never _onMissing(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    if (valueWithContext.definingFile != null) {
      _onMissingFromFiles(valueWithContext, missingPath);
    } else {
      _onMissingFromSynthetic(valueWithContext, missingPath);
    }
  }
}

/// A class that defaults to a value computed from a closure, but can
/// be overridden on the command line.
class DartdocOptionArgSynth<T> extends DartdocOption<T>
    with DartdocSyntheticOption<T>, _DartdocArgOption<T> {
  @override
  final String? abbr;
  @override
  final bool negatable;

  @override
  final T Function(DartdocSyntheticOption<T>, Folder) _compute;

  DartdocOptionArgSynth(
      String name, this._compute, ResourceProvider resourceProvider,
      {this.abbr,
      bool mustExist = false,
      String help = '',
      OptionKind optionIs = OptionKind.other,
      this.negatable = false})
      : super(name, null, help, optionIs, mustExist, null, resourceProvider);

  @override
  bool get hide => false;

  @override
  bool get splitCommas => false;

  @override
  Never _onMissing(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    _onMissingFromArgs(valueWithContext, missingPath);
  }

  @override
  T? valueAt(Folder dir) {
    if (_argResults.wasParsed(argName)) {
      return _valueAtFromArgs();
    }
    return _valueAtFromSynthetic(dir);
  }
}

/// A synthetic option takes a closure at construction time that computes
/// the value of the configuration option based on other configuration options.
/// Does not protect against closures that self-reference.  If [mustExist] and
/// [isDir] or [isFile] is set, computed values will be resolved to canonical
/// paths.
class DartdocOptionSyntheticOnly<T> extends DartdocOption<T>
    with DartdocSyntheticOption<T> {
  @override
  final T Function(DartdocSyntheticOption<T>, Folder) _compute;

  DartdocOptionSyntheticOnly(
      String name, this._compute, ResourceProvider resourceProvider,
      {bool mustExist = false,
      String help = '',
      OptionKind optionIs = OptionKind.other})
      : super(name, null, help, optionIs, mustExist, null, resourceProvider);
}

mixin DartdocSyntheticOption<T> implements DartdocOption<T> {
  T Function(DartdocSyntheticOption<T>, Folder) get _compute;

  @override
  T? valueAt(Folder dir) => _valueAtFromSynthetic(dir);

  T? _valueAtFromSynthetic(Folder dir) {
    var context = _OptionValueWithContext<T>(_compute(this, dir), dir.path);
    return _handlePathsInContext(context);
  }

  @override
  Never _onMissing(
          _OptionValueWithContext<T> valueWithContext, String missingPath) =>
      _onMissingFromSynthetic(valueWithContext, missingPath);

  Never _onMissingFromSynthetic(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    var description = 'Synthetic configuration option $name from <internal>';
    throw DartdocFileMissing(
        '$description, computed as ${valueWithContext.value}, resolves to '
        'missing path: "$missingPath"');
  }
}

typedef OptionGenerator = List<DartdocOption> Function(PackageMetaProvider);

/// This is a [DartdocOptionSet] used as a root node.
class DartdocOptionRoot extends DartdocOptionSet {
  DartdocOptionRoot(super.name, super.resourceProvider);

  late final ArgParser _argParser =
      ArgParser(usageLineLength: _usageLineLength);

  /// Asynchronous factory that is the main entry point to initialize Dartdoc
  /// options for use.
  ///
  /// [name] is the top level key for the option set.
  /// [optionGenerators] is a sequence of asynchronous functions that return
  /// [DartdocOption]s that will be added to the new option set.
  static DartdocOptionRoot fromOptionGenerators(
      String name,
      Iterable<OptionGenerator> optionGenerators,
      PackageMetaProvider packageMetaProvider) {
    var optionSet =
        DartdocOptionRoot(name, packageMetaProvider.resourceProvider);
    for (var generator in optionGenerators) {
      optionSet.addAll(generator(packageMetaProvider));
    }
    return optionSet;
  }

  ArgParser get argParser => _argParser;

  /// Initialized via [_parseArguments].
  late ArgResults __argResults;

  bool _argParserInitialized = false;

  /// Parse these as string arguments (from argv) with the argument parser.
  /// Call before calling [valueAt] for any [DartdocOptionArgOnly] or
  /// [DartdocOptionArgFile] in this tree.
  void _parseArguments(List<String> arguments) {
    if (!_argParserInitialized) {
      _argParserInitialized = true;
      traverse((DartdocOption option) {
        option._addToArgParser(argParser);
      });
    }
    __argResults = argParser.parse(arguments);
  }

  /// Traverse skips this node, because it doesn't represent a real
  /// configuration object.
  @override
  void traverse(void Function(DartdocOption option) visitor) {
    for (var value in _children.values) {
      value.traverse(visitor);
    }
  }

  @override
  DartdocOption get parent =>
      throw UnsupportedError('Root nodes have no parent');
}

/// A [DartdocOption] that only contains other [DartdocOption]s and is not an
/// option itself.
class DartdocOptionSet extends DartdocOption<void> {
  DartdocOptionSet(String name, ResourceProvider resourceProvider)
      : super(name, null, '', OptionKind.other, false, null, resourceProvider);

  /// [DartdocOptionSet] always has the null value.
  @override
  void valueAt(Folder dir) {}

  /// Since we have no value, [_onMissing] does nothing.
  @override
  void _onMissing(
      _OptionValueWithContext<void> valueWithContext, String missingFilename) {}
}

/// A [DartdocOption] that only exists as a command line argument. `--help` is a
/// good example.
class DartdocOptionArgOnly<T> extends DartdocOption<T>
    with _DartdocArgOption<T> {
  @override
  final String? abbr;
  @override
  final bool hide;
  @override
  final bool negatable;
  @override
  final bool splitCommas;

  DartdocOptionArgOnly(
      String name, T defaultsTo, ResourceProvider resourceProvider,
      {this.abbr,
      bool mustExist = false,
      String help = '',
      this.hide = false,
      OptionKind optionIs = OptionKind.other,
      this.negatable = false,
      this.splitCommas = false})
      : super(name, defaultsTo, help, optionIs, mustExist, null,
            resourceProvider);
}

/// A [DartdocOption] that works with command line arguments and
/// `dartdoc_options` files.
class DartdocOptionArgFile<T> extends DartdocOption<T>
    with _DartdocArgOption<T>, _DartdocFileOption<T> {
  @override
  final bool negatable;
  @override
  final bool splitCommas;

  DartdocOptionArgFile(
      String name, T defaultsTo, ResourceProvider resourceProvider,
      {bool mustExist = false,
      String help = '',
      OptionKind optionIs = OptionKind.other,
      this.negatable = false,
      this.splitCommas = false})
      : super(name, defaultsTo, help, optionIs, mustExist, null,
            resourceProvider);

  @override
  String? get abbr => null;

  @override
  bool get hide => false;

  @override
  bool get parentDirOverridesChild => false;

  @override
  Never _onMissing(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    if (valueWithContext.definingFile != null) {
      _onMissingFromFiles(valueWithContext, missingPath);
    } else {
      _onMissingFromArgs(valueWithContext, missingPath);
    }
  }

  /// Try to find an explicit argument setting this value, and fall back first
  /// to files, then to the default.
  @override
  T? valueAt(Folder dir) =>
      _valueAtFromArgs() ?? _valueAtFromFiles(dir) ?? defaultsTo;
}

class DartdocOptionFileOnly<T> extends DartdocOption<T>
    with _DartdocFileOption<T> {
  @override
  final bool parentDirOverridesChild;

  DartdocOptionFileOnly(
      String name, T defaultsTo, ResourceProvider resourceProvider,
      {bool mustExist = false,
      String help = '',
      OptionKind optionIs = OptionKind.other,
      this.parentDirOverridesChild = false,
      ConvertYamlToType<T>? convertYamlToType})
      : super(name, defaultsTo, help, optionIs, mustExist, convertYamlToType,
            resourceProvider);
}

/// Implements checking for options contained in dartdoc.yaml.
mixin _DartdocFileOption<T> implements DartdocOption<T> {
  /// If true, the parent directory's value overrides the child's.
  ///
  /// Otherwise, the child's value overrides values in parents.
  bool get parentDirOverridesChild;

  /// The name of the option, with nested options joined by `.`.  For example:
  ///
  /// ```yaml
  /// dartdoc:
  ///   stuff:
  ///     things:
  /// ```
  /// would have the name `things` and the fieldName `dartdoc.stuff.things`.
  String get fieldName => keys.join('.');

  @override
  Never _onMissing(
          _OptionValueWithContext<T> valueWithContext, String missingPath) =>
      _onMissingFromFiles(valueWithContext, missingPath);

  Never _onMissingFromFiles(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    var dartdocYaml = resourceProvider.pathContext.join(
        valueWithContext.canonicalDirectoryPath, valueWithContext.definingFile);
    throw DartdocFileMissing('Field $fieldName from $dartdocYaml, set to '
        '${valueWithContext.value}, resolves to missing path: "$missingPath"');
  }

  /// Searches for a value in configuration files relative to [dir], and if not
  /// found, returns [defaultsTo].
  @override
  T? valueAt(Folder dir) => _valueAtFromFiles(dir) ?? defaultsTo;

  /// The backing store for [_valueAtFromFiles].
  final Map<String, T?> __valueAtFromFiles = {};

  // The value of this option from files will not change unless files are
  // modified during execution (not allowed in Dartdoc).
  T? _valueAtFromFiles(Folder dir) {
    var key = resourceProvider.pathContext.canonicalize(dir.path);
    if (!__valueAtFromFiles.containsKey(key)) {
      _OptionValueWithContext<T>? valueWithContext;
      if (parentDirOverridesChild) {
        valueWithContext = _valueAtFromFilesLastFound(dir);
      } else {
        valueWithContext = _valueAtFromFilesFirstFound(dir);
      }
      __valueAtFromFiles[key] = _handlePathsInContext(valueWithContext);
    }
    return __valueAtFromFiles[key];
  }

  /// Searches all dartdoc options files through parent directories, starting at
  /// [folder], for the option and returns one once found.
  _OptionValueWithContext<T>? _valueAtFromFilesFirstFound(Folder folder) {
    _OptionValueWithContext<T>? value;
    for (var dir in folder.withAncestors) {
      value = _valueAtFromFile(dir);
      if (value != null) break;
    }
    return value;
  }

  /// Searches all dartdoc_options files for the option, and returns the value
  /// in the top-most parent directory `dartdoc_options.yaml` file it is
  /// mentioned in.
  _OptionValueWithContext<T>? _valueAtFromFilesLastFound(Folder folder) {
    _OptionValueWithContext<T>? value;
    for (var dir in folder.withAncestors) {
      var tmpValue = _valueAtFromFile(dir);
      if (tmpValue != null) value = tmpValue;
    }
    return value;
  }

  /// Returns null if not set in the YAML file in this directory (or its
  /// parents).
  _OptionValueWithContext<T>? _valueAtFromFile(Folder dir) {
    var yamlFileData = _yamlAtDirectory(dir);
    var contextPath = yamlFileData.canonicalDirectoryPath;
    Object yamlData = yamlFileData.data;
    for (var key in keys) {
      if (yamlData is Map && !yamlData.containsKey(key)) return null;
      yamlData = (yamlData as Map)[key] ?? {};
    }

    Object? returnData;
    if (_isListString) {
      if (yamlData is YamlList) {
        returnData = [
          for (var item in yamlData) item.toString(),
        ];
      }
    } else if (yamlData is YamlMap) {
      var convertYamlToType = _convertYamlToType;
      // TODO(jcollins-g): This special casing is unfortunate.  Consider
      // a refactor to extract yaml data conversion into closures 100% of the
      // time or find a cleaner way to do this.
      //
      // A refactor probably would integrate resolvedValue for
      // _OptionValueWithContext into the return data here, and would not have
      // that be separate.
      if (_isMapString && convertYamlToType == null) {
        convertYamlToType = (YamlMap yamlMap, String canonicalYamlPath,
            ResourceProvider resourceProvider) {
          var returnData = <String, String>{};
          for (var MapEntry(:key, :value) in yamlMap.entries) {
            returnData[key.toString()] = value.toString();
          }
          return returnData as T;
        };
      }
      if (convertYamlToType == null) {
        throw UnsupportedError(
            '$fieldName: convertYamlToType method not defined');
      }
      var canonicalDirectoryPath =
          resourceProvider.pathContext.canonicalize(contextPath);
      returnData =
          convertYamlToType(yamlData, canonicalDirectoryPath, resourceProvider);
    } else if (_isDouble) {
      if (yamlData is num) {
        returnData = yamlData.toDouble();
      }
    } else if (_isInt || _isString || _isBool) {
      if (yamlData is T) {
        returnData = yamlData;
      }
    } else {
      throw UnsupportedError('Type $T is not supported');
    }
    if (returnData == null) {
      throw DartdocOptionError('Error in dartdoc_options.yaml, $fieldName: '
          'expecting a $_expectedTypeForDisplay, got `$yamlData`');
    }
    return _OptionValueWithContext(returnData as T, contextPath,
        definingFile: 'dartdoc_options.yaml');
  }

  _YamlFileData _yamlAtDirectory(Folder folder) {
    var canonicalPaths = <String>[];
    var yamlData = _YamlFileData({}, _directoryCurrentPath);

    for (var dir in folder.withAncestors) {
      var canonicalPath =
          resourceProvider.pathContext.canonicalize(folder.path);
      if (_yamlAtCanonicalPathCache.containsKey(canonicalPath)) {
        yamlData = _yamlAtCanonicalPathCache[canonicalPath]!;
        break;
      }
      canonicalPaths.add(canonicalPath);
      if (dir.exists) {
        var dartdocOptionsFile = resourceProvider.getFile(resourceProvider
            .pathContext
            .join(dir.path, 'dartdoc_options.yaml'));
        if (dartdocOptionsFile.exists) {
          final yaml = loadYaml(dartdocOptionsFile.readAsStringSync());
          // [loadYaml] will return `null` for empty (or all comment) YAML
          // files, so we must check for that case.
          if (yaml != null) {
            yamlData = _YamlFileData(
                yaml, resourceProvider.pathContext.canonicalize(dir.path));
          }
          break;
        }
      }
    }
    for (var canonicalPath in canonicalPaths) {
      _yamlAtCanonicalPathCache[canonicalPath] = yamlData;
    }
    return yamlData;
  }
}

/// Mixin class implementing command-line arguments for [DartdocOption].
mixin _DartdocArgOption<T> implements DartdocOption<T> {
  /// For [ArgParser], set to true if the argument can be negated with `--no` on
  /// the command line.
  bool get negatable;

  /// For [ArgParser], set to true if a single string argument will be broken
  /// into a list on commas.
  bool get splitCommas;

  /// For [ArgParser], set to true to hide this from the help menu.
  bool get hide;

  /// For [ArgParser], set to a single character to have a short version of the
  /// command line argument.
  String? get abbr;

  /// valueAt for arguments ignores the [dir] parameter and only uses command
  /// line arguments and the current working directory to resolve the result.
  @override
  T? valueAt(Folder dir) => _valueAtFromArgs() ?? defaultsTo;

  /// For passing in to [int.parse] and [double.parse] `onError'.
  void _throwErrorForTypes(String value) {
    String example;
    if (defaultsTo is Map) {
      example = 'key::value';
    } else if (_isInt) {
      example = '32';
    } else if (_isDouble) {
      example = '0.76';
    } else {
      throw UnimplementedError(
          'Type for $name is not implemented in $_throwErrorForTypes');
    }
    throw DartdocOptionError(
        'Invalid argument value: --$argName, set to "$value", must be a '
        '$T.  Example:  --$argName $example');
  }

  /// Returns null if no argument was given on the command line.
  T? _valueAtFromArgs() {
    var valueWithContext = _valueAtFromArgsWithContext();
    return _handlePathsInContext(valueWithContext);
  }

  @override
  Never _onMissing(
          _OptionValueWithContext<T> valueWithContext, String missingPath) =>
      _onMissingFromArgs(valueWithContext, missingPath);

  Never _onMissingFromArgs(
      _OptionValueWithContext<T> valueWithContext, String missingPath) {
    throw DartdocFileMissing(
        'Argument --$argName, set to ${valueWithContext.value}, resolves to '
        'missing path: "$missingPath"');
  }

  /// Generates an [_OptionValueWithContext] using the value of the argument
  /// from the [_argResults] and the working directory from [_directoryCurrent].
  ///
  /// Throws [UnsupportedError] if [T] is not a supported type.
  _OptionValueWithContext<T>? _valueAtFromArgsWithContext() {
    if (!_argResults.wasParsed(argName)) return null;

    // Unlike in _DartdocFileOption, we throw here on inputs being invalid
    // rather than silently proceeding.  This is because the user presumably
    // typed something wrong on the command line and can therefore fix it.
    // dartdoc_option.yaml files from other packages may not be fully in the
    // user's control.
    if (_isBool || _isListString || _isString) {
      return _OptionValueWithContext(
          _argResults[argName], _directoryCurrentPath);
    } else if (_isInt) {
      var value = int.tryParse(_argResults[argName]);
      if (value == null) _throwErrorForTypes(_argResults[argName]);
      return _OptionValueWithContext(value as T, _directoryCurrentPath);
    } else if (_isDouble) {
      var value = double.tryParse(_argResults[argName]);
      if (value == null) _throwErrorForTypes(_argResults[argName]);
      return _OptionValueWithContext(value as T, _directoryCurrentPath);
    } else if (_isMapString) {
      var value = <String, String>{};
      for (String pair in _argResults[argName]) {
        var pairList = pair.split('::');
        if (pairList.length != 2) {
          _throwErrorForTypes(pair);
        }
        value[pairList.first] = pairList.last;
      }
      return _OptionValueWithContext(value as T, _directoryCurrentPath);
    } else {
      throw UnsupportedError('Type $T is not supported');
    }
  }

  /// The name of this option as a command line argument.
  String get argName => _keysToArgName(keys);

  /// Turns ['foo', 'somethingBar', 'over_the_hill'] into
  /// 'something-bar-over-the-hill' (with default skip).
  /// This allows argument names to reflect nested structure.
  static String _keysToArgName(Iterable<String> keys, [int skip = 1]) {
    var argName = keys.skip(skip).join('-');
    argName = argName.replaceAll('_', '-');
    // Do not consume the lowercase character after the uppercase one, to handle
    // two character words.
    final camelCaseRegexp = RegExp(r'([a-z])([A-Z])(?=([a-z]))');
    argName = argName.replaceAllMapped(camelCaseRegexp, (Match m) {
      var before = m.group(1);
      // Group 2 is not optional.
      var after = m.group(2)!.toLowerCase();
      return '$before-$after';
    });
    return argName;
  }

  /// If this argument is added to a larger tree of DartdocOptions, call
  /// [ArgParser.addFlag], [ArgParser.addOption], or [ArgParser.addMultiOption]
  /// as appropriate for [T].
  @override
  void _addToArgParser(ArgParser argParser) {
    if (_isBool) {
      argParser.addFlag(argName,
          abbr: abbr,
          defaultsTo: defaultsTo as bool?,
          help: help,
          hide: hide,
          negatable: negatable);
    } else if (_isInt || _isDouble || _isString) {
      argParser.addOption(argName,
          abbr: abbr,
          defaultsTo: defaultsTo?.toString(),
          help: help,
          hide: hide);
    } else if (_isListString || _isMapString) {
      if (defaultsTo == null) {
        argParser.addMultiOption(argName,
            abbr: abbr,
            defaultsTo: null,
            help: help,
            hide: hide,
            splitCommas: splitCommas);
      } else {
        List<String> defaultsToList;
        if (_isListString) {
          defaultsToList = defaultsTo as List<String>;
        } else {
          defaultsToList = (defaultsTo as Map<String, String>)
              .entries
              .map((m) => '${m.key}::${m.value}')
              .toList(growable: false);
        }
        argParser.addMultiOption(argName,
            abbr: abbr,
            defaultsTo: defaultsToList,
            help: help,
            hide: hide,
            splitCommas: splitCommas);
      }
    } else {
      throw UnsupportedError('Type $T is not supported');
    }
  }
}

/// All DartdocOptionContext mixins should implement this, as well as any other
/// DartdocOptionContext mixins they use for calculating synthetic options.
abstract class DartdocOptionContextBase {
  DartdocOptionSet get optionSet;

  Folder get context;
}

/// An [DartdocOptionSet] wrapped in nice accessors specific to Dartdoc, which
/// automatically passes in the right directory for a given context.
///
/// Usually, a single [ModelElement], [Package], [Category] and so forth has a
/// single context and so this can be made a member variable of those
/// structures.
class DartdocOptionContext extends DartdocOptionContextBase
    with
        DartdocExperimentOptionContext,
        PackageWarningOptionContext,
        SourceLinkerOptionContext {
  @override
  final DartdocOptionSet optionSet;
  @override
  final Folder context;

  // TODO(jcollins-g): Allow passing in structured data to initialize a
  // [DartdocOptionContext]'s arguments instead of having to parse strings
  // via optionSet.
  DartdocOptionContext(this.optionSet, Resource contextLocation,
      ResourceProvider resourceProvider)
      : context = resourceProvider.getFolder(resourceProvider.pathContext
            .canonicalize(contextLocation is File
                ? contextLocation.parent.path
                : contextLocation.path));

  /// Build a DartdocOptionContext via the 'inputDir' command line option.
  DartdocOptionContext.fromDefaultContextLocation(
      this.optionSet, ResourceProvider resourceProvider)
      : context = resourceProvider.getFolder(optionSet['inputDir'].valueAt(
                resourceProvider
                    .getFolder(resourceProvider.pathContext.current)) ??
            resourceProvider.pathContext.current);

  /// Build a DartdocOptionContext from an analyzer element (using its source
  /// location).
  factory DartdocOptionContext.fromElement(DartdocOptionSet optionSet,
      LibraryElement2 libraryElement, ResourceProvider resourceProvider) {
    return DartdocOptionContext(
        optionSet,
        resourceProvider.getFile(libraryElement.firstFragment.source.fullName),
        resourceProvider);
  }

  /// Build a DartdocOptionContext from an existing [DartdocOptionContext] and a
  /// new analyzer [Element2].
  factory DartdocOptionContext.fromContextElement(
      DartdocOptionContext optionContext,
      LibraryElement2 libraryElement,
      ResourceProvider resourceProvider) {
    return DartdocOptionContext.fromElement(
        optionContext.optionSet, libraryElement, resourceProvider);
  }

  /// Build a DartdocOptionContext from an existing [DartdocOptionContext].
  factory DartdocOptionContext.fromContext(DartdocOptionContext optionContext,
      Resource resource, ResourceProvider resourceProvider) {
    return DartdocOptionContext(
        optionContext.optionSet, resource, resourceProvider);
  }

  // All values defined in createDartdocOptions should be exposed here.
  bool get allowTools => optionSet['allowTools'].valueAt(context);

  double get ambiguousReexportScorerMinConfidence =>
      optionSet['ambiguousReexportScorerMinConfidence'].valueAt(context);

  bool get autoIncludeDependencies =>
      optionSet['autoIncludeDependencies'].valueAt(context);

  List<String> get categoryOrder => optionSet['categoryOrder'].valueAt(context);

  CategoryConfiguration get categories =>
      optionSet['categories'].valueAt(context);

  // TODO(srawlins): This memoization saved a lot of time in unit testing, but
  // is the first value in this class to be memoized. Memoize others?
  late final Set<String> exclude =
      Set.of(optionSet['exclude'].valueAt(context));

  Set<String> get _excludePackages =>
      {...optionSet['excludePackages'].valueAt(context)};

  String? get flutterRoot => optionSet['flutterRoot'].valueAt(context);

  late final Set<String> include =
      Set.of(optionSet['include'].valueAt(context));

  List<String> get includeExternal =>
      optionSet['includeExternal'].valueAt(context);

  bool get includeSource => optionSet['includeSource'].valueAt(context);

  bool get injectHtml => optionSet['injectHtml'].valueAt(context);

  bool get sanitizeHtml => optionSet['sanitizeHtml'].valueAt(context);

  bool get excludeFooterVersion =>
      optionSet['excludeFooterVersion'].valueAt(context);

  ToolConfiguration get tools => optionSet['tools'].valueAt(context);

  /// _input is only used to construct synthetic options.
  // ignore: unused_element
  String get _input => optionSet['input'].valueAt(context);

  String get inputDir => optionSet['inputDir'].valueAt(context);

  bool get linkToRemote => optionSet['linkTo']['remote'].valueAt(context);

  String get linkToUrl => optionSet['linkTo']['url'].valueAt(context);

  /// _linkToHosted is only used to construct synthetic options.
  // ignore: unused_element
  String get _linkToHosted => optionSet['linkTo']['hosted'].valueAt(context);

  String get output => optionSet['output'].valueAt(context);

  PackageMeta get packageMeta => optionSet['packageMeta'].valueAt(context);

  List<String> get packageOrder => optionSet['packageOrder'].valueAt(context);

  bool get sdkDocs => optionSet['sdkDocs'].valueAt(context);

  ResourceProvider get resourceProvider => optionSet.resourceProvider;

  String get sdkDir => optionSet['sdkDir'].valueAt(context);

  bool get showUndocumentedCategories =>
      optionSet['showUndocumentedCategories'].valueAt(context);

  PackageMeta get topLevelPackageMeta =>
      optionSet['topLevelPackageMeta'].valueAt(context);

  bool get useCategories => optionSet['useCategories'].valueAt(context);

  bool get validateLinks => optionSet['validateLinks'].valueAt(context);

  bool isLibraryExcluded(String nameOrPath) => exclude.contains(nameOrPath);

  bool isPackageExcluded(String name) => _excludePackages.contains(name);

  bool get showStats => optionSet['showStats'].valueAt(context);

  // TODO(jdkoren): temporary while we confirm href base behavior doesn't break
  // important clients
  bool get useBaseHref => optionSet['useBaseHref'].valueAt(context);

  int get maxFileCount =>
      int.parse(optionSet['maxFileCount'].valueAt(context) ?? '0');
  int get maxTotalSize =>
      int.parse(optionSet['maxTotalSize'].valueAt(context) ?? '0');
}

/// Helper class that consolidates option contexts for instantiating generators.
class DartdocGeneratorOptionContext extends DartdocOptionContext {
  DartdocGeneratorOptionContext(
      super.optionSet, super.dir, super.resourceProvider);
  DartdocGeneratorOptionContext.fromDefaultContextLocation(
      super.optionSet, super.resourceProvider)
      : super.fromDefaultContextLocation();

  /// The joined contents of any 'header' files specified in options.
  String get header =>
      _joinCustomTextFiles(optionSet['header'].valueAt(context));

  /// The joined contents of any 'footer' files specified in options.
  String get footer =>
      _joinCustomTextFiles(optionSet['footer'].valueAt(context));

  /// The joined contents of any 'footer-text' files specified in options.
  String get footerText =>
      _joinCustomTextFiles(optionSet['footerText'].valueAt(context));

  String _joinCustomTextFiles(Iterable<String> paths) => paths
      .map((p) => resourceProvider.getFile(p).readAsStringSync())
      .join('\n');

  bool get prettyIndexJson => optionSet['prettyIndexJson'].valueAt(context);

  String? get favicon => optionSet['favicon'].valueAt(context);

  String? get relCanonicalPrefix =>
      optionSet['relCanonicalPrefix'].valueAt(context);

  // TODO(jdkoren): duplicated temporarily so that GeneratorContext is enough for configuration.
  @override
  bool get useBaseHref => optionSet['useBaseHref'].valueAt(context);

  String? get resourcesDir => optionSet['resourcesDir'].valueAt(context);
}

class DartdocProgramOptionContext extends DartdocGeneratorOptionContext
    with LoggingContext {
  DartdocProgramOptionContext(
      super.optionSet, super.dir, super.resourceProvider);

  DartdocProgramOptionContext.fromDefaultContextLocation(
      super.optionSet, super.resourceProvider)
      : super.fromDefaultContextLocation();

  /// Whether to generate docs or perform a dry run.
  bool get generateDocs => optionSet['generateDocs'].valueAt(context);
}

List<DartdocOption<bool>> createDartdocProgramOptions(
    PackageMetaProvider packageMetaProvider) {
  var resourceProvider = packageMetaProvider.resourceProvider;
  return [
    DartdocOptionArgOnly<bool>('generateDocs', true, resourceProvider,
        help:
            'Generate docs into the output directory (or only display warnings '
            'if false).',
        negatable: true),
    DartdocOptionArgOnly<bool>('help', false, resourceProvider,
        abbr: 'h', help: 'Show command help.', negatable: false),
    DartdocOptionArgOnly<bool>('version', false, resourceProvider,
        help: 'Display the version for $programName.', negatable: false),
  ];
}

DartdocProgramOptionContext? parseOptions(
  PackageMetaProvider packageMetaProvider,
  List<String> arguments, {
  // Additional options are given in google3.
  OptionGenerator? additionalOptions,
}) {
  var optionRoot = DartdocOptionRoot.fromOptionGenerators(
      'dartdoc',
      [
        createDartdocOptions,
        createDartdocProgramOptions,
        createLoggingOptions,
        createGeneratorOptions,
        if (additionalOptions != null) additionalOptions,
      ],
      packageMetaProvider);

  try {
    optionRoot.parseArguments(arguments);
  } on FormatException catch (e) {
    stderr.writeln(' fatal error: ${e.message}');
    stderr.writeln('');
    _printUsage(optionRoot.argParser);
    // Do not use `exit()` as this bypasses `--pause-isolates-on-exit`.
    exitCode = 64;
    return null;
  }
  if (optionRoot['help'].valueAtCurrent() as bool) {
    logInfo('dartdoc version: $dartdocVersion');
    logInfo('Generate HTML documentation for Dart libraries.\n');
    logInfo(optionRoot.argParser.usage);
    exitCode = 0;
    return null;
  }
  if (optionRoot['version'].valueAtCurrent() as bool) {
    logInfo('dartdoc version: $dartdocVersion');
    exitCode = 0;
    return null;
  }

  DartdocProgramOptionContext config;
  try {
    config = DartdocProgramOptionContext.fromDefaultContextLocation(
        optionRoot, packageMetaProvider.resourceProvider);
  } on DartdocOptionError catch (e) {
    stderr.writeln(' fatal error: ${e.message}');
    stderr.writeln('');
    _printUsage(optionRoot.argParser);
    exitCode = 64;
    return null;
  }
  startLogging(
    isJson: config.json,
    isQuiet: config.quiet,
    showProgress: config.showProgress,
  );
  return config;
}

/// Print usage information on invalid command lines.
void _printUsage(ArgParser parser) {
  print('Usage: dartdoc [OPTIONS]\n');
  print(parser.usage);
}

/// Instantiate dartdoc's configuration file and options parser with the
/// given command line arguments.
List<DartdocOption> createDartdocOptions(
  PackageMetaProvider packageMetaProvider,
) {
  var resourceProvider = packageMetaProvider.resourceProvider;
  return [
    DartdocOptionArgOnly<bool>('allowTools', false, resourceProvider,
        help: 'Execute user-defined tools to fill in @tool directives.',
        negatable: true),
    DartdocOptionArgFile<double>(
        'ambiguousReexportScorerMinConfidence', 0.1, resourceProvider,
        help: 'Minimum scorer confidence to suppress warning on ambiguous '
            'reexport.'),
    DartdocOptionArgOnly<bool>(
        'autoIncludeDependencies', false, resourceProvider,
        help: 'Include all the used libraries into the docs, even the ones not '
            'in the current package or "include-external"',
        negatable: true),
    DartdocOptionArgFile<List<String>>(
        'categoryOrder', const [], resourceProvider,
        splitCommas: true,
        help: 'A list of categories (not package names) to place first when '
            "grouping symbols on dartdoc's sidebar. Unmentioned categories are "
            'sorted after these.'),
    DartdocOptionFileOnly<CategoryConfiguration>(
        'categories', CategoryConfiguration.empty, resourceProvider,
        convertYamlToType: CategoryConfiguration.fromYamlMap,
        help: 'A list of all categories, their display names, and markdown '
            'documentation in the order they are to be displayed.'),
    DartdocOptionArgFile<List<String>>('exclude', [], resourceProvider,
        help: 'Names of libraries to exclude from documentation.',
        splitCommas: true),
    DartdocOptionArgOnly<List<String>>('excludePackages', [], resourceProvider,
        help: 'Names of packages to exclude from documentation.',
        splitCommas: true),
    DartdocOptionSyntheticOnly<String?>('flutterRoot',
        (DartdocSyntheticOption<String?> option, Folder dir) {
      var flutterRootEnv =
          packageMetaProvider.environmentProvider['FLUTTER_ROOT'];
      return flutterRootEnv == null
          ? null
          : resourceProvider.pathContext.resolveTildePath(flutterRootEnv);
    }, resourceProvider,
        optionIs: OptionKind.dir,
        help: 'Root of the Flutter SDK, specified from the environment.',
        mustExist: true),
    DartdocOptionArgFile<List<String>>('include', [], resourceProvider,
        help: 'Names of libraries to document.', splitCommas: true),
    DartdocOptionArgFile<List<String>>('includeExternal', [], resourceProvider,
        optionIs: OptionKind.file,
        help: 'Additional (external) dart files to include; use '
            '"<directory name>/<file name>", as in "lib/material.dart".',
        mustExist: true,
        splitCommas: true),
    DartdocOptionArgOnly<bool>('includeSource', true, resourceProvider,
        help: 'Show source code blocks.', negatable: true),
    DartdocOptionArgOnly<bool>('injectHtml', false, resourceProvider,
        help: 'Allow the use of the `{@inject-html}` directive to inject raw '
            'HTML into dartdoc output.'),
    DartdocOptionArgOnly<bool>('sanitizeHtml', false, resourceProvider,
        hide: true,
        help: 'Sanitize HTML generated from markdown text, `{@tool}` and '
            '`{@inject-html}` directives.'),
    DartdocOptionArgOnly<String>(
        'input', resourceProvider.pathContext.current, resourceProvider,
        optionIs: OptionKind.dir,
        help: 'Path to source directory.',
        mustExist: true),
    DartdocOptionSyntheticOnly<String>(
        'inputDir',
        (DartdocSyntheticOption<String> option, Folder dir) =>
            option.parent['sdkDocs'].valueAt(dir) == true
                ? option.parent['sdkDir'].valueAt(dir)
                : option.parent['input'].valueAt(dir),
        resourceProvider,
        help: 'Path to source directory (with override if --sdk-docs).',
        optionIs: OptionKind.dir,
        mustExist: true),
    DartdocOptionSet('linkTo', resourceProvider)
      ..addAll([
        DartdocOptionArgOnly<Map<String, String>>(
            'hosted',
            {
              'pub.dartlang.org': 'https://pub.dev/documentation/%n%/%v%',
              'pub.dev': 'https://pub.dev/documentation/%n%/%v%',
            },
            resourceProvider,
            help: 'Specify URLs for hosted pub packages'),
        DartdocOptionArgOnly<Map<String, String>>(
          'sdks',
          {
            'Dart': 'https://api.dart.dev/%b%/%v%',
            'Flutter': 'https://api.flutter.dev/flutter',
          },
          resourceProvider,
          help: 'Specify URLs for SDKs.',
        ),
        DartdocOptionFileSynth<String>('url',
            (DartdocSyntheticOption<String> option, Folder dir) {
          PackageMeta packageMeta =
              option.parent.parent['packageMeta'].valueAt(dir);
          // Prefer SDK check first, then pub cache check.
          var inSdk = packageMeta
              .sdkType(option.parent.parent['flutterRoot'].valueAt(dir));
          if (inSdk != null) {
            Map<String, String> sdks = option.parent['sdks'].valueAt(dir);
            var inSdkVal = sdks[inSdk];
            if (inSdkVal != null) return inSdkVal;
          }
          var hostedAt = packageMeta.hostedAt;
          if (hostedAt != null) {
            Map<String, String> hostMap = option.parent['hosted'].valueAt(dir);
            var hostedAtVal = hostMap[hostedAt];
            if (hostedAtVal != null) return hostedAtVal;
          }
          return '';
        }, resourceProvider, help: 'Url to use for this particular package.'),
        DartdocOptionArgOnly<bool>('remote', true, resourceProvider,
            help: 'Allow links to be generated for packages outside this one.',
            negatable: true),
      ]),
    DartdocOptionArgOnly<String>('output',
        resourceProvider.pathContext.join('doc', 'api'), resourceProvider,
        optionIs: OptionKind.dir, help: 'Path to the output directory.'),
    DartdocOptionSyntheticOnly<PackageMeta>(
      'packageMeta',
      (DartdocSyntheticOption<PackageMeta> option, Folder dir) {
        var packageMeta = packageMetaProvider.fromDir(dir);
        if (packageMeta == null) {
          throw DartdocOptionError(
              'Unable to determine package for directory: ${dir.path}');
        }
        return packageMeta;
      },
      resourceProvider,
    ),
    DartdocOptionArgOnly<List<String>>('packageOrder', [], resourceProvider,
        splitCommas: true,
        help:
            'A list of package names to place first when grouping libraries in '
            'packages. Unmentioned packages are placed after these.'),
    DartdocOptionArgOnly<String?>('resourcesDir', null, resourceProvider,
        help: "An absolute path to dartdoc's resources directory.", hide: true),
    DartdocOptionArgOnly<bool>('sdkDocs', false, resourceProvider,
        help: 'Generate ONLY the docs for the Dart SDK.'),
    DartdocOptionArgSynth<String?>('sdkDir',
        (DartdocSyntheticOption<String?> option, Folder dir) {
      if (!(option.parent['sdkDocs'].valueAt(dir) as bool) &&
          (option.root['topLevelPackageMeta'].valueAt(dir) as PackageMeta)
              .requiresFlutter) {
        String? flutterRoot = option.root['flutterRoot'].valueAt(dir);
        return flutterRoot == null
            ? null
            : resourceProvider.pathContext
                .join(flutterRoot, 'bin', 'cache', 'dart-sdk');
      }
      return packageMetaProvider.defaultSdkDir.path;
    }, packageMetaProvider.resourceProvider,
        help: 'Path to the SDK directory.',
        optionIs: OptionKind.dir,
        mustExist: true),
    DartdocOptionArgFile<bool>(
        'showUndocumentedCategories', false, resourceProvider,
        help: "Label categories that aren't documented", negatable: true),
    DartdocOptionSyntheticOnly<PackageMeta>('topLevelPackageMeta',
        (DartdocSyntheticOption<PackageMeta> option, Folder dir) {
      var packageMeta = packageMetaProvider.fromDir(
          resourceProvider.getFolder(option.parent['inputDir'].valueAt(dir)));
      if (packageMeta == null) {
        throw DartdocOptionError(
            'Unable to generate documentation: no package found');
      }
      if (!packageMeta.isValid) {
        final firstError = packageMeta.getInvalidReasons().first;
        throw DartdocOptionError('Package is invalid: $firstError');
      }
      return packageMeta;
    }, resourceProvider, help: 'PackageMeta object for the default package.'),
    DartdocOptionArgOnly<bool>('useCategories', true, resourceProvider,
        help: 'Display categories in the sidebar of packages'),
    DartdocOptionArgOnly<bool>('validateLinks', true, resourceProvider,
        help: 'Runs the built-in link checker to display Dart context aware '
            'warnings for broken links (slow)',
        negatable: true),
    DartdocOptionArgOnly<bool>('verboseWarnings', true, resourceProvider,
        help: 'Display extra debugging information and help with warnings.',
        negatable: true),
    DartdocOptionFileOnly<bool>('excludeFooterVersion', false, resourceProvider,
        help: 'Excludes the package version number in the footer text'),
    DartdocOptionFileOnly<ToolConfiguration>(
        'tools', ToolConfiguration.empty(resourceProvider), resourceProvider,
        convertYamlToType: ToolConfiguration.fromYamlMap,
        help: 'A map of tool names to executable paths. Each executable must '
            'exist. Executables for different platforms are specified by '
            'giving the platform name as a key, and a list of strings as the '
            'command.'),
    DartdocOptionArgOnly<bool>('useBaseHref', false, resourceProvider,
        help:
            'Use <base href> in generated files (legacy behavior). This option '
            'is temporary and support will be removed in the future. Use only '
            'if the default behavior breaks links between your documentation '
            'pages, and please file an issue on GitHub.',
        negatable: false,
        hide: true),
    DartdocOptionArgOnly<bool>('showStats', false, resourceProvider,
        help: 'Show statistics useful for debugging.', hide: true),
    DartdocOptionArgOnly<String>('maxFileCount', '0', resourceProvider,
        help:
            'The maximum number of files dartdoc is allowed to create (0 for no limit).',
        hide: true),
    DartdocOptionArgOnly<String>('maxTotalSize', '0', resourceProvider,
        help:
            'The maximum total size (in bytes) dartdoc is allowed to write (0 for no limit).',
        hide: true),
    // TODO(jcollins-g): refactor so there is a single static "create" for
    // each DartdocOptionContext that traverses the inheritance tree itself.
    ...createExperimentOptions(resourceProvider),
    ...createPackageWarningOptions(packageMetaProvider),
    ...createSourceLinkerOptions(resourceProvider),
  ];
}
