// Copyright (c) 2015, 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.

import 'package:analyzer/dart/analysis/formatter_options.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/analysis_options/error/option_codes.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/source.dart' show SourceFactory;
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/lint/options_rule_validator.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:analyzer/src/plugin/options.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

List<Diagnostic> analyzeAnalysisOptions(
  Source source,
  String content,
  SourceFactory sourceFactory,
  String contextRoot,
  VersionConstraint? sdkVersionConstraint,
) {
  List<Diagnostic> errors = [];
  Source initialSource = source;
  SourceSpan? initialIncludeSpan;
  AnalysisOptionsProvider optionsProvider = AnalysisOptionsProvider(
    sourceFactory,
  );
  String? firstPluginName;
  Map<Source, SourceSpan> includeChain = {};

  // TODO(srawlins): This code is getting quite complex, with multiple local
  // functions, and should be refactored to a class maintaining state, with less
  // variable shadowing.
  void addDirectErrorOrIncludedError(
    List<Diagnostic> validationErrors,
    Source source, {
    required bool sourceIsOptionsForContextRoot,
  }) {
    if (!sourceIsOptionsForContextRoot) {
      // [source] is an included file, and we should only report errors in
      // [initialSource], noting that the included file has warnings.
      for (Diagnostic error in validationErrors) {
        var args = [
          source.fullName,
          error.offset.toString(),
          (error.offset + error.length - 1).toString(),
          error.message,
        ];
        errors.add(
          Diagnostic.tmp(
            source: initialSource,
            offset: initialIncludeSpan!.start.offset,
            length: initialIncludeSpan!.length,
            diagnosticCode: AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING,
            arguments: args,
          ),
        );
      }
    } else {
      // [source] is the options file for [contextRoot]. Report all errors
      // directly.
      errors.addAll(validationErrors);
    }
  }

  // Validates the specified options and any included option files.
  void validate(Source source, YamlMap options) {
    var sourceIsOptionsForContextRoot = initialIncludeSpan == null;
    var validationErrors = OptionsFileValidator(
      source,
      sdkVersionConstraint: sdkVersionConstraint,
      sourceIsOptionsForContextRoot: sourceIsOptionsForContextRoot,
    ).validate(options);
    addDirectErrorOrIncludedError(
      validationErrors,
      source,
      sourceIsOptionsForContextRoot: sourceIsOptionsForContextRoot,
    );

    var includeNode = options.valueAt(AnalysisOptionsFile.include);
    if (includeNode == null) {
      // Validate the 'plugins' option in [options], understanding that no other
      // options are included.
      addDirectErrorOrIncludedError(
        _validateLegacyPluginsOption(source, options: options),
        source,
        sourceIsOptionsForContextRoot: sourceIsOptionsForContextRoot,
      );
      return;
    }

    void validateInclude(YamlNode includeNode) {
      var includeSpan = includeNode.span;
      initialIncludeSpan ??= includeSpan;
      var includeUri = includeSpan.text;
      var (first, last) = (
        includeUri.codeUnits.firstOrNull,
        includeUri.codeUnits.lastOrNull,
      );
      if ((first == 0x0022 || first == 0x0027) && first == last) {
        // The URI begins and ends with either a double quote or single quote
        // i.e. the value of the "include" field is quoted.
        includeUri = includeUri.substring(1, includeUri.length - 1);
      }

      var includedSource = sourceFactory.resolveUri(source, includeUri);
      if (includedSource == initialSource) {
        errors.add(
          Diagnostic.tmp(
            source: initialSource,
            offset: initialIncludeSpan!.start.offset,
            length: initialIncludeSpan!.length,
            diagnosticCode: AnalysisOptionsWarningCode.RECURSIVE_INCLUDE_FILE,
            arguments: [includeUri, source.fullName],
          ),
        );
        return;
      }
      if (includedSource == null || !includedSource.exists()) {
        errors.add(
          Diagnostic.tmp(
            source: initialSource,
            offset: initialIncludeSpan!.start.offset,
            length: initialIncludeSpan!.length,
            diagnosticCode: AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND,
            arguments: [includeUri, source.fullName, contextRoot],
          ),
        );
        return;
      }
      var spanInChain = includeChain[includedSource];
      if (spanInChain != null) {
        errors.add(
          Diagnostic.tmp(
            source: initialSource,
            offset: initialIncludeSpan!.start.offset,
            length: initialIncludeSpan!.length,
            diagnosticCode: AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING,
            arguments: [
              includedSource,
              spanInChain.start.offset,
              spanInChain.length,
              'The file includes itself recursively.',
            ],
          ),
        );
        return;
      }
      includeChain[includedSource] = includeSpan;

      try {
        var includedOptions = optionsProvider.getOptionsFromString(
          includedSource.contents.data,
        );
        validate(includedSource, includedOptions);
        firstPluginName ??= _firstPluginName(includedOptions);
        // Validate the 'plugins' option in [options], taking into account any
        // plugins enabled by [includedOptions].
        addDirectErrorOrIncludedError(
          _validateLegacyPluginsOption(
            source,
            options: options,
            firstEnabledPluginName: firstPluginName,
          ),
          source,
          sourceIsOptionsForContextRoot: sourceIsOptionsForContextRoot,
        );
      } on OptionsFormatException catch (e) {
        var args = [
          includedSource.fullName,
          e.span!.start.offset.toString(),
          e.span!.end.offset.toString(),
          e.message,
        ];
        // Report errors for included option files on the `include` directive
        // located in the initial options file.
        errors.add(
          Diagnostic.tmp(
            source: initialSource,
            offset: initialIncludeSpan!.start.offset,
            length: initialIncludeSpan!.length,
            diagnosticCode: AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR,
            arguments: args,
          ),
        );
      }
    }

    if (includeNode is YamlScalar) {
      validateInclude(includeNode);
    } else if (includeNode is YamlList) {
      for (var includeValue in includeNode.nodes) {
        if (includeValue is YamlScalar) {
          validateInclude(includeValue);
        }
      }
    }
  }

  try {
    YamlMap options = optionsProvider.getOptionsFromString(content);
    validate(source, options);
  } on OptionsFormatException catch (e) {
    SourceSpan span = e.span!;
    errors.add(
      Diagnostic.tmp(
        source: source,
        offset: span.start.offset,
        length: span.length,
        diagnosticCode: AnalysisOptionsErrorCode.PARSE_ERROR,
        arguments: [e.message],
      ),
    );
  }
  return errors;
}

