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

// Test of Compiler.forgetElement.
library trydart.forget_element_test;

import 'package:compiler/src/elements/elements.dart' show
    AstElement,
    ClassElement,
    Element,
    FunctionElement,
    LocalFunctionElement,
    MetadataAnnotation,
    ScopeContainerElement,
    VariableElement;

import 'package:compiler/src/js_backend/js_backend.dart' show
    JavaScriptBackend;

import 'package:compiler/src/tree/tree.dart' as tree;

import 'package:compiler/src/scanner/scannerlib.dart' show
    PartialMetadataAnnotation;

import 'package:compiler/src/elements/visitor.dart' show
    ElementVisitor;

import 'package:compiler/src/dart2jslib.dart' show
    DartConstantCompiler;

import 'package:compiler/src/universe/universe.dart' show
    Universe;

import 'package:compiler/src/dart_types.dart' show
    DartType;

import 'compiler_test_case.dart';

import 'forget_element_assertion.dart' show
    assertUnimplementedLocalMetadata;

class ForgetElementTestCase extends CompilerTestCase {
  final int expectedClosureCount;

  final int expectedMetadataCount;

  final int expectedConstantCount;

  final int expectedInitialValueCount;

  final int expectedInitialDartValueCount;

  final int additionalClosureClassMaps;

  JavaScriptBackend get backend => compiler.backend;

  DartConstantCompiler get dartConstants =>
      backend.constantCompilerTask.dartConstantCompiler;

  Universe get codegenUniverse => compiler.enqueuer.codegen.universe;

  Universe get resolutionUniverse => compiler.enqueuer.resolution.universe;

  ForgetElementTestCase(
      String source,
      {int closureCount: 0,
       int metadataCount: 0,
       int constantCount: 0,
       int initialValueCount: 0,
       int initialDartValueCount: null,
       this.additionalClosureClassMaps: 0})
      : this.expectedClosureCount = closureCount,
        this.expectedMetadataCount = metadataCount,
        this.expectedConstantCount = constantCount,
        this.expectedInitialValueCount = initialValueCount,
        // Sometimes these numbers aren't the same. Appears to happen with
        // non-const fields, because those aren't compile-time constants in the
        // strict language specification sense.
        this.expectedInitialDartValueCount = (initialDartValueCount == null)
            ? initialValueCount : initialDartValueCount,
        super(source);

  Future run() => compile().then((LibraryElement library) {

    // Check that the compiler has recorded the expected number of closures.
    Expect.equals(
        expectedClosureCount, closuresInLibrary(library).length,
        'closure count');

    // Check that the compiler has recorded the expected number of metadata
    // annotations.
    Expect.equals(
        expectedMetadataCount, metadataInLibrary(library).length,
        'metadata count');

    // Check that the compiler has recorded the expected number of
    // constants. Since metadata is also constants, those must also be counted.
    Expect.equals(
        expectedConstantCount + expectedMetadataCount,
        constantsIn(library).length,
        'constant count');

    // Check that the compiler has recorded the expected number of initial
    // values.
    Expect.equals(
        expectedInitialValueCount,
        elementsWithJsInitialValuesIn(library).length,
        'number of fields with initial values (JS)');
    Expect.equals(
        expectedInitialDartValueCount,
        elementsWithDartInitialValuesIn(library).length,
        'number of fields with initial values (Dart)');

    // Check that the compiler has recorded the expected number of closure
    // class maps. There's always at least one, from main. Each top-level
    // element also seems to induce one.
    Expect.equals(
        expectedClosureCount + additionalClosureClassMaps,
        closureClassMapsIn(library).length - 1,
        'closure class map count ${closureClassMapsIn(library)}');


    // Forget about all elements.
    library.forEachLocalMember(compiler.forgetElement);

    // Check that all the closures were forgotten.
    Expect.isTrue(closuresInLibrary(library).isEmpty, 'closures');

    // Check that the metadata annotations were forgotten.
    Expect.isTrue(metadataInLibrary(library).isEmpty, 'metadata');

    // Check that the constants were forgotten.
    Expect.isTrue(constantsIn(library).isEmpty, 'constants');

    // Check that initial values were forgotten.
    Expect.isTrue(
        elementsWithJsInitialValuesIn(library).isEmpty,
        'fields with initial values (JS)');
    Expect.isTrue(
        elementsWithDartInitialValuesIn(library).isEmpty,
        'fields with initial values (Dart)');

    // Check that closure class maps were forgotten.
    Expect.isTrue(closureClassMapsIn(library).isEmpty, 'closure class maps');

    // Check that istantiated types and classes were forgotten.
    Expect.isTrue(
        resolutionTypesIn(library).isEmpty, 'resolution instantiatedTypes');
    Expect.isTrue(
        resolutionClassesIn(library).isEmpty, 'resolution instantiatedClasses');
    Expect.isTrue(
        codegenTypesIn(library).isEmpty, 'codegen instantiatedTypes');
    Expect.isTrue(
        codegenClassesIn(library).isEmpty, 'codegen instantiatedClasses');

    // Check that other members remembered by [Universe] were forgotten.
    Expect.isTrue(
        resolutionMembersIn(library).isEmpty, 'resolution misc members');
    Expect.isTrue(
        codegenMembersIn(library).isEmpty, 'codegen misc members');

    // Check that classes remembered by the enqueuer have been forgotten.
    Expect.isTrue(
        codegenSeenClassesIn(library).isEmpty, 'codegen seen classes');
    Expect.isTrue(
        resolutionSeenClassesIn(library).isEmpty, 'resolution seen classes');
  });

