// 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 'type_test_helper.dart';

void main() {
  asyncTest(() => Future.forEach([
        () => test("class Class {}", ["Class"]),
        () => test("""abstract class A {}
                  class Class extends A {}""", ["Class"]),
        () => test("""class A {}
                  class Class extends A {}""", ["Class"]),
        () => test("""class A {}
                  class B {}
                  class Class extends A {}""", ["Class"]),
        () => test("""class A {}
                  class Class implements A {}""", ["Class"]),
        () => test("""class A {}
                  class Class extends Object with A {}""", ["Class"]),
        () => test("""class A {}
                  class B {}
                  class Class extends Object with B implements A {}""",
            ["Class"]),

        () => test("""class A {}
                  class Class {}""", ["Class", "A"], ["Class", "A"]),
        () => test("""class A {}
                  class Class extends A {}""", ["Class", "A"], ["Class", "A"]),
        () => test("""class A {}
                  class Class implements A {}""", ["Class", "A"],
            ["Class", "A"]),
        () => test("""class A {}
                  class B extends A {}
                  class Class extends B {}""", ["Class", "A"], ["Class", "A"]),
        () => test("""class A {}
                  class B {}
                  class Class extends B with A {}""", ["Class", "A"],
            ["Class", "A"]),

        // TODO(johnniwinther): Avoid registration of `Class` as instantiated.
        () => test("""class A {}
                  class Class implements A {
                    factory Class() = A;
                  }""", ["Class", "A"], ["Class"]),
      ], (f) => f()));
}

Future test(String source, List<String> directlyInstantiatedClasses,
    [List<String> newClasses = const <String>["Class"]]) {
  StringBuffer mainSource = new StringBuffer();
  mainSource.write('main() {\n');
  for (String newClass in newClasses) {
    mainSource.write('  new $newClass();\n');
  }
  mainSource.write('}');
  return TypeEnvironment
      .create(source,
          mainSource: mainSource.toString(), compileMode: CompileMode.mock)
      .then((dynamic env) {
    LibraryEntity mainLibrary =
        env.compiler.frontendStrategy.elementEnvironment.mainLibrary;
    Iterable<ClassEntity> expectedClasses =
        directlyInstantiatedClasses.map(env.getElement);
    Iterable<ClassEntity> actualClasses = env
        .compiler.resolutionWorldBuilder.directlyInstantiatedClasses
        .where((c) => c.library == mainLibrary);
    Expect.setEquals(expectedClasses, actualClasses);
  });
}
