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

import "package:expect/expect.dart";
import 'dart:async';
import "package:async_helper/async_helper.dart";
import 'dart:collection';

import "package:compiler/implementation/resolution/resolution.dart";
import "compiler_helper.dart";
import "parser_helper.dart";

import 'package:compiler/implementation/dart_types.dart';
import 'package:compiler/implementation/elements/modelx.dart';
import 'link_helper.dart';

Node buildIdentifier(String name) => new Identifier(scan(name));

Node buildInitialization(String name) =>
  parseBodyCode('$name = 1',
      (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens));

createLocals(List variables) {
  var locals = <Node>[];
  for (final variable in variables) {
    String name = variable[0];
    bool init = variable[1];
    if (init) {
      locals.add(buildInitialization(name));
    } else {
      locals.add(buildIdentifier(name));
    }
  }
  var definitions = new NodeList(null, LinkFromList(locals), null, null);
  return new VariableDefinitions(null, Modifiers.EMPTY, definitions);
}

Future testLocals(List variables) {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    Element element = visitor.visit(createLocals(variables));
    // A VariableDefinitions does not have an element.
    Expect.equals(null, element);
    Expect.equals(variables.length, map(visitor).length);

    for (final variable in variables) {
      final name = variable[0];
      Identifier id = buildIdentifier(name);
      final VariableElement variableElement = visitor.visit(id);
      MethodScope scope = visitor.scope;
      Expect.equals(variableElement, scope.elements[name]);
    }
    return compiler;
  });
}

main() {
  asyncTest(() => Future.forEach([
    testLocalsOne,
    testLocalsTwo,
    testLocalsThree,
    testLocalsFour,
    testLocalsFive,
    testParametersOne,
    testFor,
    testTypeAnnotation,
    testSuperclass,
    // testVarSuperclass, // The parser crashes with 'class Foo extends var'.
    // testOneInterface, // Generates unexpected error message.
    // testTwoInterfaces, // Generates unexpected error message.
    testFunctionExpression,
    testNewExpression,
    testTopLevelFields,
    testClassHierarchy,
    testInitializers,
    testThis,
    testSuperCalls,
    testSwitch,
    testTypeVariables,
    testToString,
    testIndexedOperator,
    testIncrementsAndDecrements,
    testOverrideHashCodeCheck,
    testSupertypeOrder,
    testConstConstructorAndNonFinalFields,
  ], (f) => f()));
}

Future testSupertypeOrder() {
  return Future.wait([
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""
class I1 {}
class I2 {}
class J1 extends K1 {}
class J2 implements K2 {}
class K1 {}
class K2 {}
class L1 {}
class A implements I1, I2 {}
class B extends A implements J1, J2 {}
class C extends B implements L1 {}
""");
      compiler.resolveStatement("C c;");
      ClassElement classA = compiler.mainApp.find("A");
      ClassElement classB = compiler.mainApp.find("B");
      ClassElement classC = compiler.mainApp.find("C");
      Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString());
      Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]',
                    classB.allSupertypes.toString());
      Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]',
                    classC.allSupertypes.toString());
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""
class X<T> {}
class Foo extends X<Foo> {}
class Bar extends Foo implements X<Bar> {}
""");
      compiler.resolveStatement("Bar bar;");
      ClassElement classBar = compiler.mainApp.find("Bar");
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.MULTI_INHERITANCE,
                    compiler.errors[0].message.kind);
      Expect.equals(0, compiler.crashes.length);
    }),
  ]);
}

