provision method

Future<List<ImportDiagnostic>> provision()

Resolves and loads every package: import reachable from the currently loaded modules (transitively), returning any diagnostics (unresolved packages, or sources that ApolloVM's Dart subset can't parse).

Implementation

Future<List<ImportDiagnostic>> provision() async {
  var diagnostics = <ImportDiagnostic>[];
  var seen = <String>{};
  var queue = <PackageUri>[];

  // Seed from all currently-loaded modules' `package:` imports.
  for (var unit in vm.allCodeUnits(language)) {
    var root = unit.root;
    if (root == null) continue;
    for (var uri in _packageImportsOf(root)) {
      if (seen.add(uri.moduleId)) queue.add(uri);
    }
  }

  while (queue.isNotEmpty) {
    var uri = queue.removeLast();

    if (_isLoaded(uri.moduleId)) continue;

    PackageSource? pkgSource;
    try {
      pkgSource = await provider.resolvePackageUri(uri);
    } catch (e) {
      diagnostics.add(
        ImportDiagnostic(
          kind: ImportDiagnosticKind.missingModule,
          moduleId: uri.moduleId,
          message: "Failed to fetch package import '${uri.moduleId}': $e",
          importPath: uri.moduleId,
        ),
      );
      continue;
    }

    if (pkgSource == null) {
      diagnostics.add(
        ImportDiagnostic.missingModule(uri.moduleId, uri.moduleId),
      );
      continue;
    }

    var unit = SourceCodeUnit(
      language,
      pkgSource.source,
      id: pkgSource.moduleId,
    );

    try {
      await vm.loadCodeUnit(unit);
    } catch (e) {
      // Real-world package sources may use Dart features outside ApolloVM's
      // supported subset; record and keep going rather than aborting.
      diagnostics.add(
        ImportDiagnostic(
          kind: ImportDiagnosticKind.missingModule,
          moduleId: uri.moduleId,
          message:
              "Loaded package '${uri.moduleId}' but it couldn't be parsed by "
              "ApolloVM's Dart subset: $e",
          importPath: uri.moduleId,
          severity: ImportDiagnosticSeverity.warning,
        ),
      );
      continue;
    }

    // Enqueue the package's own `package:` imports (transitive).
    var root = unit.root;
    if (root != null) {
      for (var next in _packageImportsOf(root)) {
        if (seen.add(next.moduleId)) queue.add(next);
      }
    }
  }

  return diagnostics;
}