// 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 "../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart";
import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart";
import "../../../sdk/lib/_internal/compiler/implementation/resolution/resolution.dart";
import "../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart";
import "../../../sdk/lib/_internal/compiler/implementation/util/util.dart";
import "mock_compiler.dart";
import "parser_helper.dart";

class CallbackMockCompiler extends MockCompiler {
  CallbackMockCompiler();

  var onError;
  var onWarning;

  setOnError(var f) => onError = f;
  setOnWarning(var f) => onWarning = f;

  void reportWarning(Node node, var message) {
    if (onWarning != null) onWarning(this, node, message);
    super.reportWarning(node, message);
  }

  void reportError(Node node, var message) {
    if (onError != null) onError(this, node, message);
    super.reportError(node, message);
  }
}

testErrorHandling() {
  // Test that compiler.currentElement is set correctly when
  // reporting errors/warnings.
  CallbackMockCompiler compiler = new CallbackMockCompiler();
  ResolverVisitor visitor = compiler.resolverVisitor();
  compiler.parseScript('NoSuchPrefix.NoSuchType foo() {}');
  FunctionElement foo = compiler.mainApp.find(buildSourceString('foo'));
  compiler.setOnWarning((c, n, m) => Expect.equals(foo, compiler.currentElement));
  foo.computeType(compiler);
  Expect.equals(1, compiler.warnings.length);
}

main() {
  testErrorHandling();
}
