findExtensions function

Future<List<Extension>> findExtensions(
  1. String targetPackage, {
  2. bool useCache = true,
  3. Uri? packageConfig,
})

Find extensions for targetPackage provided by packages in .dart_tool/package_config.json.

Locating .dart_tool/package_config.json

This method requires the location of the packageConfig, unless the current isolate has been setup for package resolution. Notably, Dart programs compiled for AOT cannot find their own package_config.json.

If operating on a project that isn't the current project, for example, if you are developing a tool that users are globally activating and then running against their own projects, and you wish to detect extensions within their projects, then you must specify the path the .dart_tool/package_config.json for the users project as packageConfig.

The packageConfig parameter must reference a file, absolute or relative-path, may use the file:// scheme. This method throws, if packageConfig is not a valid Uri for a file-path.

Detection of extensions

An extension for targetPackage is detected in package:foo if foo contains extension/<targetPackage>/config.yaml, and the contents of this file is valid YAML, that can be represented as JSON.

Caching results

When useCache is true then the detected extensions will be cached in .dart_tool/extension_discovery/<targetPackage>.yaml. This function will compare modification timestamps of .dart_tool/package_config.json with the cache file, before reusing cached results. This function will also treat relative path-dependencies as mutable packages, and check such packages for extensions every time findExtensions is called. Notably, it'll compare the modification time of the extension/<targetPackage>/config.yaml file, to ensure that it's older than the extension cache file. Otherwise, it'll reload the extension configuration.

Exceptions

This method will throw PackageConfigException, if the .dart_tool/package_config.json file specified in packageConfig could not be loaded or is invalid. This usually happens if dependencies are not resolved, and users can probably address it by running dart pub get.

But, do consider catch PackageConfigException and handling the failure to load extensions appropriately.

This method will throw an Error if packageConfig is not specified, and the current isolate isn't configured for package resolution.

Implementation

Future<List<Extension>> findExtensions(
  String targetPackage, {
  bool useCache = true,
  Uri? packageConfig,
}) async {
  packageConfig ??= await Isolate.packageConfig;
  if (packageConfig == null) {
    throw UnsupportedError(
      'packageConfigUri must be provided, if not running in JIT mode',
    );
  }
  if ((packageConfig.hasScheme && !packageConfig.isScheme('file')) ||
      packageConfig.hasEmptyPath ||
      packageConfig.hasFragment ||
      packageConfig.hasPort ||
      packageConfig.hasQuery) {
    throw ArgumentError.value(
      packageConfig,
      'packageConfig',
      'must be a file:// URI',
    );
  }
  // Always normalize to an absolute URI
  final packageConfigUri = File.fromUri(packageConfig).absolute.uri;

  return await _findExtensions(
    targetPackage: targetPackage,
    useCache: useCache,
    packageConfigUri: packageConfigUri,
  );
}