Future _outputHuman()

in lib/src/command/outdated.dart [439:602]


Future<void> _outputHuman(
  List<_PackageDetails> rows,
  Mode mode, {
  required bool showAll,
  required bool useColors,
  required bool includeDevDependencies,
  required bool lockFileExists,
  required bool hasDirectDependencies,
  required bool hasDevDependencies,
  required bool showTransitiveDependencies,
  required bool hasUpgradableResolution,
  required bool hasResolvableResolution,
  required String directory,
}) async {
  final directoryDesc = directory == '.' ? '' : ' in $directory';
  log.message(mode.explanation(directoryDesc) + '\n');
  final markedRows =
      Map.fromIterables(rows, await mode.markVersionDetails(rows));

  List<_FormattedString> formatted(_PackageDetails package) => [
        _FormattedString(package.name),
        ...markedRows[package]!.map((m) => m.toHuman()),
      ];

  if (!showAll) {
    rows.removeWhere((row) => markedRows[row]![0].asDesired);
  }
  if (rows.isEmpty) {
    log.message(mode.foundNoBadText);
    return;
  }

  bool Function(_PackageDetails) hasKind(_DependencyKind kind) =>
      (row) => row.kind == kind;

  final directRows = rows.where(hasKind(_DependencyKind.direct)).map(formatted);
  final devRows = rows.where(hasKind(_DependencyKind.dev)).map(formatted);
  final transitiveRows =
      rows.where(hasKind(_DependencyKind.transitive)).map(formatted);
  final devTransitiveRows =
      rows.where(hasKind(_DependencyKind.devTransitive)).map(formatted);

  final formattedRows = <List<_FormattedString>>[
    ['Package Name', 'Current', 'Upgradable', 'Resolvable', 'Latest']
        .map((s) => _format(s, log.bold))
        .toList(),
    if (hasDirectDependencies) ...[
      [
        if (directRows.isEmpty)
          _format('\ndirect dependencies: ${mode.allGood}', log.bold)
        else
          _format('\ndirect dependencies:', log.bold)
      ],
      ...directRows,
    ],
    if (includeDevDependencies && hasDevDependencies) ...[
      [
        if (devRows.isEmpty)
          _format('\ndev_dependencies: ${mode.allGood}', log.bold)
        else
          _format('\ndev_dependencies:', log.bold)
      ],
      ...devRows,
    ],
    if (showTransitiveDependencies) ...[
      if (transitiveRows.isNotEmpty)
        [_format('\ntransitive dependencies:', log.bold)],
      ...transitiveRows,
      if (includeDevDependencies) ...[
        if (devTransitiveRows.isNotEmpty)
          [_format('\ntransitive dev_dependencies:', log.bold)],
        ...devTransitiveRows,
      ],
    ],
  ];

  final columnWidths = <int, int>{};
  for (var i = 0; i < formattedRows.length; i++) {
    if (formattedRows[i].length > 1) {
      for (var j = 0; j < formattedRows[i].length; j++) {
        final currentMaxWidth = columnWidths[j] ?? 0;
        columnWidths[j] = max(
            formattedRows[i][j].computeLength(useColors: useColors),
            currentMaxWidth);
      }
    }
  }

  for (final row in formattedRows) {
    final b = StringBuffer();
    for (var j = 0; j < row.length; j++) {
      b.write(row[j].formatted(useColors: useColors));
      b.write(' ' *
          ((columnWidths[j]! + 2) -
              row[j].computeLength(useColors: useColors)));
    }
    log.message(b.toString());
  }

  var upgradable = rows
      .where((row) =>
          row.current != null &&
          row.upgradable != null &&
          row.current != row.upgradable &&
          // Include transitive only, if we show them
          (showTransitiveDependencies ||
              hasKind(_DependencyKind.direct)(row) ||
              hasKind(_DependencyKind.dev)(row)))
      .length;

  var notAtResolvable = rows
      .where((row) =>
          (row.current != null || !lockFileExists) &&
          row.resolvable != null &&
          row.upgradable != row.resolvable &&
          // Include transitive only, if we show them
          (showTransitiveDependencies ||
              hasKind(_DependencyKind.direct)(row) ||
              hasKind(_DependencyKind.dev)(row)))
      .length;

  if (!hasUpgradableResolution || !hasResolvableResolution) {
    log.message(mode.noResolutionText);
  } else if (lockFileExists) {
    if (upgradable != 0) {
      if (upgradable == 1) {
        log.message('\n1 upgradable dependency is locked (in pubspec.lock) to '
            'an older version.\n'
            'To update it, use `$topLevelProgram pub upgrade`.');
      } else {
        log.message(
            '\n$upgradable upgradable dependencies are locked (in pubspec.lock) '
            'to older versions.\n'
            'To update these dependencies, use `$topLevelProgram pub upgrade`.');
      }
    }

    if (notAtResolvable == 0 &&
        upgradable == 0 &&
        rows.isNotEmpty &&
        (directRows.isNotEmpty || devRows.isNotEmpty)) {
      log.message(
          "You are already using the newest resolvable versions listed in the 'Resolvable' column.\n"
          "Newer versions, listed in 'Latest', may not be mutually compatible.");
    } else if (directRows.isEmpty && devRows.isEmpty) {
      log.message(mode.allSafe);
    }
  } else {
    log.message('\nNo pubspec.lock found. There are no Current versions.\n'
        'Run `pub get` to create a pubspec.lock with versions matching your '
        'pubspec.yaml.');
  }
  if (notAtResolvable != 0) {
    if (notAtResolvable == 1) {
      log.message('\n1 dependency is constrained to a '
          'version that is older than a resolvable version.\n'
          'To update it, ${mode.upgradeConstrained}.');
    } else {
      log.message('\n$notAtResolvable  dependencies are constrained to '
          'versions that are older than a resolvable version.\n'
          'To update these dependencies, ${mode.upgradeConstrained}.');
    }
  }
}