// Copyright (c) 2016, 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.analyze_test.test;

import 'dart:io';

import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/apiimpl.dart' show CompilerImpl;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show MessageKind;
import 'package:compiler/src/filenames.dart' show nativeToUriPath;

import 'analyze_helper.dart';
import 'memory_compiler.dart';

/**
 * Map of white-listed warnings and errors.
 *
 * Use an identifiable suffix of the file uri as key. Use a fixed substring of
 * the error/warning message in the list of white-listings for each file.
 */
// TODO(johnniwinther): Support canonical URIs as keys.
const Map<String, List/*<String|MessageKind>*/ > WHITE_LIST = const {
  "/test/lib/src/util/": const [
    "Library 'package:async/async.dart' doesn't export a "
        "'ForkableStream' declaration.",
  ],
};

const List<String> SKIP_LIST = const <String>[
  // Helper files:
  "/data/",
  "quarantined/http_launch_data/",
  "mirrors_helper.dart",
  "path%20with%20spaces/",
  // Broken tests:
  "quarantined/http_test.dart",
  // Package directory
  "packages/",
];

List<Uri> computeInputUris({String filter}) {
  List<Uri> uriList = <Uri>[];
  Directory dir =
      new Directory.fromUri(Uri.base.resolve('tests/compiler/dart2js/'));
  for (FileSystemEntity entity in dir.listSync(recursive: true)) {
    if (entity is File && entity.path.endsWith('.dart')) {
      Uri file = Uri.base.resolve(nativeToUriPath(entity.path));
      if (filter != null && !'$file'.contains(filter)) {
        continue;
      }
      if (!SKIP_LIST.any((skip) => file.path.contains(skip))) {
        uriList.add(file);
      }
    }
  }
  return uriList;
}

main(List<String> arguments) {
  List<String> options = <String>[];
  List<Uri> uriList = <Uri>[];
  String filter;
  bool first = true;
  for (String argument in arguments) {
    if (argument.startsWith('-')) {
      options.add(argument == '-v' ? Flags.verbose : argument);
    } else if (first) {
      File file = new File(argument);
      if (file.existsSync()) {
        // Read test files from [file].
        for (String line in file.readAsLinesSync()) {
          line = line.trim();
          if (line.startsWith('Analyzing uri: ')) {
            int filenameOffset = line.indexOf('tests/compiler/dart2js/');
            if (filenameOffset != -1) {
              uriList.add(Uri.base
                  .resolve(nativeToUriPath(line.substring(filenameOffset))));
            }
          }
        }
      } else {
        // Use argument as filter on test files.
        filter = argument;
      }
    } else {
      throw new ArgumentError("Extra argument $argument in $arguments.");
    }
    first = false;
  }

  asyncTest(() async {
    if (uriList.isEmpty) {
      uriList = computeInputUris(filter: filter);
    }
    await analyze(uriList, WHITE_LIST,
        mode: AnalysisMode.URI, options: options);
  });
}
