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

// Test that dart2js produces the expected static type warnings to ensures that
// the analyzer and dart2js agrees on the tests.

import 'dart:async';
import 'dart:io';
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'memory_compiler.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/source_file_provider.dart';
import 'package:compiler/src/util/uri_extras.dart';
import 'dart:convert';

void checkWarnings(Map<String, dynamic> tests, [List<String> arguments]) {
  bool isWindows = Platform.isWindows;
  Uri script = currentDirectory.resolveUri(Platform.script);
  bool warningsMismatch = false;
  bool verbose = arguments != null && arguments.contains('-v');
  asyncTest(() => Future.forEach(tests.keys, (String test) async {
    Uri uri = script.resolve('../../$test');
    String source = UTF8.decode(readAll(uriPathToNative(uri.path)));
    SourceFile file = new StringSourceFile(
        uri, relativize(currentDirectory, uri, isWindows), source);
    Map<int,String> expectedWarnings = {};
    int lineNo = 0;
    for (String line in source.split('\n')) {
      if (line.contains('///') &&
          (line.contains('static type warning') ||
           line.contains('static warning'))) {
        expectedWarnings[lineNo] = line;
      }
      lineNo++;
    }
    Set<int> unseenWarnings = new Set<int>.from(expectedWarnings.keys);
    DiagnosticCollector collector = new DiagnosticCollector();
    await runCompiler(
        entryPoint: uri,
        diagnosticHandler: collector,
        options: [Flags.analyzeOnly],
        showDiagnostics: verbose);
    Map<String, List<int>> statusMap = tests[test];
    // Line numbers with known unexpected warnings.
    List<int> unexpectedStatus = [];
    if (statusMap != null && statusMap.containsKey('unexpected')) {
      unexpectedStatus = statusMap['unexpected'];
    }
    // Line numbers with known missing warnings.
    List<int> missingStatus = [];
    if (statusMap != null && statusMap.containsKey('missing')) {
      missingStatus = statusMap['missing'];
    }
    for (DiagnosticMessage message in collector.warnings) {
      Expect.equals(uri, message.uri);
      int lineNo = file.getLine(message.begin);
      if (expectedWarnings.containsKey(lineNo)) {
        unseenWarnings.remove(lineNo);
      } else if (!unexpectedStatus.contains(lineNo+1)) {
        warningsMismatch = true;
        print(file.getLocationMessage(
            'Unexpected warning: ${message.message}',
            message.begin, message.end));
      }
    }
    if (!unseenWarnings.isEmpty) {
      for (int lineNo in unseenWarnings) {
        if (!missingStatus.contains(lineNo+1)) {
          warningsMismatch = true;
          String line = expectedWarnings[lineNo];
          print('$uri [${lineNo+1}]: Missing static type warning.');
          print(line);
        }
      }
    }
  }).then((_) {
    Expect.isFalse(warningsMismatch);
  }));
}
