// Copyright (c) 2013, 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 dart2js.test.message_kind_helper;

import 'package:expect/expect.dart';
import 'dart:async';

import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart' show
    Compiler;
import 'package:compiler/src/dart_backend/dart_backend.dart' show
    DartBackend;
import 'package:compiler/src/diagnostics/messages.dart' show
    MessageKind,
    MessageTemplate;
import 'package:compiler/compiler_new.dart' show
    Diagnostic;

import 'memory_compiler.dart';

const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]';

/// Most examples generate a single diagnostic.
/// Add an exception here if a single diagnostic cannot be produced.
/// However, consider that a single concise diagnostic is easier to understand,
/// so try to change error reporting logic before adding an exception.
final Set<MessageKind> kindsWithExtraMessages = new Set<MessageKind>.from([
    // If you add something here, please file a *new* bug report.
    // See http://dartbug.com/18361:
    MessageKind.CANNOT_EXTEND_MALFORMED,
    MessageKind.CANNOT_IMPLEMENT_MALFORMED,
    MessageKind.CANNOT_MIXIN,
    MessageKind.CANNOT_MIXIN_MALFORMED,
    MessageKind.CANNOT_INSTANTIATE_ENUM,
    MessageKind.CYCLIC_TYPEDEF_ONE,
    MessageKind.DUPLICATE_DEFINITION,
    MessageKind.EQUAL_MAP_ENTRY_KEY,
    MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
    MessageKind.FORMAL_DECLARED_CONST,
    MessageKind.FORMAL_DECLARED_STATIC,
    MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT,
    MessageKind.HIDDEN_IMPLICIT_IMPORT,
    MessageKind.HIDDEN_IMPORT,
    MessageKind.INHERIT_GETTER_AND_METHOD,
    MessageKind.UNIMPLEMENTED_METHOD,
    MessageKind.UNIMPLEMENTED_METHOD_ONE,
    MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
]);

/// Most messages can be tested without causing a fatal error. Add an exception
/// here if a fatal error is unavoidable and leads to pending classes.
/// Try to avoid adding exceptions here; a fatal error causes the compiler to
/// stop before analyzing all input, and it isn't safe to reuse it.
final Set<MessageKind> kindsWithPendingClasses = new Set<MessageKind>.from([
    // If you add something here, please file a *new* bug report.
]);

Future<Compiler> check(MessageTemplate template, Compiler cachedCompiler) {
  Expect.isFalse(template.examples.isEmpty);

  return Future.forEach(template.examples, (example) {
    if (example is String) {
      example = {'main.dart': example};
    } else {
      Expect.isTrue(example is Map,
                    "Example must be either a String or a Map.");
      Expect.isTrue(example.containsKey('main.dart'),
                    "Example map must contain a 'main.dart' entry.");
    }
    DiagnosticCollector collector = new DiagnosticCollector();

    bool oldBackendIsDart;
    if (cachedCompiler != null) {
      oldBackendIsDart = cachedCompiler.backend is DartBackend;
    }
    bool newBackendIsDart = template.options.contains('--output-type=dart');

    Compiler compiler = compilerFor(
        memorySourceFiles: example,
        diagnosticHandler: collector,
        options: [Flags.analyzeOnly,
                  Flags.enableExperimentalMirrors]..addAll(template.options),
        cachedCompiler:
             // TODO(johnniwinther): Remove this restriction when constant
             // values can be computed directly from the expressions.
             oldBackendIsDart == newBackendIsDart ? cachedCompiler : null);

    return compiler.run(Uri.parse('memory:main.dart')).then((_) {
      Iterable<CollectedMessage> messages = collector.filterMessagesByKinds(
          [Diagnostic.ERROR,
           Diagnostic.WARNING,
           Diagnostic.HINT,
           Diagnostic.CRASH]);

      Expect.isFalse(messages.isEmpty, 'No messages in """$example"""');

      String expectedText = !template.hasHowToFix
          ? template.template : '${template.template}\n${template.howToFix}';
      String pattern = expectedText.replaceAllMapped(
          new RegExp(ESCAPE_REGEXP), (m) => '\\${m[0]}');
      pattern = pattern.replaceAll(new RegExp(r'#\\\{[^}]*\\\}'), '.*');

      bool checkMessage(CollectedMessage message) {
        if (message.message.kind != MessageKind.GENERIC) {
          return message.message.kind == template.kind;
        } else {
          return new RegExp('^$pattern\$').hasMatch(message.text);
        }
      }

      // TODO(johnniwinther): Extend MessageKind to contain information on
      // where info messages are expected.
      bool messageFound = false;
      List unexpectedMessages = [];
      for (CollectedMessage message in messages) {
        if (!messageFound && checkMessage(message)) {
          messageFound = true;
        } else {
          unexpectedMessages.add(message);
        }
      }
      Expect.isTrue(messageFound,
          '${template.kind}} does not match any in\n '
          '${messages.join('\n ')}');
      var reporter = compiler.reporter;
      Expect.isFalse(reporter.hasCrashed);
      if (!unexpectedMessages.isEmpty) {
        for (CollectedMessage message in unexpectedMessages) {
          print("Unexpected message: $message");
        }
        if (!kindsWithExtraMessages.contains(template.kind)) {
          // Try changing the error reporting logic before adding an exception
          // to [kindsWithExtraMessages].
          throw 'Unexpected messages found.';
        }
      }

      bool pendingStuff = false;
      for (var e in compiler.resolver.pendingClassesToBePostProcessed) {
        pendingStuff = true;
        compiler.reporter.reportInfo(
            e, MessageKind.GENERIC,
            {'text': 'Pending class to be post-processed.'});
      }
      for (var e in compiler.resolver.pendingClassesToBeResolved) {
        pendingStuff = true;
        compiler.reporter.reportInfo(
            e, MessageKind.GENERIC,
            {'text': 'Pending class to be resolved.'});
      }
      Expect.isTrue(!pendingStuff ||
                    kindsWithPendingClasses.contains(template));

      if (!pendingStuff) {
        // If there is pending stuff, or the compiler was cancelled, we
        // shouldn't reuse the compiler.
        cachedCompiler = compiler;
      }
    });
  }).then((_) => cachedCompiler);
}
