// Copyright (c) 2020, 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/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/ignore_comments/ignore_info.dart';

/// Used to validate the ignore comments in a single file.
class IgnoreValidator {
  /// The error reporter to which errors are to be reported.
  final ErrorReporter _errorReporter;

  /// The diagnostics that are reported in the file being analyzed.
  final List<AnalysisError> _reportedErrors;

  /// The information about the ignore comments in the file being analyzed.
  final IgnoreInfo _ignoreInfo;

  /// The line info for the file being analyzed.
  final LineInfo _lineInfo;

  /// A list of the names and unique names of all known error codes that can't
  /// be ignored. Note that this list is incomplete. Plugins might well define
  /// diagnostics with a severity of `ERROR`, but we won't be able to flag their
  /// use because we have no visibility of them here.
  final Set<String> unignorableNames = {};

  /// Initialize a newly created validator to report any issues with ignore
  /// comments in the file being analyzed. The diagnostics will be reported to
  /// the [_errorReporter].
  IgnoreValidator(this._errorReporter, this._reportedErrors, this._ignoreInfo,
      this._lineInfo) {
    var filePath = _errorReporter.source.fullName;
    for (var code in errorCodeValues) {
      if (!isIgnorable(filePath, code)) {
        unignorableNames.add(code.name.toLowerCase());
        unignorableNames.add(code.uniqueName.toLowerCase());
      }
    }
  }

  /// Report any issues with ignore comments in the file being analyzed.
  void reportErrors() {
    if (!_ignoreInfo.hasIgnores) {
      return;
    }
    var ignoredOnLineMap = _ignoreInfo.ignoredOnLine;
    var ignoredForFile = _ignoreInfo.ignoredForFile;
    //
    // Report and remove any un-ignorable or duplicated names.
    //
    var namesIgnoredForFile = <String>{};
    var unignorable = <DiagnosticName>[];
    var duplicated = <DiagnosticName>[];
    for (var ignoredName in ignoredForFile) {
      var name = ignoredName.name;
      if (unignorableNames.contains(name)) {
        unignorable.add(ignoredName);
      } else if (!namesIgnoredForFile.add(name)) {
        duplicated.add(ignoredName);
      }
    }
    _reportUnknownAndDuplicateIgnores(unignorable, duplicated, ignoredForFile);
    for (var ignoredOnLine in ignoredOnLineMap.values) {
      var namedIgnoredOnLine = <String>{};
      var unignorable = <DiagnosticName>[];
      var duplicated = <DiagnosticName>[];
      for (var ignoredName in ignoredOnLine) {
        var name = ignoredName.name;
        if (unignorableNames.contains(name)) {
          unignorable.add(ignoredName);
        } else if (namesIgnoredForFile.contains(name) ||
            !namedIgnoredOnLine.add(name)) {
          duplicated.add(ignoredName);
        }
      }
      _reportUnknownAndDuplicateIgnores(unignorable, duplicated, ignoredOnLine);
    }
    //
    // Remove all of the errors that are actually being ignored.
    //
    for (var error in _reportedErrors) {
      var lineNumber = _lineInfo.getLocation(error.offset).lineNumber;
      var ignoredOnLine = ignoredOnLineMap[lineNumber];

      ignoredForFile.removeByName(error.ignoreName);
      ignoredForFile.removeByName(error.ignoreUniqueName);

      ignoredOnLine?.removeByName(error.ignoreName);
      ignoredOnLine?.removeByName(error.ignoreUniqueName);
    }
    //
    // Report any remaining ignored names as being unnecessary.
    //
    _reportUnnecessaryIgnores(ignoredForFile);
    for (var ignoredOnLine in ignoredOnLineMap.values) {
      _reportUnnecessaryIgnores(ignoredOnLine);
    }
  }

  /// Report the names that are [unignorable] or [duplicated] and remove them
  /// from the [list] of names from which they were extracted.
  void _reportUnknownAndDuplicateIgnores(List<DiagnosticName> unignorable,
      List<DiagnosticName> duplicated, List<DiagnosticName> list) {
    // TODO(brianwilkerson) Uncomment the code below after the unignorable
    //  ignores in the Flutter code base have been cleaned up.
    // for (var unignorableName in unignorable) {
    //   var name = unignorableName.name;
    //   _errorReporter.reportErrorForOffset(HintCode.UNIGNORABLE_IGNORE,
    //       unignorableName.offset, name.length, [name]);
    //   list.remove(unignorableName);
    // }
    for (var ignoredName in duplicated) {
      var name = ignoredName.name;
      _errorReporter.reportErrorForOffset(
          HintCode.DUPLICATE_IGNORE, ignoredName.offset, name.length, [name]);
      list.remove(ignoredName);
    }
  }

  /// Report the [ignoredNames] as being unnecessary.
  void _reportUnnecessaryIgnores(List<DiagnosticName> ignoredNames) {
    // TODO(brianwilkerson) Uncomment the code below after the unnecessary
    //  ignores in the Flutter code base have been cleaned up.
    // for (var ignoredName in ignoredNames) {
    //   var name = ignoredName.name;
    //   _errorReporter.reportErrorForOffset(
    //       HintCode.UNNECESSARY_IGNORE, ignoredName.offset, name.length,
    //       [name]);
    // }
  }

  static bool isIgnorable(String filePath, ErrorCode code) {
    if (code.isIgnorable) {
      return true;
    }
    // The [code] is not ignorable, but we've allowed a few "privileged"
    // cases. Each is annotated with an issue which represents technical
    // debt. Once cleaned up, we may remove this notion of "privileged".
    // In the case of [CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY], we may
    // just decide that it happens enough in tests that it can be declared
    // an ignorable error, and in practice other back ends will prevent
    // non-internal code from importing internal code.
    if (code == CompileTimeErrorCode.UNDEFINED_FUNCTION ||
        code == CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME) {
      // Special case a small number of errors in Flutter code which are
      // ignored. The erroneous code is found in a conditionally imported
      // library, which uses a special version of the "dart:ui" library
      // which the Analyzer does not use during analysis. See
      // https://github.com/flutter/flutter/issues/52899.
      if (filePath.contains('flutter')) {
        return true;
      }
    }

    if ((code == CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY ||
            code == CompileTimeErrorCode.UNDEFINED_ANNOTATION ||
            code == ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE) &&
        (filePath.contains('tests/compiler/dart2js') ||
            filePath.contains('pkg/compiler/test'))) {
      // Special case the dart2js language tests. Some of these import
      // various internal libraries.
      return true;
    }
    return false;
  }
}

extension on AnalysisError {
  String get ignoreName => errorCode.name.toLowerCase();

  String get ignoreUniqueName {
    String uniqueName = errorCode.uniqueName;
    int period = uniqueName.indexOf('.');
    if (period >= 0) {
      uniqueName = uniqueName.substring(period + 1);
    }
    return uniqueName.toLowerCase();
  }
}

extension on List<DiagnosticName> {
  void removeByName(String name) {
    removeWhere((ignoredName) => ignoredName.name == name);
  }
}
