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

/// Defines static information collected by the type checker and used later by
/// emitters to generate code.
// TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
// refactored to fit into analyzer.
library analyzer.src.task.strong.info;

import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/type_system.dart';

// A down cast due to a variable declaration to a ground type.  E.g.,
//   T x = expr;
// where T is ground.  We exclude non-ground types as these behave differently
// compared to standard Dart.
class AssignmentCast extends DownCast {
  AssignmentCast(TypeSystem rules, Expression expression, Cast cast)
      : super._internal(rules, expression, cast);

  @override
  String get name => 'STRONG_MODE_ASSIGNMENT_CAST';

  toErrorCode() => new HintCode(name, message);
}

// Coercion which casts one type to another
class Cast extends Coercion {
  Cast(DartType fromType, DartType toType) : super(fromType, toType);
}

// The abstract type of coercions mapping one type to another.
// This class also exposes static builder functions which
// check for errors and reduce redundant coercions to the identity.
abstract class Coercion {
  final DartType fromType;
  final DartType toType;
  Coercion(this.fromType, this.toType);
  static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT);
  static Coercion error() => new CoercionError();
  static Coercion identity(DartType type) => new Identity(type);
}

// The error coercion.  This coercion signals that a coercion
// could not be generated.  The code generator should not see
// these.
class CoercionError extends Coercion {
  CoercionError() : super(null, null);
}

/// Implicitly injected expression conversion.
abstract class CoercionInfo extends StaticInfo {
  static const String _propertyName = 'dev_compiler.src.info.CoercionInfo';

  final TypeSystem rules;

  final Expression node;

  CoercionInfo(this.rules, this.node);

  DartType get baseType => node.staticType ?? DynamicTypeImpl.instance;
  DartType get convertedType;

  String get message;
  DartType get staticType => convertedType;

  toErrorCode() => new HintCode(name, message);

  /// Gets the coercion info associated with this node.
  static CoercionInfo get(AstNode node) => node.getProperty(_propertyName);

  /// Sets the coercion info associated with this node.
  static CoercionInfo set(AstNode node, CoercionInfo info) {
    node.setProperty(_propertyName, info);
    return info;
  }
}

// Base class for all casts from base type to sub type.
abstract class DownCast extends CoercionInfo {
  Cast _cast;

  DownCast._internal(
      TypeSystem rules, Expression expression, this._cast)
      : super(rules, expression) {
    assert(_cast.toType != baseType &&
        _cast.fromType == baseType &&
        (baseType.isDynamic ||
            // Call methods make the following non-redundant
            _cast.toType.isSubtypeOf(baseType) ||
            baseType.isAssignableTo(_cast.toType)));
  }

  @override List<Object> get arguments => [node, baseType, convertedType];

  Cast get cast => _cast;

  DartType get convertedType => _cast.toType;
  @override String get message => '{0} ({1}) will need runtime check '
      'to cast to type {2}';

  // Factory to create correct DownCast variant.
  static StaticInfo create(
      StrongTypeSystemImpl rules, Expression expression, Cast cast,
      {String reason}) {
    final fromT = cast.fromType;
    final toT = cast.toType;

    // toT <:_R fromT => to <: fromT
    // NB: classes with call methods are subtypes of function
    // types, but the function type is not assignable to the class
    assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));

    // Handle null call specially.
    if (expression is NullLiteral) {
      // TODO(vsm): Create a NullCast for this once we revisit nonnullability.
      return new DownCastImplicit(rules, expression, cast);
    }

    // Inference "casts":
    if (expression is Literal) {
      // fromT should be an exact type - this will almost certainly fail at
      // runtime.
      return new StaticTypeError(rules, expression, toT, reason: reason);
    }
    if (expression is FunctionExpression) {
      // fromT should be an exact type - this will almost certainly fail at
      // runtime.
      return new UninferredClosure(rules, expression, cast);
    }
    if (expression is InstanceCreationExpression) {
      // fromT should be an exact type - this will almost certainly fail at
      // runtime.
      return new StaticTypeError(rules, expression, toT, reason: reason);
    }

    // TODO(vsm): Change this to an assert when we have generic methods and
    // fix TypeRules._coerceTo to disallow implicit sideways casts.
    if (!rules.isSubtypeOf(toT, fromT)) {
      assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));
      return new DownCastComposite(rules, expression, cast);
    }

    // Composite cast: these are more likely to fail.
    if (!rules.isGroundType(toT)) {
      // This cast is (probably) due to our different treatment of dynamic.
      // It may be more likely to fail at runtime.
      if (fromT is InterfaceType) {
        // For class types, we'd like to allow non-generic down casts, e.g.,
        // Iterable<T> to List<T>.  The intuition here is that raw (generic)
        // casts are problematic, and we should complain about those.
        var typeArgs = fromT.typeArguments;
        if (typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic)) {
          return new DownCastComposite(rules, expression, cast);
        }
      } else {
        return new DownCastComposite(rules, expression, cast);
      }
    }

    // Dynamic cast
    if (fromT.isDynamic) {
      return new DynamicCast(rules, expression, cast);
    }

    // Assignment cast
    var parent = expression.parent;
    if (parent is VariableDeclaration && (parent.initializer == expression)) {
      return new AssignmentCast(rules, expression, cast);
    }

    // Other casts
    return new DownCastImplicit(rules, expression, cast);
  }
}

