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

library analyzer.source.error_processor;

import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:yaml/yaml.dart';

/// String identifiers mapped to associated severities.
const Map<String, ErrorSeverity> severityMap = const {
  'error': ErrorSeverity.ERROR,
  'info': ErrorSeverity.INFO,
  'warning': ErrorSeverity.WARNING
};

/// Error processor configuration derived from analysis (or embedder) options.
class ErrorConfig {
  /// The processors in this config.
  final List<ErrorProcessor> processors = <ErrorProcessor>[];

  /// Create an error config for the given error code map.
  /// For example:
  ///     new ErrorConfig({'missing_return' : 'error'});
  /// will create a processor config that turns `missing_return` hints into
  /// errors.
  ErrorConfig(Object codeMap) {
    _processMap(codeMap);
  }

  void _process(String code, Object action) {
    action = toLowerCase(action);
    code = toUpperCase(code);
    if (AnalyzerOptions.ignoreSynonyms.contains(action)) {
      processors.add(new ErrorProcessor.ignore(code));
    } else {
      ErrorSeverity severity = _toSeverity(action);
      if (severity != null) {
        processors.add(new ErrorProcessor(code, severity));
      }
    }
  }

  void _processMap(Object codes) {
    if (codes is YamlMap) {
      // TODO(pq): stop traversing nodes and unify w/ standard map handling
      codes.nodes.forEach((k, v) {
        if (k is YamlScalar && v is YamlScalar) {
          _process(k.value, v.value);
        }
      });
    } else if (codes is Map) {
      codes.forEach((k, v) {
        if (k is String) {
          _process(k, v);
        }
      });
    }
  }

  ErrorSeverity _toSeverity(String severity) => severityMap[severity];
}

/// Process errors by filtering or changing associated [ErrorSeverity].
class ErrorProcessor {
  /// The code name of the associated error.
  final String code;

  /// The desired severity of the processed error.
  ///
  /// If `null`, this processor will "filter" the associated error code.
  final ErrorSeverity severity;

  /// Create an error processor that assigns errors with this [code] the
  /// given [severity].
  ///
  /// If [severity] is `null`, matching errors will be filtered.
  ErrorProcessor(this.code, [this.severity]);

  /// Create an error processor that ignores the given error by [code].
  factory ErrorProcessor.ignore(String code) => new ErrorProcessor(code);

  /// Check if this processor applies to the given [error].
  bool appliesTo(AnalysisError error) => code == error.errorCode.name;

  /// Return an error processor associated with this [context] for the given
  /// [error], or `null` if none is found.
  static ErrorProcessor getProcessor(
      AnalysisContext context, AnalysisError error) {
    if (context == null) {
      return null;
    }

    // Let the user configure how specific errors are processed.
    List<ErrorProcessor> processors = context.analysisOptions.errorProcessors;

    // Give strong mode a chance to upgrade it.
    if (context.analysisOptions.strongMode) {
      processors = processors.toList();
      processors.add(_StrongModeTypeErrorProcessor.instance);
    }
    return processors.firstWhere((ErrorProcessor p) => p.appliesTo(error),
        orElse: () => null);
  }
}

/// In strong mode, this upgrades static type warnings to errors.
class _StrongModeTypeErrorProcessor implements ErrorProcessor {
  static final instance = new _StrongModeTypeErrorProcessor();

  // TODO(rnystrom): As far as I know, this is only used to implement
  // appliesTo(). Consider making it private in ErrorProcessor if possible.
  String get code => throw new UnsupportedError(
      "_StrongModeTypeErrorProcessor is not specific to an error code.");

  /// In strong mode, type warnings are upgraded to errors.
  ErrorSeverity get severity => ErrorSeverity.ERROR;

  /// Check if this processor applies to the given [error].
  bool appliesTo(AnalysisError error) {
    ErrorCode errorCode = error.errorCode;
    if (errorCode is StaticTypeWarningCode) {
      return true;
    }
    if (errorCode is StaticWarningCode) {
      return errorCode.isStrongModeError;
    }
    return false;
  }
}
