// Copyright (c) 2018, 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:front_end/src/api_unstable/dart2js.dart'
    show operatorFromString;

import 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;

import '../common.dart';
import 'constants.dart';
import 'impact_data.dart';
import 'runtime_type_analysis.dart';
import 'scope.dart';
import 'static_type.dart';
import 'static_type_cache.dart';
import 'util.dart';

/// Interface for collecting world impact data.
///
/// This is used both for direct world impact computation through the
/// [KernelImpactBuilder] and for serialization through the [ImpactBuilder]
/// and [ImpactLoader].
abstract class ImpactRegistry {
  void registerIntLiteral(int value);

  void registerDoubleLiteral(double value);

  void registerBoolLiteral(bool value);

  void registerStringLiteral(String value);

  void registerSymbolLiteral(String value);

  void registerNullLiteral();

  void registerListLiteral(ir.DartType elementType,
      {bool isConst, bool isEmpty});

  void registerSetLiteral(ir.DartType elementType,
      {bool isConst, bool isEmpty});

  void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
      {bool isConst, bool isEmpty});

  void registerStaticTearOff(
      ir.Procedure procedure, ir.LibraryDependency import);

  void registerStaticGet(ir.Member member, ir.LibraryDependency import);

  void registerStaticSet(ir.Member member, ir.LibraryDependency import);

  void registerAssert({bool withMessage});

  void registerGenericInstantiation(
      ir.FunctionType expressionType, List<ir.DartType> typeArguments);

  void registerSyncStar(ir.DartType elementType);

  void registerAsync(ir.DartType elementType);

  void registerAsyncStar(ir.DartType elementType);

  void registerStringConcatenation();

  void registerLocalFunction(ir.TreeNode node);

  void registerLocalWithoutInitializer();

  void registerIsCheck(ir.DartType type);

  void registerImplicitCast(ir.DartType type);

  void registerAsCast(ir.DartType type);

  void registerThrow();

  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
      ClassRelation iteratorClassRelation);

  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
      ClassRelation iteratorClassRelation);

  void registerCatch();

  void registerStackTrace();

  void registerCatchType(ir.DartType type);

  void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import);

  void registerFieldInitialization(ir.Field node);

  void registerFieldConstantInitialization(
      ir.Field node, ConstantReference constant);

  void registerLoadLibrary();

  void registerRedirectingInitializer(
      ir.Constructor constructor,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerParameterCheck(ir.DartType type);

  void registerLazyField();

  void registerNew(
      ir.Member constructor,
      ir.InterfaceType type,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments,
      ir.LibraryDependency import,
      {bool isConst});

  void registerConstInstantiation(ir.Class cls, List<ir.DartType> typeArguments,
      ir.LibraryDependency import);

  void registerStaticInvocation(
      ir.Procedure target,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments,
      ir.LibraryDependency import);

  void registerLocalFunctionInvocation(
      ir.FunctionDeclaration localFunction,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerDynamicInvocation(
      ir.DartType receiverType,
      ClassRelation relation,
      ir.Name name,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerInstanceInvocation(
      ir.DartType receiverType,
      ClassRelation relation,
      ir.Member target,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerFunctionInvocation(
      ir.DartType receiverType,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerDynamicGet(
      ir.DartType receiverType, ClassRelation relation, ir.Name name);

  void registerInstanceGet(
      ir.DartType receiverType, ClassRelation relation, ir.Member target);

  void registerDynamicSet(
      ir.DartType receiverType, ClassRelation relation, ir.Name name);

  void registerInstanceSet(
      ir.DartType receiverType, ClassRelation relation, ir.Member target);

  void registerSuperInvocation(ir.Member target, int positionalArguments,
      List<String> namedArguments, List<ir.DartType> typeArguments);

  void registerSuperGet(ir.Member target);

  void registerSuperSet(ir.Member target);

  void registerSuperInitializer(
      ir.Constructor source,
      ir.Constructor target,
      int positionalArguments,
      List<String> namedArguments,
      List<ir.DartType> typeArguments);

  void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
      ir.DartType receiverType, ir.DartType argumentType);

  // TODO(johnniwinther): Remove these when CFE provides constants.
  void registerConstructorNode(ir.Constructor node);
  void registerFieldNode(ir.Field node);
  void registerProcedureNode(ir.Procedure node);
  void registerStaticInvocationNode(ir.StaticInvocation node);
  void registerSwitchStatementNode(ir.SwitchStatement node);
  void registerConstConstructorInvocationNode(ir.ConstructorInvocation node);
}

abstract class ImpactBuilderBase extends StaticTypeVisitor
    implements ImpactRegistry {
  @override
  final VariableScopeModel variableScopeModel;

  @override
  final ir.StaticTypeContext staticTypeContext;

  ImpactBuilderBase(this.staticTypeContext, StaticTypeCacheImpl staticTypeCache,
      ir.ClassHierarchy classHierarchy, this.variableScopeModel)
      : super(
            staticTypeContext.typeEnvironment, classHierarchy, staticTypeCache);

  @override
  void handleIntLiteral(ir.IntLiteral node) {
    registerIntLiteral(node.value);
  }

  @override
  void handleDoubleLiteral(ir.DoubleLiteral node) {
    registerDoubleLiteral(node.value);
  }

  @override
  void handleBoolLiteral(ir.BoolLiteral node) {
    registerBoolLiteral(node.value);
  }

  @override
  void handleStringLiteral(ir.StringLiteral node) {
    registerStringLiteral(node.value);
  }

  @override
  void handleSymbolLiteral(ir.SymbolLiteral node) {
    registerSymbolLiteral(node.value);
  }

  @override
  void handleNullLiteral(ir.NullLiteral node) {
    registerNullLiteral();
  }

  @override
  void handleListLiteral(ir.ListLiteral node) {
    registerListLiteral(node.typeArgument,
        isConst: node.isConst, isEmpty: node.expressions.isEmpty);
  }

  @override
  void handleSetLiteral(ir.SetLiteral node) {
    registerSetLiteral(node.typeArgument,
        isConst: node.isConst, isEmpty: node.expressions.isEmpty);
  }

  @override
  void handleMapLiteral(ir.MapLiteral node) {
    registerMapLiteral(node.keyType, node.valueType,
        isConst: node.isConst, isEmpty: node.entries.isEmpty);
  }

  @override
  void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
    ir.Member target = node.target;
    if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) {
      registerStaticTearOff(target, getDeferredImport(node));
    } else {
      registerStaticGet(target, getDeferredImport(node));
    }
  }

  @override
  void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
    registerStaticSet(node.target, getDeferredImport(node));
  }

  @override
  void handleAssertStatement(ir.AssertStatement node) {
    registerAssert(withMessage: node.message != null);
  }

  @override
  void handleInstantiation(ir.Instantiation node,
      ir.FunctionType expressionType, ir.DartType resultType) {
    registerGenericInstantiation(expressionType, node.typeArguments);
  }

  void handleAsyncMarker(ir.FunctionNode function) {
    ir.AsyncMarker asyncMarker = function.asyncMarker;
    ir.DartType returnType = function.returnType;

    switch (asyncMarker) {
      case ir.AsyncMarker.Sync:
        break;
      case ir.AsyncMarker.SyncStar:
        ir.DartType elementType = const ir.DynamicType();
        if (returnType is ir.InterfaceType) {
          if (returnType.classNode == typeEnvironment.coreTypes.iterableClass) {
            elementType = returnType.typeArguments.first;
          }
        }
        registerSyncStar(elementType);
        break;

      case ir.AsyncMarker.Async:
        ir.DartType elementType = const ir.DynamicType();
        if (returnType is ir.InterfaceType &&
            returnType.classNode == typeEnvironment.coreTypes.futureClass) {
          elementType = returnType.typeArguments.first;
        } else if (returnType is ir.FutureOrType) {
          elementType = returnType.typeArgument;
        }
        registerAsync(elementType);
        break;

      case ir.AsyncMarker.AsyncStar:
        ir.DartType elementType = const ir.DynamicType();
        if (returnType is ir.InterfaceType) {
          if (returnType.classNode == typeEnvironment.coreTypes.streamClass) {
            elementType = returnType.typeArguments.first;
          }
        }
        registerAsyncStar(elementType);
        break;

      case ir.AsyncMarker.SyncYielding:
        failedAt(CURRENT_ELEMENT_SPANNABLE,
            "Unexpected async marker: ${asyncMarker}");
    }
  }

  @override
  void handleStringConcatenation(ir.StringConcatenation node) {
    registerStringConcatenation();
  }

  @override
  Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
    registerLocalFunction(node);
    handleAsyncMarker(node.function);
  }

  @override
  void handleFunctionExpression(ir.FunctionExpression node) {
    registerLocalFunction(node);
    handleAsyncMarker(node.function);
  }

  @override
  void handleVariableDeclaration(ir.VariableDeclaration node) {
    if (node.initializer == null) {
      registerLocalWithoutInitializer();
    }
  }

  @override
  void handleIsExpression(ir.IsExpression node) {
    registerIsCheck(node.type);
  }

  @override
  void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
    if (typeEnvironment.isSubtypeOf(
        operandType, node.type, ir.SubtypeCheckMode.ignoringNullabilities)) {
      // Skip unneeded casts.
      return;
    }
    if (node.isTypeError) {
      registerImplicitCast(node.type);
    } else {
      registerAsCast(node.type);
    }
  }

  @override
  void handleThrow(ir.Throw node) {
    registerThrow();
  }

  @override
  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType,
      ir.DartType iteratorType) {
    if (node.isAsync) {
      registerAsyncForIn(iterableType, iteratorType,
          computeClassRelationFromType(iteratorType));
    } else {
      registerSyncForIn(iterableType, iteratorType,
          computeClassRelationFromType(iteratorType));
    }
  }

  @override
  void handleCatch(ir.Catch node) {
    registerCatch();
    if (node.stackTrace != null) {
      registerStackTrace();
    }
    if (node.guard is! ir.DynamicType) {
      registerCatchType(node.guard);
    }
  }

  @override
  void handleTypeLiteral(ir.TypeLiteral node) {
    registerTypeLiteral(node.type, getDeferredImport(node));
  }

  @override
  void handleFieldInitializer(ir.FieldInitializer node) {
    registerFieldInitialization(node.field);
  }

  @override
  void handleLoadLibrary(ir.LoadLibrary node) {
    registerLoadLibrary();
  }

  @override
  void handleRedirectingInitializer(
      ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
    registerRedirectingInitializer(
        node.target,
        node.arguments.positional.length,
        _getNamedArguments(node.arguments),
        node.arguments.types);
  }

  @override
  void handleParameter(ir.VariableDeclaration parameter) {
    registerParameterCheck(parameter.type);
  }

  @override
  void handleSignature(ir.FunctionNode node) {
    for (ir.TypeParameter parameter in node.typeParameters) {
      registerParameterCheck(parameter.bound);
    }
  }

  @override
  void handleConstructor(ir.Constructor node) {
    registerConstructorNode(node);
  }

  @override
  void handleField(ir.Field field) {
    registerParameterCheck(field.type);
    if (field.initializer != null) {
      if (!field.isInstanceMember &&
          !field.isConst &&
          field.initializer is! ir.NullLiteral) {
        registerLazyField();
      }
    } else {
      registerNullLiteral();
    }
    registerFieldNode(field);
  }

  @override
  void handleProcedure(ir.Procedure procedure) {
    handleAsyncMarker(procedure.function);
    registerProcedureNode(procedure);
  }

  @override
  void handleConstructorInvocation(ir.ConstructorInvocation node,
      ArgumentTypes argumentTypes, ir.DartType resultType) {
    registerNew(
        node.target,
        node.constructedType,
        node.arguments.positional.length,
        _getNamedArguments(node.arguments),
        node.arguments.types,
        getDeferredImport(node),
        isConst: node.isConst);
    if (node.isConst) {
      registerConstConstructorInvocationNode(node);
    }
  }

  @override
  void handleStaticInvocation(ir.StaticInvocation node,
      ArgumentTypes argumentTypes, ir.DartType returnType) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    if (node.target.kind == ir.ProcedureKind.Factory) {
      // TODO(johnniwinther): We should not mark the type as instantiated but
      // rather follow the type arguments directly.
      //
      // Consider this:
      //
      //    abstract class A<T> {
      //      factory A.regular() => new B<T>();
      //      factory A.redirect() = B<T>;
      //    }
      //
      //    class B<T> implements A<T> {}
      //
      //    main() {
      //      print(new A<int>.regular() is B<int>);
      //      print(new A<String>.redirect() is B<String>);
      //    }
      //
      // To track that B is actually instantiated as B<int> and B<String> we
      // need to follow the type arguments passed to A.regular and A.redirect
      // to B. Currently, we only do this soundly if we register A<int> and
      // A<String> as instantiated. We should instead register that A.T is
      // instantiated as int and String.
      registerNew(
          node.target,
          new ir.InterfaceType(node.target.enclosingClass,
              node.target.enclosingLibrary.nonNullable, typeArguments),
          positionArguments,
          namedArguments,
          node.arguments.types,
          getDeferredImport(node),
          isConst: node.isConst);
    } else {
      registerStaticInvocation(node.target, positionArguments, namedArguments,
          typeArguments, getDeferredImport(node));
    }
    registerStaticInvocationNode(node);
  }

  @override
  void handleMethodInvocation(
      ir.MethodInvocation node,
      ir.DartType receiverType,
      ArgumentTypes argumentTypes,
      ir.DartType returnType) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    ir.Expression receiver = node.receiver;
    if (receiver is ir.VariableGet &&
        receiver.variable.isFinal &&
        receiver.variable.parent is ir.FunctionDeclaration) {
      registerLocalFunctionInvocation(receiver.variable.parent,
          positionArguments, namedArguments, typeArguments);
    } else {
      ClassRelation relation = computeClassRelationFromType(receiverType);

      ir.Member interfaceTarget = node.interfaceTarget;
      if (interfaceTarget == null) {
        registerDynamicInvocation(receiverType, relation, node.name,
            positionArguments, namedArguments, typeArguments);
        // TODO(johnniwinther): Avoid treating a known function call as a
        // dynamic call when CFE provides a way to distinguish the two.
        if (operatorFromString(node.name.text) == null &&
            receiverType is ir.DynamicType) {
          // We might implicitly call a getter that returns a function.
          registerFunctionInvocation(const ir.DynamicType(), positionArguments,
              namedArguments, typeArguments);
        }
      } else {
        if (interfaceTarget is ir.Field ||
            interfaceTarget is ir.Procedure &&
                interfaceTarget.kind == ir.ProcedureKind.Getter) {
          registerInstanceInvocation(receiverType, relation, interfaceTarget,
              positionArguments, namedArguments, typeArguments);
          registerFunctionInvocation(interfaceTarget.getterType,
              positionArguments, namedArguments, typeArguments);
        } else {
          registerInstanceInvocation(receiverType, relation, interfaceTarget,
              positionArguments, namedArguments, typeArguments);
        }
      }
    }
  }

  @override
  void handlePropertyGet(
      ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
    ClassRelation relation = computeClassRelationFromType(receiverType);
    if (node.interfaceTarget != null) {
      registerInstanceGet(receiverType, relation, node.interfaceTarget);
    } else {
      registerDynamicGet(receiverType, relation, node.name);
    }
  }

  @override
  void handlePropertySet(
      ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
    ClassRelation relation = computeClassRelationFromType(receiverType);
    if (node.interfaceTarget != null) {
      registerInstanceSet(receiverType, relation, node.interfaceTarget);
    } else {
      registerDynamicSet(receiverType, relation, node.name);
    }
  }

  @override
  void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
      ArgumentTypes argumentTypes, ir.DartType returnType) {
    registerSuperInvocation(
        getEffectiveSuperTarget(node.interfaceTarget),
        node.arguments.positional.length,
        _getNamedArguments(node.arguments),
        node.arguments.types);
  }

  @override
  void handleSuperPropertyGet(
      ir.SuperPropertyGet node, ir.DartType resultType) {
    registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget));
  }

  @override
  void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
    registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget));
  }

  @override
  void handleSuperInitializer(
      ir.SuperInitializer node, ArgumentTypes argumentTypes) {
    registerSuperInitializer(
        node.parent,
        node.target,
        node.arguments.positional.length,
        _getNamedArguments(node.arguments),
        node.arguments.types);
  }

  @override
  Null visitSwitchStatement(ir.SwitchStatement node) {
    registerSwitchStatementNode(node);
    return super.visitSwitchStatement(node);
  }

  @override
  void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
      ir.DartType receiverType, ir.DartType argumentType) {
    registerRuntimeTypeUse(node, kind, receiverType, argumentType);
  }

  @override
  void handleConstantExpression(ir.ConstantExpression node) {
    ir.LibraryDependency import = getDeferredImport(node);
    new ConstantImpactVisitor(this, import, node).visitConstant(node.constant);
  }
}

