// 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' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
    show DataInterpreter, runTests;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.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' hide Variance;

void main(List<String> args) async {
  Directory dataDir = new Directory.fromUri(
      Platform.script.resolve('../../../_fe_analyzer_shared/test/'
          'inference/inferred_variable_types/data'));
  await runTests<DartType>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(const InferredVariableTypesDataComputer(),
          [cfeNonNullableOnlyConfig]));
}

class InferredVariableTypesDataComputer extends DataComputer<DartType> {
  const InferredVariableTypesDataComputer();

  @override
  DataInterpreter<DartType> get dataValidator =>
      const _InferredVariableTypesDataInterpreter();

  @override
  bool get supportsErrors => true;

  /// Function that computes a data mapping for [member].
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeMemberData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Member member,
      Map<Id, ActualData<DartType>> actualMap,
      {bool verbose}) {
    MemberBuilderImpl memberBuilder =
        lookupMemberBuilder(compilerResult, member);
    member.accept(new InferredTypeArgumentDataExtractor(
        compilerResult,
        memberBuilder.dataForTesting.inferenceData.typeInferenceResult,
        actualMap));
  }
}

class InferredTypeArgumentDataExtractor extends CfeDataExtractor<DartType> {
  final TypeInferenceResultForTesting typeInferenceResult;

  InferredTypeArgumentDataExtractor(InternalCompilerResult compilerResult,
      this.typeInferenceResult, Map<Id, ActualData<DartType>> actualMap)
      : super(compilerResult, actualMap);

  @override
  DartType computeNodeValue(Id id, TreeNode node) {
    if (node is VariableDeclaration || node is LocalFunction) {
      return typeInferenceResult.inferredVariableTypes[node];
    }
    return null;
  }
}

class _InferredVariableTypesDataInterpreter
    implements DataInterpreter<DartType> {
  const _InferredVariableTypesDataInterpreter();

  @override
  String getText(DartType actualData, [String indentation]) {
    return typeToText(
        actualData, TypeRepresentation.analyzerNonNullableByDefault);
  }

  @override
  String isAsExpected(DartType actualData, String expectedData) {
    if (getText(actualData) == expectedData) {
      return null;
    } else {
      return 'Expected $expectedData, got $actualData';
    }
  }

  @override
  bool isEmpty(DartType actualData) => actualData == null;
}