Future testTypeVariables() {
  matchResolvedTypes(visitor, text, name, expectedElements) {
    VariableDefinitions definition = parseStatement(text);
    visitor.visit(definition.type);
    InterfaceType type = visitor.registry.mapping.getType(definition.type);
    Expect.equals(definition.type.typeArguments.slowLength(),
                  type.typeArguments.length);
    int index = 0;
    for (DartType argument in type.typeArguments) {
      Expect.equals(true, index < expectedElements.length);
      Expect.equals(expectedElements[index], argument.element);
      index++;
    }
    Expect.equals(index, expectedElements.length);
  }

  return Future.wait([
    MockCompiler.create((MockCompiler compiler) {
      ResolverVisitor visitor = compiler.resolverVisitor();
      compiler.parseScript('class Foo<T, U> {}');
      ClassElement foo = compiler.mainApp.find('Foo');
      matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo',
                         [compiler.intClass, compiler.stringClass]);
      matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo',
                         [foo, foo]);
    }),

    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript('class Foo<T, U> {}');
      compiler.resolveStatement('Foo<notype, int> x;');
      Expect.equals(1, compiler.warnings.length);
      Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE,
                    compiler.warnings[0].message.kind);
      Expect.equals(0, compiler.errors.length);
    }),

    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript('class Foo<T, U> {}');
      compiler.resolveStatement('var x = new Foo<notype, int>();');
      Expect.equals(1, compiler.warnings.length);
      Expect.equals(0, compiler.errors.length);
      Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE,
                    compiler.warnings[0].message.kind);
    }),

    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript('class Foo<T> {'
                           '  Foo<T> t;'
                           '  foo(Foo<T> f) {}'
                           '  bar() { g(Foo<T> f) {}; g(); }'
                           '}');
      ClassElement foo = compiler.mainApp.find('Foo');
      foo.ensureResolved(compiler);
      foo.lookupLocalMember('t').computeType(compiler);;
      foo.lookupLocalMember('foo').computeType(compiler);;
      compiler.resolver.resolve(foo.lookupLocalMember('bar'));
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(0, compiler.errors.length);
    }),
  ]);
}

Future testSuperCalls() {
  return MockCompiler.create((MockCompiler compiler) {
    String script = """class A { foo() {} }
                       class B extends A { foo() => super.foo(); }""";
    compiler.parseScript(script);
    compiler.resolveStatement("B b;");

    ClassElement classB = compiler.mainApp.find("B");
    FunctionElement fooB = classB.lookupLocalMember("foo");
    ClassElement classA = compiler.mainApp.find("A");
    FunctionElement fooA = classA.lookupLocalMember("foo");

    ResolverVisitor visitor =
        new ResolverVisitor(compiler, fooB,
            new ResolutionRegistry.internal(compiler,
                new CollectingTreeElements(fooB)));
    FunctionExpression node = (fooB as FunctionElementX).parseNode(compiler);
    visitor.visit(node.body);
    Map mapping = map(visitor);

    Send superCall = node.body.asReturn().expression;
    FunctionElement called = mapping[superCall];
    Expect.isNotNull(called);
    Expect.equals(fooA, called);
  });
}

Future testSwitch() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript("class Foo { foo() {"
        "switch (null) { case '': break; case 2: break; } } }");
    compiler.resolveStatement("Foo foo;");
    ClassElement fooElement = compiler.mainApp.find("Foo");
    FunctionElement funElement = fooElement.lookupLocalMember("foo");
    compiler.processQueue(compiler.enqueuer.resolution, funElement);
    Expect.equals(0, compiler.warnings.length);
    Expect.equals(1, compiler.errors.length);
    Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL,
                  compiler.errors[0].message.kind);
    Expect.equals(2, compiler.infos.length);
    Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
                  compiler.infos[0].message.kind);
    Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
                  compiler.infos[1].message.kind);
  });
}

Future testThis() {
  return Future.wait([
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("class Foo { foo() { return this; } }");
      compiler.resolveStatement("Foo foo;");
      ClassElement fooElement = compiler.mainApp.find("Foo");
      FunctionElement funElement = fooElement.lookupLocalMember("foo");
      ResolverVisitor visitor =
          new ResolverVisitor(compiler, funElement,
              new ResolutionRegistry.internal(compiler,
                  new CollectingTreeElements(funElement)));
      FunctionExpression function =
          (funElement as FunctionElementX).parseNode(compiler);
      visitor.visit(function.body);
      Map mapping = map(visitor);
      List<Element> values = mapping.values.toList();
      Expect.equals(0, mapping.length);
      Expect.equals(0, compiler.warnings.length);
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.resolveStatement("main() { return this; }");
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE,
                    compiler.errors[0].message.kind);
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("class Foo { static foo() { return this; } }");
      compiler.resolveStatement("Foo foo;");
      ClassElement fooElement = compiler.mainApp.find("Foo");
      FunctionElement funElement = fooElement.lookupLocalMember("foo");
      ResolverVisitor visitor = new ResolverVisitor(compiler, funElement,
          new ResolutionRegistry.internal(compiler,
              new CollectingTreeElements(funElement)));
      FunctionExpression function =
          (funElement as FunctionElementX).parseNode(compiler);
      visitor.visit(function.body);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE,
                    compiler.errors[0].message.kind);
    }),
  ]);
}

