// Copyright (c) 2014, 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 instantiated_classes_test;

import 'dart:async';
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/elements/entities.dart'
    show ClassEntity, LibraryEntity;
import '../helpers/type_test_helper.dart';

void main() {
  Future runTests() async {
    Future test(String source, List<String> directlyInstantiatedClasses,
        [List<String> newClasses = const <String>["Class"]]) async {
      StringBuffer mainSource = StringBuffer();
      mainSource.writeln(source);
      mainSource.write('main() {\n');
      for (String newClass in newClasses) {
        mainSource.write('  $newClass();\n');
      }
      mainSource.write('}');
      dynamic env = await TypeEnvironment.create(mainSource.toString());
      LibraryEntity mainLibrary =
          env.compiler.frontendStrategy.elementEnvironment.mainLibrary;
      Iterable<ClassEntity> expectedClasses =
          directlyInstantiatedClasses.map((String name) {
        return env.getElement(name);
      });
      Iterable<ClassEntity> actualClasses = env
          .compiler.resolutionWorldBuilderForTesting.directlyInstantiatedClasses
          .where((c) => c.library == mainLibrary);
      Expect.setEquals(
          expectedClasses,
          actualClasses,
          "Instantiated classes mismatch: "
          "Expected $expectedClasses, actual: $actualClasses");
    }

    await test("class Class {}", ["Class"]);
    await test("""abstract class A {}
                  class Class extends A {}""", ["Class"]);
    await test("""class A {}
                  class Class extends A {}""", ["Class"]);
    await test("""class A {}
                  class B {}
                  class Class extends A {}""", ["Class"]);
    await test("""class A {}
                  class Class implements A {}""", ["Class"]);
    await test("""mixin A {}
                  class Class extends Object with A {}""", ["Class"]);
    await test("""class A {}
                  mixin B {}
                  class Class extends Object with B implements A {}""",
        ["Class"]);

    await test("""class A {}
                  class Class {}""", ["Class", "A"], ["Class", "A"]);
    await test("""class A {}
                  class Class extends A {}""", ["Class", "A"], ["Class", "A"]);
    await test("""class A {}
                  class Class implements A {}""", ["Class", "A"],
        ["Class", "A"]);
    await test("""class A {}
                  class B extends A {}
                  class Class extends B {}""", ["Class", "A"], ["Class", "A"]);
    await test("""mixin class A {}
                  class B {}
                  class Class extends B with A {}""", ["Class", "A"],
        ["Class", "A"]);

    await test("""class A implements Class {}
                  class Class {
                    factory Class() = A;
                  }""", ["A"], ["Class"]);
  }

  asyncTest(() async {
    print('--test from kernel------------------------------------------------');
    await runTests();
  });
}