//
// Implicit down casts.  These are only injected by the compiler by flag.
//
// A down cast to a non-ground type.  These behave differently from standard
// Dart and may be more likely to fail at runtime.
class DownCastComposite extends DownCast {
  DownCastComposite(
      TypeSystem rules, Expression expression, Cast cast)
      : super._internal(rules, expression, cast);

  @override
  String get name => 'STRONG_MODE_DOWN_CAST_COMPOSITE';

  toErrorCode() => new StaticTypeWarningCode(name, message);
}

// A down cast to a non-ground type.  These behave differently from standard
// Dart and may be more likely to fail at runtime.
class DownCastImplicit extends DownCast {
  DownCastImplicit(TypeSystem rules, Expression expression, Cast cast)
      : super._internal(rules, expression, cast);

  @override
  String get name => 'STRONG_MODE_DOWN_CAST_IMPLICIT';

  toErrorCode() => new HintCode(name, message);
}

// A down cast from dynamic to T.
class DynamicCast extends DownCast {
  DynamicCast(TypeSystem rules, Expression expression, Cast cast)
      : super._internal(rules, expression, cast);

  @override
  String get name => 'STRONG_MODE_DYNAMIC_CAST';

  toErrorCode() => new HintCode(name, message);
}

class DynamicInvoke extends CoercionInfo {
  static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke';

  DynamicInvoke(TypeSystem rules, Expression expression)
      : super(rules, expression);
  DartType get convertedType => DynamicTypeImpl.instance;
  String get message => '{0} requires dynamic invoke';

  @override
  String get name => 'STRONG_MODE_DYNAMIC_INVOKE';

  toErrorCode() => new HintCode(name, message);

  /// Whether this [node] is the target of a dynamic operation.
  static bool get(AstNode node) {
    var value = node.getProperty(_propertyName);
    return value != null ? value : false;
  }

  /// Sets whether this node is the target of a dynamic operation.
  static bool set(AstNode node, bool value) {
    // Free the storage for things that aren't dynamic.
    if (value == false) value = null;
    node.setProperty(_propertyName, value);
    return value;
  }
}

// The identity coercion
class Identity extends Coercion {
  Identity(DartType fromType) : super(fromType, fromType);
}

// Standard / unspecialized inferred type
class InferredType extends InferredTypeBase {
  InferredType(TypeSystem rules, Expression expression, DartType type)
      : super._internal(rules, expression, type);

  @override
  String get name => 'STRONG_MODE_INFERRED_TYPE';

  // Factory to create correct InferredType variant.
  static InferredTypeBase create(
      TypeSystem rules, Expression expression, DartType type) {
    // Specialized inference:
    if (expression is Literal) {
      return new InferredTypeLiteral(rules, expression, type);
    }
    if (expression is InstanceCreationExpression) {
      return new InferredTypeAllocation(rules, expression, type);
    }
    if (expression is FunctionExpression) {
      return new InferredTypeClosure(rules, expression, type);
    }
    return new InferredType(rules, expression, type);
  }
}

// An inferred type for a non-literal allocation site.
class InferredTypeAllocation extends InferredTypeBase {
  InferredTypeAllocation(
      TypeSystem rules, Expression expression, DartType type)
      : super._internal(rules, expression, type);

  @override
  String get name => 'STRONG_MODE_INFERRED_TYPE_ALLOCATION';
}

// An inferred type for the wrapped expression, which may need to be
// reified into the term
abstract class InferredTypeBase extends CoercionInfo {
  final DartType _type;

  InferredTypeBase._internal(
      TypeSystem rules, Expression expression, this._type)
      : super(rules, expression);

