// Copyright (c) 2019, 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/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:front_end/src/fasta/flow_analysis/flow_analysis.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/variables.dart';

/// Information about the target of an assignment expression analyzed by
/// [FixBuilder].
class AssignmentTargetInfo {
  /// The type that the assignment target has when read.  This is only relevant
  /// for compound assignments (since they both read and write the assignment
  /// target)
  final DartType readType;

  /// The type that the assignment target has when written to.
  final DartType writeType;

  AssignmentTargetInfo(this.readType, this.writeType);
}

/// Problem reported by [FixBuilder] when encountering a compound assignment
/// for which the combination result is nullable.  This occurs if the compound
/// assignment resolves to a user-defined operator that returns a nullable type,
/// but the target of the assignment expects a non-nullable type.  We need to
/// add a null check but it's nontrivial to do so because we would have to
/// rewrite the assignment as an ordinary assignment (e.g. change `x += y` to
/// `x = (x + y)!`), but that might change semantics by causing subexpressions
/// of the target to be evaluated twice.
///
/// TODO(paulberry): consider alternatives.
/// See https://github.com/dart-lang/sdk/issues/38675.
class CompoundAssignmentCombinedNullable implements Problem {
  const CompoundAssignmentCombinedNullable();
}

/// Problem reported by [FixBuilder] when encountering a compound assignment
/// for which the value read from the target of the assignment has a nullable
/// type.  We need to add a null check but it's nontrivial to do so because we
/// would have to rewrite the assignment as an ordinary assignment (e.g. change
/// `x += y` to `x = x! + y`), but that might change semantics by causing
/// subexpressions of the target to be evaluated twice.
///
/// TODO(paulberry): consider alternatives.
/// See https://github.com/dart-lang/sdk/issues/38676.
class CompoundAssignmentReadNullable implements Problem {
  const CompoundAssignmentReadNullable();
}

/// This class visits the AST of code being migrated, after graph propagation,
/// to figure out what changes need to be made to the code.  It doesn't actually
/// make the changes; it simply reports what changes are necessary through
/// abstract methods.
abstract class FixBuilder extends GeneralizingAstVisitor<DartType> {
  /// The decorated class hierarchy for this migration run.
  final DecoratedClassHierarchy _decoratedClassHierarchy;

  /// Type provider providing non-nullable types.
  final TypeProvider _typeProvider;

  /// The type system.
  final TypeSystem _typeSystem;

  /// Variables for this migration run.
  final Variables _variables;

  /// If we are visiting a function body or initializer, instance of flow
  /// analysis.  Otherwise `null`.
  FlowAnalysis<Statement, Expression, PromotableElement, DartType>
      _flowAnalysis;

  /// If we are visiting a function body or initializer, assigned variable
  /// information  used in flow analysis.  Otherwise `null`.
  AssignedVariables<AstNode, PromotableElement> _assignedVariables;

  /// If we are visiting a subexpression, the context type used for type
  /// inference.  This is used to determine when `!` needs to be inserted.
  DartType _contextType;

  /// The file being analyzed.
  final Source source;

  FixBuilder(this.source, this._decoratedClassHierarchy,
      TypeProvider typeProvider, this._typeSystem, this._variables)
      : _typeProvider = (typeProvider as TypeProviderImpl)
            .withNullability(NullabilitySuffix.none);

  /// Called whenever a type annotation is found for which a `?` needs to be
  /// inserted.
  void addNullable(TypeAnnotation node);

  /// Called whenever an expression is found for which a `!` needs to be
  /// inserted.
  void addNullCheck(Expression subexpression);

  /// Called whenever code is found that can't be automatically fixed.
  void addProblem(AstNode node, Problem problem);

  /// Initializes flow analysis for a function node.
  void createFlowAnalysis(Declaration node, FormalParameterList parameters) {
    assert(_flowAnalysis == null);
    assert(_assignedVariables == null);
    _assignedVariables =
        FlowAnalysisHelper.computeAssignedVariables(node, parameters);
    _flowAnalysis =
        FlowAnalysis<Statement, Expression, PromotableElement, DartType>(
            TypeSystemTypeOperations(_typeSystem),
            _assignedVariables.writtenAnywhere,
            _assignedVariables.capturedAnywhere);
  }