Future testLocalsOne() {
  return Future.forEach([
      () => testLocals([["foo", false]]),
      () => testLocals([["foo", false], ["bar", false]]),
      () => testLocals([["foo", false], ["bar", false], ["foobar", false]]),

      () => testLocals([["foo", true]]),
      () => testLocals([["foo", false], ["bar", true]]),
      () => testLocals([["foo", true], ["bar", true]]),

      () => testLocals([["foo", false], ["bar", false], ["foobar", true]]),
      () => testLocals([["foo", false], ["bar", true], ["foobar", true]]),
      () => testLocals([["foo", true], ["bar", true], ["foobar", true]]),

      () => testLocals([["foo", false], ["foo", false]])
          .then((MockCompiler compiler) {
      Expect.equals(1, compiler.errors.length);
      Expect.equals(
          new Message(MessageKind.DUPLICATE_DEFINITION, {'name': 'foo'}, false),
          compiler.errors[0].message);
    })], (f) => f());
}


Future testLocalsTwo() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    Node tree = parseStatement("if (true) { var a = 1; var b = 2; }");
    Element element = visitor.visit(tree);
    Expect.equals(null, element);
    MethodScope scope = visitor.scope;
    Expect.equals(0, scope.elements.length);
    Expect.equals(2, map(visitor).length);

    List<Element> elements = new List<Element>.from(map(visitor).values);
    Expect.notEquals(elements[0], elements[1]);
  });
}

Future testLocalsThree() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    Node tree = parseStatement("{ var a = 1; if (true) { a; } }");
    Element element = visitor.visit(tree);
    Expect.equals(null, element);
    MethodScope scope = visitor.scope;
    Expect.equals(0, scope.elements.length);
    Expect.equals(3, map(visitor).length);
    List<Element> elements = map(visitor).values.toList();
    Expect.equals(elements[0], elements[1]);
  });
}

Future testLocalsFour() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }");
    Element element = visitor.visit(tree);
    Expect.equals(null, element);
    MethodScope scope = visitor.scope;
    Expect.equals(0, scope.elements.length);
    Expect.equals(2, map(visitor).length);
    List<Element> elements = map(visitor).values.toList();
    Expect.notEquals(elements[0], elements[1]);
  });
}

Future testLocalsFive() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    If tree =
        parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}");
    Element element = visitor.visit(tree);
    Expect.equals(null, element);
    MethodScope scope = visitor.scope;
    Expect.equals(0, scope.elements.length);
    Expect.equals(6, map(visitor).length);

    Block thenPart = tree.thenPart;
    List statements1 = thenPart.statements.nodes.toList();
    Node def1 = statements1[0].definitions.nodes.head;
    Node id1 = statements1[1].expression;
    Expect.equals(visitor.registry.mapping[def1],
                  visitor.registry.mapping[id1]);

    Block elsePart = tree.elsePart;
    List statements2 = elsePart.statements.nodes.toList();
    Node def2 = statements2[0].definitions.nodes.head;
    Node id2 = statements2[1].expression;
    Expect.equals(visitor.registry.mapping[def2],
                  visitor.registry.mapping[id2]);

    Expect.notEquals(visitor.registry.mapping[def1],
                     visitor.registry.mapping[def2]);
    Expect.notEquals(visitor.registry.mapping[id1],
                     visitor.registry.mapping[id2]);
  });
}

