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

/// Test to ensure that desugaring APIs used by clients like dart2js are
/// always up to date.
///
/// Desugaring APIs are methods that inspect the kernel output to find
/// structures that are assumed to always be generated by the CFE. If the CFE
/// changes its invariants, the desugaring APIs will change together to hide
/// these changes from clients.

import 'dart:io';

import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:front_end/src/api_unstable/dart2js.dart' as api;
import 'package:front_end/src/compute_platform_binaries_location.dart';
import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
import 'package:front_end/src/testing/compiler_common.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;

main() async {
  await asyncTest(() async {
    await testRedirectingFactoryDirect();
    await testRedirectingFactorySerialized();
    await testRedirectingFactoryPatchFile();
  });
}

testRedirectingFactoryDirect() async {
  var component = await compileUnit(['a.dart'], {'a.dart': aSource});
  checkIsRedirectingFactory(component, 'a.dart', 'A', 'foo');
  checkIsRedirectingFactory(component, 'core', 'Uri', 'file');
}

testRedirectingFactorySerialized() async {
  var component = await compileUnit(['a.dart'], {'a.dart': aSource});
  var bytes = serializeComponent(component);
  component = new ir.Component();
  new BinaryBuilder(bytes).readComponent(component);
  checkIsRedirectingFactory(component, 'a.dart', 'A', 'foo');
  checkIsRedirectingFactory(component, 'core', 'Uri', 'file');
}

// regression test: redirecting factories from patch files don't have the
// redirecting-factory flag stored in kernel.
testRedirectingFactoryPatchFile() async {
  var componentUri =
      computePlatformBinariesLocation().resolve('dart2js_platform.dill');
  var component = new ir.Component();
  new BinaryBuilder(new File.fromUri(componentUri).readAsBytesSync())
      .readComponent(component);
  checkIsRedirectingFactory(component, 'collection', 'HashMap', 'identity',
      isPatch: true);
}

void checkIsRedirectingFactory(ir.Component component, String uriPath,
    String className, String constructorName,
    {bool isPatch: false}) {
  var lib =
      component.libraries.firstWhere((l) => l.importUri.path.endsWith(uriPath));
  var cls = lib.classes.firstWhere((c) => c.name == className);
  ir.Procedure member =
      cls.members.firstWhere((m) => m.name.name == constructorName);
  Expect.isTrue(
      member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
  Expect.isTrue(api.isRedirectingFactory(member));
  // TODO: this should always be true. Issue #33495
  Expect.equals(!isPatch, member.isRedirectingFactoryConstructor);
}

const aSource = '''
class A {
  factory A.foo(int x) = _B;
}

class _B implements A {
  _B(int x);
}
''';