/// Visitor that builds an [ImpactData] object for the world impact.
class ImpactBuilder extends ImpactBuilderBase with ImpactRegistryMixin {
  @override
  final bool useAsserts;

  @override
  final inferEffectivelyFinalVariableTypes;

  ImpactBuilder(
      ir.StaticTypeContext staticTypeContext,
      StaticTypeCacheImpl staticTypeCache,
      ir.ClassHierarchy classHierarchy,
      VariableScopeModel variableScopeModel,
      {this.useAsserts: false,
      this.inferEffectivelyFinalVariableTypes: true})
      : super(staticTypeContext, staticTypeCache, classHierarchy,
            variableScopeModel);

  ImpactBuilderData computeImpact(ir.Member node) {
    if (retainDataForTesting) {
      typeMapsForTesting = {};
    }
    node.accept(this);
    return new ImpactBuilderData(
        impactData, typeMapsForTesting, getStaticTypeCache());
  }
}

/// Return the named arguments names as a list of strings.
List<String> _getNamedArguments(ir.Arguments arguments) =>
    arguments.named.map((n) => n.name).toList();

class ImpactBuilderData {
  final ImpactData impactData;
  final Map<ir.Expression, TypeMap> typeMapsForTesting;
  final StaticTypeCache cachedStaticTypes;