/// Returns the name of the first legacy plugin, if one is specified in
/// [options], otherwise `null`.
String? _firstPluginName(YamlMap options) {
  var analyzerMap = options.valueAt(AnalysisOptionsFile.analyzer);
  if (analyzerMap is! YamlMap) {
    return null;
  }
  var plugins = analyzerMap.valueAt(AnalysisOptionsFile.plugins);
  if (plugins is YamlScalar) {
    return plugins.value as String?;
  } else if (plugins is YamlList) {
    return plugins.first as String?;
  } else if (plugins is YamlMap) {
    return plugins.keys.first as String?;
  } else {
    return null;
  }
}

/// Validates the legacy 'plugins' options in [options], given
/// [firstEnabledPluginName].
List<Diagnostic> _validateLegacyPluginsOption(
  Source source, {
  required YamlMap options,
  String? firstEnabledPluginName,
}) {
  RecordingDiagnosticListener recorder = RecordingDiagnosticListener();
  DiagnosticReporter reporter = DiagnosticReporter(recorder, source);
  _LegacyPluginsOptionValidator(
    firstEnabledPluginName,
  ).validate(reporter, options);
  return recorder.diagnostics;
}

/// Options (keys) that can be specified in an analysis options file.
final class AnalysisOptionsFile {
  // Top-level options.
  static const String analyzer = 'analyzer';
  static const String codeStyle = 'code-style';
  static const String formatter = 'formatter';
  static const String linter = 'linter';

  /// The shared key for top-level plugins and `analyzer`-level plugins.
  static const String plugins = 'plugins';

  // `analyzer` analysis options.
  static const String cannotIgnore = 'cannot-ignore';
  static const String enableExperiment = 'enable-experiment';
  static const String errors = 'errors';
  static const String exclude = 'exclude';
  static const String include = 'include';
  static const String language = 'language';
  static const String optionalChecks = 'optional-checks';
  static const String strongMode = 'strong-mode';

  // Optional checks options.
  static const String chromeOsManifestChecks = 'chrome-os-manifest-checks';

  // Strong mode options (see AnalysisOptionsImpl for documentation).
  static const String declarationCasts = 'declaration-casts';
  static const String implicitCasts = 'implicit-casts';
  static const String implicitDynamic = 'implicit-dynamic';

  // Language options (see AnalysisOptionsImpl for documentation).
  static const String strictCasts = 'strict-casts';
  static const String strictInference = 'strict-inference';
  static const String strictRawTypes = 'strict-raw-types';

  // Code style options.
  static const String format = 'format';