Future testParametersOne() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    FunctionExpression tree =
        parseFunction("void foo(int a) { return a; }", compiler);
    visitor.visit(tree);

    // Check that an element has been created for the parameter.
    VariableDefinitions vardef = tree.parameters.nodes.head;
    Node param = vardef.definitions.nodes.head;
    Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[param].kind);

    // Check that 'a' in 'return a' is resolved to the parameter.
    Block body = tree.body;
    Return ret = body.statements.nodes.head;
    Send use = ret.expression;
    Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[use].kind);
    Expect.equals(visitor.registry.mapping[param],
                  visitor.registry.mapping[use]);
  });
}

Future testFor() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }");
    visitor.visit(tree);

    MethodScope scope = visitor.scope;
    Expect.equals(0, scope.elements.length);
    Expect.equals(10, map(visitor).length);

    VariableDefinitions initializer = tree.initializer;
    Node iNode = initializer.definitions.nodes.head;
    Element iElement = visitor.registry.mapping[iNode];

    // Check that we have the expected nodes. This test relies on the mapping
    // field to be a linked hash map (preserving insertion order).
    Expect.isTrue(map(visitor) is LinkedHashMap);
    List<Node> nodes = map(visitor).keys.toList();
    List<Element> elements = map(visitor).values.toList();


    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //      ^^^
    Expect.isTrue(nodes[0] is TypeAnnotation);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //          ^^^^^
    checkSendSet(iElement, nodes[1], elements[1]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                 ^
    checkIdentifier(iElement, nodes[2], elements[2]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                 ^
    checkSend(iElement, nodes[3], elements[3]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                         ^
    checkIdentifier(iElement, nodes[4], elements[4]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                             ^
    checkIdentifier(iElement, nodes[5], elements[5]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                             ^
    checkSend(iElement, nodes[6], elements[6]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                         ^^^^^^^^^
    checkSendSet(iElement, nodes[7], elements[7]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                                      ^
    checkIdentifier(iElement, nodes[8], elements[8]);

    // for (int i = 0; i < 10; i = i + 1) { i = 5; };
    //                                      ^^^^^
    checkSendSet(iElement, nodes[9], elements[9]);
  });
}

checkIdentifier(Element expected, Node node, Element actual) {
  Expect.isTrue(node is Identifier, node.toDebugString());
  Expect.equals(expected, actual);
}

checkSend(Element expected, Node node, Element actual) {
  Expect.isTrue(node is Send, node.toDebugString());
  Expect.isTrue(node is !SendSet, node.toDebugString());
  Expect.equals(expected, actual);
}

checkSendSet(Element expected, Node node, Element actual) {
  Expect.isTrue(node is SendSet, node.toDebugString());
  Expect.equals(expected, actual);
}

Future testTypeAnnotation() {
  return MockCompiler.create((MockCompiler compiler) {
    String statement = "Foo bar;";

    // Test that we get a warning when Foo is not defined.
    Map mapping = compiler.resolveStatement(statement).map;

    Expect.equals(2, mapping.length); // Both Foo and bar have an element.
    Expect.equals(1, compiler.warnings.length);

    Node warningNode = compiler.warnings[0].node;

    Expect.equals(
        new Message(
            MessageKind.CANNOT_RESOLVE_TYPE,  {'typeName': 'Foo'}, false),
        compiler.warnings[0].message);
    VariableDefinitions definition = compiler.parsedTree;
    Expect.equals(warningNode, definition.type);
    compiler.clearMessages();

    // Test that there is no warning after defining Foo.
    compiler.parseScript("class Foo {}");
    mapping = compiler.resolveStatement(statement).map;
    Expect.equals(2, mapping.length);
    Expect.equals(0, compiler.warnings.length);

    // Test that 'var' does not create a warning.
    mapping = compiler.resolveStatement("var foo;").map;
    Expect.equals(1, mapping.length);
    Expect.equals(0, compiler.warnings.length);
  });
}

Future testSuperclass() {
  return Future.wait([
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("class Foo extends Bar {}");
      compiler.resolveStatement("Foo bar;");
      Expect.equals(1, compiler.errors.length);
      var cannotResolveBar = new Message(MessageKind.CANNOT_EXTEND_MALFORMED,
          {'className': 'Foo', 'malformedType': 'Bar'}, false);
      Expect.equals(cannotResolveBar, compiler.errors[0].message);
      compiler.clearMessages();
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("class Foo extends Bar {}");
      compiler.parseScript("class Bar {}");
      Map mapping = compiler.resolveStatement("Foo bar;").map;
      Expect.equals(2, mapping.length);

      ClassElement fooElement = compiler.mainApp.find('Foo');
      ClassElement barElement = compiler.mainApp.find('Bar');
      Expect.equals(barElement.computeType(compiler),
                    fooElement.supertype);
      Expect.isTrue(fooElement.interfaces.isEmpty);
      Expect.isTrue(barElement.interfaces.isEmpty);
    }),
  ]);
}

Future testVarSuperclass() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript("class Foo extends var {}");
    compiler.resolveStatement("Foo bar;");
    Expect.equals(1, compiler.errors.length);
    Expect.equals(
        new Message(
            MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'var'}, false),
        compiler.errors[0].message);
    compiler.clearMessages();
  });
}

