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

// @dart = 2.9

import 'dart:io' show Directory, Platform;
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/type_environment.dart';

Future<void> main(List<String> args) async {
  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
  await runTests<String>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(const StaticTypeDataComputer(),
          [cfeNoNonNullableConfig, cfeNonNullableConfig]),
      skipMap: {
        defaultCfeConfig.marker: [
          // NNBD-only tests.
          'constant_from_opt_in',
          'constant_from_opt_out',
          'from_opt_in',
          'from_opt_out',
          'if_null.dart',
          'null_check.dart',
          'never.dart',
        ]
      });
}

class StaticTypeDataComputer extends DataComputer<String> {
  const StaticTypeDataComputer();

  /// Function that computes a data mapping for [library].
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeLibraryData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Library library,
      Map<Id, ActualData<String>> actualMap,
      {bool verbose}) {
    new StaticTypeDataExtractor(compilerResult, actualMap)
        .computeForLibrary(library);
  }

  @override
  void computeMemberData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Member member,
      Map<Id, ActualData<String>> actualMap,
      {bool verbose}) {
    member.accept(new StaticTypeDataExtractor(compilerResult, actualMap));
  }

  @override
  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
}

class StaticTypeDataExtractor extends CfeDataExtractor<String> {
  final TypeEnvironment _environment;
  StaticTypeContext _staticTypeContext;

  StaticTypeDataExtractor(InternalCompilerResult compilerResult,
      Map<Id, ActualData<String>> actualMap)
      : _environment = new TypeEnvironment(
            compilerResult.coreTypes, compilerResult.classHierarchy),
        super(compilerResult, actualMap);

  @override
  void visitField(Field node) {
    _staticTypeContext = new StaticTypeContext(node, _environment);
    super.visitField(node);
    _staticTypeContext = null;
  }

  @override
  void visitConstructor(Constructor node) {
    _staticTypeContext = new StaticTypeContext(node, _environment);
    super.visitConstructor(node);
    _staticTypeContext = null;
  }

  @override
  void visitProcedure(Procedure node) {
    _staticTypeContext = new StaticTypeContext(node, _environment);
    super.visitProcedure(node);
    _staticTypeContext = null;
  }

  @override
  String computeLibraryValue(Id id, Library node) {
    return 'nnbd=${node.isNonNullableByDefault}';
  }

  @override
  String computeMemberValue(Id id, Member node) {
    if (node is Procedure && node.function.futureValueType != null) {
      return 'futureValueType=${typeToText(node.function.futureValueType)}';
    }
    return null;
  }

  @override
  String computeNodeValue(Id id, TreeNode node) {
    if (isSkippedExpression(node)) {
      return null;
    }
    if (node is Expression) {
      DartType type = node.getStaticType(_staticTypeContext);
      if (node is FunctionExpression && node.function.futureValueType != null) {
        return '${typeToText(type)},'
            'futureValueType=${typeToText(node.function.futureValueType)}';
      }
      return typeToText(type);
    } else if (node is Arguments) {
      if (node.types.isNotEmpty) {
        return '<${node.types.map(typeToText).join(',')}>';
      }
    } else if (node is ForInStatement) {
      if (id.kind == IdKind.current) {
        DartType type = _staticTypeContext.typeEnvironment.forInElementType(
            node, node.iterable.getStaticType(_staticTypeContext));
        return typeToText(type);
      }
    } else if (node is FunctionDeclaration) {
      if (node.function.futureValueType != null) {
        return 'futureValueType=${typeToText(node.function.futureValueType)}';
      }
    }
    return null;
  }

  bool isNewReachabilityError(object) {
    if (object is ConstructorInvocation) {
      Class cls = object.target.enclosingClass;
      return cls.name == 'ReachabilityError' &&
          cls.enclosingLibrary.importUri.scheme == 'dart' &&
          cls.enclosingLibrary.importUri.path == '_internal';
    }
    return false;
  }

  bool isNewReachabilityErrorArgument(object) {
    return object is StringLiteral &&
        isNewReachabilityError(object.parent.parent);
  }

  bool isThrowReachabilityError(object) {
    return object is Throw && isNewReachabilityError(object.expression);
  }

  bool isReachabilityErrorLet(object) {
    return object is Let &&
        (isThrowReachabilityError(object.variable.initializer) ||
            isThrowReachabilityError(object.body));
  }

  bool isSkippedExpression(object) =>
      isReachabilityErrorLet(object) ||
      isThrowReachabilityError(object) ||
      isNewReachabilityErrorArgument(object) ||
      isNewReachabilityError(object);

  @override
  ActualData<String> mergeData(
      ActualData<String> value1, ActualData<String> value2) {
    if (value1.object is NullLiteral && value2.object is! NullLiteral) {
      // Skip `null` literals from null-aware operations.
      return value2;
    } else if (value1.object is! NullLiteral && value2.object is NullLiteral) {
      // Skip `null` literals from null-aware operations.
      return value1;
    }

    return new ActualData<String>(value1.id, '${value1.value}|${value2.value}',
        value1.uri, value1.offset, value1.object);
  }
}
