// 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 analyze_helper;

import 'dart:async';
import 'dart:io';
import 'package:compiler/compiler.dart' as api;
import 'package:compiler/src/apiimpl.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show
    Message,
    MessageKind;
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/source_file_provider.dart';
import 'package:compiler/src/util/uri_extras.dart';

/**
 * Map of whitelisted warnings and errors.
 *
 * Only add a whitelisting together with a bug report to dartbug.com and add
 * the bug issue number as a comment on the whitelisting.
 *
 * Use an identifiable suffix of the file uri as key. Use a fixed substring of
 * the error/warning message in the list of whitelistings for each file.
 */
// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
// values.

class CollectingDiagnosticHandler extends FormattingDiagnosticHandler {
  bool hasWarnings = false;
  bool hasHint = false;
  bool hasErrors = false;
  bool lastWasWhitelisted = false;

  Map<String, Map<dynamic/*String|MessageKind*/, int>> whiteListMap
      = new Map<String, Map<dynamic/*String|MessageKind*/, int>>();

  CollectingDiagnosticHandler(
      Map<String, List/*<String|MessageKind>*/> whiteList,
      SourceFileProvider provider)
      : super(provider) {
    whiteList.forEach((String file, List/*<String|MessageKind>*/ messageParts) {
      var useMap = new Map<dynamic/*String|MessageKind*/, int>();
      for (var messagePart in messageParts) {
        useMap[messagePart] = 0;
      }
      whiteListMap[file] = useMap;
    });
  }

  bool checkResults() {
    bool validWhiteListUse = checkWhiteListUse();
    reportWhiteListUse();
    return !hasWarnings && !hasHint && !hasErrors && validWhiteListUse;
  }

  bool checkWhiteListUse() {
    bool allUsed = true;
    for (String file in whiteListMap.keys) {
      for (var messagePart in whiteListMap[file].keys) {
        if (whiteListMap[file][messagePart] == 0) {
          print("Whitelisting '$messagePart' is unused in '$file'. "
                "Remove the whitelisting from the whitelist map.");
          allUsed = false;
        }
      }
    }
    return allUsed;
  }

  void reportWhiteListUse() {
    for (String file in whiteListMap.keys) {
      for (var messagePart in whiteListMap[file].keys) {
        int useCount = whiteListMap[file][messagePart];
        print("Whitelisted message '$messagePart' suppressed $useCount "
              "time(s) in '$file'.");
      }
    }
  }

  bool checkWhiteList(Uri uri, Message message, String text) {
    if (uri == null) {
      return false;
    }
    String path = uri.path;
    for (String file in whiteListMap.keys) {
      if (path.contains(file)) {
        for (var messagePart in whiteListMap[file].keys) {
          bool found = false;
          if (messagePart is String) {
            found = text.contains(messagePart);
          } else {
            assert(messagePart is MessageKind);
            found = message.kind == messagePart;
          }
          if (found) {
            whiteListMap[file][messagePart]++;
            return true;
          }
        }
      }
    }
    return false;
  }

  @override
  void report(Message message, Uri uri, int begin, int end, String text,
              api.Diagnostic kind) {
    if (kind == api.Diagnostic.WARNING) {
      if (checkWhiteList(uri, message, text)) {
        // Suppress whitelisted warnings.
        lastWasWhitelisted = true;
        return;
      }
      hasWarnings = true;
    }
    if (kind == api.Diagnostic.HINT) {
      if (checkWhiteList(uri, message, text)) {
        // Suppress whitelisted hints.
        lastWasWhitelisted = true;
        return;
      }
      hasHint = true;
    }
    if (kind == api.Diagnostic.ERROR) {
      if (checkWhiteList(uri, message, text)) {
        // Suppress whitelisted errors.
        lastWasWhitelisted = true;
        return;
      }
      hasErrors = true;
    }
    if (kind == api.Diagnostic.INFO && lastWasWhitelisted) {
      return;
    }
    lastWasWhitelisted = false;
    super.report(message, uri, begin, end, text, kind);
  }
}

typedef bool CheckResults(CompilerImpl compiler,
                          CollectingDiagnosticHandler handler);

enum AnalysisMode {
  /// Analyze all declarations in all libraries in one go.
  ALL,
  /// Analyze all declarations in the main library.
  MAIN,
  /// Analyze all declarations in the given URIs one at a time. This mode can
  /// handle URIs for parts (i.e. skips these).
  URI,
  /// Analyze all declarations reachable from the entry point.
  TREE_SHAKING,
}

Future analyze(List<Uri> uriList,
               Map<String, List/*<String|MessageKind>*/> whiteList,
               {AnalysisMode mode: AnalysisMode.ALL,
                CheckResults checkResults}) async {
  String testFileName =
      relativize(Uri.base, Platform.script, Platform.isWindows);

  print("""


===
=== NOTE: If this test fails, update [WHITE_LIST] in $testFileName
===


""");

  var libraryRoot = currentDirectory.resolve('sdk/');
  var packageRoot =
      currentDirectory.resolve(Platform.packageRoot);
  var provider = new CompilerSourceFileProvider();
  var handler = new CollectingDiagnosticHandler(whiteList, provider);
  var options = <String>[Flags.analyzeOnly, '--categories=Client,Server',
      Flags.showPackageWarnings];
  switch (mode) {
    case AnalysisMode.URI:
    case AnalysisMode.MAIN:
      options.add(Flags.analyzeMain);
      break;
    case AnalysisMode.ALL:
      options.add(Flags.analyzeAll);
      break;
    case AnalysisMode.TREE_SHAKING:
      break;
  }
  var compiler = new CompilerImpl(
      provider,
      null,
      handler,
      libraryRoot,
      packageRoot,
      options,
      {});
  String MESSAGE = """


===
=== ERROR: Unexpected result of analysis.
===
=== Please update [WHITE_LIST] in $testFileName
===
""";

  if (mode == AnalysisMode.URI) {
    for (Uri uri in uriList) {
      await compiler.analyzeUri(uri);
    }
  } else if (mode != AnalysisMode.TREE_SHAKING) {
    compiler.librariesToAnalyzeWhenRun = uriList;
    await compiler.run(null);
  } else {
    await compiler.run(uriList.single);
  }

  bool result;
  if (checkResults != null) {
    result = checkResults(compiler, handler);
  } else {
    result = handler.checkResults();
  }
  if (!result) {
    print(MESSAGE);
    exit(1);
  }
}