  @override List get arguments => [node, type];
  DartType get convertedType => type;
  @override String get message => '{0} has inferred type {1}';
  DartType get type => _type;

  toErrorCode() => new HintCode(name, message);
}

// An inferred type for a closure expression
class InferredTypeClosure extends InferredTypeBase {
  InferredTypeClosure(
      TypeSystem rules, Expression expression, DartType type)
      : super._internal(rules, expression, type);

  @override
  String get name => 'STRONG_MODE_INFERRED_TYPE_CLOSURE';
}

// An inferred type for a literal expression.
class InferredTypeLiteral extends InferredTypeBase {
  InferredTypeLiteral(
      TypeSystem rules, Expression expression, DartType type)
      : super._internal(rules, expression, type);

  @override
  String get name => 'STRONG_MODE_INFERRED_TYPE_LITERAL';
}

class InvalidFieldOverride extends InvalidOverride {
  InvalidFieldOverride(AstNode node, ExecutableElement element,
      InterfaceType base, DartType subType, DartType baseType)
      : super(node, element, base, subType, baseType);

  String get message => 'Field declaration {3}.{1} cannot be '
      'overridden in {0}.';

  @override
  String get name => 'STRONG_MODE_INVALID_FIELD_OVERRIDE';
}

// Invalid override due to incompatible type.  I.e., the overridden signature
// is not compatible with the original.
class InvalidMethodOverride extends InvalidOverride {
  InvalidMethodOverride(AstNode node, ExecutableElement element,
      InterfaceType base, FunctionType subType, FunctionType baseType)
      : super(node, element, base, subType, baseType);

  String get message => _messageHelper('Invalid override');

  @override
  String get name => 'STRONG_MODE_INVALID_METHOD_OVERRIDE';
}

// Invalid override of an instance member of a class.
abstract class InvalidOverride extends StaticError {
  /// Member declaration with the invalid override.
  final ExecutableElement element;

  /// Type (class or interface) that provides the base declaration.
  final InterfaceType base;

  /// Actual type of the overridden member.
  final DartType subType;

  /// Actual type of the base member.
  final DartType baseType;

  /// Whether the error comes from combining a base class and an interface
  final bool fromBaseClass;

  /// Whether the error comes from a mixin (either overriding a base class or an
  /// interface declaration).
  final bool fromMixin;

  InvalidOverride(
      AstNode node, this.element, this.base, this.subType, this.baseType)
      : fromBaseClass = node is ExtendsClause,
        fromMixin = node.parent is WithClause,
        super(node);

  @override List<Object> get arguments =>
      [parent.name, element.name, subType, base, baseType];

  ClassElement get parent => element.enclosingElement;

  String _messageHelper(String errorName) {
    var lcErrorName = errorName.toLowerCase();
    var intro = fromBaseClass
        ? 'Base class introduces an $lcErrorName'
        : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName);
    return '$intro. The type of {0}.{1} ({2}) is not a '
        'subtype of {3}.{1} ({4}).';
  }
}

class InvalidParameterDeclaration extends StaticError {
  final DartType expectedType;

  InvalidParameterDeclaration(TypeSystem rules,
      FormalParameter declaration, this.expectedType)
      : super(declaration);

  @override List<Object> get arguments => [node, expectedType];
  @override String get message => 'Type check failed: {0} is not of type {1}';
  @override
  String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION';
}

/// Dart constructors have one weird quirk, illustrated with this example:
///
///     class Base {
///       var x;
///       Base() : x = print('Base.1') {
///         print('Base.2');
///       }
///     }
///
///     class Derived extends Base {
///       var y, z;
///       Derived()
///           : y = print('Derived.1'),
///             super(),
///             z = print('Derived.2') {
///         print('Derived.3');
///       }
///     }
///
/// The order will be Derived.1, Base.1, Derived.2, Base.2, Derived.3; this
/// ordering preserves the invariant that code can't observe uninitialized
/// state, however it results in super constructor body not being run
/// immediately after super initializers. Normally this isn't observable, but it
/// could be if initializers have side effects.
///
/// Better to have `super` at the end, as required by the Dart style guide:
/// <http://goo.gl/q1T4BB>
///
/// For now this is the only pattern we support.
class InvalidSuperInvocation extends StaticError {
  InvalidSuperInvocation(SuperConstructorInvocation node) : super(node);

  @override String get message => "super call must be last in an initializer "
      "list (see http://goo.gl/q1T4BB): {0}";