  /// Ways to say `ignore`.
  static const List<String> ignoreSynonyms = ['ignore', 'false'];

  /// Valid error `severity`s.
  static final List<String> severities = List.unmodifiable(severityMap.keys);

  /// Ways to say `include`.
  static const List<String> includeSynonyms = ['include', 'true'];

  // Formatter options.
  static const String pageWidth = 'page_width';
  static const String trailingCommas = 'trailing_commas';

  // Linter options.
  static const String rules = 'rules';

  // Plugins options.
  static const String diagnostics = 'diagnostics';
  static const String path = 'path';
  static const String version = 'version';

  /// Supported 'plugins' options.
  static const Set<String> _pluginsOptions = {diagnostics, path, version};

  static const String propagateLinterExceptions = 'propagate-linter-exceptions';

  /// Ways to say `true` or `false`.
  static const List<String> _trueOrFalse = ['true', 'false'];

  /// Supported top-level `analyzer` options.
  static const Set<String> _analyzerOptions = {
    cannotIgnore,
    enableExperiment,
    errors,
    exclude,
    language,
    optionalChecks,
    plugins,
    strongMode,
  };

  /// Supported `analyzer` strong-mode options.
  ///
  /// This section is deprecated.
  static const Set<String> _strongModeOptions = {
    declarationCasts,
    implicitCasts,
    implicitDynamic,
  };

  /// Supported `analyzer` language options.
  static const Set<String> _languageOptions = {
    strictCasts,
    strictInference,
    strictRawTypes,
  };

  /// Supported 'linter' options.
  static const Set<String> _linterOptions = {rules};

  /// Supported 'analyzer' optional checks options.
  static const Set<String> _optionalChecksOptions = {
    chromeOsManifestChecks,
    propagateLinterExceptions,
  };

  /// Proposed values for a `true` or `false` option.
  static String get _trueOrFalseProposal =>
      AnalysisOptionsFile._trueOrFalse.quotedAndCommaSeparatedWithAnd;
}

/// Validates `analyzer` options.
class AnalyzerOptionsValidator extends _CompositeValidator {
  AnalyzerOptionsValidator()
    : super([
        _AnalyzerTopLevelOptionsValidator(),
        _StrongModeOptionValueValidator(),
        _ErrorFilterOptionValidator(),
        _EnabledExperimentsValidator(),
        _LanguageOptionValidator(),
        _OptionalChecksValueValidator(),
        _CannotIgnoreOptionValidator(),
      ]);
}

/// Validates options defined in an analysis options file.
@visibleForTesting
class OptionsFileValidator {
  /// The source being validated.
  final Source _source;

  final List<OptionsValidator> _validators;

  OptionsFileValidator(
    this._source, {
    VersionConstraint? sdkVersionConstraint,
    required bool sourceIsOptionsForContextRoot,
  }) : _validators = [
         AnalyzerOptionsValidator(),
         _CodeStyleOptionsValidator(),
         _FormatterOptionsValidator(),
         _LinterTopLevelOptionsValidator(),
         LinterRuleOptionsValidator(
           sdkVersionConstraint: sdkVersionConstraint,
           sourceIsOptionsForContextRoot: sourceIsOptionsForContextRoot,
         ),
         _PluginsOptionsValidator(),
       ];

  List<Diagnostic> validate(YamlMap options) {
    RecordingDiagnosticListener recorder = RecordingDiagnosticListener();
    DiagnosticReporter reporter = DiagnosticReporter(recorder, _source);
    for (var validator in _validators) {
      validator.validate(reporter, options);
    }
    return recorder.diagnostics;
  }
}

/// Validates `analyzer` top-level options.
class _AnalyzerTopLevelOptionsValidator extends _TopLevelOptionValidator {
  _AnalyzerTopLevelOptionsValidator()
    : super(AnalysisOptionsFile.analyzer, AnalysisOptionsFile._analyzerOptions);
}

/// Validates the `analyzer` `cannot-ignore` option.
///
/// This includes the format of the `cannot-ignore` section, the format of
/// values in the section, and whether each value is a valid string.
class _CannotIgnoreOptionValidator extends OptionsValidator {
  /// Lazily populated set of diagnostic code names.
  static final Set<String> _diagnosticCodes =
      diagnosticCodeValues.map((DiagnosticCode code) => code.name).toSet();

  /// The diagnostic code names that existed, but were removed.
  /// We don't want to report these, this breaks clients.
  // TODO(scheglov): https://github.com/flutter/flutter/issues/141576
  static const Set<String> _removedDiagnosticCodes = {'MISSING_RETURN'};

