// Copyright (c) 2012, 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.
package com.google.dart.compiler.resolver;

import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ErrorSeverity;
import com.google.dart.compiler.SubSystem;

/**
 * {@link ErrorCode}s for type resolver.
 */
public enum TypeErrorCode implements ErrorCode {
  ASSERT_BOOL("assert requires  'bool' expression or '() -> bool' function"),
  CANNOT_ASSIGN_TO("cannot assign to '%s'"),
  CANNOT_BE_RESOLVED("cannot resolve %s", true),
  CANNOT_OVERRIDE_TYPED_MEMBER("cannot override %s of %s because %s is not assignable to %s"),
  CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE("cannot override method '%s', default value doesn't match '%s'"),
  CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE("cannot override %s of %s because %s is not a subtype of %s"),
  CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS("Concrete class %s has unimplemented member(s) %s"),
  CYCLIC_REFERENCE_TO_TYPE_VARIABLE(
      "Invalid type expression, cyclic reference to type variable '%s'"),
  DEPRECATED_ELEMENT(ErrorSeverity.INFO, "%s is deprecated"),
  DEFAULT_CONSTRUCTOR_TYPES(
      "Constructor '%s' in '%s' has parameters types (%s), doesn't match '%s' in '%s' with (%s)"),
  DUPLICATE_NAMED_ARGUMENT("Named parameter argument already provided as positional argument"),
  CASE_EXPRESSION_TYPE_SHOULD_NOT_HAVE_EQUALS(ErrorSeverity.ERROR,
      "Case expression type '%s' should not implement operator =="),
  CASE_EXPRESSIONS_SHOULD_BE_SAME_TYPE(ErrorSeverity.ERROR,
      "All case expressions should be compiler-time constants of the same type - 'int' or 'String'. '%s' expected but '%s' found"),
  EXPECTED_POSITIONAL_ARGUMENT("Expected positional argument of type %s before named arguments"),
  EXTRA_ARGUMENT("extra argument"),
  FIELD_GETTER_SETTER_SAME_STATIC("Field's getter and setter should be both static or not static"),
  FIELD_HAS_NO_GETTER("Field '%s' has no getter"),
  FIELD_HAS_NO_SETTER("Field '%s' has no setter"),
  FIELD_IS_FINAL("Field '%s' is final"),
  FOR_IN_WITH_ITERATOR_FIELD("iterator is a field, expected an iterator() method"),
  FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE("iterator method's return type is not assignable to %s"),
  ILLEGAL_ACCESS_TO_PRIVATE("'%s' is private and not defined in this library"),
  INCOMPATIBLE_TYPES_IN_HIERARCHY(ErrorSeverity.INFO,
      "Class inherits two variations of the same interface '%s' and '%s' with parameters that are not assignable to each other."),
  INSTANTIATION_OF_ABSTRACT_CLASS("instantiation of an abstract class '%s'"),
  INTERFACE_HAS_NO_METHOD_NAMED("\"%s\" has no method named \"%s\""),
  INTERFACE_HAS_NO_METHOD_NAMED_INFERRED(ErrorSeverity.INFO, "\"%s\" has no method named \"%s\""),
  INTERNAL_ERROR("internal error: %s", true),
  IS_STATIC_FIELD_IN("\"%s\" is a static field in \"%s\""),
  IS_STATIC_METHOD_IN("\"%s\" is a static method in \"%s\""),
  MAP_LITERAL_KEY_UNIQUE("Map literal keys should be unique."),
  MEMBER_IS_A_CONSTRUCTOR("%s is a constructor in %s"),
  MISSING_ARGUMENT("missing argument of type %s"),
  MISSING_RETURN_VALUE("no return value; expected a value of type %s"),
  NEW_EXPRESSION_NOT_CONSTRUCTOR("New expression does not resolve to a constructor"),
  NO_SUCH_NAMED_PARAMETER("no such named parameter \"%s\" defined"),
  NO_SUCH_TYPE("no such type \"%s\"", true),
  NOT_A_FUNCTION_TYPE("\"%s\" is not a function type"),
  NOT_A_FUNCTION_TYPE_FIELD("'%s' is a field of type '%s', not a function; remove parentheses"),
  NOT_A_MEMBER_OF("\"%s\" is not a member of %s"),
  NOT_A_MEMBER_OF_INFERRED(ErrorSeverity.INFO, "\"%s\" is not a member of %s"),
  NOT_A_METHOD_IN("\"%s\" is not a method in %s"),
  NOT_A_METHOD_IN_INFERRED(ErrorSeverity.INFO, "\"%s\" is not a method in %s"),
  NOT_A_TYPE("type \"%s\" expected, but \"%s\" found"),
  OPERATOR_EQUALS_BOOL_RETURN_TYPE("operator 'equals' should return bool type"),
  OPERATOR_INDEX_ASSIGN_VOID_RETURN_TYPE("operator '[]=' must have a return type of 'void'"),
  OPERATOR_WRONG_OPERAND_TYPE("operand of \"%s\" must be assignable to \"%s\", found \"%s\""),
  OVERRIDING_STATIC_MEMBER("overriding static member \"%s\" of \"%s\""),
  REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE(
      "Target type of redirecting factory constructor '%s' is not subtype of '%s'"),
  SETTER_RETURN_TYPE("Specified return type of setter '%s' is non-void"),
  SETTER_TYPE_MUST_BE_ASSIGNABLE("Setter type '%s' must be assignable to getter type '%s'"),
  STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE(
      "static member %s of %s cannot be accessed through an instance"),
  SUPERTYPE_HAS_FIELD(ErrorSeverity.ERROR, "%s is a field in %s"),
  SUPERTYPE_HAS_METHOD(ErrorSeverity.ERROR, "%s is a method in %s"),
  TYPE_ALIAS_CANNOT_REFERENCE_ITSELF(ErrorSeverity.ERROR,
      "Type alias cannot reference itself directly of via other typedefs"),
  TYPE_NOT_ASSIGNMENT_COMPATIBLE("'%s' is not assignable to '%s'"),
  TYPE_NOT_ASSIGNMENT_COMPATIBLE_INFERRED(ErrorSeverity.INFO, "'%s' is not assignable to '%s'"),
  USE_ASSIGNMENT_ON_SETTER("Use assignment to set field '%s'"),
  USE_INTEGER_DIVISION(ErrorSeverity.INFO, "Use integer division ~/ instead"),
  VOID("expression does not yield a value"),
  WRONG_NUMBER_OF_TYPE_ARGUMENTS("%s: wrong number of type arguments (%d), Expected %d");

  private final ErrorSeverity severity;
  private final String message;
  private final boolean needsRecompilation;

  /**
   * Initialize a newly created error code to have the given message.
   */
  private TypeErrorCode(String message) {
    this(message, false);
  }

  /**
   * Initialize a newly created error code to have the given message and compilation flag.
   */
  private TypeErrorCode(String message, boolean needsRecompilation) {
    this(ErrorSeverity.WARNING, message, needsRecompilation);
  }

  private TypeErrorCode(ErrorSeverity severity, String message) {
    this(severity, message, false);
  }

  private TypeErrorCode(ErrorSeverity severity, String message, boolean needsRecompilation) {
    this.severity = severity;
    this.message = message;
    this.needsRecompilation = needsRecompilation;
  }

  @Override
  public String getMessage() {
    return message;
  }

  @Override
  public ErrorSeverity getErrorSeverity() {
    return severity;
  }

  @Override
  public SubSystem getSubSystem() {
    return SubSystem.STATIC_TYPE;
  }

  @Override
  public boolean needsRecompilation() {
    return this.needsRecompilation;
  }
}