  ImpactBuilderData(
      this.impactData, this.typeMapsForTesting, this.cachedStaticTypes);
}

class ConstantImpactVisitor extends ir.VisitOnceConstantVisitor {
  final ImpactRegistry registry;
  final ir.LibraryDependency import;
  final ir.ConstantExpression expression;

  ConstantImpactVisitor(this.registry, this.import, this.expression);

  @override
  void defaultConstant(ir.Constant node) {
    throw new UnsupportedError(
        "Unexpected constant ${node} (${node.runtimeType}).");
  }

  @override
  void visitUnevaluatedConstant(ir.UnevaluatedConstant node) {
    // Do nothing. This occurs when the constant couldn't be evaluated because
    // of a compile-time error.
  }

  @override
  void visitTypeLiteralConstant(ir.TypeLiteralConstant node) {
    registry.registerTypeLiteral(node.type, import);
  }

  @override
  void visitTearOffConstant(ir.TearOffConstant node) {
    registry.registerStaticTearOff(node.procedure, import);
  }

  @override
  void visitPartialInstantiationConstant(ir.PartialInstantiationConstant node) {
    registry.registerGenericInstantiation(
        node.tearOffConstant.procedure.function.computeFunctionType(
            node.tearOffConstant.procedure.enclosingLibrary.nonNullable),
        node.types);
    visitConstant(node.tearOffConstant);
  }