  Iterable closuresInLibrary(LibraryElement library) {
    return compiler.enqueuer.resolution.universe.allClosures.where(
        (LocalFunctionElement closure) => closure.library == library);
  }

  Iterable metadataInLibrary(LibraryElement library) {
    return backend.constants.metadataConstantMap.keys.where(
        (MetadataAnnotation metadata) {
          return metadata.annotatedElement.library == library;
        });
  }

  Iterable<tree.Node> nodesIn(LibraryElement library) {
    NodeCollector collector = new NodeCollector();
    library.forEachLocalMember((e) {
      if (e is AstElement && e.hasNode) {
        e.node.accept(collector);
      }

      // Due to quirks of history, only parameter metadata is recorded in AST
      // nodes, so they must be extracted from the elements.
      for (MetadataAnnotation metadata in e.metadata) {
        if (metadata is PartialMetadataAnnotation) {
          if (metadata.cachedNode != null) {
            metadata.cachedNode.accept(collector);
          }
        }
      }
    });

    List<MetadataAnnotation> metadata =
        (new MetadataCollector()..visit(library)).metadata;
    return collector.nodes;
  }

  Iterable constantsIn(LibraryElement library) {
    return nodesIn(library)
        .map((node) => backend.constants.nodeConstantMap[node])
        .where((constant) => constant != null);
  }

  Iterable elementsWithJsInitialValuesIn(LibraryElement library) {
    return backend.constants.initialVariableValues.keys.where(
        (VariableElement element) => element.library == library);
  }

  Iterable elementsWithDartInitialValuesIn(LibraryElement library) {
    return dartConstants.initialVariableValues.keys.where(
        (VariableElement element) => element.library == library);
  }

  Iterable closureClassMapsIn(LibraryElement library) {
    Map cache = compiler.closureToClassMapper.closureMappingCache;
    return nodesIn(library).where((node) => cache[node] != null);
  }

  Iterable codegenTypesIn(LibraryElement library) {
    return codegenUniverse.instantiatedTypes.where(
        (DartType type) => type.element.library == library);
  }

  Iterable codegenClassesIn(LibraryElement library) {
    return codegenUniverse.directlyInstantiatedClasses.where(
        (ClassElement cls) => cls.library == library);
  }

  Iterable codegenMembersIn(LibraryElement library) {
    sameLibrary(e) => e.library == library;
    return new Set()
        ..addAll(codegenUniverse.closurizedMembers.where(sameLibrary))
        ..addAll(codegenUniverse.fieldSetters.where(sameLibrary))
        ..addAll(codegenUniverse.fieldGetters.where(sameLibrary));
  }

  Iterable resolutionTypesIn(LibraryElement library) {
    return resolutionUniverse.instantiatedTypes.where(
        (DartType type) => type.element.library == library);
  }

  Iterable resolutionClassesIn(LibraryElement library) {
    return resolutionUniverse.directlyInstantiatedClasses.where(
        (ClassElement cls) => cls.library == library);
  }

  Iterable resolutionMembersIn(LibraryElement library) {
    sameLibrary(e) => e.library == library;
    return new Set()
        ..addAll(resolutionUniverse.closurizedMembers.where(sameLibrary))
        ..addAll(resolutionUniverse.fieldSetters.where(sameLibrary))
        ..addAll(resolutionUniverse.fieldGetters.where(sameLibrary));
  }

