// 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://www.dartlang.org/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 dartdoc.dartdoc_options;

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

import 'package:analyzer/dart/element/element.dart';
import 'package:args/args.dart';
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/tuple.dart';
import 'package:path/path.dart' as pathLib;
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 = const <String>[];
const Map<String, String> _kMapStringVal = const <String, String>{};
const int _kIntVal = 0;
const double _kDoubleVal = 0.0;
const bool _kBoolVal = true;

/// Args are computed relative to the current directory at the time the
/// program starts.
final Directory directoryCurrent = Directory.current;
final String directoryCurrentPath =
    pathLib.canonicalize(Directory.current.path);

String resolveTildePath(String originalPath) {
  if (originalPath == null || !originalPath.startsWith('~/')) {
    return originalPath;
  }

  String homeDir;

  if (Platform.isWindows) {
    homeDir = pathLib.absolute(Platform.environment['USERPROFILE']);
  } else {
    homeDir = pathLib.absolute(Platform.environment['HOME']);
  }

  return pathLib.join(homeDir, originalPath.substring(2));
}

class DartdocOptionError extends DartdocFailure {
  DartdocOptionError(String details) : super(details);
}

class DartdocFileMissing extends DartdocOptionError {
  DartdocFileMissing(String details) : 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.
  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;

  CategoryDefinition(this.name, this._displayName, this.documentationMarkdown);

  /// 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 new CategoryConfiguration._({});
  }

  static CategoryConfiguration fromYamlMap(
      YamlMap yamlMap, pathLib.Context pathContext) {
    Map<String, CategoryDefinition> newCategoryDefinitions = {};
    for (MapEntry entry in yamlMap.entries) {
      String name = entry.key.toString();
      String displayName;
      String documentationMarkdown;
      var categoryMap = entry.value;
      if (categoryMap is Map) {
        displayName = categoryMap['displayName']?.toString();
        documentationMarkdown = categoryMap['markdown']?.toString();
        if (documentationMarkdown != null) {
          documentationMarkdown =
              pathContext.canonicalize(documentationMarkdown);
          if (!new File(documentationMarkdown).existsSync()) {
            throw new DartdocFileMissing(
                'In categories definition for ${name}, "markdown" resolves to the missing file $documentationMarkdown');
          }
        }
        newCategoryDefinitions[name] =
            new CategoryDefinition(name, displayName, documentationMarkdown);
      }
    }
    return new CategoryConfiguration._(newCategoryDefinitions);
  }
}

/// Defines the attributes of a tool in the options file, corresponding to
/// the 'tools' keyword in the options file, and populated by the
/// [ToolConfiguration] class.
class ToolDefinition {
  /// A list containing the command and options to be run for this tool. The
  /// first argument in the command is the tool executable, and will have its
  /// path evaluated relative to the `dartdoc_options.yaml` location. Must not
  /// be an empty list, or be null.
  final List<String> command;

  /// A list containing the command and options to setup phase for this tool.
  /// The first argument in the command is the tool executable, and will have
  /// its path evaluated relative to the `dartdoc_options.yaml` location. May
  /// be null or empty, in which case it will be ignored at setup time.
  final List<String> setupCommand;

  /// A description of the defined tool. Must not be null.
  final String description;

  /// If set, then the setup command has been run once for this tool definition.
  bool setupComplete = false;

  /// Returns true if the given executable path has an extension recognized as a
  /// Dart extension (e.g. '.dart' or '.snapshot').
  static bool isDartExecutable(String executable) {
    var extension = pathLib.extension(executable);
    return extension == '.dart' || extension == '.snapshot';
  }

  /// Creates a ToolDefinition or subclass that is appropriate for the command
  /// given.
  factory ToolDefinition.fromCommand(
      List<String> command, List<String> setupCommand, String description) {
    assert(command != null);
    assert(command.isNotEmpty);
    assert(description != null);
    if (isDartExecutable(command[0])) {
      return DartToolDefinition(command, setupCommand, description);
    } else {
      return ToolDefinition(command, setupCommand, description);
    }
  }

  ToolDefinition(this.command, this.setupCommand, this.description)
      : assert(command != null),
        assert(command.isNotEmpty),
        assert(description != null);

  @override
  String toString() {
    final String commandString =
        '${this is DartToolDefinition ? '(Dart) ' : ''}"${command.join(' ')}"';
    if (setupCommand == null) {
      return '$runtimeType: $commandString ($description)';
    } else {
      return '$runtimeType: $commandString, with setup command '
          '"${setupCommand.join(' ')}" ($description)';
    }
  }
}

/// A singleton that keeps track of cached snapshot files. The [dispose]
/// function must be called before process exit to clean up snapshots in the
/// cache.
class SnapshotCache {
  static SnapshotCache _instance;

  Directory snapshotCache;
  final Map<String, File> snapshots = {};
  int _serial = 0;

  SnapshotCache._()
      : snapshotCache =
            Directory.systemTemp.createTempSync('dartdoc_snapshot_cache_');

  static SnapshotCache get instance {
    _instance ??= SnapshotCache._();
    return _instance;
  }