  @override
  void visitInstanceConstant(ir.InstanceConstant node) {
    registry.registerConstInstantiation(
        node.classNode, node.typeArguments, import);
    node.fieldValues.forEach((ir.Reference reference, ir.Constant value) {
      ir.Field field = reference.asField;
      registry.registerFieldConstantInitialization(
          field, new ConstantReference(expression, value));
      visitConstant(value);
    });
  }

  @override
  void visitSetConstant(ir.SetConstant node) {
    registry.registerSetLiteral(node.typeArgument,
        isConst: true, isEmpty: node.entries.isEmpty);
    for (ir.Constant element in node.entries) {
      visitConstant(element);
    }
  }

  @override
  void visitListConstant(ir.ListConstant node) {
    registry.registerListLiteral(node.typeArgument,
        isConst: true, isEmpty: node.entries.isEmpty);
    for (ir.Constant element in node.entries) {
      visitConstant(element);
    }
  }

  @override
  void visitMapConstant(ir.MapConstant node) {
    registry.registerMapLiteral(node.keyType, node.valueType,
        isConst: true, isEmpty: node.entries.isEmpty);
    for (ir.ConstantMapEntry entry in node.entries) {
      visitConstant(entry.key);
      visitConstant(entry.value);
    }
  }

  @override
  void visitSymbolConstant(ir.SymbolConstant node) {
    // TODO(johnniwinther): Handle the library reference.
    registry.registerSymbolLiteral(node.name);
  }

  @override
  void visitStringConstant(ir.StringConstant node) {
    registry.registerStringLiteral(node.value);
  }

  @override
  void visitDoubleConstant(ir.DoubleConstant node) {
    registry.registerDoubleLiteral(node.value);
  }

  @override
  void visitIntConstant(ir.IntConstant node) {
    registry.registerIntLiteral(node.value);
  }

  @override
  void visitBoolConstant(ir.BoolConstant node) {
    registry.registerBoolLiteral(node.value);
  }

  @override
  void visitNullConstant(ir.NullConstant node) {
    registry.registerNullLiteral();
  }
}