  /// Lazily populated set of lint code names.
  late final Set<String> _lintCodes =
      Registry.ruleRegistry.rules
          .map((rule) => rule.name.toUpperCase())
          .toSet();

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var unignorableNames = analyzer.valueAt(AnalysisOptionsFile.cannotIgnore);
      if (unignorableNames is YamlList) {
        var listedNames = <String>{};
        for (var unignorableNameNode in unignorableNames.nodes) {
          var unignorableName = unignorableNameNode.value;
          if (unignorableName is String) {
            if (AnalysisOptionsFile.severities.contains(unignorableName)) {
              listedNames.add(unignorableName);
              continue;
            }
            var upperCaseName = unignorableName.toUpperCase();
            if (!_diagnosticCodes.contains(upperCaseName) &&
                !_lintCodes.contains(upperCaseName) &&
                !_removedDiagnosticCodes.contains(upperCaseName)) {
              reporter.atSourceSpan(
                unignorableNameNode.span,
                AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE,
                arguments: [unignorableName],
              );
            } else if (listedNames.contains(upperCaseName)) {
              // TODO(srawlins): Create a "duplicate value" code and report it
              // here.
            } else {
              listedNames.add(upperCaseName);
            }
          } else {
            reporter.atSourceSpan(
              unignorableNameNode.span,
              AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
              arguments: [AnalysisOptionsFile.cannotIgnore],
            );
          }
        }
      } else if (unignorableNames != null) {
        reporter.atSourceSpan(
          unignorableNames.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.cannotIgnore],
        );
      }
    }
  }
}

/// Validates `code-style` options.
class _CodeStyleOptionsValidator extends OptionsValidator {
  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var codeStyle = options.valueAt(AnalysisOptionsFile.codeStyle);
    if (codeStyle is YamlMap) {
      codeStyle.nodeMap.forEach((keyNode, valueNode) {
        var key = keyNode.value;
        if (key == AnalysisOptionsFile.format) {
          _validateFormat(reporter, valueNode);
        } else {
          reporter.atSourceSpan(
            keyNode.span,
            AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES,
            arguments: [AnalysisOptionsFile.codeStyle, keyNode.toString()],
          );
        }
      });
    } else if (codeStyle is YamlScalar && codeStyle.value != null) {
      reporter.atSourceSpan(
        codeStyle.span,
        AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
        arguments: [AnalysisOptionsFile.codeStyle],
      );
    } else if (codeStyle is YamlList) {
      reporter.atSourceSpan(
        codeStyle.span,
        AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
        arguments: [AnalysisOptionsFile.codeStyle],
      );
    }
  }

  void _validateFormat(DiagnosticReporter reporter, YamlNode format) {
    if (format is YamlMap) {
      reporter.atSourceSpan(
        format.span,
        AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
        arguments: [AnalysisOptionsFile.format],
      );
    } else if (format is YamlScalar) {
      var formatValue = toBool(format.valueOrThrow);
      if (formatValue == null) {
        reporter.atSourceSpan(
          format.span,
          AnalysisOptionsWarningCode.UNSUPPORTED_VALUE,
          arguments: [
            AnalysisOptionsFile.format,
            format.valueOrThrow,
            AnalysisOptionsFile._trueOrFalseProposal,
          ],
        );
      }
    } else if (format is YamlList) {
      reporter.atSourceSpan(
        format.span,
        AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
        arguments: [AnalysisOptionsFile.format],
      );
    }
  }
}

/// Convenience class for composing validators.
class _CompositeValidator extends OptionsValidator {
  final List<OptionsValidator> validators;

  _CompositeValidator(this.validators);

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    for (var validator in validators) {
      validator.validate(reporter, options);
    }
  }
}

/// Validates `analyzer` enabled experiments configuration options.
class _EnabledExperimentsValidator extends OptionsValidator {
  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var experimentNames = analyzer.valueAt(
        AnalysisOptionsFile.enableExperiment,
      );
      if (experimentNames is YamlList) {
        var flags =
            experimentNames.nodes.map((node) => node.toString()).toList();
        for (var validationResult in validateFlags(flags)) {
          var flagIndex = validationResult.stringIndex;
          var span = experimentNames.nodes[flagIndex].span;
          if (validationResult is UnrecognizedFlag) {
            reporter.atSourceSpan(
              span,
              AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES,
              arguments: [
                AnalysisOptionsFile.enableExperiment,
                flags[flagIndex],
              ],
            );
          } else {
            reporter.atSourceSpan(
              span,
              AnalysisOptionsWarningCode.INVALID_OPTION,
              arguments: [
                AnalysisOptionsFile.enableExperiment,
                validationResult.message,
              ],
            );
          }
        }
      } else if (experimentNames != null) {
        reporter.atSourceSpan(
          experimentNames.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.enableExperiment],
        );
      }
    }
  }
}

