// Copyright (c) 2016, 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.

library dart2js.serialization.class_members_test;

import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common/names.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/resolution/class_members.dart';
import 'package:compiler/src/serialization/equivalence.dart';
import '../memory_compiler.dart';
import 'helper.dart';
import 'test_helper.dart';


main(List<String> args) {
  Arguments arguments = new Arguments.from(args);
  asyncTest(() async {
    SerializedData serializedData =
    await serializeDartCore(arguments: arguments);
    if (arguments.filename != null) {
      Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.filename));
      await checkClassMembers(
          serializedData, entryPoint, verbose: arguments.verbose);
    } else {
      await checkClassMembers(
          serializedData, Uris.dart_core, verbose: arguments.verbose);
    }
  });
}

Future checkClassMembers(
    SerializedData serializedData,
    Uri entryPoint,
    {bool verbose: false}) async {

  Compiler compilerNormal = compilerFor(
      options: [Flags.analyzeAll]);
  await compilerNormal.run(entryPoint);

  Compiler compilerDeserialized = compilerFor(
      memorySourceFiles: serializedData.toMemorySourceFiles(),
      resolutionInputs: serializedData.toUris(),
      options: [Flags.analyzeAll]);
  await compilerDeserialized.run(entryPoint);

  checkAllMembers(compilerNormal, compilerDeserialized, verbose: true);
}

void checkAllMembers(
    Compiler compiler1,
    Compiler compiler2,
    {bool verbose: false}) {
  checkLoadedLibraryMembers(
      compiler1,
      compiler2,
      (Element member1) => member1 is ClassElement,
      checkMembers,
      verbose: verbose);
}


/// Check equivalence of members of [class1] and [class2].
void checkMembers(
    Compiler compiler1, ClassMemberMixin class1,
    Compiler compiler2, ClassMemberMixin class2,
    {bool verbose: false}) {
  if (verbose) {
    print('Checking $class1 vs $class2');
  }
  MembersCreator.computeAllClassMembers(compiler1.resolution, class1);
  MembersCreator.computeAllClassMembers(compiler2.resolution, class2);

  check(class1, class2, 'interfaceMemberAreClassMembers',
      class1.interfaceMembersAreClassMembers,
      class2.interfaceMembersAreClassMembers);
  class1.forEachClassMember((Member member1) {
    Name name1 = member1.name;
    Name name2 = convertName(name1, compiler2);
    checkMember(class1, class2, 'classMember:$name1',
        member1, class2.lookupClassMember(name2));
  });

  class1.forEachInterfaceMember((MemberSignature member1) {
    Name name1 = member1.name;
    Name name2 = convertName(name1, compiler2);
    checkMemberSignature(class1, class2, 'interfaceMember:$name1',
        member1, class2.lookupInterfaceMember(name2));
  });
}

Name convertName(Name name, Compiler compiler) {
  if (name.isPrivate) {
    LibraryElement library =
        compiler.libraryLoader.lookupLibrary(name.library.canonicalUri);
    if (!areElementsEquivalent(name.library, library)) {
      throw 'Libraries ${name.library} and ${library} are not equivalent';
    }
    name = new Name(name.text, library, isSetter: name.isSetter);
  }
  return name;
}

void checkMember(ClassElement class1, ClassElement class2, String property,
    Member member1, Member member2) {
  if (member2 == null) {
    print('$class1 class members:');
    class1.forEachClassMember((m) => print(' ${m.name} $m'));
    print('$class2 class members:');
    class2.forEachClassMember((m) => print(' ${m.name} $m'));
    throw "No member ${member1.name} in $class2 for $property";
  }
  checkMemberSignature(class1, class2, property, member1, member2);
  checkElementIdentities(class1, class2, '$property.element',
      member1.element, member2.element);
  check(class1, class2, '$property.declarer',
      member1.declarer, member2.declarer, areTypesEquivalent);
  check(class1, class2, '$property.isStatic',
      member1.isStatic, member2.isStatic);
  check(class1, class2, '$property.isDeclaredByField',
      member1.isDeclaredByField, member2.isDeclaredByField);
  check(class1, class2, '$property.isAbstract',
      member1.isAbstract, member2.isAbstract);
  if (member1.isAbstract && member1.implementation != null) {
    checkMember(class1, class2, '$property.implementation',
        member1.implementation, member2.implementation);
  }
}

void checkMemberSignature(ClassElement class1, ClassElement class2,
    String property,
    MemberSignature member1, MemberSignature member2) {
  if (member2 == null) {
    print('$class1 interface members:');
    class1.forEachInterfaceMember((m) => print(' ${m.name} $m'));
    print('$class2 interface members:');
    class2.forEachInterfaceMember((m) => print(' ${m.name} $m'));
    throw "No member ${member1.name} in $class2 for $property";
  }
  check(class1, class2, '$property.name',
      member1.name, member2.name, areNamesEquivalent);
  check(class1, class2, '$property.type',
      member1.type, member2.type, areTypesEquivalent);
  check(class1, class2, '$property.functionType',
      member1.functionType, member2.functionType, areTypesEquivalent);
  check(class1, class2, '$property.isGetter',
      member1.isGetter, member2.isGetter);
  check(class1, class2, '$property.isSetter',
      member1.isSetter, member2.isSetter);
  check(class1, class2, '$property.isMethod',
      member1.isMethod, member2.isMethod);
}