  File getSnapshot(String toolPath) {
    if (snapshots.containsKey(toolPath)) {
      return snapshots[toolPath];
    }
    File snapshot =
        File(pathLib.join(snapshotCache.absolute.path, 'snapshot_$_serial'));
    _serial++;
    snapshots[toolPath] = snapshot;
    return snapshot;
  }

  void dispose() {
    if (snapshotCache != null && snapshotCache.existsSync()) {
      snapshotCache.deleteSync(recursive: true);
    }
    _instance = null;
  }
}

/// A special kind of tool definition for Dart commands.
class DartToolDefinition extends ToolDefinition {
  /// Takes a list of args to modify, and returns the name of the executable
  /// to run. If no snapshot file existed, then create one and modify the args
  /// so that if they are executed with dart, will result in the snapshot being
  /// built.
  Future<Tuple2<String, Function()>> modifyArgsToCreateSnapshotIfNeeded(
      List<String> args) async {
    assert(args[0] == command.first);
    // Set up flags to create a new snapshot, if needed, and use the first run as the training
    // run.
    File snapshotFile = await getSnapshotFile();
    if (snapshotFile.existsSync()) {
      // replace the first argument with the path to the snapshot.
      args[0] = snapshotFile.absolute.path;
    } else {
      args.insertAll(0, [
        '--snapshot=${snapshotFile.absolute.path}',
        '--snapshot_kind=app-jit'
      ]);
    }
    return new Tuple2(Platform.resolvedExecutable,
        _snapshotCompleter.isCompleted ? null : _snapshotCompleter.complete);
  }

  DartToolDefinition(
      List<String> command, List<String> setupCommand, String description)
      : super(command, setupCommand, description) {
    // If the dart tool is already a snapshot, then we just use that.
    if (command[0].endsWith('.snapshot')) {
      _snapshotPath = File(command[0]);
      _snapshotCompleter.complete();
    }
  }

  final Completer _snapshotCompleter = new Completer();

  /// If the tool has a pre-built snapshot, it will be stored here.
  File _snapshotPath;

  Future<File> getSnapshotFile() async {
    if (_snapshotPath == null) {
      _snapshotPath = SnapshotCache.instance.getSnapshot(command.first);
    } else {
      await _snapshotCompleter.future;
    }
    return _snapshotPath;
  }
}

/// A configuration class that can interpret [ToolDefinition]s from a YAML map.
class ToolConfiguration {
  final Map<String, ToolDefinition> tools;

  ToolConfiguration._(this.tools);

  static ToolConfiguration get empty {
    return new ToolConfiguration._({});
  }

  static ToolConfiguration fromYamlMap(
      YamlMap yamlMap, pathLib.Context pathContext) {
    var newToolDefinitions = <String, ToolDefinition>{};
    for (var entry in yamlMap.entries) {
      var name = entry.key.toString();
      var toolMap = entry.value;
      var description;
      List<String> command;
      List<String> setupCommand;
      if (toolMap is Map) {
        description = toolMap['description']?.toString();
        List<String> findCommand([String prefix = '']) {
          List<String> command;
          // If the command key is given, then it applies to all platforms.
          var commandFrom = toolMap.containsKey('${prefix}command')
              ? '${prefix}command'
              : '$prefix${Platform.operatingSystem}';
          if (toolMap.containsKey(commandFrom)) {
            if (toolMap[commandFrom].value is String) {
              command = [toolMap[commandFrom].toString()];
              if (command[0].isEmpty) {
                throw new DartdocOptionError(
                    'Tool commands must not be empty. Tool $name command entry '
                    '"$commandFrom" must contain at least one path.');
              }
            } else if (toolMap[commandFrom] is YamlList) {
              command = (toolMap[commandFrom] as YamlList)
                  .map<String>((node) => node.toString())
                  .toList();
              if (command.isEmpty) {
                throw new DartdocOptionError(
                    'Tool commands must not be empty. Tool $name command entry '
                    '"$commandFrom" must contain at least one path.');
              }
            } else {
              throw new DartdocOptionError(
                  'Tool commands must be a path to an executable, or a list of '
                  'strings that starts with a path to an executable. '
                  'The tool $name has a $commandFrom entry that is a '
                  '${toolMap[commandFrom].runtimeType}');
            }
          }
          return command;
        }

        command = findCommand();
        setupCommand = findCommand('setup_');
      } else {
        throw new DartdocOptionError(
            'Tools must be defined as a map of tool names to definitions. Tool '
            '$name is not a map.');
      }
      if (command == null) {
        throw new DartdocOptionError(
            'At least one of "command" or "${Platform.operatingSystem}" must '
            'be defined for the tool $name.');
      }
      bool validateExecutable(String executable) {
        bool isExecutable(int mode) {
          return (0x1 & ((mode >> 6) | (mode >> 3) | mode)) != 0;
        }

        var executableFile = new File(executable);
        var exeStat = executableFile.statSync();
        if (exeStat.type == FileSystemEntityType.notFound) {
          throw new DartdocOptionError('Command executables must exist. '
              'The file "$executable" does not exist for tool $name.');
        }

        var isDartCommand = ToolDefinition.isDartExecutable(executable);
        // Dart scripts don't need to be executable, because they'll be
        // executed with the Dart binary.
        if (!isDartCommand && !isExecutable(exeStat.mode)) {
          throw new DartdocOptionError('Non-Dart commands must be '
              'executable. The file "$executable" for tool $name does not have '
              'execute permission.');
        }
        return isDartCommand;
      }

      var executable = pathContext.canonicalize(command.removeAt(0));
      validateExecutable(executable);
      if (setupCommand != null) {
        var setupExecutable =
            pathContext.canonicalize(setupCommand.removeAt(0));
        var isDartSetupCommand = validateExecutable(executable);
        // Setup commands aren't snapshotted, since they're only run once.
        setupCommand = (isDartSetupCommand
                ? [Platform.resolvedExecutable, setupExecutable]
                : [setupExecutable]) +
            setupCommand;
      }
      newToolDefinitions[name] = new ToolDefinition.fromCommand(
          [executable] + command, setupCommand, description);
    }
    return new ToolConfiguration._(newToolDefinitions);
  }
}

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

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

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

