scan method

Future<ProjectDiagnosis> scan(
  1. String pubspecPath,
  2. ScanOptions opts
)

Implementation

Future<ProjectDiagnosis> scan(String pubspecPath, ScanOptions opts) async {
  final info = await PubspecParser().parse(pubspecPath);
  final sdk = _detectSdk();
  final packages = opts.includeDev ? info.all : info.dependencies;

  if (packages.isEmpty) {
    return ProjectDiagnosis(
      results: [],
      scannedAt: DateTime.now(),
      pubspecPath: pubspecPath,
      dartSdkVersion: sdk?.toString(),
    );
  }

  Map<String, PackageMetadata> meta;

  if (opts.offline) {
    meta = await _fromCacheOnly(packages);
  } else {
    _pub ??= PubApiClient(cache: _cache, concurrency: opts.concurrency);
    _gh ??= GitHubClient(cache: _cache);

    meta = await _pub!.fetchAll(packages, fresh: opts.fresh);
    await _augmentGitHub(meta);
    await _probeRepos(meta);
  }

  final repoReachability = {
    for (final m in meta.values)
      if (m.repositoryUrl != null && m.repoHealth != null)
        m.repositoryUrl.toString(): true,
  };

  final scorer =
      RiskScorer(dartSdkVersion: sdk, repoReachability: repoReachability);
  var results = meta.values.map(scorer.diagnose).toList()
    ..sort((a, b) => b.riskScore.compareTo(a.riskScore));

  // For any high-risk package, try to find alternatives if online
  if (!opts.offline) {
    _alt ??= AlternativeService(_pub!);
    results = await Future.wait(results.map((r) async {
      if (r.riskLevel == RiskLevel.critical ||
          r.riskLevel == RiskLevel.risky) {
        final originalMeta = meta[r.packageName];
        if (originalMeta != null) {
          final alternatives =
              await _alt!.findBetterAlternatives(originalMeta);
          if (alternatives.isNotEmpty) {
            return DiagnosisResult(
              packageName: r.packageName,
              currentVersion: r.currentVersion,
              latestVersion: r.latestVersion,
              riskScore: r.riskScore,
              riskLevel: r.riskLevel,
              signals: r.signals,
              recommendations: r.recommendations,
              suggestedAlternatives: alternatives,
              verification: r.verification,
              repoHealth: r.repoHealth,
              isFromCache: r.isFromCache,
            );
          }
        }
      }
      return r;
    }));
  }

  String? latestToolVersion;

  if (!opts.offline) {
    latestToolVersion = await _checkSelfUpdate();
  }

  return ProjectDiagnosis(
    results: results,
    scannedAt: DateTime.now(),
    pubspecPath: pubspecPath,
    dartSdkVersion: sdk?.toString(),
    latestToolVersion: latestToolVersion,
  );
}