// 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 for type
// promotion langauge tests. This ensures that the analyzer and dart2js agrees
// on these tests.

import 'dart:async';
import 'dart:io';
import 'package:expect/expect.dart';
import 'memory_compiler.dart';
import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
import '../../../sdk/lib/_internal/compiler/implementation/util/uri_extras.dart';

const List<String> TESTS = const [
    'language/type_promotion_assign_test.dart',
    'language/type_promotion_closure_test.dart',
    'language/type_promotion_functions_test.dart',
    'language/type_promotion_local_test.dart',
    'language/type_promotion_logical_and_test.dart',
    'language/type_promotion_more_specific_test.dart',
    'language/type_promotion_multiple_test.dart',
    'language/type_promotion_parameter_test.dart',
];

void main() {
  bool isWindows = (Platform.operatingSystem == 'windows');
  Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
  bool warningsMismatch = false;
  Future.forEach(TESTS, (String test) {
    Uri uri = script.resolve('../../$test');
    String source = readAll(uriPathToNative(uri.path));
    SourceFile file = new SourceFile(
        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')) {
        expectedWarnings[lineNo] = line;
      }
      lineNo++;
    }
    Set<int> unseenWarnings = new Set<int>.from(expectedWarnings.keys);
    DiagnosticCollector collector = new DiagnosticCollector();
    var compiler = compilerFor(const {},
         diagnosticHandler: collector,
         options: ['--analyze-only'],
         showDiagnostics: false);
    return compiler.run(uri).then((_) {
      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 {
          warningsMismatch = true;
          print(file.getLocationMessage(
              'Unexpected warning: ${message.message}',
              message.begin, message.end, true, (x) => x));
        }
      }
      if (!unseenWarnings.isEmpty) {
        warningsMismatch = true;
        for (int lineNo in unseenWarnings) {
          String line = expectedWarnings[lineNo];
          print('$uri [${lineNo+1}]: Missing static type warning.');
          print(line);
        }
      }
    });
  }).then((_) {
    Expect.isFalse(warningsMismatch);
  });
}