/// 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 [pathLib.Context] variable initialized with canonicalDirectoryPath.
  pathLib.Context pathContext;

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

  /// Assume value is a path, and attempt to resolve it.  Throws [UnsupportedError]
  /// if [T] isn't a [String] or [List<String>].
  T get resolvedValue {
    if (value is List<String>) {
      return (value as List<String>)
          .map((v) => pathContext.canonicalize(resolveTildePath(v)))
          .cast<String>()
          .toList() as T;
    } else if (value is String) {
      return pathContext.canonicalize(resolveTildePath(value as String)) as T;
    } else if (value is Map<String, String>) {
      return (value as Map<String, String>)
          .map<String, String>((String key, String value) {
        return new MapEntry(
            key, pathContext.canonicalize(resolveTildePath(value)));
      }) as T;
    } else {
      throw new 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.
///
/// Use via implementations [DartdocOptionSet], [DartdocOptionArgFile],
/// [DartdocOptionArgOnly], and [DartdocOptionFileOnly].
abstract class DartdocOption<T> {
  /// 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.
  final bool isDir;

  /// Set to true if this option represents the name of a file.
  final bool isFile;

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

  DartdocOption._(this.name, this.defaultsTo, this.help, this.isDir,
      this.isFile, this.mustExist, this._convertYamlToType) {
    assert(!(isDir && isFile));
    if (isDir || isFile) assert(_isString || _isListString || _isMapString);
    if (mustExist) {
      assert(isDir || isFile);
    }
  }

  /// Closure to convert yaml data into some other structure.
  T Function(YamlMap, pathLib.Context) _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;

  DartdocOption _parent;

  /// The parent of this DartdocOption, or null if this is the root.
  DartdocOption get parent => _parent;

  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;

  final ArgParser __argParser = new ArgParser();
  ArgParser get argParser => root.__argParser;

  ArgResults __argResults;

  /// 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) {
    __argResults = argParser.parse(arguments);
  }

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

  /// Call [_onMissing] for every path that does not exist.
  void _validatePaths(_OptionValueWithContext valueWithContext) {
    if (!mustExist) return;
    assert(isDir || isFile);
    List<String> resolvedPaths;
    if (valueWithContext.value is String) {
      resolvedPaths = [valueWithContext.resolvedValue];
    } else if (valueWithContext.value is List<String>) {
      resolvedPaths = valueWithContext.resolvedValue.toList();
    } else if (valueWithContext.value is Map<String, String>) {
      resolvedPaths = valueWithContext.resolvedValue.values.toList();
    } else {
      assert(
          false,
          "Trying to ensure existence of unsupported type "
          "${valueWithContext.value.runtimeType}");
    }
    for (String path in resolvedPaths) {
      FileSystemEntity f = isDir ? new Directory(path) : new File(path);
      if (!f.existsSync()) {
        _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 valueWithContext) {
    if (valueWithContext?.value == null || !(isDir || isFile))
      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;

  /// Set the parent of this [DartdocOption].  Do not call more than once.
  set parent(DartdocOption newParent) {
    assert(_parent == null);
    _parent = newParent;
  }

  /// The root [DartdocOption] containing this object, or [this] if the object
  /// has no parent.
  DartdocOption get root {
    DartdocOption p = this;
    while (p.parent != null) {
      p = p.parent;
    }
    return p;
  }

  /// All object names starting at the root.
  Iterable<String> get keys {
    List<String> keyList = [];
    DartdocOption option = this;
    while (option?.name != null) {
      keyList.add(option.name);
      option = option.parent;
    }
    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.
  T valueAt(Directory dir);

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

  /// Calls [valueAt] on the directory this element is defined in.
  T valueAtElement(Element element) => valueAt(new Directory(
      pathLib.canonicalize(pathLib.basename(element.source.fullName))));

  /// Adds a DartdocOption to the children of this DartdocOption.
  void add(DartdocOption option) {
    if (_children.containsKey(option.name))
      throw new DartdocOptionError(
          'Tried to add two children with the same name: ${option.name}');
    _children[option.name] = option;
    option.parent = this;
    option.traverse((option) => option._onAdd());
  }

  /// This method is guaranteed to be called when [this] or any parent is added.
  void _onAdd() {}

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

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

  /// Apply the function [visit] to [this] and all children.
  void traverse(void visit(DartdocOption)) {
    visit(this);
    _children.values.forEach((d) => d.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> {
  bool _parentDirOverridesChild;
  @override
  T Function(DartdocSyntheticOption<T>, Directory) _compute;
  DartdocOptionFileSynth(String name, this._compute,
      {bool mustExist = false,
      String help = '',
      bool isDir = false,
      bool isFile = false,
      bool parentDirOverridesChild,
      T Function(YamlMap, pathLib.Context) convertYamlToType})
      : super._(name, null, help, isDir, isFile, mustExist, convertYamlToType) {
    _parentDirOverridesChild = parentDirOverridesChild;
  }

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

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

  @override
  bool get parentDirOverridesChild => _parentDirOverridesChild;
}

/// 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> {
  String _abbr;
  bool _hide;
  bool _negatable;
  bool _splitCommas;

  @override
  T Function(DartdocSyntheticOption<T>, Directory) _compute;
  DartdocOptionArgSynth(String name, this._compute,
      {String abbr,
      bool mustExist = false,
      String help = '',
      bool hide = false,
      bool isDir = false,
      bool isFile = false,
      bool negatable = false,
      bool splitCommas})
      : super._(name, null, help, isDir, isFile, mustExist, null) {
    _hide = hide;
    _negatable = negatable;
    _splitCommas = splitCommas;
    _abbr = abbr;
  }

  @override
  void _onMissing(
      _OptionValueWithContext valueWithContext, String missingPath) {
    _onMissingFromArgs(valueWithContext, missingPath);
  }

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

  @override
  String get abbr => _abbr;
  @override
  bool get hide => _hide;
  @override
  bool get negatable => _negatable;

  @override
  bool get splitCommas => _splitCommas;
}

/// 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
  T Function(DartdocSyntheticOption<T>, Directory) _compute;
  DartdocOptionSyntheticOnly(String name, this._compute,
      {bool mustExist = false,
      String help = '',
      bool isDir = false,
      bool isFile = false})
      : super._(name, null, help, isDir, isFile, mustExist, null);
}

abstract class DartdocSyntheticOption<T> implements DartdocOption<T> {
  T Function(DartdocSyntheticOption<T>, Directory) get _compute;

  @override
  T valueAt(Directory dir) => _valueAtFromSynthetic(dir);

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

  @override
  void _onMissing(
          _OptionValueWithContext valueWithContext, String missingPath) =>
      _onMissingFromSynthetic(valueWithContext, missingPath);

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

typedef Future<List<DartdocOption>> OptionGenerator();

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

  /// 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 Future<DartdocOptionSet> fromOptionGenerators(
      String name, Iterable<OptionGenerator> optionGenerators) async {
    DartdocOptionSet optionSet = new DartdocOptionSet(name);
    for (OptionGenerator generator in optionGenerators) {
      optionSet.addAll(await generator());
    }
    return optionSet;
  }

  /// [DartdocOptionSet] always has the null value.
  @override
  Null valueAt(Directory dir) => null;

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

  /// Traverse skips this node, because it doesn't represent a real configuration object.
  @override
  void traverse(void visitor(DartdocOption)) {
    _children.values.forEach((d) => d.traverse(visitor));
  }
}

/// A [DartdocOption] that only exists as a command line argument. --help would
/// be a good example.
class DartdocOptionArgOnly<T> extends DartdocOption<T>
    with _DartdocArgOption<T> {
  String _abbr;
  bool _hide;
  bool _negatable;
  bool _splitCommas;

  DartdocOptionArgOnly(String name, T defaultsTo,
      {String abbr,
      bool mustExist = false,
      String help = '',
      bool hide = false,
      bool isDir = false,
      bool isFile = false,
      bool negatable = false,
      bool splitCommas})
      : super._(name, defaultsTo, help, isDir, isFile, mustExist, null) {
    _hide = hide;
    _negatable = negatable;
    _splitCommas = splitCommas;
    _abbr = abbr;
  }

  @override
  String get abbr => _abbr;
  @override
  bool get hide => _hide;
  @override
  bool get negatable => _negatable;
  @override
  bool get splitCommas => _splitCommas;
}

/// A [DartdocOption] that works with command line arguments and dartdoc_options files.
class DartdocOptionArgFile<T> extends DartdocOption<T>
    with _DartdocArgOption<T>, _DartdocFileOption<T> {
  String _abbr;
  bool _hide;
  bool _negatable;
  bool _parentDirOverridesChild;
  bool _splitCommas;

  DartdocOptionArgFile(String name, T defaultsTo,
      {String abbr,
      bool mustExist = false,
      String help: '',
      bool hide = false,
      bool isDir = false,
      bool isFile = false,
      bool negatable = false,
      bool parentDirOverridesChild: false,
      bool splitCommas})
      : super._(name, defaultsTo, help, isDir, isFile, mustExist, null) {
    _abbr = abbr;
    _hide = hide;
    _negatable = negatable;
    _parentDirOverridesChild = parentDirOverridesChild;
    _splitCommas = splitCommas;
  }

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

  /// Try to find an explicit argument setting this value, but if not, fall back to files
  /// finally, the default.
  @override
  T valueAt(Directory dir) {
    T value = _valueAtFromArgs();
    if (value == null) value = _valueAtFromFiles(dir);
    if (value == null) value = defaultsTo;
    return value;
  }

  @override
  String get abbr => _abbr;
  @override
  bool get hide => _hide;
  @override
  bool get negatable => _negatable;
  @override
  bool get parentDirOverridesChild => _parentDirOverridesChild;
  @override
  bool get splitCommas => _splitCommas;
}

class DartdocOptionFileOnly<T> extends DartdocOption<T>
    with _DartdocFileOption<T> {
  bool _parentDirOverridesChild;
  DartdocOptionFileOnly(String name, T defaultsTo,
      {bool mustExist = false,
      String help: '',
      bool isDir = false,
      bool isFile = false,
      bool parentDirOverridesChild: false,
      T Function(YamlMap, pathLib.Context) convertYamlToType})
      : super._(name, defaultsTo, help, isDir, isFile, mustExist,
            convertYamlToType) {
    _parentDirOverridesChild = parentDirOverridesChild;
  }

  @override
  bool get parentDirOverridesChild => _parentDirOverridesChild;
}

/// Implements checking for options contained in dartdoc.yaml.
abstract class _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
  void _onMissing(
          _OptionValueWithContext valueWithContext, String missingPath) =>
      _onMissingFromFiles(valueWithContext, missingPath);

  void _onMissingFromFiles(
      _OptionValueWithContext valueWithContext, String missingPath) {
    String dartdocYaml = pathLib.join(
        valueWithContext.canonicalDirectoryPath, valueWithContext.definingFile);
    throw new DartdocFileMissing(
        'Field ${fieldName} from ${dartdocYaml}, set to ${valueWithContext.value}, resolves to missing path: "${missingPath}"');
  }

  @override

  /// Searches for a value in configuration files relative to [dir], and if not
  /// found, returns [defaultsTo].
  T valueAt(Directory dir) {
    return _valueAtFromFiles(dir) ?? defaultsTo;
  }

  final Map<String, T> __valueAtFromFiles = new Map();
  // The value of this option from files will not change unless files are
  // modified during execution (not allowed in Dartdoc).
  T _valueAtFromFiles(Directory dir) {
    String key = pathLib.canonicalize(dir.path);
    if (!__valueAtFromFiles.containsKey(key)) {
      _OptionValueWithContext 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 [dir], for the option and returns one once
  /// found.
  _OptionValueWithContext _valueAtFromFilesFirstFound(Directory dir) {
    _OptionValueWithContext value;
    while (true) {
      value = _valueAtFromFile(dir);
      if (value != null || pathLib.equals(dir.parent.path, dir.path)) break;
      dir = dir.parent;
    }
    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 _valueAtFromFilesLastFound(Directory dir) {
    _OptionValueWithContext value;
    while (true) {
      _OptionValueWithContext tmpValue = _valueAtFromFile(dir);
      if (tmpValue != null) value = tmpValue;
      if (pathLib.equals(dir.parent.path, dir.path)) break;
      dir = dir.parent;
    }
    return value;
  }

  /// Returns null if not set in the yaml file in this directory (or its
  /// parents).
  _OptionValueWithContext _valueAtFromFile(Directory dir) {
    _YamlFileData yamlFileData = _yamlAtDirectory(dir);
    String contextPath = yamlFileData.canonicalDirectoryPath;
    dynamic yamlData = yamlFileData.data;
    for (String key in keys) {
      if (!yamlData.containsKey(key)) return null;
      yamlData = yamlData[key];
    }

    var returnData;
    if (_isListString) {
      if (yamlData is YamlList) {
        returnData = <String>[];
        for (var item in yamlData) {
          returnData.add(item.toString());
        }
      }
    } else if (yamlData is YamlMap) {
      // 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, pathLib.Context pathContext) {
          var returnData = <String, String>{};
          for (MapEntry entry in yamlMap.entries) {
            returnData[entry.key.toString()] = entry.value.toString();
          }
          return returnData as T;
        };
      }
      if (_convertYamlToType == null) {
        throw new DartdocOptionError(
            'Unable to convert yaml to type for option: $fieldName, method not defined');
      }
      String canonicalDirectoryPath = pathLib.canonicalize(contextPath);
      returnData = _convertYamlToType(
          yamlData, new pathLib.Context(current: canonicalDirectoryPath));
    } else if (_isDouble) {
      if (yamlData is num) {
        returnData = yamlData.toDouble();
      }
    } else if (_isInt || _isString || _isBool) {
      if (yamlData is T) {
        returnData = yamlData;
      }
    } else {
      throw new UnsupportedError('Type ${T} is not supported');
    }
    return new _OptionValueWithContext(returnData as T, contextPath,
        definingFile: 'dartdoc_options.yaml');
  }

  _YamlFileData _yamlAtDirectory(Directory dir) {
    List<String> canonicalPaths = [pathLib.canonicalize(dir.path)];
    if (!_yamlAtCanonicalPathCache.containsKey(canonicalPaths.first)) {
      _YamlFileData yamlData =
          new _YamlFileData(new Map(), directoryCurrentPath);
      if (dir.existsSync()) {
        File dartdocOptionsFile;

        while (true) {
          dartdocOptionsFile =
              new File(pathLib.join(dir.path, 'dartdoc_options.yaml'));
          if (dartdocOptionsFile.existsSync() ||
              pathLib.equals(dir.parent.path, dir.path)) break;
          dir = dir.parent;
          canonicalPaths.add(pathLib.canonicalize(dir.path));
        }
        if (dartdocOptionsFile.existsSync()) {
          yamlData = new _YamlFileData(
              loadYaml(dartdocOptionsFile.readAsStringSync()),
              pathLib.canonicalize(dir.path));
        }
      }
      canonicalPaths.forEach((p) => _yamlAtCanonicalPathCache[p] = yamlData);
    }
    return _yamlAtCanonicalPathCache[canonicalPaths.first];
  }
}

/// Mixin class implementing command-line arguments for [DartdocOption].
abstract class _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(Directory 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';
    }
    throw new 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() {
    _OptionValueWithContext valueWithContext = _valueAtFromArgsWithContext();
    return _handlePathsInContext(valueWithContext);
  }

  @override
  void _onMissing(
          _OptionValueWithContext valueWithContext, String missingPath) =>
      _onMissingFromArgs(valueWithContext, missingPath);

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

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

    T retval;
    // Unlike in _DartdocFileOption, we throw here on inputs being invalid rather
    // than silently proceeding.  TODO(jcollins-g): throw on input formatting for
    // files too?
    if (_isBool || _isListString || _isString) {
      retval = _argResults[argName];
    } else if (_isInt) {
      retval = int.tryParse(_argResults[argName]) as T;
      if (retval == null) _throwErrorForTypes(_argResults[argName]);
    } else if (_isDouble) {
      retval = double.tryParse(_argResults[argName]) as T;
      if (retval == null) _throwErrorForTypes(_argResults[argName]);
    } else if (_isMapString) {
      retval = <String, String>{} as T;
      for (String pair in _argResults[argName]) {
        List<String> pairList = pair.split('::');
        if (pairList.length != 2) {
          _throwErrorForTypes(pair);
        }
        assert(pairList.length == 2);
        (retval as Map<String, String>)[pairList.first] = pairList.last;
      }
    } else {
      throw UnsupportedError('Type ${T} is not supported');
    }
    return new _OptionValueWithContext(retval, directoryCurrentPath);
  }

  /// 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]) {
    String 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 = new RegExp(r'([a-z])([A-Z])(?=([a-z]))');
    argName = argName.replaceAllMapped(camelCaseRegexp, (Match m) {
      String before = m.group(1);
      String 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 _onAdd() {
    if (_isBool) {
      argParser.addFlag(argName,
          abbr: abbr,
          defaultsTo: defaultsTo as bool,
          help: help,
          hide: hide,
          negatable: negatable ?? false);
    } else if (_isInt || _isDouble || _isString) {
      argParser.addOption(argName,
          abbr: abbr,
          defaultsTo: defaultsTo?.toString() ?? null,
          help: help,
          hide: hide);
    } else if (_isListString || _isMapString) {
      List<String> defaultsToList = [];
      if (_isListString) {
        defaultsToList = defaultsTo as List<String>;
      } else {
        defaultsToList.addAll((defaultsTo as Map<String, String>)
            .entries
            .map((m) => '${m.key}::${m.value}'));
      }
      argParser.addMultiOption(argName,
          abbr: abbr,
          defaultsTo: defaultsToList,
          help: help,
          hide: hide,
          splitCommas: splitCommas);
    } else {
      throw new UnsupportedError('Type ${T} is not supported');
    }
  }
}

/// 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 {
  final DartdocOptionSet optionSet;
  Directory context;

  // TODO(jcollins-g): Allow passing in structured data to initialize a
  // [DartdocOptionContext]'s arguments instead of having to parse strings
  // via optionSet.
  /// If [entity] is null, assume this is the initialization case and use
  /// the inputDir flag to determine the context.
  DartdocOptionContext(this.optionSet, FileSystemEntity entity) {
    if (entity == null) {
      String inputDir = optionSet['inputDir'].valueAt(directoryCurrent) ??
          directoryCurrentPath;
      context = new Directory(inputDir);
    } else {
      context = new Directory(pathLib
          .canonicalize(entity is File ? entity.parent.path : entity.path));
    }
  }

  /// Build a DartdocOptionContext from an analyzer element (using its source
  /// location).
  factory DartdocOptionContext.fromElement(
      DartdocOptionSet optionSet, Element element) {
    return new DartdocOptionContext(
        optionSet, new File(element.source.fullName));
  }

  /// Build a DartdocOptionContext from an existing [DartdocOptionContext] and a new analyzer [Element].
  factory DartdocOptionContext.fromContextElement(
      DartdocOptionContext optionContext, Element element) {
    return new DartdocOptionContext.fromElement(
        optionContext.optionSet, element);
  }

  /// Build a DartdocOptionContext from an existing [DartdocOptionContext].
  factory DartdocOptionContext.fromContext(
      DartdocOptionContext optionContext, FileSystemEntity entity) {
    return new DartdocOptionContext(optionContext.optionSet, entity);
  }

  // All values defined in createDartdocOptions should be exposed here.
  bool get addCrossdart => optionSet['addCrossdart'].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);
  List<String> get dropTextFrom => optionSet['dropTextFrom'].valueAt(context);
  String get examplePathPrefix =>
      optionSet['examplePathPrefix'].valueAt(context);
  List<String> get exclude => optionSet['exclude'].valueAt(context);
  List<String> get excludePackages =>
      optionSet['excludePackages'].valueAt(context);

  String get flutterRoot => optionSet['flutterRoot'].valueAt(context);
  bool get hideSdkText => optionSet['hideSdkText'].valueAt(context);
  List<String> get include => 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);
  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);
  String get sdkDir => optionSet['sdkDir'].valueAt(context);
  bool get showUndocumentedCategories =>
      optionSet['showUndocumentedCategories'].valueAt(context);
  bool get showWarnings => optionSet['showWarnings'].valueAt(context);
  PackageMeta get topLevelPackageMeta =>
      optionSet['topLevelPackageMeta'].valueAt(context);
  bool get useCategories => optionSet['useCategories'].valueAt(context);
  bool get validateLinks => optionSet['validateLinks'].valueAt(context);
  bool get verboseWarnings => optionSet['verboseWarnings'].valueAt(context);

  bool isLibraryExcluded(String name) =>
      exclude.any((pattern) => name == pattern);
  bool isPackageExcluded(String name) =>
      excludePackages.any((pattern) => name == pattern);
}

/// Instantiate dartdoc's configuration file and options parser with the
/// given command line arguments.
Future<List<DartdocOption>> createDartdocOptions() async {
  return <DartdocOption>[
    new DartdocOptionArgOnly<bool>('addCrossdart', false,
        help: 'Add Crossdart links to the source code pieces.',
        negatable: true),
    new DartdocOptionArgFile<double>(
        'ambiguousReexportScorerMinConfidence', 0.1,
        help: 'Minimum scorer confidence to suppress warning on ambiguous '
            'reexport.'),
    new DartdocOptionArgOnly<bool>('autoIncludeDependencies', false,
        help: 'Include all the used libraries into the docs, even the ones not '
            'in the current package or "include-external"',
        negatable: true),
    new DartdocOptionArgFile<List<String>>('categoryOrder', [],
        help:
            "A list of categories (not package names) to place first when grouping symbols on dartdoc's sidebar. "
            'Unmentioned categories are sorted after these.'),
    new DartdocOptionFileOnly<CategoryConfiguration>(
        'categories', CategoryConfiguration.empty,
        convertYamlToType: CategoryConfiguration.fromYamlMap,
        help: 'A list of all categories, their display names, and markdown '
            'documentation in the order they are to be displayed.'),
    new DartdocOptionSyntheticOnly<List<String>>('dropTextFrom',
        (DartdocSyntheticOption<List<String>> option, Directory dir) {
      if (option.parent['hideSdkText'].valueAt(dir)) {
        return [
          'dart.async',
          'dart.collection',
          'dart.convert',
          'dart.core',
          'dart.developer',
          'dart.html',
          'dart.indexed_db',
          'dart.io',
          'dart.lisolate',
          'dart.js',
          'dart.js_util',
          'dart.math',
          'dart.mirrors',
          'dart.svg',
          'dart.typed_data',
          'dart.web_audio'
        ];
      }
      return [];
    }, help: 'Remove text from libraries with the following names.'),
    new DartdocOptionArgFile<String>('examplePathPrefix', null,
        isDir: true,
        help: 'Prefix for @example paths.\n(defaults to the project root)',
        mustExist: true),
    new DartdocOptionArgFile<List<String>>('exclude', [],
        help: 'Library names to ignore.', splitCommas: true),
    new DartdocOptionArgOnly<List<String>>('excludePackages', [],
        help: 'Package names to ignore.', splitCommas: true),
    // This could be a ArgOnly, but trying to not provide too many ways
    // to set the flutter root.
    new DartdocOptionSyntheticOnly<String>(
        'flutterRoot',
        (DartdocSyntheticOption<String> option, Directory dir) =>
            resolveTildePath(Platform.environment['FLUTTER_ROOT']),
        isDir: true,
        help: 'Root of the Flutter SDK, specified from environment.',
        mustExist: true),
    new DartdocOptionArgOnly<bool>('hideSdkText', false,
        hide: true,
        help: 'Drop all text for SDK components.  Helpful for integration '
            'tests for dartdoc, probably not useful for anything else.',
        negatable: true),
    new DartdocOptionArgFile<List<String>>('include', [],
        help: 'Library names to generate docs for.', splitCommas: true),
    new DartdocOptionArgFile<List<String>>('includeExternal', null,
        isFile: true,
        help:
            'Additional (external) dart files to include; use "dir/fileName", '
            'as in lib/material.dart.',
        mustExist: true,
        splitCommas: true),
    new DartdocOptionArgOnly<bool>('includeSource', true,
        help: 'Show source code blocks.', negatable: true),
    new DartdocOptionArgOnly<bool>('injectHtml', false,
        help: 'Allow the use of the {@inject-html} directive to inject raw '
            'HTML into dartdoc output.'),
    new DartdocOptionArgOnly<String>('input', directoryCurrentPath,
        isDir: true, help: 'Path to source directory', mustExist: true),
    new DartdocOptionSyntheticOnly<String>('inputDir',
        (DartdocSyntheticOption<String> option, Directory dir) {
      if (option.parent['sdkDocs'].valueAt(dir)) {
        return option.parent['sdkDir'].valueAt(dir);
      }
      return option.parent['input'].valueAt(dir);
    },
        help: 'Path to source directory (with override if --sdk-docs)',
        isDir: true,
        mustExist: true),
    new DartdocOptionSet('linkTo')
      ..addAll([
        new DartdocOptionArgOnly<Map<String, String>>(
            'hosted',
            {
              'pub.dartlang.org':
                  'https://pub.dartlang.org/documentation/%n%/%v%'
            },
            help: 'Specify URLs for hosted pub packages'),
        new DartdocOptionArgOnly<Map<String, String>>(
          'sdks',
          {
            'Dart': 'https://api.dartlang.org/%b%/%v%',
            'Flutter': 'https://docs.flutter.io/flutter',
          },
          help: 'Specify URLs for SDKs.',
        ),
        new DartdocOptionFileSynth<String>('url',
            (DartdocSyntheticOption<String> option, Directory dir) {
          PackageMeta packageMeta =
              option.parent.parent['packageMeta'].valueAt(dir);
          // Prefer SDK check first, then pub cache check.
          String inSdk = packageMeta
              .sdkType(option.parent.parent['flutterRoot'].valueAt(dir));
          if (inSdk != null) {
            Map<String, String> sdks = option.parent['sdks'].valueAt(dir);
            if (sdks.containsKey(inSdk)) return sdks[inSdk];
          }
          String hostedAt = packageMeta.hostedAt;
          if (hostedAt != null) {
            Map<String, String> hostMap = option.parent['hosted'].valueAt(dir);
            if (hostMap.containsKey(hostedAt)) return hostMap[hostedAt];
          }
          return '';
        }, help: 'Url to use for this particular package.'),
        new DartdocOptionArgOnly<bool>('remote', false,
            help: 'Allow links to be generated for packages outside this one.',
            negatable: true),
      ]),
    new DartdocOptionArgOnly<String>('output', pathLib.join('doc', 'api'),
        isDir: true, help: 'Path to output directory.'),
    new DartdocOptionSyntheticOnly<PackageMeta>(
      'packageMeta',
      (DartdocSyntheticOption<PackageMeta> option, Directory dir) {
        PackageMeta packageMeta = new PackageMeta.fromDir(dir);
        if (packageMeta == null) {
          throw new DartdocOptionError(
              'Unable to determine package for directory: ${dir.path}');
        }
        return packageMeta;
      },
    ),
    new DartdocOptionArgOnly<List<String>>('packageOrder', [],
        help:
            'A list of package names to place first when grouping libraries in packages. '
            'Unmentioned packages are sorted after these.'),
    new DartdocOptionArgOnly<bool>('sdkDocs', false,
        help: 'Generate ONLY the docs for the Dart SDK.'),
    new DartdocOptionArgSynth<String>('sdkDir',
        (DartdocSyntheticOption<String> option, Directory dir) {
      if (!option.parent['sdkDocs'].valueAt(dir) &&
          (option.root['topLevelPackageMeta'].valueAt(dir) as PackageMeta)
              .requiresFlutter) {
        String flutterRoot = option.root['flutterRoot'].valueAt(dir);
        if (flutterRoot == null) {
          throw new DartdocOptionError(
              'Top level package requires Flutter but FLUTTER_ROOT environment variable not set');
        }
        return pathLib.join(flutterRoot, 'bin', 'cache', 'dart-sdk');
      }
      return defaultSdkDir.absolute.path;
    }, help: 'Path to the SDK directory.', isDir: true, mustExist: true),
    new DartdocOptionArgFile<bool>('showUndocumentedCategories', false,
        help: "Label categories that aren't documented", negatable: true),
    new DartdocOptionArgOnly<bool>('showWarnings', false,
        help: 'Display all warnings.'),
    new DartdocOptionSyntheticOnly<PackageMeta>('topLevelPackageMeta',
        (DartdocSyntheticOption<PackageMeta> option, Directory dir) {
      PackageMeta packageMeta = new PackageMeta.fromDir(
          new Directory(option.parent['inputDir'].valueAt(dir)));
      if (packageMeta == null) {
        throw new DartdocOptionError(
            'Unable to generate documentation: no package found');
      }
      if (!packageMeta.isValid) {
        final String firstError = packageMeta.getInvalidReasons().first;
        throw new DartdocOptionError('Package is invalid: $firstError');
      }
      return packageMeta;
    }, help: 'PackageMeta object for the default package.'),
    new DartdocOptionArgOnly<bool>('useCategories', true,
        help: 'Display categories in the sidebar of packages'),
    new DartdocOptionArgOnly<bool>('validateLinks', true,
        help:
            'Runs the built-in link checker to display Dart context aware warnings for broken links (slow)',
        negatable: true),
    new DartdocOptionArgOnly<bool>('verboseWarnings', true,
        help: 'Display extra debugging information and help with warnings.',
        negatable: true),
    new DartdocOptionFileOnly<ToolConfiguration>(
        'tools', ToolConfiguration.empty,
        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.'),
  ];
}
