serveAvailableExtensions method

Future<void> serveAvailableExtensions(
  1. String? rootFileUriString,
  2. List<String> logs,
  3. DtdInfo? dtd
)

Serves any available DevTools extensions for the given rootFileUriString, where rootFileUriString is the root for a Dart or Flutter project containing the .dart_tool/ directory.

rootFileUriString is expected to be a file URI string (e.g. starting with 'file://').

This method first looks up the available extensions using package:extension_discovery, and the available extension's assets will be copied to the build/devtools_extensions directory that DevTools server is serving.

Implementation

Future<void> serveAvailableExtensions(
  String? rootFileUriString,
  List<String> logs,
  DtdInfo? dtd,
) async {
  logs.add(
    'ExtensionsManager.serveAvailableExtensions for '
    'rootPathFileUri: $rootFileUriString',
  );

  _clear();
  final parsingErrors = StringBuffer();

  // Find all runtime extensions for [rootFileUriString], if non-null and
  // non-empty.
  if (rootFileUriString != null && rootFileUriString.isNotEmpty) {
    logs.add(
      'ExtensionsManager.serveAvailableExtensions adding extensions for app '
      'root.',
    );
    await _addExtensionsForRoot(
      rootFileUriString,
      logs: logs,
      parsingErrors: parsingErrors,
      staticContext: false,
    );
  }

  // Find all static extensions for the project roots, which are derived from
  // the Dart Tooling Daemon, and add them to [devtoolsExtensions].
  final dtdUri = dtd?.localUri;
  if (dtdUri != null) {
    DartToolingDaemon? dartToolingDaemon;
    try {
      dartToolingDaemon = await DartToolingDaemon.connect(dtdUri);
      final projectRoots = await dartToolingDaemon.getProjectRoots(
        depth: staticExtensionsSearchDepth,
      );
      logs.add(
        'ExtensionsManager.serveAvailableExtensions adding extensions for '
        'DTD project roots: ${projectRoots.uris?.toString() ?? []}',
      );

      for (final root in projectRoots.uris ?? const <Uri>[]) {
        // Skip the runtime app root. These extensions have already been
        // added to [devtoolsExtensions].
        if (root.toString() == rootFileUriString) continue;

        await _addExtensionsForRoot(
          // TODO(https://github.com/flutter/devtools/issues/7944): this logic
          // assumes that the .dart_tool folder containing the
          // package_config.json file is in the same directory as the
          // pubspec.yaml file (since `dartToolingDaemon.getProjectRoots`
          // returns all directories within the IDE workspace roots that have
          // a pubspec.yaml file). This may be an incorrect assumption for
          // pub workspaces.
          root.toString(),
          logs: logs,
          parsingErrors: parsingErrors,
          staticContext: true,
        );
      }
    } finally {
      await dartToolingDaemon?.close();
    }
  }

  if (parsingErrors.isNotEmpty) {
    throw ExtensionParsingException(
      'Encountered errors while parsing extension config.yaml '
      'files:\n$parsingErrors',
    );
  }
}