Migrate to null safety (#93)
* Migrate non-deprecated libraries to null safety.
* Major version increment, removing deprecated APIs.
This is the null safe, non-deprecated API for package_config.json
file manipulation.
Also address #86.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6dcae80..32ff3f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.0.0
+
+- Migrate to null safety.
+- Remove legacy APIs.
+
## 1.9.3
- Fix `Package` constructor not accepting relative `packageUriRoot`.
diff --git a/README.md b/README.md
index b47a682..1ad4b41 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,12 @@
The primary libraries are
* `package_config.dart`:
Defines the `PackageConfig` class and other types needed to use
- package configurations.
+ package configurations, and provides functions to find, read and
+ write package configuration files.
-* `package_config_discovery.dart`:
- Provides functions for reading configurations from files,
- and writing them back out.
+* `package_config_types.dart`:
+ Just the `PackageConfig` class and other types needed to use
+ package configurations. This library does not depend on `dart:io`.
The package includes deprecated backwards compatible functionality to
work with the `.packages` file. This functionality will not be maintained,
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 66639ec..a785408 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -6,6 +6,5 @@
analyzer:
errors:
annotate_overrides: ignore
- curly_braces_in_flow_control_structures: ignore
prefer_single_quotes: ignore
use_function_type_syntax_for_parameters: ignore
diff --git a/lib/discovery.dart b/lib/discovery.dart
deleted file mode 100644
index a72bb12..0000000
--- a/lib/discovery.dart
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated("Use the package_config.json based API")
-library package_config.discovery;
-
-import "dart:io";
-import "dart:typed_data" show Uint8List;
-
-import "package:path/path.dart" as path;
-
-import "packages.dart";
-import "packages_file.dart" as pkgfile show parse;
-import "src/packages_impl.dart";
-import "src/packages_io_impl.dart";
-
-/// Reads a package resolution file and creates a [Packages] object from it.
-///
-/// The [packagesFile] must exist and be loadable.
-/// Currently that means the URI must have a `file`, `http` or `https` scheme,
-/// and that the file can be loaded and its contents parsed correctly.
-///
-/// If the [loader] is provided, it is used to fetch non-`file` URIs, and
-/// it can support other schemes or set up more complex HTTP requests.
-///
-/// This function can be used to load an explicitly configured package
-/// resolution file, for example one specified using a `--packages`
-/// command-line parameter.
-Future<Packages> loadPackagesFile(Uri packagesFile,
- {Future<List<int>> loader(Uri uri)}) async {
- Packages parseBytes(List<int> bytes) {
- return MapPackages(pkgfile.parse(bytes, packagesFile));
- }
-
- if (packagesFile.scheme == "file") {
- return parseBytes(await File.fromUri(packagesFile).readAsBytes());
- }
- if (loader == null) {
- return parseBytes(await _httpGet(packagesFile));
- }
- return parseBytes(await loader(packagesFile));
-}
-
-/// Create a [Packages] object for a package directory.
-///
-/// The [packagesDir] URI should refer to a directory.
-/// Package names are resolved as relative to sub-directories of the
-/// package directory.
-///
-/// This function can be used for explicitly configured package directories,
-/// for example one specified using a `--package-root` comand-line parameter.
-Packages getPackagesDirectory(Uri packagesDir) {
- if (packagesDir.scheme == "file") {
- return FilePackagesDirectoryPackages(Directory.fromUri(packagesDir));
- }
- if (!packagesDir.path.endsWith('/')) {
- packagesDir = packagesDir.replace(path: packagesDir.path + '/');
- }
- return NonFilePackagesDirectoryPackages(packagesDir);
-}
-
-/// Discover the package configuration for a Dart script.
-///
-/// The [baseUri] points to either the Dart script or its directory.
-/// A package resolution strategy is found by going through the following steps,
-/// and stopping when something is found.
-///
-/// * Check if a `.packages` file exists in the same directory.
-/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory
-/// in the same directory, and resolve packages relative to that.
-/// * If `baseUri`'s scheme *is* `file`:
-/// * Check if a `packages` directory exists.
-/// * Otherwise check each successive parent directory of `baseUri` for a
-/// `.packages` file.
-///
-/// If any of these tests succeed, a `Packages` class is returned.
-/// Returns the constant [noPackages] if no resolution strategy is found.
-///
-/// This function currently only supports `file`, `http` and `https` URIs.
-/// It needs to be able to load a `.packages` file from the URI, so only
-/// recognized schemes are accepted.
-///
-/// To support other schemes, or more complex HTTP requests,
-/// an optional [loader] function can be supplied.
-/// It's called to load the `.packages` file for a non-`file` scheme.
-/// The loader function returns the *contents* of the file
-/// identified by the URI it's given.
-/// The content should be a UTF-8 encoded `.packages` file, and must return an
-/// error future if loading fails for any reason.
-Future<Packages> findPackages(Uri baseUri,
- {Future<List<int>> loader(Uri unsupportedUri)}) {
- if (baseUri.scheme == "file") {
- return Future<Packages>.sync(() => findPackagesFromFile(baseUri));
- } else if (loader != null) {
- return findPackagesFromNonFile(baseUri, loader: loader);
- } else if (baseUri.scheme == "http" || baseUri.scheme == "https") {
- return findPackagesFromNonFile(baseUri, loader: _httpGet);
- } else {
- return Future<Packages>.value(Packages.noPackages);
- }
-}
-
-/// Find the location of the package resolution file/directory for a Dart file.
-///
-/// Checks for a `.packages` file in the [workingDirectory].
-/// If not found, checks for a `packages` directory in the same directory.
-/// If still not found, starts checking parent directories for
-/// `.packages` until reaching the root directory.
-///
-/// Returns a [File] object of a `.packages` file if one is found, or a
-/// [Directory] object for the `packages/` directory if that is found.
-FileSystemEntity _findPackagesFile(String workingDirectory) {
- var dir = Directory(workingDirectory);
- if (!dir.isAbsolute) dir = dir.absolute;
- if (!dir.existsSync()) {
- throw ArgumentError.value(
- workingDirectory, "workingDirectory", "Directory does not exist.");
- }
- File checkForConfigFile(Directory directory) {
- assert(directory.isAbsolute);
- var file = File(path.join(directory.path, ".packages"));
- if (file.existsSync()) return file;
- return null;
- }
-
- // Check for $cwd/.packages
- var packagesCfgFile = checkForConfigFile(dir);
- if (packagesCfgFile != null) return packagesCfgFile;
- // Check for $cwd/packages/
- var packagesDir = Directory(path.join(dir.path, "packages"));
- if (packagesDir.existsSync()) return packagesDir;
- // Check for cwd(/..)+/.packages
- var parentDir = dir.parent;
- while (parentDir.path != dir.path) {
- packagesCfgFile = checkForConfigFile(parentDir);
- if (packagesCfgFile != null) break;
- dir = parentDir;
- parentDir = dir.parent;
- }
- return packagesCfgFile;
-}
-
-/// Finds a package resolution strategy for a local Dart script.
-///
-/// The [fileBaseUri] points to either a Dart script or the directory of the
-/// script. The `fileBaseUri` must be a `file:` URI.
-///
-/// This function first tries to locate a `.packages` file in the `fileBaseUri`
-/// directory. If that is not found, it instead checks for the presence of
-/// a `packages/` directory in the same place.
-/// If that also fails, it starts checking parent directories for a `.packages`
-/// file, and stops if it finds it.
-/// Otherwise it gives up and returns [Packages.noPackages].
-Packages findPackagesFromFile(Uri fileBaseUri) {
- var baseDirectoryUri = fileBaseUri;
- if (!fileBaseUri.path.endsWith('/')) {
- baseDirectoryUri = baseDirectoryUri.resolve(".");
- }
- var baseDirectoryPath = baseDirectoryUri.toFilePath();
- var location = _findPackagesFile(baseDirectoryPath);
- if (location == null) return Packages.noPackages;
- if (location is File) {
- var fileBytes = location.readAsBytesSync();
- var map = pkgfile.parse(fileBytes, Uri.file(location.path));
- return MapPackages(map);
- }
- assert(location is Directory);
- return FilePackagesDirectoryPackages(location);
-}
-
-/// Finds a package resolution strategy for a Dart script.
-///
-/// The [nonFileUri] points to either a Dart script or the directory of the
-/// script.
-/// The [nonFileUri] should not be a `file:` URI since the algorithm for
-/// finding a package resolution strategy is more elaborate for `file:` URIs.
-/// In that case, use [findPackagesFromFile].
-///
-/// This function first tries to locate a `.packages` file in the [nonFileUri]
-/// directory. If that is not found, it instead assumes a `packages/` directory
-/// in the same place.
-///
-/// By default, this function only works for `http:` and `https:` URIs.
-/// To support other schemes, a loader must be provided, which is used to
-/// try to load the `.packages` file. The loader should return the contents
-/// of the requested `.packages` file as bytes, which will be assumed to be
-/// UTF-8 encoded.
-Future<Packages> findPackagesFromNonFile(Uri nonFileUri,
- {Future<List<int>> loader(Uri name)}) async {
- loader ??= _httpGet;
- var packagesFileUri = nonFileUri.resolve(".packages");
-
- try {
- var fileBytes = await loader(packagesFileUri);
- var map = pkgfile.parse(fileBytes, packagesFileUri);
- return MapPackages(map);
- } catch (_) {
- // Didn't manage to load ".packages". Assume a "packages/" directory.
- var packagesDirectoryUri = nonFileUri.resolve("packages/");
- return NonFilePackagesDirectoryPackages(packagesDirectoryUri);
- }
-}
-
-/// Fetches a file over http.
-Future<List<int>> _httpGet(Uri uri) async {
- var client = HttpClient();
- var request = await client.getUrl(uri);
- var response = await request.close();
- if (response.statusCode != HttpStatus.ok) {
- throw HttpException('${response.statusCode} ${response.reasonPhrase}',
- uri: uri);
- }
- var splitContent = await response.toList();
- var totalLength = 0;
- for (var list in splitContent) {
- totalLength += list.length;
- }
- var result = Uint8List(totalLength);
- var offset = 0;
- for (var contentPart in splitContent) {
- result.setRange(offset, offset + contentPart.length, contentPart);
- offset += contentPart.length;
- }
- return result;
-}
diff --git a/lib/discovery_analysis.dart b/lib/discovery_analysis.dart
deleted file mode 100644
index 2af0729..0000000
--- a/lib/discovery_analysis.dart
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Analyse a directory structure and find packages resolvers for each
-/// sub-directory.
-///
-/// The resolvers are generally the same that would be found by using
-/// the `discovery.dart` library on each sub-directory in turn,
-/// but more efficiently and with some heuristics for directories that
-/// wouldn't otherwise have a package resolution strategy, or that are
-/// determined to be "package directories" themselves.
-@Deprecated("Use the package_config.json based API")
-library package_config.discovery_analysis;
-
-import "dart:collection" show HashMap;
-import "dart:io" show File, Directory;
-
-import "package:path/path.dart" as path;
-
-import "packages.dart";
-import "packages_file.dart" as pkgfile;
-import "src/packages_impl.dart";
-import "src/packages_io_impl.dart";
-
-/// Associates a [Packages] package resolution strategy with a directory.
-///
-/// The package resolution applies to the directory and any sub-directory
-/// that doesn't have its own overriding child [PackageContext].
-abstract class PackageContext {
- /// The directory that introduced the [packages] resolver.
- Directory get directory;
-
- /// A [Packages] resolver that applies to the directory.
- ///
- /// Introduced either by a `.packages` file or a `packages/` directory.
- Packages get packages;
-
- /// Child contexts that apply to sub-directories of [directory].
- List<PackageContext> get children;
-
- /// Look up the [PackageContext] that applies to a specific directory.
- ///
- /// The directory must be inside [directory].
- PackageContext operator [](Directory directory);
-
- /// A map from directory to package resolver.
- ///
- /// Has an entry for this package context and for each child context
- /// contained in this one.
- Map<Directory, Packages> asMap();
-
- /// Analyze [directory] and sub-directories for package resolution strategies.
- ///
- /// Returns a mapping from sub-directories to [Packages] objects.
- ///
- /// The analysis assumes that there are no `.packages` files in a parent
- /// directory of `directory`. If there is, its corresponding `Packages` object
- /// should be provided as `root`.
- static PackageContext findAll(Directory directory,
- {Packages root = Packages.noPackages}) {
- if (!directory.existsSync()) {
- throw ArgumentError("Directory not found: $directory");
- }
- var contexts = <PackageContext>[];
- void findRoots(Directory directory) {
- Packages packages;
- List<PackageContext> oldContexts;
- var packagesFile = File(path.join(directory.path, ".packages"));
- if (packagesFile.existsSync()) {
- packages = _loadPackagesFile(packagesFile);
- oldContexts = contexts;
- contexts = [];
- } else {
- var packagesDir = Directory(path.join(directory.path, "packages"));
- if (packagesDir.existsSync()) {
- packages = FilePackagesDirectoryPackages(packagesDir);
- oldContexts = contexts;
- contexts = [];
- }
- }
- for (var entry in directory.listSync()) {
- if (entry is Directory) {
- if (packages == null || !entry.path.endsWith("/packages")) {
- findRoots(entry);
- }
- }
- }
- if (packages != null) {
- oldContexts.add(_PackageContext(directory, packages, contexts));
- contexts = oldContexts;
- }
- }
-
- findRoots(directory);
- // If the root is not itself context root, add a the wrapper context.
- if (contexts.length == 1 && contexts[0].directory == directory) {
- return contexts[0];
- }
- return _PackageContext(directory, root, contexts);
- }
-}
-
-class _PackageContext implements PackageContext {
- final Directory directory;
- final Packages packages;
- final List<PackageContext> children;
- _PackageContext(this.directory, this.packages, List<PackageContext> children)
- : children = List<PackageContext>.unmodifiable(children);
-
- Map<Directory, Packages> asMap() {
- var result = HashMap<Directory, Packages>();
- void recurse(_PackageContext current) {
- result[current.directory] = current.packages;
- for (var child in current.children) {
- recurse(child);
- }
- }
-
- recurse(this);
- return result;
- }
-
- PackageContext operator [](Directory directory) {
- var path = directory.path;
- if (!path.startsWith(this.directory.path)) {
- throw ArgumentError("Not inside $path: $directory");
- }
- var current = this;
- // The current path is know to agree with directory until deltaIndex.
- var deltaIndex = current.directory.path.length;
- List children = current.children;
- var i = 0;
- while (i < children.length) {
- // TODO(lrn): Sort children and use binary search.
- _PackageContext child = children[i];
- var childPath = child.directory.path;
- if (_stringsAgree(path, childPath, deltaIndex, childPath.length)) {
- deltaIndex = childPath.length;
- if (deltaIndex == path.length) {
- return child;
- }
- current = child;
- children = current.children;
- i = 0;
- continue;
- }
- i++;
- }
- return current;
- }
-
- static bool _stringsAgree(String a, String b, int start, int end) {
- if (a.length < end || b.length < end) return false;
- for (var i = start; i < end; i++) {
- if (a.codeUnitAt(i) != b.codeUnitAt(i)) return false;
- }
- return true;
- }
-}
-
-Packages _loadPackagesFile(File file) {
- var uri = Uri.file(file.path);
- var bytes = file.readAsBytesSync();
- var map = pkgfile.parse(bytes, uri);
- return MapPackages(map);
-}
diff --git a/lib/package_config.dart b/lib/package_config.dart
index 1113ac8..3dfd8ef 100644
--- a/lib/package_config.dart
+++ b/lib/package_config.dart
@@ -3,8 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
/// A package configuration is a way to assign file paths to package URIs,
-/// and vice-versa,
-library package_config.package_config_discovery;
+/// and vice-versa.
+///
+/// This package provides functionality to find, read and write package
+/// configurations in the [specified format](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md).
+library package_config.package_config;
import "dart:io" show File, Directory;
import "dart:typed_data" show Uint8List;
@@ -39,7 +42,7 @@
/// a valid configuration from the invalid configuration file.
/// If no [onError] is provided, errors are thrown immediately.
Future<PackageConfig> loadPackageConfig(File file,
- {bool preferNewest = true, void onError(Object error)}) =>
+ {bool preferNewest = true, void onError(Object error)?}) =>
readAnyConfigFile(file, preferNewest, onError ?? throwError);
/// Reads a specific package configuration URI.
@@ -84,9 +87,9 @@
/// a valid configuration from the invalid configuration file.
/// If no [onError] is provided, errors are thrown immediately.
Future<PackageConfig> loadPackageConfigUri(Uri file,
- {Future<Uint8List /*?*/ > loader(Uri uri) /*?*/,
+ {Future<Uint8List?> loader(Uri uri)?,
bool preferNewest = true,
- void onError(Object error)}) =>
+ void onError(Object error)?}) =>
readAnyConfigFileUri(file, loader, onError ?? throwError, preferNewest);
/// Finds a package configuration relative to [directory].
@@ -109,8 +112,8 @@
/// If no [onError] is provided, errors are thrown immediately.
///
/// Returns `null` if no configuration file is found.
-Future<PackageConfig> findPackageConfig(Directory directory,
- {bool recurse = true, void onError(Object error)}) =>
+Future<PackageConfig?> findPackageConfig(Directory directory,
+ {bool recurse = true, void onError(Object error)?}) =>
discover.findPackageConfig(directory, recurse, onError ?? throwError);
/// Finds a package configuration relative to [location].
@@ -153,10 +156,10 @@
/// If no [onError] is provided, errors are thrown immediately.
///
/// Returns `null` if no configuration file is found.
-Future<PackageConfig> findPackageConfigUri(Uri location,
+Future<PackageConfig?> findPackageConfigUri(Uri location,
{bool recurse = true,
- Future<Uint8List /*?*/ > loader(Uri uri),
- void onError(Object error)}) =>
+ Future<Uint8List?> loader(Uri uri)?,
+ void onError(Object error)?}) =>
discover.findPackageConfigUri(
location, loader, onError ?? throwError, recurse);
diff --git a/lib/packages.dart b/lib/packages.dart
deleted file mode 100644
index 203f32f..0000000
--- a/lib/packages.dart
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated("Use the package_config.json based API")
-library package_config.packages;
-
-import "src/packages_impl.dart";
-
-/// A package resolution strategy.
-///
-/// Allows converting a `package:` URI to a different kind of URI.
-///
-/// May also allow listing the available packages and converting
-/// to a `Map<String, Uri>` that gives the base location of each available
-/// package. In some cases there is no way to find the available packages,
-/// in which case [packages] and [asMap] will throw if used.
-/// One such case is if the packages are resolved relative to a
-/// `packages/` directory available over HTTP.
-@Deprecated("Use the package_config.json based API")
-abstract class Packages {
- /// A [Packages] resolver containing no packages.
- ///
- /// This constant object is returned by [find] above if no
- /// package resolution strategy is found.
- static const Packages noPackages = NoPackages();
-
- /// Resolve a package URI into a non-package URI.
- ///
- /// Translates a `package:` URI, according to the package resolution
- /// strategy, into a URI that can be loaded.
- /// By default, only `file`, `http` and `https` URIs are returned.
- /// Custom `Packages` objects may return other URIs.
- ///
- /// If resolution fails because a package with the requested package name
- /// is not available, the [notFound] function is called.
- /// If no `notFound` function is provided, it defaults to throwing an error.
- ///
- /// The [packageUri] must be a valid package URI.
- Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)});
-
- /// Return the names of the available packages.
- ///
- /// Returns an iterable that allows iterating the names of available packages.
- ///
- /// Some `Packages` objects are unable to find the package names,
- /// and getting `packages` from such a `Packages` object will throw.
- Iterable<String> get packages;
-
- /// Retrieve metadata associated with a package.
- ///
- /// Metadata have string keys and values, and are looked up by key.
- ///
- /// Returns `null` if the argument is not a valid package name,
- /// or if the package is not one of the packages configured by
- /// this packages object, or if the package does not have associated
- /// metadata with the provided [key].
- ///
- /// Not all `Packages` objects can support metadata.
- /// Those will always return `null`.
- String packageMetadata(String packageName, String key);
-
- /// Retrieve metadata associated with a library.
- ///
- /// If [libraryUri] is a `package:` URI, the returned value
- /// is the same that would be returned by [packageMetadata] with
- /// the package's name and the same key.
- ///
- /// If [libraryUri] is not a `package:` URI, and this [Packages]
- /// object has a [defaultPackageName], then the [key] is looked
- /// up on the default package instead.
- ///
- /// Otherwise the result is `null`.
- String libraryMetadata(Uri libraryUri, String key);
-
- /// Return the names-to-base-URI mapping of the available packages.
- ///
- /// Returns a map from package name to a base URI.
- /// The [resolve] method will resolve a package URI with a specific package
- /// name to a path extending the base URI that this map gives for that
- /// package name.
- ///
- /// Some `Packages` objects are unable to find the package names,
- /// and calling `asMap` on such a `Packages` object will throw.
- Map<String, Uri> asMap();
-
- /// The name of the "default package".
- ///
- /// A default package is a package that *non-package* libraries
- /// may be considered part of for some purposes.
- ///
- /// The value is `null` if there is no default package.
- /// Not all implementations of [Packages] supports a default package,
- /// and will always have a `null` value for those.
- String get defaultPackageName;
-}
diff --git a/lib/packages_file.dart b/lib/packages_file.dart
deleted file mode 100644
index ef0b0b3..0000000
--- a/lib/packages_file.dart
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated("Use the package_config.json based API")
-library package_config.packages_file;
-
-import "package:charcode/ascii.dart";
-
-import "src/util.dart" show isValidPackageName;
-
-/// Parses a `.packages` file into a map from package name to base URI.
-///
-/// The [source] is the byte content of a `.packages` file, assumed to be
-/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII,
-/// so Latin-1 or Windows-1252 encoding will also work fine.
-///
-/// If the file content is available as a string, its [String.codeUnits] can
-/// be used as the `source` argument of this function.
-///
-/// The [baseLocation] is used as a base URI to resolve all relative
-/// URI references against.
-/// If the content was read from a file, `baseLocation` should be the
-/// location of that file.
-///
-/// If [allowDefaultPackage] is set to true, an entry with an empty package name
-/// is accepted. This entry does not correspond to a package, but instead
-/// represents a *default package* which non-package libraries may be considered
-/// part of in some cases. The value of that entry must be a valid package name.
-///
-/// Returns a simple mapping from package name to package location.
-/// If default package is allowed, the map maps the empty string to the default package's name.
-Map<String, Uri> parse(List<int> source, Uri baseLocation,
- {bool allowDefaultPackage = false}) {
- var index = 0;
- var result = <String, Uri>{};
- while (index < source.length) {
- var isComment = false;
- var start = index;
- var separatorIndex = -1;
- var end = source.length;
- var char = source[index++];
- if (char == $cr || char == $lf) {
- continue;
- }
- if (char == $colon) {
- if (!allowDefaultPackage) {
- throw FormatException("Missing package name", source, index - 1);
- }
- separatorIndex = index - 1;
- }
- isComment = char == $hash;
- while (index < source.length) {
- char = source[index++];
- if (char == $colon && separatorIndex < 0) {
- separatorIndex = index - 1;
- } else if (char == $cr || char == $lf) {
- end = index - 1;
- break;
- }
- }
- if (isComment) continue;
- if (separatorIndex < 0) {
- throw FormatException("No ':' on line", source, index - 1);
- }
- var packageName = String.fromCharCodes(source, start, separatorIndex);
- if (packageName.isEmpty
- ? !allowDefaultPackage
- : !isValidPackageName(packageName)) {
- throw FormatException("Not a valid package name", packageName, 0);
- }
- var packageValue = String.fromCharCodes(source, separatorIndex + 1, end);
- Uri packageLocation;
- if (packageName.isEmpty) {
- if (!isValidPackageName(packageValue)) {
- throw FormatException(
- "Default package entry value is not a valid package name");
- }
- packageLocation = Uri(path: packageValue);
- } else {
- packageLocation = baseLocation.resolve(packageValue);
- if (!packageLocation.path.endsWith('/')) {
- packageLocation =
- packageLocation.replace(path: packageLocation.path + "/");
- }
- }
- if (result.containsKey(packageName)) {
- if (packageName.isEmpty) {
- throw FormatException(
- "More than one default package entry", source, start);
- }
- throw FormatException("Same package name occured twice", source, start);
- }
- result[packageName] = packageLocation;
- }
- return result;
-}
-
-/// Writes the mapping to a [StringSink].
-///
-/// If [comment] is provided, the output will contain this comment
-/// with `# ` in front of each line.
-/// Lines are defined as ending in line feed (`'\n'`). If the final
-/// line of the comment doesn't end in a line feed, one will be added.
-///
-/// If [baseUri] is provided, package locations will be made relative
-/// to the base URI, if possible, before writing.
-///
-/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an
-/// empty string mapping to the _default package name_.
-///
-/// All the keys of [packageMapping] must be valid package names,
-/// and the values must be URIs that do not have the `package:` scheme.
-void write(StringSink output, Map<String, Uri> packageMapping,
- {Uri baseUri, String comment, bool allowDefaultPackage = false}) {
- ArgumentError.checkNotNull(allowDefaultPackage, 'allowDefaultPackage');
-
- if (baseUri != null && !baseUri.isAbsolute) {
- throw ArgumentError.value(baseUri, "baseUri", "Must be absolute");
- }
-
- if (comment != null) {
- var lines = comment.split('\n');
- if (lines.last.isEmpty) lines.removeLast();
- for (var commentLine in lines) {
- output.write('# ');
- output.writeln(commentLine);
- }
- } else {
- output.write("# generated by package:package_config at ");
- output.write(DateTime.now());
- output.writeln();
- }
-
- packageMapping.forEach((String packageName, Uri uri) {
- // If [packageName] is empty then [uri] is the _default package name_.
- if (allowDefaultPackage && packageName.isEmpty) {
- final defaultPackageName = uri.toString();
- if (!isValidPackageName(defaultPackageName)) {
- throw ArgumentError.value(
- defaultPackageName,
- 'defaultPackageName',
- '"$defaultPackageName" is not a valid package name',
- );
- }
- output.write(':');
- output.write(defaultPackageName);
- output.writeln();
- return;
- }
- // Validate packageName.
- if (!isValidPackageName(packageName)) {
- throw ArgumentError('"$packageName" is not a valid package name');
- }
- if (uri.scheme == "package") {
- throw ArgumentError.value(
- "Package location must not be a package: URI", uri.toString());
- }
- output.write(packageName);
- output.write(':');
- // If baseUri provided, make uri relative.
- if (baseUri != null) {
- uri = _relativize(uri, baseUri);
- }
- if (!uri.path.endsWith('/')) {
- uri = uri.replace(path: uri.path + '/');
- }
- output.write(uri);
- output.writeln();
- });
-}
-
-/// Attempts to return a relative URI for [uri].
-///
-/// The result URI satisfies `baseUri.resolveUri(result) == uri`,
-/// but may be relative.
-/// The `baseUri` must be absolute.
-Uri _relativize(Uri uri, Uri baseUri) {
- assert(baseUri.isAbsolute);
- if (uri.hasQuery || uri.hasFragment) {
- uri = Uri(
- scheme: uri.scheme,
- userInfo: uri.hasAuthority ? uri.userInfo : null,
- host: uri.hasAuthority ? uri.host : null,
- port: uri.hasAuthority ? uri.port : null,
- path: uri.path);
- }
-
- // Already relative. We assume the caller knows what they are doing.
- if (!uri.isAbsolute) return uri;
-
- if (baseUri.scheme != uri.scheme) {
- return uri;
- }
-
- // If authority differs, we could remove the scheme, but it's not worth it.
- if (uri.hasAuthority != baseUri.hasAuthority) return uri;
- if (uri.hasAuthority) {
- if (uri.userInfo != baseUri.userInfo ||
- uri.host.toLowerCase() != baseUri.host.toLowerCase() ||
- uri.port != baseUri.port) {
- return uri;
- }
- }
-
- baseUri = baseUri.normalizePath();
- var base = baseUri.pathSegments.toList();
- if (base.isNotEmpty) {
- base = List<String>.from(base)..removeLast();
- }
- uri = uri.normalizePath();
- var target = uri.pathSegments.toList();
- if (target.isNotEmpty && target.last.isEmpty) target.removeLast();
- var index = 0;
- while (index < base.length && index < target.length) {
- if (base[index] != target[index]) {
- break;
- }
- index++;
- }
- if (index == base.length) {
- if (index == target.length) {
- return Uri(path: "./");
- }
- return Uri(path: target.skip(index).join('/'));
- } else if (index > 0) {
- return Uri(
- path: '../' * (base.length - index) + target.skip(index).join('/'));
- } else {
- return uri;
- }
-}
diff --git a/lib/src/discovery.dart b/lib/src/discovery.dart
index 8ac6a01..a3e01d7 100644
--- a/lib/src/discovery.dart
+++ b/lib/src/discovery.dart
@@ -32,7 +32,7 @@
/// If any of these tests succeed, a `PackageConfig` class is returned.
/// Returns `null` if no configuration was found. If a configuration
/// is needed, then the caller can supply [PackageConfig.empty].
-Future<PackageConfig /*?*/ > findPackageConfig(
+Future<PackageConfig?> findPackageConfig(
Directory baseDirectory, bool recursive, void onError(Object error)) async {
var directory = baseDirectory;
if (!directory.isAbsolute) directory = directory.absolute;
@@ -53,10 +53,10 @@
}
/// Similar to [findPackageConfig] but based on a URI.
-Future<PackageConfig /*?*/ > findPackageConfigUri(
+Future<PackageConfig?> findPackageConfigUri(
Uri location,
- Future<Uint8List /*?*/ > loader(Uri uri) /*?*/,
- void onError(Object error) /*?*/,
+ Future<Uint8List?> loader(Uri uri)?,
+ void onError(Object error),
bool recursive) async {
if (location.isScheme("package")) {
onError(PackageConfigArgumentError(
@@ -102,7 +102,7 @@
/// If [onError] is supplied, parsing errors are reported using that, and
/// a best-effort attempt is made to return a package configuration.
/// This may be the empty package configuration.
-Future<PackageConfig /*?*/ > findPackagConfigInDirectory(
+Future<PackageConfig?> findPackagConfigInDirectory(
Directory directory, void onError(Object error)) async {
var packageConfigFile = await checkForPackageConfigJsonFile(directory);
if (packageConfigFile != null) {
@@ -115,7 +115,7 @@
return null;
}
-Future<File> /*?*/ checkForPackageConfigJsonFile(Directory directory) async {
+Future<File?> checkForPackageConfigJsonFile(Directory directory) async {
assert(directory.isAbsolute);
var file =
File(pathJoin(directory.path, ".dart_tool", "package_config.json"));
@@ -123,7 +123,7 @@
return null;
}
-Future<File /*?*/ > checkForDotPackagesFile(Directory directory) async {
+Future<File?> checkForDotPackagesFile(Directory directory) async {
var file = File(pathJoin(directory.path, ".packages"));
if (await file.exists()) return file;
return null;
diff --git a/lib/src/errors.dart b/lib/src/errors.dart
index c973617..f351571 100644
--- a/lib/src/errors.dart
+++ b/lib/src/errors.dart
@@ -12,7 +12,7 @@
class PackageConfigArgumentError extends ArgumentError
implements PackageConfigError {
- PackageConfigArgumentError(Object /*?*/ value, String name, String message)
+ PackageConfigArgumentError(Object? value, String name, String message)
: super.value(value, name, message);
PackageConfigArgumentError.from(ArgumentError error)
@@ -21,8 +21,7 @@
class PackageConfigFormatException extends FormatException
implements PackageConfigError {
- PackageConfigFormatException(String message, Object /*?*/ source,
- [int /*?*/ offset])
+ PackageConfigFormatException(String message, Object? source, [int? offset])
: super(message, source, offset);
PackageConfigFormatException.from(FormatException exception)
@@ -30,4 +29,4 @@
}
/// The default `onError` handler.
-void /*Never*/ throwError(Object error) => throw error;
+Never throwError(Object error) => throw error;
diff --git a/lib/src/package_config.dart b/lib/src/package_config.dart
index 30c758a..63d01ea 100644
--- a/lib/src/package_config.dart
+++ b/lib/src/package_config.dart
@@ -50,7 +50,7 @@
/// [PackageConfig.extraData] of the created configuration.
///
/// The version of the resulting configuration is always [maxVersion].
- factory PackageConfig(Iterable<Package> packages, {dynamic extraData}) =>
+ factory PackageConfig(Iterable<Package> packages, {Object? extraData}) =>
SimplePackageConfig(maxVersion, packages, extraData);
/// Parses a package configuration file.
@@ -67,10 +67,10 @@
/// the configuration are reported by calling [onError] instead of
/// throwing, and parser makes a *best effort* attempt to continue
/// despite the error. The input must still be valid JSON.
- /// The result may be a [PackageConfig.empty] if there is no way to
+ /// The result may be [PackageConfig.empty] if there is no way to
/// extract useful information from the bytes.
static PackageConfig parseBytes(Uint8List bytes, Uri baseUri,
- {void onError(Object error)}) =>
+ {void onError(Object error)?}) =>
parsePackageConfigBytes(bytes, baseUri, onError ?? throwError);
/// Parses a package configuration file.
@@ -87,10 +87,10 @@
/// the configuration are reported by calling [onError] instead of
/// throwing, and parser makes a *best effort* attempt to continue
/// despite the error. The input must still be valid JSON.
- /// The result may be a [PackageConfig.empty] if there is no way to
+ /// The result may be [PackageConfig.empty] if there is no way to
/// extract useful information from the bytes.
static PackageConfig parseString(String configuration, Uri baseUri,
- {void onError(Object error)}) =>
+ {void onError(Object error)?}) =>
parsePackageConfigString(configuration, baseUri, onError ?? throwError);
/// Parses the JSON data of a package configuration file.
@@ -108,10 +108,10 @@
/// the configuration are reported by calling [onError] instead of
/// throwing, and parser makes a *best effort* attempt to continue
/// despite the error. The input must still be valid JSON.
- /// The result may be a [PackageConfig.empty] if there is no way to
+ /// The result may be [PackageConfig.empty] if there is no way to
/// extract useful information from the bytes.
- static PackageConfig parseJson(dynamic jsonData, Uri baseUri,
- {void onError(Object error)}) =>
+ static PackageConfig parseJson(Object? jsonData, Uri baseUri,
+ {void onError(Object error)?}) =>
parsePackageConfigJson(jsonData, baseUri, onError ?? throwError);
/// Writes a configuration file for this configuration on [output].
@@ -119,7 +119,7 @@
/// If [baseUri] is provided, URI references in the generated file
/// will be made relative to [baseUri] where possible.
static void writeBytes(PackageConfig configuration, Sink<Uint8List> output,
- [Uri /*?*/ baseUri]) {
+ [Uri? baseUri]) {
writePackageConfigJsonUtf8(configuration, baseUri, output);
}
@@ -128,7 +128,7 @@
/// If [baseUri] is provided, URI references in the generated file
/// will be made relative to [baseUri] where possible.
static void writeString(PackageConfig configuration, StringSink output,
- [Uri /*?*/ baseUri]) {
+ [Uri? baseUri]) {
writePackageConfigJsonString(configuration, baseUri, output);
}
@@ -136,8 +136,8 @@
///
/// If [baseUri] is provided, URI references in the generated data
/// will be made relative to [baseUri] where possible.
- static Map<String, dynamic> toJson(PackageConfig configuration,
- [Uri /*?*/ baseUri]) =>
+ static Map<String, Object?> toJson(PackageConfig configuration,
+ [Uri? baseUri]) =>
packageConfigToJson(configuration, baseUri);
/// The configuration version number.
@@ -162,7 +162,7 @@
/// Returns the [Package] fron [packages] with [packageName] as
/// [Package.name]. Returns `null` if the package is not available in the
/// current configuration.
- Package /*?*/ operator [](String packageName);
+ Package? operator [](String packageName);
/// Provides the associated package for a specific [file] (or directory).
///
@@ -171,7 +171,7 @@
/// of the [file]'s location.
///
/// Returns `null` if the file does not belong to any package.
- Package /*?*/ packageOf(Uri file);
+ Package? packageOf(Uri file);
/// Resolves a `package:` URI to a non-package URI
///
@@ -188,7 +188,7 @@
/// in this package configuration.
/// Returns the remaining path of the package URI resolved relative to the
/// [Package.packageUriRoot] of the corresponding package.
- Uri /*?*/ resolve(Uri packageUri);
+ Uri? resolve(Uri packageUri);
/// The package URI which resolves to [nonPackageUri].
///
@@ -199,14 +199,14 @@
///
/// Returns a package URI which [resolve] will convert to [nonPackageUri],
/// if any such URI exists. Returns `null` if no such package URI exists.
- Uri /*?*/ toPackageUri(Uri nonPackageUri);
+ Uri? toPackageUri(Uri nonPackageUri);
/// Extra data associated with the package configuration.
///
/// The data may be in any format, depending on who introduced it.
/// The standard `packjage_config.json` file storage will only store
/// JSON-like list/map data structures.
- dynamic get extraData;
+ Object? get extraData;
}
/// Configuration data for a single package.
@@ -227,11 +227,11 @@
/// If [extraData] is supplied, it will be available as the
/// [Package.extraData] of the created package.
factory Package(String name, Uri root,
- {Uri /*?*/ packageUriRoot,
- LanguageVersion /*?*/ languageVersion,
- dynamic extraData}) =>
+ {Uri? packageUriRoot,
+ LanguageVersion? languageVersion,
+ Object? extraData}) =>
SimplePackage.validate(
- name, root, packageUriRoot, languageVersion, extraData, throwError);
+ name, root, packageUriRoot, languageVersion, extraData, throwError)!;
/// The package-name of the package.
String get name;
@@ -263,14 +263,18 @@
/// Dart files in the package.
/// A package version is defined by two non-negative numbers,
/// the *major* and *minor* version numbers.
- LanguageVersion /*?*/ get languageVersion;
+ ///
+ /// A package may have no language version associated with it
+ /// in the package configuration, in which case tools should
+ /// use a default behavior for the package.
+ LanguageVersion? get languageVersion;
/// Extra data associated with the specific package.
///
/// The data may be in any format, depending on who introduced it.
- /// The standard `packjage_config.json` file storage will only store
+ /// The standard `package_config.json` file storage will only store
/// JSON-like list/map data structures.
- dynamic get extraData;
+ Object? get extraData;
}
/// A language version.
@@ -307,7 +311,7 @@
/// If [onError] is not supplied, it defaults to throwing the exception.
/// If the call does not throw, then an [InvalidLanguageVersion] is returned
/// containing the original [source].
- static LanguageVersion parse(String source, {void onError(Object error)}) =>
+ static LanguageVersion parse(String source, {void onError(Object error)?}) =>
parseLanguageVersion(source, onError ?? throwError);
/// The major language version.
diff --git a/lib/src/package_config_impl.dart b/lib/src/package_config_impl.dart
index 9e23af0..5c6b7f7 100644
--- a/lib/src/package_config_impl.dart
+++ b/lib/src/package_config_impl.dart
@@ -14,10 +14,10 @@
final int version;
final Map<String, Package> _packages;
final PackageTree _packageTree;
- final dynamic extraData;
+ final Object? extraData;
factory SimplePackageConfig(int version, Iterable<Package> packages,
- [dynamic extraData, void onError(Object error)]) {
+ [Object? extraData, void onError(Object error)?]) {
onError ??= throwError;
var validVersion = _validateVersion(version, onError);
var sortedPackages = [...packages]..sort(_compareRoot);
@@ -53,11 +53,7 @@
var packageNames = <String>{};
var tree = MutablePackageTree();
for (var originalPackage in packages) {
- if (originalPackage == null) {
- onError(ArgumentError.notNull("element of packages"));
- continue;
- }
- SimplePackage package;
+ SimplePackage? package;
if (originalPackage is! SimplePackage) {
// SimplePackage validates these properties.
package = SimplePackage.validate(
@@ -68,7 +64,7 @@
originalPackage.extraData, (error) {
if (error is PackageConfigArgumentError) {
onError(PackageConfigArgumentError(packages, "packages",
- "Package ${package.name}: ${error.message}"));
+ "Package ${package!.name}: ${error.message}"));
} else {
onError(error);
}
@@ -92,7 +88,7 @@
onError(PackageConfigArgumentError(
originalPackages,
"packages",
- "Packages ${package.name} and ${existingPackage.name} "
+ "Packages ${package!.name} and ${existingPackage.name} "
"have the same root directory: ${package.root}.\n"));
} else {
assert(error.isPackageRootConflict);
@@ -100,7 +96,7 @@
onError(PackageConfigArgumentError(
originalPackages,
"packages",
- "Package ${package.name} is inside the package URI root of "
+ "Package ${package!.name} is inside the package URI root of "
"package ${existingPackage.name}.\n"
"${existingPackage.name} URI root: "
"${existingPackage.packageUriRoot}\n"
@@ -117,7 +113,7 @@
Iterable<Package> get packages => _packages.values;
- Package /*?*/ operator [](String packageName) => _packages[packageName];
+ Package? operator [](String packageName) => _packages[packageName];
/// Provides the associated package for a specific [file] (or directory).
///
@@ -125,15 +121,15 @@
/// That is, the [Package.rootUri] directory is a parent directory
/// of the [file]'s location.
/// Returns `null` if the file does not belong to any package.
- Package /*?*/ packageOf(Uri file) => _packageTree.packageOf(file);
+ Package? packageOf(Uri file) => _packageTree.packageOf(file);
- Uri /*?*/ resolve(Uri packageUri) {
+ Uri? resolve(Uri packageUri) {
var packageName = checkValidPackageUri(packageUri, "packageUri");
- return _packages[packageName]?.packageUriRoot?.resolveUri(
+ return _packages[packageName]?.packageUriRoot.resolveUri(
Uri(path: packageUri.path.substring(packageName.length + 1)));
}
- Uri /*?*/ toPackageUri(Uri nonPackageUri) {
+ Uri? toPackageUri(Uri nonPackageUri) {
if (nonPackageUri.isScheme("package")) {
throw PackageConfigArgumentError(
nonPackageUri, "nonPackageUri", "Must not be a package URI");
@@ -161,8 +157,8 @@
final String name;
final Uri root;
final Uri packageUriRoot;
- final LanguageVersion /*?*/ languageVersion;
- final dynamic extraData;
+ final LanguageVersion? languageVersion;
+ final Object? extraData;
SimplePackage._(this.name, this.root, this.packageUriRoot,
this.languageVersion, this.extraData);
@@ -182,12 +178,12 @@
///
/// Returns `null` if the input is invalid and an approximately valid package
/// cannot be salvaged from the input.
- static SimplePackage /*?*/ validate(
+ static SimplePackage? validate(
String name,
Uri root,
- Uri packageUriRoot,
- LanguageVersion /*?*/ languageVersion,
- dynamic extraData,
+ Uri? packageUriRoot,
+ LanguageVersion? languageVersion,
+ Object? extraData,
void onError(Object error)) {
var fatalError = false;
var invalidIndex = checkPackageName(name);
@@ -244,7 +240,7 @@
/// Reports a format exception on [onError] if not, or if the numbers
/// are too large (at most 32-bit signed integers).
LanguageVersion parseLanguageVersion(
- String source, void onError(Object error)) {
+ String? source, void onError(Object error)) {
var index = 0;
// Reads a positive decimal numeral. Returns the value of the numeral,
// or a negative number in case of an error.
@@ -254,7 +250,7 @@
// It is a recoverable error if the numeral starts with leading zeros.
int readNumeral() {
const maxValue = 0x7FFFFFFF;
- if (index == source.length) {
+ if (index == source!.length) {
onError(PackageConfigFormatException("Missing number", source, index));
return -1;
}
@@ -291,7 +287,7 @@
if (major < 0) {
return SimpleInvalidLanguageVersion(source);
}
- if (index == source.length || source.codeUnitAt(index) != $dot) {
+ if (index == source!.length || source.codeUnitAt(index) != $dot) {
onError(PackageConfigFormatException("Missing '.'", source, index));
return SimpleInvalidLanguageVersion(source);
}
@@ -319,7 +315,7 @@
class SimpleLanguageVersion extends _SimpleLanguageVersionBase {
final int major;
final int minor;
- String /*?*/ _source;
+ String? _source;
SimpleLanguageVersion(this.major, this.minor, this._source);
bool operator ==(Object other) =>
@@ -332,17 +328,17 @@
class SimpleInvalidLanguageVersion extends _SimpleLanguageVersionBase
implements InvalidLanguageVersion {
- final String _source;
+ final String? _source;
SimpleInvalidLanguageVersion(this._source);
int get major => -1;
int get minor => -1;
- String toString() => _source;
+ String toString() => _source!;
}
abstract class PackageTree {
Iterable<Package> get allPackages;
- SimplePackage /*?*/ packageOf(Uri file);
+ SimplePackage? packageOf(Uri file);
}
/// Packages of a package configuration ordered by root path.
@@ -373,12 +369,17 @@
/// Indexed by [Package.name].
/// If a package has no nested packages (which is most often the case),
/// there is no tree object associated with it.
- Map<String, MutablePackageTree /*?*/ > /*?*/ _packageChildren;
+ Map<String, MutablePackageTree>? _packageChildren;
Iterable<Package> get allPackages sync* {
- for (var package in packages) yield package;
- if (_packageChildren != null) {
- for (var tree in _packageChildren.values) yield* tree.allPackages;
+ for (var package in packages) {
+ yield package;
+ }
+ var children = _packageChildren;
+ if (children != null) {
+ for (var tree in children.values) {
+ yield* tree.allPackages;
+ }
}
}
@@ -424,7 +425,7 @@
packages.add(package);
}
- SimplePackage /*?*/ packageOf(Uri file) {
+ SimplePackage? packageOf(Uri file) {
return findPackageOf(0, file.toString());
}
@@ -434,7 +435,7 @@
///
/// Assumes the first [start] characters of path agrees with all
/// the packages at this level of the tree.
- SimplePackage /*?*/ findPackageOf(int start, String path) {
+ SimplePackage? findPackageOf(int start, String path) {
for (var childPackage in packages) {
var childPath = childPackage.root.toString();
if (_beginsWith(start, childPath, path)) {
@@ -447,14 +448,9 @@
_beginsWith(childPathLength, uriRoot, path)) {
return childPackage;
}
- // Otherwise add [package] as child of [childPackage].
- // TODO(lrn): When NNBD comes, convert to:
- // return _packageChildren?[childPackage.name]
- // ?.packageOf(childPathLength, path) ?? childPackage;
- if (_packageChildren == null) return childPackage;
- var childTree = _packageChildren[childPackage.name];
- if (childTree == null) return childPackage;
- return childTree.findPackageOf(childPathLength, path) ?? childPackage;
+ return _packageChildren?[childPackage.name]
+ ?.findPackageOf(childPathLength, path) ??
+ childPackage;
}
}
return null;
@@ -474,7 +470,7 @@
Iterable<Package> get allPackages => const Iterable<Package>.empty();
- SimplePackage packageOf(Uri file) => null;
+ SimplePackage? packageOf(Uri file) => null;
}
/// Checks whether [longerPath] begins with [parentPath].
diff --git a/lib/src/package_config_io.dart b/lib/src/package_config_io.dart
index bfbb1e3..d3e59be 100644
--- a/lib/src/package_config_io.dart
+++ b/lib/src/package_config_io.dart
@@ -15,6 +15,21 @@
import "util.dart";
import "util_io.dart";
+/// Name of directory where Dart tools store their configuration.
+///
+/// Directory is created in the package root directory.
+const dartToolDirName = ".dart_tool";
+
+/// Name of file containing new package configuration data.
+///
+/// File is stored in the dart tool directory.
+const packageConfigFileName = "package_config.json";
+
+/// Name of file containing legacy package configuration data.
+///
+/// File is stored in the package root directory.
+const packagesFileName = ".packages";
+
/// Reads a package configuration file.
///
/// Detects whether the [file] is a version one `.packages` file or
@@ -29,9 +44,9 @@
/// The file must exist and be a normal file.
Future<PackageConfig> readAnyConfigFile(
File file, bool preferNewest, void onError(Object error)) async {
- if (preferNewest && fileName(file.path) == ".packages") {
- var alternateFile =
- File(pathJoin(dirName(file.path), ".dart_tool", "package_config.json"));
+ if (preferNewest && fileName(file.path) == packagesFileName) {
+ var alternateFile = File(
+ pathJoin(dirName(file.path), dartToolDirName, packageConfigFileName));
if (alternateFile.existsSync()) {
return await readPackageConfigJsonFile(alternateFile, onError);
}
@@ -49,7 +64,7 @@
/// Like [readAnyConfigFile] but uses a URI and an optional loader.
Future<PackageConfig> readAnyConfigFileUri(
Uri file,
- Future<Uint8List /*?*/ > loader(Uri uri) /*?*/,
+ Future<Uint8List?> loader(Uri uri)?,
void onError(Object error),
bool preferNewest) async {
if (file.isScheme("package")) {
@@ -62,9 +77,9 @@
}
loader = defaultLoader;
}
- if (preferNewest && file.pathSegments.last == ".packages") {
- var alternateFile = file.resolve(".dart_tool/package_config.json");
- Uint8List /*?*/ bytes;
+ if (preferNewest && file.pathSegments.last == packagesFileName) {
+ var alternateFile = file.resolve("$dartToolDirName/$packageConfigFileName");
+ Uint8List? bytes;
try {
bytes = await loader(alternateFile);
} catch (e) {
@@ -75,7 +90,7 @@
return parsePackageConfigBytes(bytes, alternateFile, onError);
}
}
- Uint8List /*?*/ bytes;
+ Uint8List? bytes;
try {
bytes = await loader(file);
} catch (e) {
@@ -131,15 +146,17 @@
Future<void> writePackageConfigJsonFile(
PackageConfig config, Directory targetDirectory) async {
// Write .dart_tool/package_config.json first.
- var file =
- File(pathJoin(targetDirectory.path, ".dart_tool", "package_config.json"));
+ var dartToolDir = Directory(pathJoin(targetDirectory.path, dartToolDirName));
+ await dartToolDir.create(recursive: true);
+ var file = File(pathJoin(dartToolDir.path, packageConfigFileName));
var baseUri = file.uri;
+
var sink = file.openWrite(encoding: utf8);
writePackageConfigJsonUtf8(config, baseUri, sink);
var doneJson = sink.close();
// Write .packages too.
- file = File(pathJoin(targetDirectory.path, ".packages"));
+ file = File(pathJoin(targetDirectory.path, packagesFileName));
baseUri = file.uri;
sink = file.openWrite(encoding: utf8);
writeDotPackages(config, baseUri, sink);
diff --git a/lib/src/package_config_json.dart b/lib/src/package_config_json.dart
index 27abf50..25b04c4 100644
--- a/lib/src/package_config_json.dart
+++ b/lib/src/package_config_json.dart
@@ -59,10 +59,10 @@
/// Creates a [PackageConfig] from a parsed JSON-like object structure.
///
-/// The [json] argument must be a JSON object (`Map<String, dynamic>`)
+/// The [json] argument must be a JSON object (`Map<String, Object?>`)
/// containing a `"configVersion"` entry with an integer value in the range
/// 1 to [PackageConfig.maxVersion],
-/// and with a `"packages"` entry which is a JSON array (`List<dynamic>`)
+/// and with a `"packages"` entry which is a JSON array (`List<Object?>`)
/// containing JSON objects which each has the following properties:
///
/// * `"name"`: The package name as a string.
@@ -80,7 +80,7 @@
/// The [baseLocation] is used as base URI to resolve the "rootUri"
/// URI referencestring.
PackageConfig parsePackageConfigJson(
- dynamic json, Uri baseLocation, void onError(Object error)) {
+ Object? json, Uri baseLocation, void onError(Object error)) {
if (!baseLocation.hasScheme || baseLocation.isScheme("package")) {
throw PackageConfigArgumentError(baseLocation.toString(), "baseLocation",
"Must be an absolute non-package: URI");
@@ -97,10 +97,10 @@
return "object";
}
- T checkType<T>(dynamic value, String name, [String /*?*/ packageName]) {
+ T? checkType<T>(Object? value, String name, [String? packageName]) {
if (value is T) return value;
- // The only types we are called with are [int], [String], [List<dynamic>]
- // and Map<String, dynamic>. Recognize which to give a better error message.
+ // The only types we are called with are [int], [String], [List<Object?>]
+ // and Map<String, Object?>. Recognize which to give a better error message.
var message =
"$name${packageName != null ? " of package $packageName" : ""}"
" is not a JSON ${typeName<T>()}";
@@ -108,12 +108,12 @@
return null;
}
- Package /*?*/ parsePackage(Map<String, dynamic> entry) {
- String /*?*/ name;
- String /*?*/ rootUri;
- String /*?*/ packageUri;
- String /*?*/ languageVersion;
- Map<String, dynamic> /*?*/ extraData;
+ Package? parsePackage(Map<String, Object?> entry) {
+ String? name;
+ String? rootUri;
+ String? packageUri;
+ String? languageVersion;
+ Map<String, Object?>? extraData;
var hasName = false;
var hasRoot = false;
var hasVersion = false;
@@ -146,22 +146,22 @@
onError(PackageConfigFormatException("Missing rootUri entry", entry));
}
if (name == null || rootUri == null) return null;
- var root = baseLocation.resolve(rootUri);
+ var root = baseLocation.resolve(rootUri!);
if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/");
var packageRoot = root;
- if (packageUri != null) packageRoot = root.resolve(packageUri);
+ if (packageUri != null) packageRoot = root.resolve(packageUri!);
if (!packageRoot.path.endsWith("/")) {
packageRoot = packageRoot.replace(path: packageRoot.path + "/");
}
- LanguageVersion /*?*/ version;
+ LanguageVersion? version;
if (languageVersion != null) {
version = parseLanguageVersion(languageVersion, onError);
} else if (hasVersion) {
version = SimpleInvalidLanguageVersion("invalid");
}
- return SimplePackage.validate(name, root, packageRoot, version, extraData,
+ return SimplePackage.validate(name!, root, packageRoot, version, extraData,
(error) {
if (error is ArgumentError) {
onError(
@@ -172,22 +172,22 @@
});
}
- var map = checkType<Map<String, dynamic>>(json, "value");
+ var map = checkType<Map<String, Object?>>(json, "value");
if (map == null) return const SimplePackageConfig.empty();
- Map<String, dynamic> /*?*/ extraData;
- List<Package> /*?*/ packageList;
- int /*?*/ configVersion;
+ Map<String, Object?>? extraData;
+ List<Package>? packageList;
+ int? configVersion;
map.forEach((key, value) {
switch (key) {
case _configVersionKey:
configVersion = checkType<int>(value, _configVersionKey) ?? 2;
break;
case _packagesKey:
- var packageArray = checkType<List<dynamic>>(value, _packagesKey) ?? [];
+ var packageArray = checkType<List<Object?>>(value, _packagesKey) ?? [];
var packages = <Package>[];
for (var package in packageArray) {
var packageMap =
- checkType<Map<String, dynamic>>(package, "package entry");
+ checkType<Map<String, Object?>>(package, "package entry");
if (packageMap != null) {
var entry = parsePackage(packageMap);
if (entry != null) {
@@ -210,7 +210,7 @@
onError(PackageConfigFormatException("Missing packages list", json));
packageList = [];
}
- return SimplePackageConfig(configVersion, packageList, extraData, (error) {
+ return SimplePackageConfig(configVersion!, packageList!, extraData, (error) {
if (error is ArgumentError) {
onError(PackageConfigFormatException(error.message, error.invalidValue));
} else {
@@ -222,26 +222,26 @@
final _jsonUtf8Encoder = JsonUtf8Encoder(" ");
void writePackageConfigJsonUtf8(
- PackageConfig config, Uri baseUri, Sink<List<int>> output) {
+ PackageConfig config, Uri? baseUri, Sink<List<int>> output) {
// Can be optimized.
var data = packageConfigToJson(config, baseUri);
output.add(_jsonUtf8Encoder.convert(data) as Uint8List);
}
void writePackageConfigJsonString(
- PackageConfig config, Uri baseUri, StringSink output) {
+ PackageConfig config, Uri? baseUri, StringSink output) {
// Can be optimized.
var data = packageConfigToJson(config, baseUri);
output.write(JsonEncoder.withIndent(" ").convert(data) as Uint8List);
}
-Map<String, dynamic> packageConfigToJson(PackageConfig config, Uri baseUri) =>
- <String, dynamic>{
+Map<String, Object?> packageConfigToJson(PackageConfig config, Uri? baseUri) =>
+ <String, Object?>{
...?_extractExtraData(config.extraData, _topNames),
_configVersionKey: PackageConfig.maxVersion,
_packagesKey: [
for (var package in config.packages)
- <String, dynamic>{
+ <String, Object?>{
_nameKey: package.name,
_rootUriKey: relativizeUri(package.root, baseUri).toString(),
if (package.root != package.packageUriRoot)
@@ -259,15 +259,15 @@
void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) {
var extraData = config.extraData;
// Write .packages too.
- String /*?*/ comment;
- if (extraData != null) {
- String /*?*/ generator = extraData[_generatorKey];
- if (generator != null) {
- String /*?*/ generated = extraData[_generatedKey];
- String /*?*/ generatorVersion = extraData[_generatorVersionKey];
+ String? comment;
+ if (extraData is Map<String, Object?>) {
+ var generator = extraData[_generatorKey];
+ if (generator is String) {
+ var generated = extraData[_generatedKey];
+ var generatorVersion = extraData[_generatorVersionKey];
comment = "Generated by $generator"
- "${generatorVersion != null ? " $generatorVersion" : ""}"
- "${generated != null ? " on $generated" : ""}.";
+ "${generatorVersion is String ? " $generatorVersion" : ""}"
+ "${generated is String ? " on $generated" : ""}.";
}
}
packages_file.write(output, config, baseUri: baseUri, comment: comment);
@@ -277,20 +277,21 @@
///
/// If the value contains any of the [reservedNames] for the current context,
/// entries with that name in the extra data are dropped.
-Map<String, dynamic> /*?*/ _extractExtraData(
- dynamic data, Iterable<String> reservedNames) {
- if (data is Map<String, dynamic>) {
+Map<String, Object?>? _extractExtraData(
+ Object? data, Iterable<String> reservedNames) {
+ if (data is Map<String, Object?>) {
if (data.isEmpty) return null;
for (var name in reservedNames) {
if (data.containsKey(name)) {
- data = {
+ var filteredData = {
for (var key in data.keys)
if (!reservedNames.contains(key)) key: data[key]
};
- if (data.isEmpty) return null;
- for (var value in data.values) {
+ if (filteredData.isEmpty) return null;
+ for (var value in filteredData.values) {
if (!_validateJson(value)) return null;
}
+ return filteredData;
}
}
return data;
@@ -299,13 +300,13 @@
}
/// Checks that the object is a valid JSON-like data structure.
-bool _validateJson(dynamic object) {
+bool _validateJson(Object? object) {
if (object == null || true == object || false == object) return true;
if (object is num || object is String) return true;
- if (object is List<dynamic>) {
+ if (object is List<Object?>) {
return object.every(_validateJson);
}
- if (object is Map<String, dynamic>) {
+ if (object is Map<String, Object?>) {
return object.values.every(_validateJson);
}
return false;
diff --git a/lib/src/packages_file.dart b/lib/src/packages_file.dart
index 184b0dd..071d548 100644
--- a/lib/src/packages_file.dart
+++ b/lib/src/packages_file.dart
@@ -154,7 +154,7 @@
/// All the keys of [packageMapping] must be valid package names,
/// and the values must be URIs that do not have the `package:` scheme.
void write(StringSink output, PackageConfig config,
- {Uri baseUri, String comment}) {
+ {Uri? baseUri, String? comment}) {
if (baseUri != null && !baseUri.isAbsolute) {
throw PackageConfigArgumentError(baseUri, "baseUri", "Must be absolute");
}
@@ -187,7 +187,7 @@
output.write(':');
// If baseUri is provided, make the URI relative to baseUri.
if (baseUri != null) {
- uri = relativizeUri(uri, baseUri);
+ uri = relativizeUri(uri, baseUri)!;
}
if (!uri.path.endsWith('/')) {
uri = uri.replace(path: uri.path + '/');
diff --git a/lib/src/packages_impl.dart b/lib/src/packages_impl.dart
deleted file mode 100644
index 19f1039..0000000
--- a/lib/src/packages_impl.dart
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Implementations of [Packages] that may be used in either server or browser
-/// based applications. For implementations that can only run in the browser,
-/// see [package_config.packages_io_impl].
-@Deprecated("Use the package_config.json based API")
-library package_config.packages_impl;
-
-import "dart:collection" show UnmodifiableMapView;
-
-import "../packages.dart";
-import "util.dart" show checkValidPackageUri;
-
-/// A [Packages] null-object.
-class NoPackages implements Packages {
- const NoPackages();
-
- Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) {
- var packageName = checkValidPackageUri(packageUri, "packageUri");
- if (notFound != null) return notFound(packageUri);
- throw ArgumentError.value(
- packageUri, "packageUri", 'No package named "$packageName"');
- }
-
- Iterable<String> get packages => Iterable<String>.empty();
-
- Map<String, Uri> asMap() => const <String, Uri>{};
-
- String get defaultPackageName => null;
-
- String packageMetadata(String packageName, String key) => null;
-
- String libraryMetadata(Uri libraryUri, String key) => null;
-}
-
-/// Base class for [Packages] implementations.
-///
-/// This class implements the [resolve] method in terms of a private
-/// member
-abstract class PackagesBase implements Packages {
- Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) {
- packageUri = packageUri.normalizePath();
- var packageName = checkValidPackageUri(packageUri, "packageUri");
- var packageBase = getBase(packageName);
- if (packageBase == null) {
- if (notFound != null) return notFound(packageUri);
- throw ArgumentError.value(
- packageUri, "packageUri", 'No package named "$packageName"');
- }
- var packagePath = packageUri.path.substring(packageName.length + 1);
- return packageBase.resolve(packagePath);
- }
-
- /// Find a base location for a package name.
- ///
- /// Returns `null` if no package exists with that name, and that can be
- /// determined.
- Uri getBase(String packageName);
-
- String get defaultPackageName => null;
-
- String packageMetadata(String packageName, String key) => null;
-
- String libraryMetadata(Uri libraryUri, String key) => null;
-}
-
-/// A [Packages] implementation based on an existing map.
-class MapPackages extends PackagesBase {
- final Map<String, Uri> _mapping;
- MapPackages(this._mapping);
-
- Uri getBase(String packageName) =>
- packageName.isEmpty ? null : _mapping[packageName];
-
- Iterable<String> get packages => _mapping.keys;
-
- Map<String, Uri> asMap() => UnmodifiableMapView<String, Uri>(_mapping);
-
- String get defaultPackageName => _mapping[""]?.toString();
-
- String packageMetadata(String packageName, String key) {
- if (packageName.isEmpty) return null;
- var uri = _mapping[packageName];
- if (uri == null || !uri.hasFragment) return null;
- // This can be optimized, either by caching the map or by
- // parsing incrementally instead of parsing the entire fragment.
- return Uri.splitQueryString(uri.fragment)[key];
- }
-
- String libraryMetadata(Uri libraryUri, String key) {
- if (libraryUri.isScheme("package")) {
- return packageMetadata(libraryUri.pathSegments.first, key);
- }
- var defaultPackageNameUri = _mapping[""];
- if (defaultPackageNameUri != null) {
- return packageMetadata(defaultPackageNameUri.toString(), key);
- }
- return null;
- }
-}
-
-/// A [Packages] implementation based on a remote (e.g., HTTP) directory.
-///
-/// There is no way to detect which packages exist short of trying to use
-/// them. You can't necessarily check whether a directory exists,
-/// except by checking for a know file in the directory.
-class NonFilePackagesDirectoryPackages extends PackagesBase {
- final Uri _packageBase;
- NonFilePackagesDirectoryPackages(this._packageBase);
-
- Uri getBase(String packageName) => _packageBase.resolve("$packageName/");
-
- Error _failListingPackages() {
- return UnsupportedError(
- "Cannot list packages for a ${_packageBase.scheme}: "
- "based package root");
- }
-
- Iterable<String> get packages {
- throw _failListingPackages();
- }
-
- Map<String, Uri> asMap() {
- throw _failListingPackages();
- }
-}
diff --git a/lib/src/packages_io_impl.dart b/lib/src/packages_io_impl.dart
deleted file mode 100644
index c623f4d..0000000
--- a/lib/src/packages_io_impl.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Implementations of [Packages] that can only be used in server based
-/// applications.
-@Deprecated("Use the package_config.json based API")
-library package_config.packages_io_impl;
-
-import "dart:collection" show UnmodifiableMapView;
-import "dart:io" show Directory;
-
-import "packages_impl.dart";
-
-import "util_io.dart";
-
-/// A [Packages] implementation based on a local directory.
-class FilePackagesDirectoryPackages extends PackagesBase {
- final Directory _packageDir;
- final Map<String, Uri> _packageToBaseUriMap = <String, Uri>{};
-
- FilePackagesDirectoryPackages(this._packageDir);
-
- Uri getBase(String packageName) {
- return _packageToBaseUriMap.putIfAbsent(packageName, () {
- return Uri.file(pathJoin(_packageDir.path, packageName, '.'));
- });
- }
-
- Iterable<String> _listPackageNames() {
- return _packageDir
- .listSync()
- .whereType<Directory>()
- .map((e) => fileName(e.path));
- }
-
- Iterable<String> get packages => _listPackageNames();
-
- Map<String, Uri> asMap() {
- var result = <String, Uri>{};
- for (var packageName in _listPackageNames()) {
- result[packageName] = getBase(packageName);
- }
- return UnmodifiableMapView<String, Uri>(result);
- }
-}
diff --git a/lib/src/util.dart b/lib/src/util.dart
index 50b140f..9b263ae 100644
--- a/lib/src/util.dart
+++ b/lib/src/util.dart
@@ -153,10 +153,10 @@
/// `baseUri.resolveUri(result) == uri`,
///
/// The `baseUri` must be absolute.
-Uri relativizeUri(Uri uri, Uri /*?*/ baseUri) {
+Uri? relativizeUri(Uri? uri, Uri? baseUri) {
if (baseUri == null) return uri;
assert(baseUri.isAbsolute);
- if (uri.hasQuery || uri.hasFragment) {
+ if (uri!.hasQuery || uri.hasFragment) {
uri = Uri(
scheme: uri.scheme,
userInfo: uri.hasAuthority ? uri.userInfo : null,
diff --git a/lib/src/util_io.dart b/lib/src/util_io.dart
index 2aa8c94..8e5f0b8 100644
--- a/lib/src/util_io.dart
+++ b/lib/src/util_io.dart
@@ -9,7 +9,7 @@
import 'dart:io';
import 'dart:typed_data';
-Future<Uint8List> defaultLoader(Uri uri) async {
+Future<Uint8List?> defaultLoader(Uri uri) async {
if (uri.isScheme("file")) {
var file = File.fromUri(uri);
try {
@@ -24,7 +24,7 @@
throw UnsupportedError("Default URI unsupported scheme: $uri");
}
-Future<Uint8List /*?*/ > _httpGet(Uri uri) async {
+Future<Uint8List?> _httpGet(Uri uri) async {
assert(uri.isScheme("http") || uri.isScheme("https"));
var client = HttpClient();
var request = await client.getUrl(uri);
@@ -45,7 +45,7 @@
}
var result = Uint8List(totalLength);
var offset = 0;
- for (Uint8List contentPart in splitContent) {
+ for (var contentPart in splitContent as Iterable<Uint8List>) {
result.setRange(offset, offset + contentPart.length, contentPart);
offset += contentPart.length;
}
@@ -80,7 +80,7 @@
///
/// If a part ends with a path separator, then no extra separator is
/// inserted.
-String pathJoin(String part1, String part2, [String part3]) {
+String pathJoin(String part1, String part2, [String? part3]) {
var separator = Platform.pathSeparator;
var separator1 = part1.endsWith(separator) ? "" : separator;
if (part3 == null) {
diff --git a/pubspec.yaml b/pubspec.yaml
index b7d5969..05c5266 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,20 +1,55 @@
name: package_config
-version: 1.9.3
+version: 2.0.0-dev
description: Support for working with Package Configuration files.
homepage: https://github.com/dart-lang/package_config
environment:
- sdk: '>=2.7.0 <3.0.0'
+ sdk: '>=2.12.0-0 <3.0.0'
dependencies:
- path: ^1.6.4
- charcode: ^1.1.0
+ path: ^1.8.0-nullsafety.3
dev_dependencies:
- test: ^1.6.4
- matcher: ^0.12.5
- pedantic: ^1.9.0
+ build_resolvers: ^1.10.0
+ build_runner: ^1.10.0
+ build_runner_core: ^1.10.0
+ build_test: ^1.3.0
+ build_web_compilers: ^2.15.0
+ pedantic: ^1.10.0-nullsafety.3
+ test: ^1.16.0-nullsafety.4
- build_runner: ^1.0.0
- build_web_compilers: ^2.0.0
- build_test: ^0.10.0
+dependency_overrides:
+ analyzer:
+ git:
+ url: git://github.com/dart-lang/sdk.git
+ path: pkg/analyzer
+ build_resolvers:
+ git:
+ url: git://github.com/dart-lang/build.git
+ path: build_resolvers
+ build_runner:
+ git:
+ url: git://github.com/dart-lang/build.git
+ path: build_runner
+ build_runner_core:
+ git:
+ url: git://github.com/dart-lang/build.git
+ path: build_runner_core
+ build_test:
+ git:
+ url: git://github.com/dart-lang/build.git
+ path: build_test
+ coverage:
+ git: git://github.com/dart-lang/coverage.git
+ test:
+ git:
+ url: git://github.com/dart-lang/test.git
+ path: pkgs/test
+ test_api:
+ git:
+ url: git://github.com/dart-lang/test.git
+ path: pkgs/test_api
+ test_core:
+ git:
+ url: git://github.com/dart-lang/test.git
+ path: pkgs/test_core
diff --git a/test/discovery_test.dart b/test/discovery_test.dart
index 5cbc992..df2374d 100644
--- a/test/discovery_test.dart
+++ b/test/discovery_test.dart
@@ -63,7 +63,7 @@
"package_config.json": packageConfigFile,
}
}, (Directory directory) async {
- var config = await findPackageConfig(directory);
+ var config = (await findPackageConfig(directory))!;
expect(config.version, 2); // Found package_config.json file.
validatePackagesFile(config, directory);
});
@@ -74,7 +74,7 @@
"script.dart": "main(){}",
"packages": {"shouldNotBeFound": {}}
}, (Directory directory) async {
- var config = await findPackageConfig(directory);
+ var config = (await findPackageConfig(directory))!;
expect(config.version, 1); // Found .packages file.
validatePackagesFile(config, directory);
});
@@ -89,7 +89,7 @@
"script.dart": "main(){}",
}
}, (Directory directory) async {
- var config = await findPackageConfig(subdir(directory, "subdir/"));
+ var config = (await findPackageConfig(subdir(directory, "subdir/")))!;
expect(config.version, 2);
validatePackagesFile(config, directory);
});
diff --git a/test/discovery_uri_test.dart b/test/discovery_uri_test.dart
index 23c02d7..a895279 100644
--- a/test/discovery_uri_test.dart
+++ b/test/discovery_uri_test.dart
@@ -61,7 +61,7 @@
"package_config.json": packageConfigFile,
}
}, (directory, loader) async {
- var config = await findPackageConfigUri(directory, loader: loader);
+ var config = (await findPackageConfigUri(directory, loader: loader))!;
expect(config.version, 2); // Found package_config.json file.
validatePackagesFile(config, directory);
});
@@ -72,7 +72,7 @@
"script.dart": "main(){}",
"packages": {"shouldNotBeFound": {}}
}, (directory, loader) async {
- var config = await findPackageConfigUri(directory, loader: loader);
+ var config = (await findPackageConfigUri(directory, loader: loader))!;
expect(config.version, 1); // Found .packages file.
validatePackagesFile(config, directory);
});
@@ -87,8 +87,8 @@
"script.dart": "main(){}",
}
}, (directory, loader) async {
- var config = await findPackageConfigUri(directory.resolve("subdir/"),
- loader: loader);
+ var config = (await findPackageConfigUri(directory.resolve("subdir/"),
+ loader: loader))!;
expect(config.version, 2);
validatePackagesFile(config, directory);
});
diff --git a/test/legacy/all.dart b/test/legacy/all.dart
deleted file mode 100644
index 22e2e4f..0000000
--- a/test/legacy/all.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@deprecated
-library package_config.all_test;
-
-import "package:test/test.dart";
-
-import "discovery_analysis_test.dart" as discovery_analysis;
-import "discovery_test.dart" as discovery;
-import "parse_test.dart" as parse;
-import "parse_write_test.dart" as parse_write;
-
-void main() {
- group("parse:", parse.main);
- group("discovery:", discovery.main);
- group("discovery-analysis:", discovery_analysis.main);
- group("parse/write:", parse_write.main);
-}
diff --git a/test/legacy/discovery_analysis_test.dart b/test/legacy/discovery_analysis_test.dart
deleted file mode 100644
index 7554d85..0000000
--- a/test/legacy/discovery_analysis_test.dart
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@deprecated
-@TestOn('vm')
-library package_config.discovery_analysis_test;
-
-import "dart:io";
-
-import "package:package_config/discovery_analysis.dart";
-import "package:package_config/packages.dart";
-import "package:path/path.dart" as path;
-import "package:test/test.dart";
-
-void main() {
- fileTest("basic", {
- ".packages": packagesFile,
- "foo": {".packages": packagesFile},
- "bar": {
- "packages": {"foo": {}, "bar": {}, "baz": {}}
- },
- "baz": {}
- }, (Directory directory) {
- var dirUri = Uri.directory(directory.path);
- var ctx = PackageContext.findAll(directory);
- var root = ctx[directory];
- expect(root, same(ctx));
- validatePackagesFile(root.packages, dirUri);
- var fooDir = sub(directory, "foo");
- var foo = ctx[fooDir];
- expect(identical(root, foo), isFalse);
- validatePackagesFile(foo.packages, dirUri.resolve("foo/"));
- var barDir = sub(directory, "bar");
- var bar = ctx[sub(directory, "bar")];
- validatePackagesDir(bar.packages, dirUri.resolve("bar/"));
- var barbar = ctx[sub(barDir, "bar")];
- expect(barbar, same(bar)); // inherited.
- var baz = ctx[sub(directory, "baz")];
- expect(baz, same(root)); // inherited.
-
- var map = ctx.asMap();
- expect(map.keys.map((dir) => dir.path),
- unorderedEquals([directory.path, fooDir.path, barDir.path]));
- return null;
- });
-}
-
-Directory sub(Directory parent, String dirName) {
- return Directory(path.join(parent.path, dirName));
-}
-
-const packagesFile = """
-# A comment
-foo:file:///dart/packages/foo/
-bar:http://example.com/dart/packages/bar/
-baz:packages/baz/
-""";
-
-void validatePackagesFile(Packages resolver, Uri location) {
- expect(resolver, isNotNull);
- expect(resolver.resolve(pkg("foo", "bar/baz")),
- equals(Uri.parse("file:///dart/packages/foo/bar/baz")));
- expect(resolver.resolve(pkg("bar", "baz/qux")),
- equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux")));
- expect(resolver.resolve(pkg("baz", "qux/foo")),
- equals(location.resolve("packages/baz/qux/foo")));
- expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"]));
-}
-
-void validatePackagesDir(Packages resolver, Uri location) {
- // Expect three packages: foo, bar and baz
- expect(resolver, isNotNull);
- expect(resolver.resolve(pkg("foo", "bar/baz")),
- equals(location.resolve("packages/foo/bar/baz")));
- expect(resolver.resolve(pkg("bar", "baz/qux")),
- equals(location.resolve("packages/bar/baz/qux")));
- expect(resolver.resolve(pkg("baz", "qux/foo")),
- equals(location.resolve("packages/baz/qux/foo")));
- if (location.scheme == "file") {
- expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"]));
- } else {
- expect(() => resolver.packages, throwsUnsupportedError);
- }
-}
-
-Uri pkg(String packageName, String packagePath) {
- var path;
- if (packagePath.startsWith('/')) {
- path = "$packageName$packagePath";
- } else {
- path = "$packageName/$packagePath";
- }
- return Uri(scheme: "package", path: path);
-}
-
-/// Create a directory structure from [description] and run [fileTest].
-///
-/// Description is a map, each key is a file entry. If the value is a map,
-/// it's a sub-dir, otherwise it's a file and the value is the content
-/// as a string.
-void fileTest(
- String name, Map description, Future fileTest(Directory directory)) {
- group("file-test", () {
- var tempDir = Directory.systemTemp.createTempSync("file-test");
- setUp(() {
- _createFiles(tempDir, description);
- });
- tearDown(() {
- tempDir.deleteSync(recursive: true);
- });
- test(name, () => fileTest(tempDir));
- });
-}
-
-void _createFiles(Directory target, Map description) {
- description.forEach((name, content) {
- if (content is Map) {
- var subDir = Directory(path.join(target.path, name));
- subDir.createSync();
- _createFiles(subDir, content);
- } else {
- var file = File(path.join(target.path, name));
- file.writeAsStringSync(content, flush: true);
- }
- });
-}
diff --git a/test/legacy/discovery_test.dart b/test/legacy/discovery_test.dart
deleted file mode 100644
index 72874c8..0000000
--- a/test/legacy/discovery_test.dart
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@deprecated
-@TestOn('vm')
-library package_config.discovery_test;
-
-import "dart:async";
-import "dart:io";
-import "package:test/test.dart";
-import "package:package_config/packages.dart";
-import "package:package_config/discovery.dart";
-import "package:path/path.dart" as path;
-
-const packagesFile = """
-# A comment
-foo:file:///dart/packages/foo/
-bar:http://example.com/dart/packages/bar/
-baz:packages/baz/
-""";
-
-void validatePackagesFile(Packages resolver, Uri location) {
- expect(resolver, isNotNull);
- expect(resolver.resolve(pkg("foo", "bar/baz")),
- equals(Uri.parse("file:///dart/packages/foo/bar/baz")));
- expect(resolver.resolve(pkg("bar", "baz/qux")),
- equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux")));
- expect(resolver.resolve(pkg("baz", "qux/foo")),
- equals(location.resolve("packages/baz/qux/foo")));
- expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"]));
-}
-
-void validatePackagesDir(Packages resolver, Uri location) {
- // Expect three packages: foo, bar and baz
- expect(resolver, isNotNull);
- expect(resolver.resolve(pkg("foo", "bar/baz")),
- equals(location.resolve("packages/foo/bar/baz")));
- expect(resolver.resolve(pkg("bar", "baz/qux")),
- equals(location.resolve("packages/bar/baz/qux")));
- expect(resolver.resolve(pkg("baz", "qux/foo")),
- equals(location.resolve("packages/baz/qux/foo")));
- if (location.scheme == "file") {
- expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"]));
- } else {
- expect(() => resolver.packages, throwsUnsupportedError);
- }
-}
-
-Uri pkg(String packageName, String packagePath) {
- var path;
- if (packagePath.startsWith('/')) {
- path = "$packageName$packagePath";
- } else {
- path = "$packageName/$packagePath";
- }
- return Uri(scheme: "package", path: path);
-}
-
-void main() {
- generalTest(".packages", {
- ".packages": packagesFile,
- "script.dart": "main(){}",
- "packages": {"shouldNotBeFound": {}}
- }, (Uri location) async {
- Packages resolver;
- resolver = await findPackages(location);
- validatePackagesFile(resolver, location);
- resolver = await findPackages(location.resolve("script.dart"));
- validatePackagesFile(resolver, location);
- var specificDiscovery = (location.scheme == "file")
- ? findPackagesFromFile
- : findPackagesFromNonFile;
- resolver = await specificDiscovery(location);
- validatePackagesFile(resolver, location);
- resolver = await specificDiscovery(location.resolve("script.dart"));
- validatePackagesFile(resolver, location);
- });
-
- generalTest("packages/", {
- "packages": {"foo": {}, "bar": {}, "baz": {}},
- "script.dart": "main(){}"
- }, (Uri location) async {
- Packages resolver;
- var isFile = (location.scheme == "file");
- resolver = await findPackages(location);
- validatePackagesDir(resolver, location);
- resolver = await findPackages(location.resolve("script.dart"));
- validatePackagesDir(resolver, location);
- var specificDiscovery =
- isFile ? findPackagesFromFile : findPackagesFromNonFile;
- resolver = await specificDiscovery(location);
- validatePackagesDir(resolver, location);
- resolver = await specificDiscovery(location.resolve("script.dart"));
- validatePackagesDir(resolver, location);
- });
-
- generalTest("underscore packages", {
- "packages": {"_foo": {}}
- }, (Uri location) async {
- var resolver = await findPackages(location);
- expect(resolver.resolve(pkg("_foo", "foo.dart")),
- equals(location.resolve("packages/_foo/foo.dart")));
- });
-
- fileTest(".packages recursive", {
- ".packages": packagesFile,
- "subdir": {"script.dart": "main(){}"}
- }, (Uri location) async {
- Packages resolver;
- resolver = await findPackages(location.resolve("subdir/"));
- validatePackagesFile(resolver, location);
- resolver = await findPackages(location.resolve("subdir/script.dart"));
- validatePackagesFile(resolver, location);
- resolver = await findPackagesFromFile(location.resolve("subdir/"));
- validatePackagesFile(resolver, location);
- resolver =
- await findPackagesFromFile(location.resolve("subdir/script.dart"));
- validatePackagesFile(resolver, location);
- });
-
- httpTest(".packages not recursive", {
- ".packages": packagesFile,
- "subdir": {"script.dart": "main(){}"}
- }, (Uri location) async {
- Packages resolver;
- var subdir = location.resolve("subdir/");
- resolver = await findPackages(subdir);
- validatePackagesDir(resolver, subdir);
- resolver = await findPackages(subdir.resolve("script.dart"));
- validatePackagesDir(resolver, subdir);
- resolver = await findPackagesFromNonFile(subdir);
- validatePackagesDir(resolver, subdir);
- resolver = await findPackagesFromNonFile(subdir.resolve("script.dart"));
- validatePackagesDir(resolver, subdir);
- });
-
- fileTest("no packages", {"script.dart": "main(){}"}, (Uri location) async {
- // A file: location with no .packages or packages returns
- // Packages.noPackages.
- Packages resolver;
- resolver = await findPackages(location);
- expect(resolver, same(Packages.noPackages));
- resolver = await findPackages(location.resolve("script.dart"));
- expect(resolver, same(Packages.noPackages));
- resolver = findPackagesFromFile(location);
- expect(resolver, same(Packages.noPackages));
- resolver = findPackagesFromFile(location.resolve("script.dart"));
- expect(resolver, same(Packages.noPackages));
- });
-
- httpTest("no packages", {"script.dart": "main(){}"}, (Uri location) async {
- // A non-file: location with no .packages or packages/:
- // Assumes a packages dir exists, and resolves relative to that.
- Packages resolver;
- resolver = await findPackages(location);
- validatePackagesDir(resolver, location);
- resolver = await findPackages(location.resolve("script.dart"));
- validatePackagesDir(resolver, location);
- resolver = await findPackagesFromNonFile(location);
- validatePackagesDir(resolver, location);
- resolver = await findPackagesFromNonFile(location.resolve("script.dart"));
- validatePackagesDir(resolver, location);
- });
-
- test(".packages w/ loader", () async {
- var location = Uri.parse("krutch://example.com/path/");
- Future<List<int>> loader(Uri file) async {
- if (file.path.endsWith(".packages")) {
- return packagesFile.codeUnits;
- }
- throw "not found";
- }
-
- // A non-file: location with no .packages or packages/:
- // Assumes a packages dir exists, and resolves relative to that.
- Packages resolver;
- resolver = await findPackages(location, loader: loader);
- validatePackagesFile(resolver, location);
- resolver =
- await findPackages(location.resolve("script.dart"), loader: loader);
- validatePackagesFile(resolver, location);
- resolver = await findPackagesFromNonFile(location, loader: loader);
- validatePackagesFile(resolver, location);
- resolver = await findPackagesFromNonFile(location.resolve("script.dart"),
- loader: loader);
- validatePackagesFile(resolver, location);
- });
-
- test("no packages w/ loader", () async {
- var location = Uri.parse("krutch://example.com/path/");
- Future<List<int>> loader(Uri file) async {
- throw "not found";
- }
-
- // A non-file: location with no .packages or packages/:
- // Assumes a packages dir exists, and resolves relative to that.
- Packages resolver;
- resolver = await findPackages(location, loader: loader);
- validatePackagesDir(resolver, location);
- resolver =
- await findPackages(location.resolve("script.dart"), loader: loader);
- validatePackagesDir(resolver, location);
- resolver = await findPackagesFromNonFile(location, loader: loader);
- validatePackagesDir(resolver, location);
- resolver = await findPackagesFromNonFile(location.resolve("script.dart"),
- loader: loader);
- validatePackagesDir(resolver, location);
- });
-
- generalTest("loadPackagesFile", {".packages": packagesFile},
- (Uri directory) async {
- var file = directory.resolve(".packages");
- var resolver = await loadPackagesFile(file);
- validatePackagesFile(resolver, file);
- });
-
- generalTest(
- "loadPackagesFile non-default name", {"pheldagriff": packagesFile},
- (Uri directory) async {
- var file = directory.resolve("pheldagriff");
- var resolver = await loadPackagesFile(file);
- validatePackagesFile(resolver, file);
- });
-
- test("loadPackagesFile w/ loader", () async {
- Future<List<int>> loader(Uri uri) async => packagesFile.codeUnits;
- var file = Uri.parse("krutz://example.com/.packages");
- var resolver = await loadPackagesFile(file, loader: loader);
- validatePackagesFile(resolver, file);
- });
-
- generalTest("loadPackagesFile not found", {}, (Uri directory) async {
- var file = directory.resolve(".packages");
- expect(
- loadPackagesFile(file),
- throwsA(anyOf(
- TypeMatcher<FileSystemException>(), TypeMatcher<HttpException>())));
- });
-
- generalTest("loadPackagesFile syntax error", {".packages": "syntax error"},
- (Uri directory) async {
- var file = directory.resolve(".packages");
- expect(loadPackagesFile(file), throwsFormatException);
- });
-
- generalTest("getPackagesDir", {
- "packages": {"foo": {}, "bar": {}, "baz": {}}
- }, (Uri directory) async {
- var packages = directory.resolve("packages/");
- var resolver = getPackagesDirectory(packages);
- var resolved = resolver.resolve(pkg("foo", "flip/flop"));
- expect(resolved, packages.resolve("foo/flip/flop"));
- });
-}
-
-/// Create a directory structure from [description] and run [fileTest].
-///
-/// Description is a map, each key is a file entry. If the value is a map,
-/// it's a sub-dir, otherwise it's a file and the value is the content
-/// as a string.
-void fileTest(String name, Map description, Future fileTest(Uri directory)) {
- group("file-test", () {
- var tempDir = Directory.systemTemp.createTempSync("file-test");
- setUp(() {
- _createFiles(tempDir, description);
- });
- tearDown(() {
- tempDir.deleteSync(recursive: true);
- });
- test(name, () => fileTest(Uri.file(path.join(tempDir.path, "."))));
- });
-}
-
-/// HTTP-server the directory structure from [description] and run [htpTest].
-///
-/// Description is a map, each key is a file entry. If the value is a map,
-/// it's a sub-dir, otherwise it's a file and the value is the content
-/// as a string.
-void httpTest(String name, Map description, Future httpTest(Uri directory)) {
- group("http-test", () {
- var serverSub;
- var uri;
- setUp(() {
- return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) {
- uri = Uri(
- scheme: "http", host: "127.0.0.1", port: server.port, path: "/");
- serverSub = server.listen((HttpRequest request) {
- // No error handling.
- var path = request.uri.path;
- if (path.startsWith('/')) path = path.substring(1);
- if (path.endsWith('/')) path = path.substring(0, path.length - 1);
- var parts = path.split('/');
- dynamic fileOrDir = description;
- for (var i = 0; i < parts.length; i++) {
- fileOrDir = fileOrDir[parts[i]];
- if (fileOrDir == null) {
- request.response.statusCode = 404;
- request.response.close();
- return;
- }
- }
- request.response.write(fileOrDir);
- request.response.close();
- });
- });
- });
- tearDown(() => serverSub.cancel());
- test(name, () => httpTest(uri));
- });
-}
-
-void generalTest(String name, Map description, Future action(Uri location)) {
- fileTest(name, description, action);
- httpTest(name, description, action);
-}
-
-void _createFiles(Directory target, Map description) {
- description.forEach((name, content) {
- if (content is Map) {
- var subDir = Directory(path.join(target.path, name));
- subDir.createSync();
- _createFiles(subDir, content);
- } else {
- var file = File(path.join(target.path, name));
- file.writeAsStringSync(content, flush: true);
- }
- });
-}
diff --git a/test/legacy/parse_test.dart b/test/legacy/parse_test.dart
deleted file mode 100644
index b9cf1f8..0000000
--- a/test/legacy/parse_test.dart
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@deprecated
-library package_config.parse_test;
-
-import "package:package_config/packages.dart";
-import "package:package_config/packages_file.dart" show parse;
-import "package:package_config/src/packages_impl.dart";
-import "package:test/test.dart";
-
-void main() {
- var base = Uri.parse("file:///one/two/three/packages.map");
- test("empty", () {
- var packages = doParse(emptySample, base);
- expect(packages.asMap(), isEmpty);
- });
- test("comment only", () {
- var packages = doParse(commentOnlySample, base);
- expect(packages.asMap(), isEmpty);
- });
- test("empty lines only", () {
- var packages = doParse(emptyLinesSample, base);
- expect(packages.asMap(), isEmpty);
- });
-
- test("empty lines only", () {
- var packages = doParse(emptyLinesSample, base);
- expect(packages.asMap(), isEmpty);
- });
-
- test("single", () {
- var packages = doParse(singleRelativeSample, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- });
-
- test("single no slash", () {
- var packages = doParse(singleRelativeSampleNoSlash, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- });
-
- test("single no newline", () {
- var packages = doParse(singleRelativeSampleNoNewline, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- });
-
- test("single absolute authority", () {
- var packages = doParse(singleAbsoluteSample, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(Uri.parse("http://example.com/some/where/bar/baz.dart")));
- });
-
- test("single empty path", () {
- var packages = doParse(singleEmptyPathSample, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.replace(path: "${base.path}/bar/baz.dart")));
- });
-
- test("single absolute path", () {
- var packages = doParse(singleAbsolutePathSample, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.replace(path: "/test/bar/baz.dart")));
- });
-
- test("multiple", () {
- var packages = doParse(multiRelativeSample, base);
- expect(packages.packages.toList()..sort(), equals(["bar", "foo"]));
- expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")),
- equals(base.resolve("../test2/").resolve("foo/baz.dart")));
- });
-
- test("dot-dot 1", () {
- var packages = doParse(singleRelativeSample, base);
- expect(packages.packages.toList(), equals(["foo"]));
- expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- });
-
- test("all valid chars can be used in URI segment", () {
- var packages = doParse(allValidCharsSample, base);
- expect(packages.packages.toList(), equals([allValidChars]));
- expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")),
- equals(base.resolve("../test/").resolve("bar/baz.dart")));
- });
-
- test("no invalid chars accepted", () {
- var map = {};
- for (var i = 0; i < allValidChars.length; i++) {
- map[allValidChars.codeUnitAt(i)] = true;
- }
- for (var i = 0; i <= 255; i++) {
- if (map[i] == true) continue;
- var char = String.fromCharCode(i);
- expect(() => doParse("x${char}x:x", null),
- anyOf(throwsNoSuchMethodError, throwsFormatException));
- }
- });
-
- test("no escapes", () {
- expect(() => doParse("x%41x:x", base), throwsFormatException);
- });
-
- test("same name twice", () {
- expect(
- () => doParse(singleRelativeSample * 2, base), throwsFormatException);
- });
-
- test("disallow default package", () {
- expect(() => doParse(":foo", base, allowDefaultPackage: false),
- throwsFormatException);
- });
-
- test("allow default package", () {
- var packages = doParse(":foo", base, allowDefaultPackage: true);
- expect(packages.defaultPackageName, "foo");
- });
-
- test("allow default package name with dot", () {
- var packages = doParse(":foo.bar", base, allowDefaultPackage: true);
- expect(packages.defaultPackageName, "foo.bar");
- });
-
- test("not two default packages", () {
- expect(() => doParse(":foo\n:bar", base, allowDefaultPackage: true),
- throwsFormatException);
- });
-
- test("default package invalid package name", () {
- // Not a valid *package name*.
- expect(() => doParse(":foo/bar", base, allowDefaultPackage: true),
- throwsFormatException);
- });
-
- group("metadata", () {
- var packages = doParse(
- ":foo\n"
- "foo:foo#metafoo=1\n"
- "bar:bar#metabar=2\n"
- "baz:baz\n"
- "qux:qux#metaqux1=3&metaqux2=4\n",
- base,
- allowDefaultPackage: true);
- test("non-existing", () {
- // non-package name.
- expect(packages.packageMetadata("///", "f"), null);
- expect(packages.packageMetadata("", "f"), null);
- // unconfigured package name.
- expect(packages.packageMetadata("absent", "f"), null);
- // package name without that metadata
- expect(packages.packageMetadata("foo", "notfoo"), null);
- });
- test("lookup", () {
- expect(packages.packageMetadata("foo", "metafoo"), "1");
- expect(packages.packageMetadata("bar", "metabar"), "2");
- expect(packages.packageMetadata("qux", "metaqux1"), "3");
- expect(packages.packageMetadata("qux", "metaqux2"), "4");
- });
- test("by library URI", () {
- expect(
- packages.libraryMetadata(
- Uri.parse("package:foo/index.dart"), "metafoo"),
- "1");
- expect(
- packages.libraryMetadata(
- Uri.parse("package:bar/index.dart"), "metabar"),
- "2");
- expect(
- packages.libraryMetadata(
- Uri.parse("package:qux/index.dart"), "metaqux1"),
- "3");
- expect(
- packages.libraryMetadata(
- Uri.parse("package:qux/index.dart"), "metaqux2"),
- "4");
- });
- test("by default package", () {
- expect(
- packages.libraryMetadata(
- Uri.parse("file:///whatever.dart"), "metafoo"),
- "1");
- });
- });
-
- for (var invalidSample in invalid) {
- test("invalid '$invalidSample'", () {
- var result;
- try {
- result = doParse(invalidSample, base);
- } on FormatException {
- // expected
- return;
- }
- fail("Resolved to $result");
- });
- }
-}
-
-Packages doParse(String sample, Uri baseUri,
- {bool allowDefaultPackage = false}) {
- var map = parse(sample.codeUnits, baseUri,
- allowDefaultPackage: allowDefaultPackage);
- return MapPackages(map);
-}
-
-// Valid samples.
-var emptySample = "";
-var commentOnlySample = "# comment only\n";
-var emptyLinesSample = "\n\n\r\n";
-var singleRelativeSample = "foo:../test/\n";
-var singleRelativeSampleNoSlash = "foo:../test\n";
-var singleRelativeSampleNoNewline = "foo:../test/";
-var singleAbsoluteSample = "foo:http://example.com/some/where/\n";
-var singleEmptyPathSample = "foo:\n";
-var singleAbsolutePathSample = "foo:/test/\n";
-var multiRelativeSample = "foo:../test/\nbar:../test2/\n";
-// All valid path segment characters in an URI.
-var allValidChars = r"!$&'()*+,-.0123456789;="
- r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
-
-var allValidCharsSample = "${allValidChars}:../test/\n";
-
-// Invalid samples.
-var invalid = [
- ":baz.dart", // empty.
- "foobar=baz.dart", // no colon (but an equals, which is not the same)
- ".:../test/", // dot segment
- "..:../test/", // dot-dot segment
- "...:../test/", // dot-dot-dot segment
- "foo/bar:../test/", // slash in name
- "/foo:../test/", // slash at start of name
- "?:../test/", // invalid characters.
- "[:../test/", // invalid characters.
- "x#:../test/", // invalid characters.
-];
diff --git a/test/legacy/parse_write_test.dart b/test/legacy/parse_write_test.dart
deleted file mode 100644
index a51ced1..0000000
--- a/test/legacy/parse_write_test.dart
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@deprecated
-library package_config.parse_write_test;
-
-import "dart:convert" show utf8;
-import "package:package_config/packages_file.dart";
-import "package:test/test.dart";
-
-void main() {
- void testBase(baseDirString) {
- var baseDir = Uri.parse(baseDirString);
- group("${baseDir.scheme} base", () {
- var packagesFile = baseDir.resolve(".packages");
-
- void roundTripTest(String name, Map<String, Uri> map) {
- group(name, () {
- test("write with no baseUri", () {
- var content = writeToString(map).codeUnits;
- var resultMap = parse(content, packagesFile);
- expect(resultMap, map);
- });
-
- test("write with base directory", () {
- var content = writeToString(map, baseUri: baseDir).codeUnits;
- var resultMap = parse(content, packagesFile);
- expect(resultMap, map);
- });
-
- test("write with base .packages file", () {
- var content = writeToString(map, baseUri: packagesFile).codeUnits;
- var resultMap = parse(content, packagesFile);
- expect(resultMap, map);
- });
-
- test("write with defaultPackageName", () {
- var content = writeToString(
- {'': Uri.parse('my_pkg')}..addAll(map),
- allowDefaultPackage: true,
- ).codeUnits;
- var resultMap = parse(
- content,
- packagesFile,
- allowDefaultPackage: true,
- );
- expect(resultMap[''].toString(), 'my_pkg');
- expect(
- resultMap,
- {'': Uri.parse('my_pkg')}..addAll(map),
- );
- });
-
- test("write with defaultPackageName (utf8)", () {
- var content = utf8.encode(writeToString(
- {'': Uri.parse('my_pkg')}..addAll(map),
- allowDefaultPackage: true,
- ));
- var resultMap = parse(
- content,
- packagesFile,
- allowDefaultPackage: true,
- );
- expect(resultMap[''].toString(), 'my_pkg');
- expect(
- resultMap,
- {'': Uri.parse('my_pkg')}..addAll(map),
- );
- });
- });
- }
-
- var lowerDir = baseDir.resolve("path3/path4/");
- var higherDir = baseDir.resolve("../");
- var parallelDir = baseDir.resolve("../path3/");
- var rootDir = baseDir.resolve("/");
- var fileDir = Uri.parse("file:///path1/part2/");
- var httpDir = Uri.parse("http://example.com/path1/path2/");
- var otherDir = Uri.parse("other:/path1/path2/");
-
- roundTripTest("empty", {});
- roundTripTest("lower directory", {"foo": lowerDir});
- roundTripTest("higher directory", {"foo": higherDir});
- roundTripTest("parallel directory", {"foo": parallelDir});
- roundTripTest("same directory", {"foo": baseDir});
- roundTripTest("root directory", {"foo": rootDir});
- roundTripTest("file directory", {"foo": fileDir});
- roundTripTest("http directory", {"foo": httpDir});
- roundTripTest("other scheme directory", {"foo": otherDir});
- roundTripTest("multiple same-type directories",
- {"foo": lowerDir, "bar": higherDir, "baz": parallelDir});
- roundTripTest("multiple scheme directories",
- {"foo": fileDir, "bar": httpDir, "baz": otherDir});
- roundTripTest("multiple scheme directories and mutliple same type", {
- "foo": fileDir,
- "bar": httpDir,
- "baz": otherDir,
- "qux": lowerDir,
- "hip": higherDir,
- "dep": parallelDir
- });
- });
- }
-
- testBase("file:///base1/base2/");
- testBase("http://example.com/base1/base2/");
- testBase("other:/base1/base2/");
-
- // Check that writing adds the comment.
- test("write preserves comment", () {
- var comment = "comment line 1\ncomment line 2\ncomment line 3";
- var result = writeToString({}, comment: comment);
- // Comment with "# " before each line and "\n" after last.
- var expectedComment =
- "# comment line 1\n# comment line 2\n# comment line 3\n";
- expect(result, startsWith(expectedComment));
- });
-}
-
-String writeToString(
- Map<String, Uri> map, {
- Uri baseUri,
- String comment,
- bool allowDefaultPackage = false,
-}) {
- var buffer = StringBuffer();
- write(buffer, map,
- baseUri: baseUri,
- comment: comment,
- allowDefaultPackage: allowDefaultPackage);
- return buffer.toString();
-}
diff --git a/test/parse_test.dart b/test/parse_test.dart
index 59a7e71..385be36 100644
--- a/test/parse_test.dart
+++ b/test/parse_test.dart
@@ -32,7 +32,7 @@
expect(result.resolve(pkg("baz", "baz.dart")),
Uri.parse("file:///tmp/lib/baz.dart"));
- var foo = result["foo"];
+ var foo = result["foo"]!;
expect(foo, isNotNull);
expect(foo.root, Uri.parse("file:///foo/"));
expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/"));
@@ -111,8 +111,10 @@
"other": [42]
}
""";
- var config = parsePackageConfigBytes(utf8.encode(packageConfigFile),
- Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError);
+ var config = parsePackageConfigBytes(
+ utf8.encode(packageConfigFile) as Uint8List,
+ Uri.parse("file:///tmp/.dart_tool/file.dart"),
+ throwError);
expect(config.version, 2);
expect({for (var p in config.packages) p.name},
{"foo", "bar", "baz", "noslash"});
@@ -124,28 +126,28 @@
expect(config.resolve(pkg("baz", "baz.dart")),
Uri.parse("file:///tmp/lib/baz.dart"));
- var foo = config["foo"];
+ var foo = config["foo"]!;
expect(foo, isNotNull);
expect(foo.root, Uri.parse("file:///foo/"));
expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/"));
expect(foo.languageVersion, LanguageVersion(2, 5));
expect(foo.extraData, {"nonstandard": true});
- var bar = config["bar"];
+ var bar = config["bar"]!;
expect(bar, isNotNull);
expect(bar.root, Uri.parse("file:///bar/"));
expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/"));
expect(bar.languageVersion, LanguageVersion(9999, 9999));
expect(bar.extraData, null);
- var baz = config["baz"];
+ var baz = config["baz"]!;
expect(baz, isNotNull);
expect(baz.root, Uri.parse("file:///tmp/"));
expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/"));
expect(baz.languageVersion, null);
// No slash after root or package root. One is inserted.
- var noslash = config["noslash"];
+ var noslash = config["noslash"]!;
expect(noslash, isNotNull);
expect(noslash.root, Uri.parse("file:///tmp/noslash/"));
expect(noslash.packageUriRoot, Uri.parse("file:///tmp/noslash/lib/"));
@@ -185,8 +187,10 @@
"configVersion": 2
}
""";
- var config = parsePackageConfigBytes(utf8.encode(packageConfigFile),
- Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError);
+ var config = parsePackageConfigBytes(
+ utf8.encode(packageConfigFile) as Uint8List,
+ Uri.parse("file:///tmp/.dart_tool/file.dart"),
+ throwError);
expect(config.version, 2);
expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"});
@@ -209,8 +213,10 @@
var name = '"name":"foo"';
var root = '"rootUri":"/foo/"';
test("minimal", () {
- var config = parsePackageConfigBytes(utf8.encode("{$cfg,$pkgs}"),
- Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError);
+ var config = parsePackageConfigBytes(
+ utf8.encode("{$cfg,$pkgs}") as Uint8List,
+ Uri.parse("file:///tmp/.dart_tool/file.dart"),
+ throwError);
expect(config.version, 2);
expect(config.packages, isEmpty);
});
@@ -218,7 +224,7 @@
// A package must have a name and a rootUri, the remaining properties
// are optional.
var config = parsePackageConfigBytes(
- utf8.encode('{$cfg,"packages":[{$name,$root}]}'),
+ utf8.encode('{$cfg,"packages":[{$name,$root}]}') as Uint8List,
Uri.parse("file:///tmp/.dart_tool/file.dart"),
throwError);
expect(config.version, 2);
@@ -235,17 +241,17 @@
{"name": "qux", "rootUri": "/foo/qux/", "packageUri": "lib/"},
]
}));
- var config = parsePackageConfigBytes(configBytes,
+ var config = parsePackageConfigBytes(configBytes as Uint8List,
Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError);
expect(config.version, 2);
- expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart")).name,
+ expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart"))!.name,
"foo");
- expect(
- config.packageOf(Uri.parse("file:///foo/bar/lala.dart")).name, "bar");
- expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart")).name,
+ expect(config.packageOf(Uri.parse("file:///foo/bar/lala.dart"))!.name,
+ "bar");
+ expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart"))!.name,
"baz");
- expect(
- config.packageOf(Uri.parse("file:///foo/qux/lala.dart")).name, "qux");
+ expect(config.packageOf(Uri.parse("file:///foo/qux/lala.dart"))!.name,
+ "qux");
expect(config.toPackageUri(Uri.parse("file:///foo/lib/diz")),
Uri.parse("package:foo/diz"));
expect(config.toPackageUri(Uri.parse("file:///foo/bar/lib/diz")),
@@ -260,7 +266,7 @@
void testThrows(String name, String source) {
test(name, () {
expect(
- () => parsePackageConfigBytes(utf8.encode(source),
+ () => parsePackageConfigBytes(utf8.encode(source) as Uint8List,
Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError),
throwsA(TypeMatcher<FormatException>()));
});
@@ -386,7 +392,7 @@
for (var package in config.packages) {
var name = package.name;
test("package $name", () {
- var expectedPackage = expected[name];
+ var expectedPackage = expected[name]!;
expect(expectedPackage, isNotNull);
expect(package.root, expectedPackage.root, reason: "root");
expect(package.packageUriRoot, expectedPackage.packageUriRoot,
diff --git a/test/src/util.dart b/test/src/util.dart
index 6e689b7..2b262e1 100644
--- a/test/src/util.dart
+++ b/test/src/util.dart
@@ -34,18 +34,18 @@
/// it's a subdirectory, otherwise it's a file and the value is the content
/// as a string.
void loaderTest(String name, Map<String, Object> description,
- void loaderTest(Uri root, Future<Uint8List> loader(Uri uri))) {
+ void loaderTest(Uri root, Future<Uint8List?> loader(Uri uri))) {
var root = Uri(scheme: "test", path: "/");
- Future<Uint8List> loader(Uri uri) async {
+ Future<Uint8List?> loader(Uri uri) async {
var path = uri.path;
if (!uri.isScheme("test") || !path.startsWith("/")) return null;
var parts = path.split("/");
- dynamic value = description;
+ Object? value = description;
for (var i = 1; i < parts.length; i++) {
- if (value is! Map<String, dynamic>) return null;
+ if (value is! Map<String, Object?>) return null;
value = value[parts[i]];
}
- if (value is String) return utf8.encode(value);
+ if (value is String) return utf8.encode(value) as Uint8List;
return null;
}
diff --git a/test/src/util_io.dart b/test/src/util_io.dart
index d05618a..37deee9 100644
--- a/test/src/util_io.dart
+++ b/test/src/util_io.dart
@@ -35,20 +35,20 @@
/// with the content as description.
/// Otherwise the content should be a string,
/// which is written to the file as UTF-8.
-Directory createTestFiles(Map<String, Object> description) {
- var target = Directory.systemTemp.createTempSync("pkgcfgtest");
- _createFiles(target, description);
- return target;
-}
+// Directory createTestFiles(Map<String, Object> description) {
+// var target = Directory.systemTemp.createTempSync("pkgcfgtest");
+// _createFiles(target, description);
+// return target;
+// }
// Creates temporary files in the target directory.
-void _createFiles(Directory target, Map<Object, Object> description) {
+void _createFiles(Directory target, Map<Object?, Object?> description) {
description.forEach((name, content) {
var entryName = pathJoin(target.path, "$name");
- if (content is Map<Object, Object>) {
+ if (content is Map<Object?, Object?>) {
_createFiles(Directory(entryName)..createSync(), content);
} else {
- File(entryName).writeAsStringSync(content, flush: true);
+ File(entryName).writeAsStringSync(content as String, flush: true);
}
});
}