Future testOneInterface() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript("class Foo implements Bar {}");
    compiler.resolveStatement("Foo bar;");
    Expect.equals(1, compiler.errors.length);
    Expect.equals(
        new Message(
            MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'bar'}, false),
        compiler.errors[0].message);
    compiler.clearMessages();

    // Add the abstract class to the world and make sure everything is setup
    // correctly.
    compiler.parseScript("abstract class Bar {}");

    ResolverVisitor visitor =
        new ResolverVisitor(compiler, null,
            new ResolutionRegistry.internal(compiler,
                new CollectingTreeElements(null)));
    compiler.resolveStatement("Foo bar;");

    ClassElement fooElement = compiler.mainApp.find('Foo');
    ClassElement barElement = compiler.mainApp.find('Bar');

    Expect.equals(null, barElement.supertype);
    Expect.isTrue(barElement.interfaces.isEmpty);

    Expect.equals(barElement.computeType(compiler),
                  fooElement.interfaces.head);
    Expect.equals(1, length(fooElement.interfaces));
  });
}

Future testTwoInterfaces() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript(
        """abstract class I1 {} 
           abstract class I2 {} 
           class C implements I1, I2 {}""");
    compiler.resolveStatement("Foo bar;");

    ClassElement c = compiler.mainApp.find('C');
    Element i1 = compiler.mainApp.find('I1');
    Element i2 = compiler.mainApp.find('I2');

    Expect.equals(2, length(c.interfaces));
    Expect.equals(i1.computeType(compiler), at(c.interfaces, 0));
    Expect.equals(i2.computeType(compiler), at(c.interfaces, 1));
  });
}

Future testFunctionExpression() {
  return MockCompiler.create((MockCompiler compiler) {
    ResolverVisitor visitor = compiler.resolverVisitor();
    Map mapping = compiler.resolveStatement("int f() {}").map;
    Expect.equals(3, mapping.length);
    Element element;
    Node node;
    mapping.forEach((Node n, Element e) {
      if (n is FunctionExpression) {
        element = e;
        node = n;
      }
    });
    Expect.equals(ElementKind.FUNCTION, element.kind);
    Expect.equals('f', element.name);
    Expect.equals((element as FunctionElement).node, node);
  });
}

Future testNewExpression() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript("class A {} foo() { print(new A()); }");
    ClassElement aElement = compiler.mainApp.find('A');

    FunctionElement fooElement = compiler.mainApp.find('foo');
    compiler.resolver.resolve(fooElement);

    Expect.isNotNull(aElement);
    Expect.isNotNull(fooElement);

    fooElement.node;
    compiler.resolver.resolve(fooElement);

    TreeElements elements = compiler.resolveStatement("new A();");
    NewExpression expression =
        compiler.parsedTree.asExpressionStatement().expression;
    Element element = elements[expression.send];
    Expect.equals(ElementKind.GENERATIVE_CONSTRUCTOR, element.kind);
    Expect.isTrue(element.isSynthesized);
  });
}