  @override
  DartType visitAssignmentExpression(AssignmentExpression node) {
    var targetInfo = visitAssignmentTarget(node.leftHandSide);
    if (node.operator.type == TokenType.EQ) {
      return visitSubexpression(node.rightHandSide, targetInfo.writeType);
    } else if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
      // TODO(paulberry): if targetInfo.readType is non-nullable, then the
      // assignment is dead code.
      // See https://github.com/dart-lang/sdk/issues/38678
      // TODO(paulberry): once flow analysis supports `??=`, integrate it here.
      // See https://github.com/dart-lang/sdk/issues/38680
      var rhsType =
          visitSubexpression(node.rightHandSide, targetInfo.writeType);
      return _typeSystem.leastUpperBound(
          _typeSystem.promoteToNonNull(targetInfo.readType as TypeImpl),
          rhsType);
    } else {
      var combiner = node.staticElement;
      DartType combinedType;
      if (combiner == null) {
        visitSubexpression(node.rightHandSide, _typeProvider.dynamicType);
        combinedType = _typeProvider.dynamicType;
      } else {
        if (_typeSystem.isNullable(targetInfo.readType)) {
          addProblem(node, const CompoundAssignmentReadNullable());
        }
        var combinerType = _computeMigratedType(combiner) as FunctionType;
        visitSubexpression(node.rightHandSide, combinerType.parameters[0].type);
        combinedType =
            _fixNumericTypes(combinerType.returnType, node.staticType);
      }
      if (_doesAssignmentNeedCheck(
          from: combinedType, to: targetInfo.writeType)) {
        addProblem(node, const CompoundAssignmentCombinedNullable());
        combinedType = _typeSystem.promoteToNonNull(combinedType as TypeImpl);
      }
      return combinedType;
    }
  }

  /// Recursively visits an assignment target, returning information about the
  /// target's read and write types.
  AssignmentTargetInfo visitAssignmentTarget(Expression node) {
    if (node is SimpleIdentifier) {
      var writeType = _computeMigratedType(node.staticElement);
      var auxiliaryElements = node.auxiliaryElements;
      var readType = auxiliaryElements == null
          ? writeType
          : _computeMigratedType(auxiliaryElements.staticElement);
      return AssignmentTargetInfo(readType, writeType);
    } else {
      throw UnimplementedError('TODO(paulberry)');
    }
  }

  @override
  DartType visitBinaryExpression(BinaryExpression node) {
    var leftOperand = node.leftOperand;
    var rightOperand = node.rightOperand;
    var operatorType = node.operator.type;
    var staticElement = node.staticElement;
    switch (operatorType) {
      case TokenType.BANG_EQ:
      case TokenType.EQ_EQ:
        visitSubexpression(leftOperand, _typeProvider.dynamicType);
        _flowAnalysis.equalityOp_rightBegin(leftOperand);
        visitSubexpression(rightOperand, _typeProvider.dynamicType);
        _flowAnalysis.equalityOp_end(node, rightOperand,
            notEqual: operatorType == TokenType.BANG_EQ);
        return _typeProvider.boolType;
      case TokenType.AMPERSAND_AMPERSAND:
      case TokenType.BAR_BAR:
        var isAnd = operatorType == TokenType.AMPERSAND_AMPERSAND;
        visitSubexpression(leftOperand, _typeProvider.boolType);
        _flowAnalysis.logicalBinaryOp_rightBegin(leftOperand, isAnd: isAnd);
        visitSubexpression(rightOperand, _typeProvider.boolType);
        _flowAnalysis.logicalBinaryOp_end(node, rightOperand, isAnd: isAnd);
        return _typeProvider.boolType;
      case TokenType.QUESTION_QUESTION:
        // If `a ?? b` is used in a non-nullable context, we don't want to
        // migrate it to `(a ?? b)!`.  We want to migrate it to `a ?? b!`.
        var leftType = visitSubexpression(node.leftOperand,
            _typeSystem.makeNullable(_contextType as TypeImpl));
        _flowAnalysis.ifNullExpression_rightBegin();
        var rightType = visitSubexpression(node.rightOperand, _contextType);
        _flowAnalysis.ifNullExpression_end();
        return _typeSystem.leastUpperBound(
            _typeSystem.promoteToNonNull(leftType as TypeImpl), rightType);
      default:
        var targetType =
            visitSubexpression(leftOperand, _typeProvider.objectType);
        DartType contextType;
        DartType returnType;
        if (staticElement == null) {
          contextType = _typeProvider.dynamicType;
          returnType = _typeProvider.dynamicType;
        } else {
          var methodType =
              _computeMigratedType(staticElement, targetType: targetType)
                  as FunctionType;
          contextType = methodType.parameters[0].type;
          returnType = methodType.returnType;
        }
        visitSubexpression(rightOperand, contextType);
        return _fixNumericTypes(returnType, node.staticType);
    }
  }

  @override
  DartType visitBlock(Block node) {
    for (var statement in node.statements) {
      statement.accept(this);
    }
    return null;
  }

  @override
  DartType visitConditionalExpression(ConditionalExpression node) {
    visitSubexpression(node.condition, _typeProvider.boolType);
    _flowAnalysis.conditional_thenBegin(node.condition);
    var thenType = visitSubexpression(node.thenExpression, _contextType);
    _flowAnalysis.conditional_elseBegin(node.thenExpression);
    var elseType = visitSubexpression(node.elseExpression, _contextType);
    _flowAnalysis.conditional_end(node, node.elseExpression);
    return _typeSystem.leastUpperBound(thenType, elseType);
  }

  @override
  DartType visitExpressionStatement(ExpressionStatement node) {
    visitSubexpression(node.expression, UnknownInferredType.instance);
    return null;
  }

  @override
  DartType visitIfStatement(IfStatement node) {
    visitSubexpression(node.condition, _typeProvider.boolType);
    _flowAnalysis.ifStatement_thenBegin(node.condition);
    node.thenStatement.accept(this);
    bool hasElse = node.elseStatement != null;
    if (hasElse) {
      _flowAnalysis.ifStatement_elseBegin();
      node.elseStatement.accept(this);
    }
    _flowAnalysis.ifStatement_end(hasElse);
    return null;
  }

  @override
  DartType visitListLiteral(ListLiteral node) {
    DartType contextType;
    var typeArguments = node.typeArguments;
    if (typeArguments != null) {
      var typeArgumentTypes = _visitTypeArgumentList(typeArguments);
      if (typeArgumentTypes.isNotEmpty) {
        contextType = typeArgumentTypes[0];
      } else {
        contextType = UnknownInferredType.instance;
      }
    } else {
      throw UnimplementedError(
          'TODO(paulberry): extract from surrounding context');
    }
    for (var listElement in node.elements) {
      if (listElement is Expression) {
        visitSubexpression(listElement, contextType);
      } else {
        throw UnimplementedError(
            'TODO(paulberry): handle spread and control flow');
      }
    }
    if (typeArguments != null) {
      return _typeProvider.listType2(contextType);
    } else {
      throw UnimplementedError(
          'TODO(paulberry): infer list type based on contents');
    }
  }

  @override
  DartType visitLiteral(Literal node) {
    if (node is AdjacentStrings) {
      // TODO(paulberry): need to visit interpolations
      throw UnimplementedError('TODO(paulberry)');
    }
    if (node is TypedLiteral) {
      throw UnimplementedError('TODO(paulberry)');
    }
    return (node.staticType as TypeImpl)
        .withNullability(NullabilitySuffix.none);
  }

  @override
  DartType visitNode(AstNode node) {
    // Every node type needs its own visit method.
    throw UnimplementedError('No visit method for ${node.runtimeType}');
  }

  @override
  DartType visitNullLiteral(NullLiteral node) {
    _flowAnalysis.nullLiteral(node);
    return _typeProvider.nullType;
  }

  @override
  DartType visitParenthesizedExpression(ParenthesizedExpression node) {
    var result = node.expression.accept(this);
    _flowAnalysis.parenthesizedExpression(node, node.expression);
    return result;
  }

  @override
  DartType visitPostfixExpression(PostfixExpression node) {
    if (node.operator.type == TokenType.BANG) {
      throw UnimplementedError(
          'TODO(paulberry): re-migration of already migrated code not '
          'supported yet');
    } else {
      var targetInfo = visitAssignmentTarget(node.operand);
      _handleIncrementOrDecrement(node.staticElement, targetInfo, node);
      return targetInfo.readType;
    }
  }

  @override
  DartType visitPrefixExpression(PrefixExpression node) {
    var operand = node.operand;
    switch (node.operator.type) {
      case TokenType.BANG:
        visitSubexpression(operand, _typeProvider.boolType);
        _flowAnalysis.logicalNot_end(node, operand);
        return _typeProvider.boolType;
      case TokenType.MINUS:
      case TokenType.TILDE:
        var targetType = visitSubexpression(operand, _typeProvider.objectType);
        var staticElement = node.staticElement;
        if (staticElement == null) {
          return _typeProvider.dynamicType;
        } else {
          var methodType =
              _computeMigratedType(staticElement, targetType: targetType)
                  as FunctionType;
          return methodType.returnType;
        }
        break;
      case TokenType.PLUS_PLUS:
      case TokenType.MINUS_MINUS:
        return _handleIncrementOrDecrement(
            node.staticElement, visitAssignmentTarget(operand), node);
      default:
        throw StateError('Unexpected prefix operator: ${node.operator}');
    }
  }

  @override
  DartType visitSimpleIdentifier(SimpleIdentifier node) {
    assert(!node.inSetterContext(),
        'Should use visitAssignmentTarget in setter contexts');
    var element = node.staticElement;
    if (element == null) return _typeProvider.dynamicType;
    if (element is PromotableElement) {
      var promotedType = _flowAnalysis.variableRead(node, element);
      if (promotedType != null) return promotedType;
    }
    return _computeMigratedType(element);
  }

  /// Recursively visits a subexpression, providing a context type.
  DartType visitSubexpression(Expression subexpression, DartType contextType) {
    var oldContextType = _contextType;
    try {
      _contextType = contextType;
      var type = subexpression.accept(this);
      if (_doesAssignmentNeedCheck(from: type, to: contextType)) {
        addNullCheck(subexpression);
        _flowAnalysis.nonNullAssert_end(subexpression);
        return _typeSystem.promoteToNonNull(type as TypeImpl);
      } else {
        return type;
      }
    } finally {
      _contextType = oldContextType;
    }
  }

  @override
  DartType visitThrowExpression(ThrowExpression node) {
    visitSubexpression(node.expression, _typeProvider.objectType);
    _flowAnalysis.handleExit();
    return _typeProvider.neverType;
  }

  @override
  DartType visitTypeName(TypeName node) {
    var decoratedType = _variables.decoratedTypeAnnotation(source, node);
    assert(decoratedType != null);
    List<DartType> arguments = [];
    if (node.typeArguments != null) {
      for (var argument in node.typeArguments.arguments) {
        arguments.add(argument.accept(this));
      }
    }
    if (decoratedType.type.isDynamic || decoratedType.type.isVoid) {
      // Already nullable.  Nothing to do.
      return decoratedType.type;
    } else {
      var element = decoratedType.type.element as ClassElement;
      bool isNullable = decoratedType.node.isNullable;
      if (isNullable) {
        addNullable(node);
      }
      return InterfaceTypeImpl.explicit(element, arguments,
          nullabilitySuffix:
              isNullable ? NullabilitySuffix.question : NullabilitySuffix.none);
    }
  }

  @override
  DartType visitVariableDeclarationList(VariableDeclarationList node) {
    node.metadata.accept(this);
    DartType contextType;
    var typeAnnotation = node.type;
    if (typeAnnotation != null) {
      contextType = typeAnnotation.accept(this);
      assert(contextType != null);
    } else {
      contextType = UnknownInferredType.instance;
    }
    for (var variable in node.variables) {
      if (variable.initializer != null) {
        visitSubexpression(variable.initializer, contextType);
      }
    }
    return null;
  }

  @override
  DartType visitVariableDeclarationStatement(
      VariableDeclarationStatement node) {
    node.variables.accept(this);
    return null;
  }

  /// Computes the type that [element] will have after migration.
  ///
  /// If [targetType] is present, and [element] is a class member, it is the
  /// type of the class within which [element] is being accessed; this is used
  /// to perform the correct substitutions.
  DartType _computeMigratedType(Element element, {DartType targetType}) {
    Element baseElement;
    if (element is Member) {
      baseElement = element.baseElement;
    } else {
      baseElement = element;
    }
    DartType type;
    if (baseElement is ClassElement || baseElement is TypeParameterElement) {
      return _typeProvider.typeType;
    } else if (baseElement is PropertyAccessorElement) {
      if (baseElement.isSynthetic) {
        type = _variables
            .decoratedElementType(baseElement.variable)
            .toFinalType(_typeProvider);
      } else {
        var functionType = _variables.decoratedElementType(baseElement);
        var decoratedType = baseElement.isGetter
            ? functionType.returnType
            : functionType.positionalParameters[0];
        type = decoratedType.toFinalType(_typeProvider);
      }
    } else {
      type = _variables
          .decoratedElementType(baseElement)
          .toFinalType(_typeProvider);
    }
    if (targetType is InterfaceType && targetType.typeArguments.isNotEmpty) {
      var superclass = baseElement.enclosingElement as ClassElement;
      var class_ = targetType.element;
      if (class_ != superclass) {
        var supertype = _decoratedClassHierarchy
            .getDecoratedSupertype(class_, superclass)
            .toFinalType(_typeProvider) as InterfaceType;
        type = Substitution.fromInterfaceType(supertype).substituteType(type);
      }
      return substitute(type, {
        for (int i = 0; i < targetType.typeArguments.length; i++)
          class_.typeParameters[i]: targetType.typeArguments[i]
      });
    } else {
      return type;
    }
  }

  /// Determines whether a null check is needed when assigning a value of type
  /// [from] to a context of type [to].
  bool _doesAssignmentNeedCheck(
      {@required DartType from, @required DartType to}) {
    return !from.isDynamic &&
        _typeSystem.isNullable(from) &&
        !_typeSystem.isNullable(to);
  }

  /// Determines whether a `num` type originating from a call to a
  /// user-definable operator needs to be changed to `int`.  [type] is the type
  /// determined by naive operator lookup; [originalType] is the type that was
  /// determined by the analyzer's full resolution algorithm when analyzing the
  /// pre-migrated code.
  DartType _fixNumericTypes(DartType type, DartType originalType) {
    if (type.isDartCoreNum && originalType.isDartCoreInt) {
      return (originalType as TypeImpl)
          .withNullability((type as TypeImpl).nullabilitySuffix);
    } else {
      return type;
    }
  }

  DartType _handleIncrementOrDecrement(MethodElement combiner,
      AssignmentTargetInfo targetInfo, Expression node) {
    DartType combinedType;
    if (combiner == null) {
      combinedType = _typeProvider.dynamicType;
    } else {
      if (_typeSystem.isNullable(targetInfo.readType)) {
        addProblem(node, const CompoundAssignmentReadNullable());
      }
      var combinerType = _computeMigratedType(combiner) as FunctionType;
      combinedType = _fixNumericTypes(combinerType.returnType, node.staticType);
    }
    if (_doesAssignmentNeedCheck(
        from: combinedType, to: targetInfo.writeType)) {
      addProblem(node, const CompoundAssignmentCombinedNullable());
      combinedType = _typeSystem.promoteToNonNull(combinedType as TypeImpl);
    }
    return combinedType;
  }

  /// Visits all the type arguments in a [TypeArgumentList] and returns the
  /// types they ger migrated to.
  List<DartType> _visitTypeArgumentList(TypeArgumentList arguments) =>
      [for (var argument in arguments.arguments) argument.accept(this)];
}

/// Common supertype for problems reported by [FixBuilder.addProblem].
abstract class Problem {}
