orderedLibraryAssetIds method

Future<Set<AssetId>> orderedLibraryAssetIds(
  1. BuildStep buildStep
)

Returns a ordered set of library asset ids ordered in reverse topological dependency order.

  • If a file B includes a file A, then A will be appear before B.
  • Throws ErrorOf if a dependency cycle is detected.

Implementation

Future<Set<AssetId>> orderedLibraryAssetIds(BuildStep buildStep) async {
  final assetGraph =
      DirectedGraph<AssetId>({}, comparator: ((v1, v2) => -v1.compareTo(v2)));

  // An assetId map of all input libraries with the uri as key.
  final assetMap = <Uri, AssetId>{};

  // Access libraries
  await for (final input in buildStep.findAssets(Glob(inputFiles))) {
    // Check if input file is a library.
    if (await buildStep.resolver.isLibrary(input)) {
      assetMap[input.uri] = input;
      assetGraph.addEdges(assetMap[input.uri]!, {});
    }
  }

  for (final assetId in assetGraph) {
    final importedAsseIds = <AssetId>{};

    // Read library.
    final library = await buildStep.resolver.libraryFor(assetId);
    // Get dependencies
    for (final import in library.libraryImports) {
      final uri = Uri.parse(import.uri.toString());
      // Skip if uri scheme is not "package" or "asset".
      if (uri.scheme == 'package' ||
          uri.scheme == 'asset' ||
          uri.scheme == '') {
        // Normalise uri to handle relative and package import directives.
        final importedAssetId = AssetId.resolve(uri, from: assetId);
        // Add vertex matching import directive.
        if (assetMap[importedAssetId.uri] != null) {
          importedAsseIds.add(assetMap[importedAssetId.uri]!);
        }
      }
    }
    assetGraph.addEdges(assetId, importedAsseIds);
  }

  final topologicalOrdering = assetGraph.sortedTopologicalOrdering;

  if (topologicalOrdering == null) {
    // Find the first cycle
    final cycle = assetGraph.cycle;

    throw ErrorOf<SyntheticBuilder>(
        message: 'Circular dependency detected.',
        expectedState: 'Input files must not include each other. '
            'Alternatively, set constructor parameter "sortAssets: false".',
        invalidState: 'File ${cycle.join(' imports ')}.');
  }

  // Return reversed topological ordering of asset ids.
  return topologicalOrdering;
}