Future testTopLevelFields() {
  return MockCompiler.create((MockCompiler compiler) {
    compiler.parseScript("int a;");
    VariableElementX element = compiler.mainApp.find("a");
    Expect.equals(ElementKind.FIELD, element.kind);
    VariableDefinitions node = element.variables.parseNode(element, compiler);
    Identifier typeName = node.type.typeName;
    Expect.equals(typeName.source, 'int');

    compiler.parseScript("var b, c;");
    VariableElementX bElement = compiler.mainApp.find("b");
    VariableElementX cElement = compiler.mainApp.find("c");
    Expect.equals(ElementKind.FIELD, bElement.kind);
    Expect.equals(ElementKind.FIELD, cElement.kind);
    Expect.isTrue(bElement != cElement);

    VariableDefinitions bNode = bElement.variables.parseNode(bElement, compiler);
    VariableDefinitions cNode = cElement.variables.parseNode(cElement, compiler);
    Expect.equals(bNode, cNode);
    Expect.isNull(bNode.type);
    Expect.isTrue(bNode.modifiers.isVar);
  });
}

Future resolveConstructor(
    String script, String statement, String className,
    String constructor, int expectedElementCount,
    {List expectedWarnings: const [],
     List expectedErrors: const [],
     List expectedInfos: const [],
     String corelib: DEFAULT_CORELIB}) {
  MockCompiler compiler = new MockCompiler.internal(coreSource: corelib);
  return compiler.init().then((_) {
    compiler.parseScript(script);
    compiler.resolveStatement(statement);
    ClassElement classElement = compiler.mainApp.find(className);
    Element element;
    if (constructor != '') {
      element = classElement.lookupConstructor(
          new Selector.callConstructor(constructor, classElement.library));
    } else {
      element = classElement.lookupConstructor(
          new Selector.callDefaultConstructor(classElement.library));
    }

    FunctionExpression tree = (element as FunctionElement).node;
    ResolverVisitor visitor =
        new ResolverVisitor(compiler, element,
            new ResolutionRegistry.internal(compiler,
                new CollectingTreeElements(element)));
    new InitializerResolver(visitor).resolveInitializers(element, tree);
    visitor.visit(tree.body);
    Expect.equals(expectedElementCount, map(visitor).length);

    compareWarningKinds(script, expectedWarnings, compiler.warnings);
    compareWarningKinds(script, expectedErrors, compiler.errors);
    compareWarningKinds(script, expectedInfos, compiler.infos);
  });
}

