// Copyright (c) 2015, 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.

// @dart = 2.11

/// This tool checks that the output from dart2js meets a given specification,
/// given in a YAML file. The format of the YAML file is:
///
///     main:
///       include:
///         - some_package
///         - other_package
///
///     foo:
///       include:
///         - foo
///         - bar
///
///     baz:
///       include:
///         - baz
///         - quux
///       exclude:
///         - zardoz
///
/// The YAML file consists of a list of declarations, one for each deferred
/// part expected in the output. At least one of these parts must be named
/// "main"; this is the main part that contains the program entrypoint. Each
/// top-level part contains a list of package names that are expected to be
/// contained in that part, a list of package names that are expected to be in
/// another part, or both. For instance, in the example YAML above the part
/// named "baz" is expected to contain the packages "baz" and "quux" and not to
/// contain the package "zardoz".
///
/// The names for parts given in the specification YAML file (besides "main")
/// are the same as the name given to the deferred import in the dart file. For
/// instance, if you have `import 'package:foo/bar.dart' deferred as baz;` in
/// your dart file, then the corresponding name in the specification file is
/// 'baz'.
library dart2js_info.deferred_library_check;

import 'info.dart';

List<ManifestComplianceFailure> checkDeferredLibraryManifest(
    AllInfo info, Map manifest) {
  var includedPackages = <String, Set<String>>{};
  var excludedPackages = <String, Set<String>>{};
  for (var part in manifest.keys) {
    for (var package in manifest[part]['include'] ?? []) {
      (includedPackages[part] ??= {}).add(package);
    }
    for (var package in manifest[part]['exclude'] ?? []) {
      (excludedPackages[part] ??= {}).add(package);
    }
  }

  // There are 2 types of parts that are valid to mention in the specification
  // file. These are the main part and directly imported deferred parts. The
  // main part is always named 'main'; the directly imported deferred parts are
  // the outputUnits whose list of 'imports' contains a single import. If the
  // part is shared, it will have more than one import since it will include the
  // imports of all the top-level deferred parts that will load the shared part.
  List<String> validParts = [
    'main',
    ...info.outputUnits
        .where((unit) => unit.imports.length == 1)
        .map((unit) => unit.imports.single)
  ];
  List<String> mentionedParts = [
    ...includedPackages.keys,
    ...excludedPackages.keys
  ];
  var partNameFailures = <_InvalidPartName>[];
  for (var part in mentionedParts) {
    if (!validParts.contains(part)) {
      partNameFailures.add(_InvalidPartName(part, validParts));
    }
  }
  if (partNameFailures.isNotEmpty) {
    return partNameFailures;
  }

  var mentionedPackages = {
    for (var values in includedPackages.values) ...values,
    for (var values in excludedPackages.values) ...values
  };
  var actualIncludedPackages = <String, Set<String>>{};

  var failures = <ManifestComplianceFailure>[];

  checkInfo(BasicInfo info) {
    if (info.size == 0) return;
    var lib = _getLibraryOf(info);
    if (lib != null && _isPackageUri(lib.uri)) {
      var packageName = _getPackageName(lib.uri);
      if (!mentionedPackages.contains(packageName)) return;
      var containingParts = <String>[];
      if (info.outputUnit.name == 'main') {
        containingParts.add('main');
      } else {
        containingParts.addAll(info.outputUnit.imports);
      }
      for (var part in containingParts) {
        (actualIncludedPackages[part] ??= {}).add(packageName);
        if (excludedPackages[part].contains(packageName)) {
          failures.add(_PartContainedExcludedPackage(part, packageName, info));
        }
      }
    }
  }

  info.functions.forEach(checkInfo);
  info.fields.forEach(checkInfo);

  includedPackages.forEach((part, packages) {
    for (var package in packages) {
      if (!actualIncludedPackages.containsKey(part) ||
          !actualIncludedPackages[part].contains(package)) {
        failures.add(_PartDidNotContainPackage(part, package));
      }
    }
  });
  return failures;
}

LibraryInfo _getLibraryOf(Info info) {
  var current = info;
  while (current is! LibraryInfo) {
    if (current == null) {
      return null;
    }
    current = current.parent;
  }
  return current;
}

bool _isPackageUri(Uri uri) => uri.isScheme('package');

String _getPackageName(Uri uri) {
  assert(_isPackageUri(uri));
  return uri.pathSegments.first;
}

class ManifestComplianceFailure {
  const ManifestComplianceFailure();
}

class _InvalidPartName extends ManifestComplianceFailure {
  final String part;
  final List<String> validPartNames;
  const _InvalidPartName(this.part, this.validPartNames);

  @override
  String toString() {
    return 'Manifest file declares invalid part "$part". '
        'Valid part names are: $validPartNames';
  }
}

class _PartContainedExcludedPackage extends ManifestComplianceFailure {
  final String part;
  final String package;
  final BasicInfo info;
  const _PartContainedExcludedPackage(this.part, this.package, this.info);

  @override
  String toString() {
    return 'Part "$part" was specified to exclude package "$package" but it '
        'actually contains ${kindToString(info.kind)} "${info.name}" which '
        'is from package "$package"';
  }
}

class _PartDidNotContainPackage extends ManifestComplianceFailure {
  final String part;
  final String package;
  const _PartDidNotContainPackage(this.part, this.package);

  @override
  String toString() {
    return 'Part "$part" was specified to include package "$package" but it '
        'does not contain any elements from that package.';
  }
}