/// Builds error reports with value proposals.
class _ErrorBuilder {
  static AnalysisOptionsWarningCode get noProposalCode =>
      AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES;

  static AnalysisOptionsWarningCode get pluralProposalCode =>
      AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES;

  static AnalysisOptionsWarningCode get singularProposalCode =>
      AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE;

  final String proposal;

  final AnalysisOptionsWarningCode code;

  /// Create a builder for the given [supportedOptions].
  factory _ErrorBuilder(Set<String> supportedOptions) {
    var proposal = supportedOptions.quotedAndCommaSeparatedWithAnd;
    if (supportedOptions.isEmpty) {
      return _ErrorBuilder._(proposal: proposal, code: noProposalCode);
    } else if (supportedOptions.length == 1) {
      return _ErrorBuilder._(proposal: proposal, code: singularProposalCode);
    } else {
      return _ErrorBuilder._(proposal: proposal, code: pluralProposalCode);
    }
  }

  _ErrorBuilder._({required this.proposal, required this.code});

  /// Report an unsupported [node] value, defined in the given [scopeName].
  void reportError(
    DiagnosticReporter reporter,
    String scopeName,
    YamlNode node,
  ) {
    if (proposal.isNotEmpty) {
      reporter.atSourceSpan(
        node.span,
        code,
        arguments: [scopeName, node.valueOrThrow, proposal],
      );
    } else {
      reporter.atSourceSpan(
        node.span,
        code,
        arguments: [scopeName, node.valueOrThrow],
      );
    }
  }
}

/// Validates `analyzer` error filter options.
class _ErrorFilterOptionValidator extends OptionsValidator {
  /// Legal values.
  static final List<String> legalValues = [
    ...AnalysisOptionsFile.ignoreSynonyms,
    ...AnalysisOptionsFile.includeSynonyms,
    ...AnalysisOptionsFile.severities,
  ];

  /// Pretty String listing legal values.
  static final String legalValueString =
      legalValues.quotedAndCommaSeparatedWithAnd;

  /// Lazily populated set of diagnostic code names.
  static final Set<String> _diagnosticCodes =
      diagnosticCodeValues.map((DiagnosticCode code) => code.name).toSet();

  /// The diagnostic code names that existed, but were removed.
  /// We don't want to report these, this breaks clients.
  // TODO(scheglov): https://github.com/flutter/flutter/issues/141576
  static const Set<String> _removedDiagnosticCodes = {'MISSING_RETURN'};

  /// Lazily populated set of lint code names.
  late final Set<String> _lintCodes =
      Registry.ruleRegistry.rules
          .map((rule) => rule.name.toUpperCase())
          .toSet();

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var filters = analyzer.valueAt(AnalysisOptionsFile.errors);
      if (filters is YamlMap) {
        filters.nodes.forEach((k, v) {
          String? value;
          if (k is YamlScalar) {
            value = toUpperCase(k.value);
            if (!_diagnosticCodes.contains(value) &&
                !_lintCodes.contains(value) &&
                !_removedDiagnosticCodes.contains(value)) {
              reporter.atSourceSpan(
                k.span,
                AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE,
                arguments: [k.value.toString()],
              );
            }
          }
          if (v is YamlScalar) {
            value = toLowerCase(v.value);
            if (!legalValues.contains(value)) {
              reporter.atSourceSpan(
                v.span,
                AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES,
                arguments: [
                  AnalysisOptionsFile.errors,
                  v.value.toString(),
                  legalValueString,
                ],
              );
            }
          } else {
            reporter.atSourceSpan(
              v.span,
              AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
              arguments: [AnalysisOptionsFile.enableExperiment],
            );
          }
        });
      } else if (filters != null) {
        reporter.atSourceSpan(
          filters.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.enableExperiment],
        );
      }
    }
  }
}

/// Validates `formatter` options.
class _FormatterOptionsValidator extends OptionsValidator {
  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var formatter = options.valueAt(AnalysisOptionsFile.formatter);
    if (formatter == null) {
      return;
    }