Future testClassHierarchy() {
  final MAIN = "main";
  return Future.wait([
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A extends A {}
                              main() { return new A(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
                    compiler.errors[0].message.kind);
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A extends B {}
                              class B extends A {}
                              main() { return new A(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(2, compiler.errors.length);
      Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
                    compiler.errors[0].message.kind);
      Expect.equals(MessageKind.CANNOT_FIND_CONSTRUCTOR,
                    compiler.errors[1].message.kind);
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""abstract class A extends B {}
                              abstract class B extends A {}
                              class C implements A {}
                              main() { return new C(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
                    compiler.errors[0].message.kind);
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A extends B {}
                              class B extends C {}
                              class C {}
                              main() { return new A(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(0, compiler.errors.length);
      ClassElement aElement = compiler.mainApp.find("A");
      Link<DartType> supertypes = aElement.allSupertypes;
      Expect.equals(<String>['B', 'C', 'Object'].toString(),
                    asSortedStrings(supertypes).toString());
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A<T> {}
                              class B<Z,W> extends A<int> 
                                  implements I<Z,List<W>> {}
                              class I<X,Y> {}
                              class C extends B<bool,String> {}
                              main() { return new C(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(0, compiler.errors.length);
      ClassElement aElement = compiler.mainApp.find("C");
      Link<DartType> supertypes = aElement.allSupertypes;
      // Object is once per inheritance path, that is from both A and I.
      Expect.equals(<String>['A<int>', 'B<bool, String>',
                             'I<bool, List<String>>', 'Object'].toString(),
                    asSortedStrings(supertypes).toString());
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A<T> {}
                              class D extends A<E> {}
                              class E extends D {}
                              main() { return new E(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(0, compiler.errors.length);
      ClassElement aElement = compiler.mainApp.find("E");
      Link<DartType> supertypes = aElement.allSupertypes;
      Expect.equals(<String>['A<E>', 'D', 'Object'].toString(),
                    asSortedStrings(supertypes).toString());
    }),
    MockCompiler.create((MockCompiler compiler) {
      compiler.parseScript("""class A<T> {}
                              class D extends A<int> implements A<double> {}
                              main() { return new D(); }""");
      FunctionElement mainElement = compiler.mainApp.find(MAIN);
      compiler.resolver.resolve(mainElement);
      Expect.equals(0, compiler.warnings.length);
      Expect.equals(1, compiler.errors.length);
      Expect.equals(MessageKind.MULTI_INHERITANCE,
                    compiler.errors[0].message.kind);
      Expect.equals(0, compiler.crashes.length);
    }),
  ]);
}

Future testInitializers() {
  return Future.forEach([
    () {
      String script =
          """class A {
                    int foo; int bar;
                    A() : this.foo = 1, bar = 2;
                  }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 2);
    },
    () {
      String script =
          """class A {
               int foo; A a;
               A() : a.foo = 1;
             }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 0,
          expectedWarnings: [],
          expectedErrors: [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]);
    },
    () {
      String script =
          """class A {
               int foo;
               A() : this.foo = 1, this.foo = 2;
             }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 2,
          expectedInfos: [MessageKind.ALREADY_INITIALIZED],
          expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]);
    },
    () {
      String script =
          """class A {
               A() : this.foo = 1;
             }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 0,
          expectedWarnings: [],
          expectedErrors: [MessageKind.CANNOT_RESOLVE]);
    },
    () {
      String script =
          """class A {
               int foo;
               int bar;
               A() : this.foo = bar;
             }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 3,
          expectedWarnings: [],
          expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]);
    },
    () {
      String script =
          """class A {
               int foo() => 42;
               A() : foo();
             }""";
      return resolveConstructor(script, "A a = new A();", "A", "", 0,
          expectedWarnings: [],
          expectedErrors: [MessageKind.CONSTRUCTOR_CALL_EXPECTED]);
    },
    () {
      String script =
          """class A {
               int i;
               A.a() : this.b(0);
               A.b(int i);
             }""";
      return resolveConstructor(script, "A a = new A.a();", "A", "a", 1);
    },
    () {
      String script =
          """class A {
               int i;
               A.a() : i = 42, this(0);
               A(int i);
             }""";
      return resolveConstructor(script, "A a = new A.a();", "A", "a", 2,
          expectedWarnings: [],
          expectedErrors:
              [MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER]);
    },
    () {
      String script =
          """class A {
               int i;
               A(i);
             }
             class B extends A {
               B() : super(0);
             }""";
      return resolveConstructor(script, "B a = new B();", "B", "", 1);
    },
    () {
      String script =
          """class A {
               int i;
               A(i);
             }
             class B extends A {
               B() : super(0), super(1);
             }""";
      return resolveConstructor(script, "B b = new B();", "B", "", 2,
          expectedWarnings: [],
          expectedErrors: [MessageKind.DUPLICATE_SUPER_INITIALIZER]);
    },
    () {
      String script = "";
      final String CORELIB_WITH_INVALID_OBJECT =
          '''print(var obj) {}
             class int {}
             class double {}
             class bool {}
             class String {}
             class num {}
             class Function {}
             class List<E> {}
             class Map {}
             class Closure {}
             class Null {}
             class StackTrace {}
             class Dynamic_ {}
             class Type {}
             class Object { Object() : super(); }
             const proxy = 0;''';
      return resolveConstructor(script,
          "Object o = new Object();", "Object", "", 1,
          expectedWarnings: [],
          expectedErrors: [MessageKind.SUPER_INITIALIZER_IN_OBJECT],
          corelib: CORELIB_WITH_INVALID_OBJECT);
    },
  ], (f) => f());
}

map(ResolverVisitor visitor) {
  CollectingTreeElements elements = visitor.registry.mapping;
  return elements.map;
}

at(Link link, int index) => (index == 0) ? link.head : at(link.tail, index - 1);

List<String> asSortedStrings(Link link) {
  List<String> result = <String>[];
  for (; !link.isEmpty; link = link.tail) result.add(link.head.toString());
  result.sort((s1, s2) => s1.compareTo(s2));
  return result;
}

Future compileScript(String source) {
  Uri uri = new Uri(scheme: 'source');
  MockCompiler compiler = compilerFor(source, uri);
  compiler.diagnosticHandler = createHandler(compiler, source);
  return compiler.runCompiler(uri).then((_) {
    return compiler;
  });
}

checkMemberResolved(compiler, className, memberName) {
  ClassElement cls = findElement(compiler, className);
  Element memberElement = cls.lookupLocalMember(memberName);
  Expect.isNotNull(memberElement);
  Expect.isTrue(
      compiler.enqueuer.resolution.hasBeenResolved(memberElement));
}

testToString() {
  final script = r"class C { toString() => 'C'; } main() { '${new C()}'; }";
  asyncTest(() => compileScript(script).then((compiler) {
    checkMemberResolved(compiler, 'C', 'toString');
  }));
}

operatorName(op, isUnary) {
  return Elements.constructOperatorName(op, isUnary);
}

testIndexedOperator() {
  final script = r"""
      class C {
        operator[](ix) => ix;
        operator[]=(ix, v) {}
      }
      main() { var c = new C(); c[0]++; }""";
  asyncTest(() => compileScript(script).then((compiler) {
    checkMemberResolved(compiler, 'C', operatorName('[]', false));
    checkMemberResolved(compiler, 'C', operatorName('[]=', false));
  }));
}

testIncrementsAndDecrements() {
  final script = r"""
      class A { operator+(o)=>null; }
      class B { operator+(o)=>null; }
      class C { operator-(o)=>null; }
      class D { operator-(o)=>null; }
      main() {
        var a = new A();
        a++;
        var b = new B();
        ++b;
        var c = new C();
        c--;
        var d = new D();
        --d;
      }""";
  asyncTest(() => compileScript(script).then((compiler) {
    checkMemberResolved(compiler, 'A', operatorName('+', false));
    checkMemberResolved(compiler, 'B', operatorName('+', false));
    checkMemberResolved(compiler, 'C', operatorName('-', false));
    checkMemberResolved(compiler, 'D', operatorName('-', false));
  }));
}

testOverrideHashCodeCheck() {
  final script = r"""
      class A {
        operator==(other) => true;
      }
      class B {
        operator==(other) => true;
        get hashCode => 0;
      }
      main() {
        new A() == new B();
      }""";
  asyncTest(() => compileScript(script).then((compiler) {
    Expect.equals(0, compiler.warnings.length);
    Expect.equals(0, compiler.infos.length);
    Expect.equals(1, compiler.hints.length);
    Expect.equals(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
                  compiler.hints[0].message.kind);
    Expect.equals(0, compiler.errors.length);
  }));
}

testConstConstructorAndNonFinalFields() {
  void expect(compiler, List errors, List infos) {
    Expect.equals(errors.length, compiler.errors.length);
    for (int i = 0 ; i < errors.length ; i++) {
      Expect.equals(errors[i], compiler.errors[i].message.kind);
    }
    Expect.equals(0, compiler.warnings.length);
    Expect.equals(infos.length, compiler.infos.length);
    for (int i = 0 ; i < infos.length ; i++) {
      Expect.equals(infos[i], compiler.infos[i].message.kind);
    }
  }

  final script1 = r"""
      class A {
        var a;
        const A(this.a);
      }
      main() {
        new A(0);
      }""";
  asyncTest(() => compileScript(script1).then((compiler) {
    expect(compiler,
           [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS],
           [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]);
  }));

  final script2 = r"""
      class A {
        var a;
        var b;
        const A(this.a, this.b);
        const A.named(this.a, this.b);
      }
      main() {
        new A(0, 1);
      }""";
  asyncTest(() => compileScript(script2).then((compiler) {
    expect(compiler,
        [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS],
        [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR,
         MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR,
         MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD,
         MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]);
  }));
}
