// Copyright (c) 2017, 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 'dart:io';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/inferrer/typemasks/masks.dart';
import 'package:compiler/src/types/types.dart';
import 'package:compiler/src/js_model/locals.dart';
import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/inferrer/builder_kernel.dart';
import 'package:kernel/ast.dart' as ir;
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';

const List<String> skipForStrong = const <String>[
  // TODO(johnniwinther): Remove this when issue 31767 is fixed.
  'mixin_constructor_default_parameter_values.dart',
  // These contain compile-time errors:
  'erroneous_super_get.dart',
  'erroneous_super_invoke.dart',
  'erroneous_super_set.dart',
  'switch3.dart',
  'switch4.dart',
  // TODO(johnniwinther): Make a strong mode clean version of this?
  'call_in_loop.dart',
];

main(List<String> args) {
  runTests(args);
}

runTests(List<String> args, [int shardIndex]) {
  asyncTest(() async {
    Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
    await checkTests(dataDir, const TypeMaskDataComputer(),
        libDirectory: new Directory.fromUri(Platform.script.resolve('libs')),
        forUserLibrariesOnly: true,
        args: args,
        options: [stopAfterTypeInference],
        skipForStrong: skipForStrong,
        shardIndex: shardIndex ?? 0,
        shards: shardIndex != null ? 2 : 1, onTest: (Uri uri) {
      useStaticResultTypes = uri.path.endsWith('/use_static_types.dart');
    });
  });
}

class TypeMaskDataComputer extends DataComputer {
  const TypeMaskDataComputer();

  /// Compute type inference data for [member] from kernel based inference.
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeMemberData(
      Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
      {bool verbose: false}) {
    KernelBackendStrategy backendStrategy = compiler.backendStrategy;
    KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
    GlobalLocalsMap localsMap = backendStrategy.globalLocalsMapForTesting;
    MemberDefinition definition = elementMap.getMemberDefinition(member);
    new TypeMaskIrComputer(
            compiler.reporter,
            actualMap,
            elementMap,
            member,
            localsMap.getLocalsMap(member),
            compiler.globalInference.resultsForTesting,
            backendStrategy.closureDataLookup)
        .run(definition.node);
  }
}

/// IR visitor for computing inference data for a member.
class TypeMaskIrComputer extends IrDataExtractor {
  final GlobalTypeInferenceResults results;
  GlobalTypeInferenceElementResult result;
  final KernelToElementMapForBuilding _elementMap;
  final KernelToLocalsMap _localsMap;
  final ClosureDataLookup _closureDataLookup;

  TypeMaskIrComputer(
      DiagnosticReporter reporter,
      Map<Id, ActualData> actualMap,
      this._elementMap,
      MemberEntity member,
      this._localsMap,
      this.results,
      this._closureDataLookup)
      : result = results.resultOfMember(member),
        super(reporter, actualMap);

  String getMemberValue(MemberEntity member) {
    GlobalTypeInferenceMemberResult memberResult =
        results.resultOfMember(member);
    if (member.isFunction || member.isConstructor || member.isGetter) {
      return getTypeMaskValue(memberResult.returnType);
    } else if (member.isField) {
      return getTypeMaskValue(memberResult.type);
    } else {
      assert(member.isSetter);
      // Setters have no type mask of interest; the return type is always void
      // and shouldn't be used, and their type is a closure which cannot be
      // created.
      return null;
    }
  }

  String getParameterValue(Local parameter) {
    GlobalTypeInferenceParameterResult elementResult =
        results.resultOfParameter(parameter);
    return getTypeMaskValue(elementResult.type);
  }

  String getTypeMaskValue(TypeMask typeMask) {
    return typeMask != null ? '$typeMask' : null;
  }

  @override
  visitFunctionExpression(ir.FunctionExpression node) {
    GlobalTypeInferenceElementResult oldResult = result;
    ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
    result = results.resultOfMember(info.callMethod);
    super.visitFunctionExpression(node);
    result = oldResult;
  }

  @override
  visitFunctionDeclaration(ir.FunctionDeclaration node) {
    GlobalTypeInferenceElementResult oldResult = result;
    ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
    result = results.resultOfMember(info.callMethod);
    super.visitFunctionDeclaration(node);
    result = oldResult;
  }

  @override
  String computeMemberValue(Id id, ir.Member node) {
    return getMemberValue(_elementMap.getMember(node));
  }

  @override
  String computeNodeValue(Id id, ir.TreeNode node) {
    if (node is ir.VariableDeclaration && node.parent is ir.FunctionNode) {
      Local parameter = _localsMap.getLocalVariable(node);
      return getParameterValue(parameter);
    } else if (node is ir.FunctionExpression ||
        node is ir.FunctionDeclaration) {
      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
      return getMemberValue(info.callMethod);
    } else if (node is ir.MethodInvocation) {
      return getTypeMaskValue(result.typeOfSend(node));
    } else if (node is ir.PropertyGet) {
      return getTypeMaskValue(result.typeOfGetter(node));
    } else if (node is ir.PropertySet) {
      return getTypeMaskValue(result.typeOfSend(node));
    } else if (node is ir.ForInStatement) {
      if (id.kind == IdKind.iterator) {
        return getTypeMaskValue(result.typeOfIterator(node));
      } else if (id.kind == IdKind.current) {
        return getTypeMaskValue(result.typeOfIteratorCurrent(node));
      } else if (id.kind == IdKind.moveNext) {
        return getTypeMaskValue(result.typeOfIteratorMoveNext(node));
      }
    }
    return null;
  }
}