    if (formatter is YamlMap) {
      for (var MapEntry(key: keyNode, value: valueNode)
          in formatter.nodeMap.entries) {
        if (keyNode.value == AnalysisOptionsFile.pageWidth) {
          _validatePageWidth(keyNode, valueNode, reporter);
        } else if (keyNode.value == AnalysisOptionsFile.trailingCommas) {
          _validateTrailingCommas(keyNode, valueNode, reporter);
        } else {
          reporter.atSourceSpan(
            keyNode.span,
            AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITHOUT_VALUES,
            arguments: [AnalysisOptionsFile.formatter, keyNode.toString()],
          );
        }
      }
    } else if (formatter.value != null) {
      reporter.atSourceSpan(
        formatter.span,
        AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
        arguments: [AnalysisOptionsFile.formatter],
      );
    }
  }

  void _validatePageWidth(
    YamlNode keyNode,
    YamlNode valueNode,
    DiagnosticReporter reporter,
  ) {
    var value = valueNode.value;
    if (value is! int || value <= 0) {
      reporter.atSourceSpan(
        valueNode.span,
        AnalysisOptionsWarningCode.INVALID_OPTION,
        arguments: [
          keyNode.toString(),
          '"page_width" must be a positive integer.',
        ],
      );
    }
  }

  void _validateTrailingCommas(
    YamlNode keyNode,
    YamlNode valueNode,
    DiagnosticReporter reporter,
  ) {
    var value = valueNode.value;

    if (!TrailingCommas.values.any((item) => item.name == value)) {
      reporter.atSourceSpan(
        valueNode.span,
        AnalysisOptionsWarningCode.INVALID_OPTION,
        arguments: [
          keyNode.toString(),
          '"trailing_commas" must be "automate" or "preserve".',
        ],
      );
    }
  }
}

/// Validates `analyzer` language configuration options.
class _LanguageOptionValidator extends OptionsValidator {
  final _ErrorBuilder _builder = _ErrorBuilder(
    AnalysisOptionsFile._languageOptions,
  );

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var language = analyzer.valueAt(AnalysisOptionsFile.language);
      if (language is YamlMap) {
        language.nodes.forEach((k, v) {
          String? key, value;
          bool validKey = false;
          if (k is YamlScalar) {
            key = k.value?.toString();
            if (!AnalysisOptionsFile._languageOptions.contains(key)) {
              _builder.reportError(reporter, AnalysisOptionsFile.language, k);
            } else {
              // If we have a valid key, go on and check the value.
              validKey = true;
            }
          }
          if (validKey && v is YamlScalar) {
            value = toLowerCase(v.value);
            // `null` is not a valid key, so we can safely assume `key` is
            // non-`null`.
            if (!AnalysisOptionsFile._trueOrFalse.contains(value)) {
              reporter.atSourceSpan(
                v.span,
                AnalysisOptionsWarningCode.UNSUPPORTED_VALUE,
                arguments: [
                  key!,
                  v.valueOrThrow,
                  AnalysisOptionsFile._trueOrFalseProposal,
                ],
              );
            }
          }
        });
      } else if (language is YamlScalar && language.value != null) {
        reporter.atSourceSpan(
          language.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.language],
        );
      } else if (language is YamlList) {
        reporter.atSourceSpan(
          language.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.language],
        );
      }
    }
  }
}

/// Validates `analyzer` plugins configuration options.
class _LegacyPluginsOptionValidator extends OptionsValidator {
  /// The name of the first included legacy plugin, if there is one.
  ///
  /// If there are no included legacy plugins, this is `null`.
  final String? _firstIncludedPluginName;