  Iterable codegenSeenClassesIn(LibraryElement library) {
    return compiler.codegenWorld.allInstantiatedClasses.where(
        (e) => e.library == library);
  }

  Iterable resolutionSeenClassesIn(LibraryElement library) {
    return compiler.resolverWorld.allInstantiatedClasses.where(
        (e) => e.library == library);
  }
}

class NodeCollector extends tree.Visitor {
  final List<tree.Node> nodes = <tree.Node>[];

  void visitNode(tree.Node node) {
    nodes.add(node);
    node.visitChildren(this);
  }
}

class MetadataCollector extends ElementVisitor {
  final List<MetadataAnnotation> metadata = <MetadataAnnotation>[];

  void visitElement(Element e) {
    metadata.addAll(e.metadata.toList());
  }

  void visitScopeContainerElement(ScopeContainerElement e) {
    super.visitScopeContainerElement(e);
    e.forEachLocalMember(this.visit);
  }

  void visitFunctionElement(FunctionElement e) {
    super.visitFunctionElement(e);
    if (e.hasFunctionSignature) {
      e.functionSignature.forEachParameter(this.visit);
    }
  }
}

void main() {
  runTests(tests);
}

List<CompilerTestCase> get tests => <CompilerTestCase>[

    // Edge case: empty body.
    new ForgetElementTestCase(
        'main() {}'),

    // Edge case: simple arrow function.
    new ForgetElementTestCase(
        'main() => null;'),

    // Test that a local closure is discarded correctly.
    new ForgetElementTestCase(
        'main() => (() => null)();',
        closureCount: 1),

    // Test that nested closures are discarded correctly.
    new ForgetElementTestCase(
        'main() => (() => (() => null)())();',
        closureCount: 2),

    // Test that nested closures are discarded correctly.
    new ForgetElementTestCase(
        'main() => (() => (() => (() => null)())())();',
        closureCount: 3),

    // Test that metadata on top-level function is discarded correctly.
    new ForgetElementTestCase(
        '@Constant() main() => null; $CONSTANT_CLASS',
        metadataCount: 1),

    // Test that metadata on top-level variable is discarded correctly.
    new ForgetElementTestCase(
        '@Constant() var x; main() => x; $CONSTANT_CLASS',
        metadataCount: 1,
        initialValueCount: 1,
        initialDartValueCount: 0),

    // Test that metadata on parameter on a local function is discarded
    // correctly.
    new ForgetElementTestCase(
        'main() => ((@Constant() x) => x)(null); $CONSTANT_CLASS',
        closureCount: 1,
        metadataCount: 1),

    // Test that a constant in a top-level method body is discarded
    // correctly.
    new ForgetElementTestCase(
        'main() => const Constant(); $CONSTANT_CLASS',
        constantCount: 1),

    // Test that a constant in a nested function body is discarded
    // correctly.
    new ForgetElementTestCase(
        'main() => (() => const Constant())(); $CONSTANT_CLASS',
        constantCount: 1,
        closureCount: 1),

    // Test that a constant in a nested function body is discarded
    // correctly.
    new ForgetElementTestCase(
        'main() => (() => (() => const Constant())())(); $CONSTANT_CLASS',
        constantCount: 1,
        closureCount: 2),

    // Test that a constant in a top-level variable initializer is
    // discarded correctly.
    new ForgetElementTestCase(
        'main() => x; var x = const Constant(); $CONSTANT_CLASS',
        constantCount: 1,
        initialValueCount: 1,
        initialDartValueCount: 0,
        additionalClosureClassMaps: 1),

    // Test that a constant in a parameter initializer is discarded
    // correctly.
    new ForgetElementTestCase(
        'main([x = const Constant()]) => x; $CONSTANT_CLASS',
        constantCount: 1,
        initialValueCount: 1),

    // Test that a constant in a parameter initializer is discarded
    // correctly (nested function).
    new ForgetElementTestCase(
        'main() => (([x = const Constant()]) => x)(); $CONSTANT_CLASS',
        closureCount: 1,
        constantCount: 1,
        initialValueCount: 1),

    // Test that a constant in a parameter initializer is discarded
    // correctly (deeply nested function).
    new ForgetElementTestCase(
        'main() => (() => (([x = const Constant()]) => x)())();'
        ' $CONSTANT_CLASS',
        closureCount: 2,
        constantCount: 1,
        initialValueCount: 1),

    // TODO(ahe): Add test for super sends [backend.aliasedSuperMembers].
]..addAll(assertUnimplementedLocalMetadata());