  @override
  String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION';
}

class InvalidVariableDeclaration extends StaticError {
  final DartType expectedType;

  InvalidVariableDeclaration(
      TypeSystem rules, AstNode declaration, this.expectedType)
      : super(declaration);

  @override List<Object> get arguments => [expectedType];
  @override String get message => 'Type check failed: null is not of type {0}';

  @override
  String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION';
}

class NonGroundTypeCheckInfo extends StaticInfo {
  final DartType type;
  final AstNode node;

  NonGroundTypeCheckInfo(this.node, this.type) {
    assert(node is IsExpression || node is AsExpression);
  }

  @override List<Object> get arguments => [type];
  String get message =>
      "Runtime check on non-ground type {0} may throw StrongModeError";

  @override
  String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO';

  toErrorCode() => new HintCode(name, message);
}

abstract class StaticError extends StaticInfo {
  final AstNode node;

  StaticError(this.node);

  String get message;

  toErrorCode() => new CompileTimeErrorCode(name, message);
}

// TODO(jmesserly): this could use some refactoring. These are essentially
// like ErrorCodes in analyzer, but we're including some details in our message.
// Analyzer instead has template strings, and replaces '{0}' with the first
// argument.
abstract class StaticInfo {
  /// Strong-mode error code names.
  ///
  /// Used for error code configuration validation in `.analysis_options`.
  static const List<String> names = const [
    //
    // Manually populated.
    //
    'STRONG_MODE_ASSIGNMENT_CAST',
    'STRONG_MODE_DOWN_CAST_COMPOSITE',
    'STRONG_MODE_DOWN_CAST_IMPLICIT',
    'STRONG_MODE_DYNAMIC_CAST',
    'STRONG_MODE_DYNAMIC_INVOKE',
    'STRONG_MODE_INFERRED_TYPE',
    'STRONG_MODE_INFERRED_TYPE_ALLOCATION',
    'STRONG_MODE_INFERRED_TYPE_CLOSURE',
    'STRONG_MODE_INFERRED_TYPE_LITERAL',
    'STRONG_MODE_INVALID_FIELD_OVERRIDE',
    'STRONG_MODE_INVALID_METHOD_OVERRIDE',
    'STRONG_MODE_INVALID_PARAMETER_DECLARATION',
    'STRONG_MODE_INVALID_SUPER_INVOCATION',
    'STRONG_MODE_INVALID_VARIABLE_DECLARATION',
    'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO',
    'STRONG_MODE_STATIC_TYPE_ERROR',
    'STRONG_MODE_UNINFERRED_CLOSURE',
  ];

  List<Object> get arguments => [node];

  String get name;

  /// AST Node this info is attached to.
  AstNode get node;

  AnalysisError toAnalysisError() {
    int begin = node is AnnotatedNode
        ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
        : node.offset;
    int length = node.end - begin;
    var source = (node.root as CompilationUnit).element.source;
    return new AnalysisError(source, begin, length, toErrorCode(), arguments);
  }

  // TODO(jmesserly): review the usage of error codes. We probably want our own,
  // as well as some DDC specific [ErrorType]s.
  ErrorCode toErrorCode();
}

class StaticTypeError extends StaticError {
  final DartType baseType;
  final DartType expectedType;
  String reason = null;

  StaticTypeError(
      TypeSystem rules, Expression expression, this.expectedType,
      {this.reason})
      : baseType = expression.staticType ?? DynamicTypeImpl.instance,
        super(expression);

  @override List<Object> get arguments => [node, baseType, expectedType];
  @override String get message =>
      'Type check failed: {0} ({1}) is not of type {2}' +
          ((reason == null) ? '' : ' because $reason');

  @override
  String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
}

//
// Temporary "casts" of allocation sites - literals, constructor invocations,
// and closures.  These should be handled by contextual inference.  In most
// cases, inference will be sufficient, though in some it may unmask an actual
// error: e.g.,
//   List<int> l = [1, 2, 3]; // Inference succeeds
//   List<String> l = [1, 2, 3]; // Inference reveals static type error
// We're marking all as warnings for now.
//
// TODO(vsm,leafp): Remove this.
class UninferredClosure extends DownCast {
  UninferredClosure(
      TypeSystem rules, FunctionExpression expression, Cast cast)
      : super._internal(rules, expression, cast);

  @override
  String get name => 'STRONG_MODE_UNINFERRED_CLOSURE';

  toErrorCode() => new StaticTypeWarningCode(name, message);
}