  _LegacyPluginsOptionValidator(this._firstIncludedPluginName);

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is! YamlMap) {
      return;
    }
    var plugins = analyzer.valueAt(AnalysisOptionsFile.plugins);
    if (plugins is YamlScalar && plugins.value != null) {
      if (_firstIncludedPluginName != null &&
          _firstIncludedPluginName != plugins.value) {
        reporter.atSourceSpan(
          plugins.span,
          AnalysisOptionsWarningCode.MULTIPLE_PLUGINS,
          arguments: [_firstIncludedPluginName],
        );
      }
    } else if (plugins is YamlList) {
      var pluginValues = plugins.nodes.whereType<YamlNode>().toList();
      if (_firstIncludedPluginName != null) {
        // There is already at least one plugin specified in included options.
        for (var plugin in pluginValues) {
          if (plugin.value != _firstIncludedPluginName) {
            reporter.atSourceSpan(
              plugin.span,
              AnalysisOptionsWarningCode.MULTIPLE_PLUGINS,
              arguments: [_firstIncludedPluginName],
            );
          }
        }
      } else if (plugins.length > 1) {
        String? firstPlugin;
        for (var plugin in pluginValues) {
          if (firstPlugin == null) {
            var pluginValue = plugin.value;
            if (pluginValue is String) {
              firstPlugin = pluginValue;
              continue;
            } else {
              // This plugin is bad and should not be marked as the first one.
              continue;
            }
          } else if (plugin.value != firstPlugin) {
            reporter.atSourceSpan(
              plugin.span,
              AnalysisOptionsWarningCode.MULTIPLE_PLUGINS,
              arguments: [firstPlugin],
            );
          }
        }
      }
    } else if (plugins is YamlMap) {
      var pluginValues = plugins.nodes.keys.cast<YamlNode?>();
      if (_firstIncludedPluginName != null) {
        // There is already at least one plugin specified in included options.
        for (var plugin in pluginValues) {
          if (plugin != null && plugin.value != _firstIncludedPluginName) {
            reporter.atSourceSpan(
              plugin.span,
              AnalysisOptionsWarningCode.MULTIPLE_PLUGINS,
              arguments: [_firstIncludedPluginName],
            );
          }
        }
      } else if (plugins.length > 1) {
        String? firstPlugin;
        for (var plugin in pluginValues) {
          if (firstPlugin == null) {
            var pluginValue = plugin?.value;
            if (pluginValue is String) {
              firstPlugin = pluginValue;
              continue;
            } else {
              // This plugin is bad and should not be marked as the first one.
              continue;
            }
          } else if (plugin != null && plugin.value != firstPlugin) {
            reporter.atSourceSpan(
              plugin.span,
              AnalysisOptionsWarningCode.MULTIPLE_PLUGINS,
              arguments: [firstPlugin],
            );
          }
        }
      }
    }
  }
}

/// Validates `linter` top-level options.
class _LinterTopLevelOptionsValidator extends _TopLevelOptionValidator {
  _LinterTopLevelOptionsValidator()
    : super(AnalysisOptionsFile.linter, AnalysisOptionsFile._linterOptions);
}

/// Validates `analyzer` optional-checks value configuration options.
class _OptionalChecksValueValidator extends OptionsValidator {
  final _ErrorBuilder _builder = _ErrorBuilder(
    AnalysisOptionsFile._optionalChecksOptions,
  );

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var v = analyzer.valueAt(AnalysisOptionsFile.optionalChecks);
      if (v is YamlScalar) {
        var value = toLowerCase(v.value);
        if (value != AnalysisOptionsFile.chromeOsManifestChecks) {
          _builder.reportError(
            reporter,
            AnalysisOptionsFile.chromeOsManifestChecks,
            v,
          );
        }
      } else if (v is YamlMap) {
        v.nodes.forEach((k, v) {
          String? key, value;
          if (k is YamlScalar) {
            key = k.value?.toString();
            if (key != AnalysisOptionsFile.chromeOsManifestChecks) {
              _builder.reportError(
                reporter,
                AnalysisOptionsFile.chromeOsManifestChecks,
                k,
              );
            } else {
              value = toLowerCase(v.value);
              if (!AnalysisOptionsFile._trueOrFalse.contains(value)) {
                reporter.atSourceSpan(
                  v.span,
                  AnalysisOptionsWarningCode.UNSUPPORTED_VALUE,
                  arguments: [
                    key!,
                    v.valueOrThrow,
                    AnalysisOptionsFile._trueOrFalseProposal,
                  ],
                );
              }
            }
          }
        });
      } else if (v != null) {
        reporter.atSourceSpan(
          v.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.enableExperiment],
        );
      }
    }
  }
}

/// Validates options for each `plugins` map value.
class _PluginsOptionsValidator extends OptionsValidator {
  final _ErrorBuilder _builder = _ErrorBuilder(
    AnalysisOptionsFile._pluginsOptions,
  );

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var plugins = options.valueAt(AnalysisOptionsFile.plugins);
    switch (plugins) {
      case YamlMap():
        plugins.nodes.forEach((pluginName, pluginValue) {
          if (pluginName is! String) {
            return;
          }
          switch (pluginValue) {
            case YamlScalar(value: String()):
              // Valid enough. We could validate that it is a legal VersionConstraint
              // from the pub_semver package.
              break;
            case YamlMap():
              _validatePluginMap(reporter, pluginName, pluginValue);
            default:
              reporter.atSourceSpan(
                plugins.span,
                AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
                arguments: ['${AnalysisOptionsFile.plugins}/$pluginName'],
              );
          }
        });
      case YamlList():
        reporter.atSourceSpan(
          plugins.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.plugins],
        );
      case YamlScalar(:var value):
        if (value != null) {
          reporter.atSourceSpan(
            plugins.span,
            AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
            arguments: [AnalysisOptionsFile.plugins],
          );
        }
    }
  }

  void _validatePluginMap(
    DiagnosticReporter reporter,
    String pluginName,
    YamlMap pluginValue,
  ) {
    pluginValue.nodes.forEach((pluginMapKeyNode, pluginMapValueNode) {
      if (pluginMapKeyNode case YamlScalar(value: String pluginMapKey)) {
        if (!AnalysisOptionsFile._pluginsOptions.contains(pluginMapKey)) {
          _builder.reportError(
            reporter,
            '${AnalysisOptionsFile.plugins}/$pluginName',
            pluginMapKeyNode,
          );
        }
      }
      // TODO(srawlins): Validate 'path' is a YamlScalar.
      // TODO(srawlins): Validate 'git' value is a YamlScalar. Change when
      // supporting refs.
    });
  }
}

/// Validates `analyzer` strong-mode value configuration options.
class _StrongModeOptionValueValidator extends OptionsValidator {
  final _ErrorBuilder _builder = _ErrorBuilder(
    AnalysisOptionsFile._strongModeOptions,
  );

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var analyzer = options.valueAt(AnalysisOptionsFile.analyzer);
    if (analyzer is YamlMap) {
      var strongModeNode = analyzer.valueAt(AnalysisOptionsFile.strongMode);
      if (strongModeNode is YamlMap) {
        return _validateStrongModeAsMap(reporter, strongModeNode);
      } else if (strongModeNode != null) {
        reporter.atSourceSpan(
          strongModeNode.span,
          AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT,
          arguments: [AnalysisOptionsFile.strongMode],
        );
      }
    }
  }

  void _validateStrongModeAsMap(
    DiagnosticReporter reporter,
    YamlMap strongModeNode,
  ) {
    strongModeNode.nodes.forEach((k, v) {
      if (k is YamlScalar) {
        var key = k.value?.toString();
        if (!AnalysisOptionsFile._strongModeOptions.contains(key)) {
          _builder.reportError(reporter, AnalysisOptionsFile.strongMode, k);
        } else if (key == AnalysisOptionsFile.declarationCasts) {
          reporter.atSourceSpan(
            v.span,
            AnalysisOptionsWarningCode.UNSUPPORTED_VALUE,
            arguments: [
              AnalysisOptionsFile.strongMode,
              v.valueOrThrow,
              AnalysisOptionsFile._trueOrFalseProposal,
            ],
          );
        } else {
          // The key is valid.
          if (v is YamlScalar) {
            var value = toLowerCase(v.value);
            if (!AnalysisOptionsFile._trueOrFalse.contains(value)) {
              reporter.atSourceSpan(
                v.span,
                AnalysisOptionsWarningCode.UNSUPPORTED_VALUE,
                arguments: [
                  key!,
                  v.valueOrThrow,
                  AnalysisOptionsFile._trueOrFalseProposal,
                ],
              );
            }
          }
        }
      }
    });
  }
}

/// Validates top-level options. For example,
///
/// ```yaml
///     plugin:
///       top-level-option: true
/// ```
class _TopLevelOptionValidator extends OptionsValidator {
  final String pluginName;
  final Set<String> supportedOptions;
  final String _valueProposal;
  final AnalysisOptionsWarningCode _warningCode;

  _TopLevelOptionValidator(this.pluginName, this.supportedOptions)
    : assert(supportedOptions.isNotEmpty),
      _valueProposal = supportedOptions.quotedAndCommaSeparatedWithAnd,
      _warningCode =
          supportedOptions.length == 1
              ? AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE
              : AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES;

  @override
  void validate(DiagnosticReporter reporter, YamlMap options) {
    var node = options.valueAt(pluginName);
    if (node is YamlMap) {
      node.nodes.forEach((k, v) {
        if (k is YamlScalar) {
          if (!supportedOptions.contains(k.value)) {
            reporter.atSourceSpan(
              k.span,
              _warningCode,
              arguments: [pluginName, k.valueOrThrow, _valueProposal],
            );
          }
        }
        // TODO(pq): consider an error if the node is not a Scalar.
      });
    }
    // TODO(srawlins): Report non-Map with
    //  AnalysisOptionsWarningCode.INVALID_SECTION_FORMAT.
  }
}
