Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Unified Diff: sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart

Issue 1165473002: Start pulling pub from its own repo. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Code review changes Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart b/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
deleted file mode 100644
index facf14084a28056e6d900ebaee570abb05a1bbc2..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
+++ /dev/null
@@ -1,446 +0,0 @@
-// Copyright (c) 2014, 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.
-
-library pub.barback.dependency_computer;
-
-import 'package:barback/barback.dart';
-import 'package:path/path.dart' as p;
-
-import '../dart.dart';
-import '../io.dart';
-import '../package.dart';
-import '../package_graph.dart';
-import '../pubspec.dart';
-import '../utils.dart';
-import 'cycle_exception.dart';
-import 'transformer_config.dart';
-import 'transformer_id.dart';
-
-/// A class for determining dependencies between transformers and from Dart
-/// libraries onto transformers.
-class DependencyComputer {
- /// The package graph being analyzed.
- final PackageGraph _graph;
-
- /// The names of packages for which [_PackageDependencyComputer]s are
- /// currently loading.
- ///
- /// This is used to detect transformer cycles. If a package's libraries or
- /// transformers are referenced while the transformers that apply to it are
- /// being processed, that indicates an unresolvable cycle.
- final _loadingPackageComputers = new Set<String>();
-
- /// [_PackageDependencyComputer]s that have been loaded.
- final _packageComputers = new Map<String, _PackageDependencyComputer>();
-
- /// A cache of the results of [transformersNeededByPackage].
- final _transformersNeededByPackages = new Map<String, Set<TransformerId>>();
-
- /// The set of all packages that neither use transformers themselves nor
- /// import packages that use transformers.
- ///
- /// This is precomputed before any package computers are loaded.
- final _untransformedPackages = new Set<String>();
-
- DependencyComputer(this._graph) {
- for (var package in ordered(_graph.packages.keys)) {
- if (_graph.transitiveDependencies(package).every((dependency) =>
- dependency.pubspec.transformers.isEmpty)) {
- _untransformedPackages.add(package);
- }
- }
-
- ordered(_graph.packages.keys).forEach(_loadPackageComputer);
- }
-
- /// Returns a dependency graph for [transformers], or for all transformers if
- /// [transformers] is `null`.
- ///
- /// This graph is represented by a map whose keys are the vertices and whose
- /// values are sets representing edges from the given vertex. Each vertex is a
- /// [TransformerId]. If there's an edge from `T1` to `T2`, then `T2` must be
- /// loaded before `T1` can be loaded.
- ///
- /// The returned graph is transitively closed. That is, if there's an edge
- /// from `T1` to `T2` and an edge from `T2` to `T3`, there's also an edge from
- /// `T1` to `T2`.
- Map<TransformerId, Set<TransformerId>> transformersNeededByTransformers(
- [Iterable<TransformerId> transformers]) {
- var result = {};
-
- if (transformers == null) {
- transformers = ordered(_graph.packages.keys).expand((packageName) {
- var package = _graph.packages[packageName];
- return package.pubspec.transformers.expand((phase) {
- return phase.expand((config) {
- var id = config.id;
- if (id.isBuiltInTransformer) return [];
- if (package.name != _graph.entrypoint.root.name &&
- !config.canTransformPublicFiles) {
- return [];
- }
- return [id];
- });
- });
- });
- }
-
- for (var id in transformers) {
- result[id] = _transformersNeededByTransformer(id);
- }
- return result;
- }
-
- /// Returns the set of all transformers needed to load the library identified
- /// by [id].
- Set<TransformerId> transformersNeededByLibrary(AssetId id) {
- var library = _graph.packages[id.package].path(p.fromUri(id.path));
- _loadPackageComputer(id.package);
- return _packageComputers[id.package].transformersNeededByLibrary(library)
- .where((id) => !id.isBuiltInTransformer).toSet();
- }
-
- /// Returns the set of all transformers that need to be loaded before [id] is
- /// loaded.
- Set<TransformerId> _transformersNeededByTransformer(TransformerId id) {
- if (id.isBuiltInTransformer) return new Set();
-
- if (!_graph.packages.containsKey(id.package)) {
- // Throw this here rather than during pubspec parsing because by the time
- // we're here, we're sure that the package is actually transforming public
- // assets and that being unable to load it will be a problem.
- throw new PubspecException(
- 'Error loading transformer "$id": package "${id.package}" is not '
- 'a dependency.',
- id.span);
- }
-
- _loadPackageComputer(id.package);
- return _packageComputers[id.package]._transformersNeededByTransformer(id);
- }
-
- /// Returns the set of all transformers that need to be loaded before
- /// [packageUri] (a "package:" URI) can be safely imported from an external
- /// package.
- Set<TransformerId> _transformersNeededByPackageUri(Uri packageUri) {
- var components = p.split(p.fromUri(packageUri.path));
- var packageName = components.first;
- if (_untransformedPackages.contains(packageName)) return new Set();
-
- var package = _graph.packages[packageName];
- if (package == null) {
- // TODO(nweiz): include source range information here.
- fail('A transformer imported unknown package "$packageName" (in '
- '"$packageUri").');
- }
-
- var library = package.path('lib', p.joinAll(components.skip(1)));
-
- _loadPackageComputer(packageName);
- return _packageComputers[packageName].transformersNeededByLibrary(library);
- }
-
- /// Returns the set of all transformers that need to be loaded before
- /// everything in [rootPackage] can be used.
- ///
- /// This is conservative in that it returns all transformers that could
- /// theoretically affect [rootPackage]. It only looks at which transformers
- /// packages use and which packages they depend on; it ignores imports
- /// entirely.
- ///
- /// We fall back on this conservative analysis when a transformer
- /// (transitively) imports a transformed library. The result of the
- /// transformation may import any dependency or hit any transformer, so we
- /// have to assume that it will.
- Set<TransformerId> _transformersNeededByPackage(String rootPackage) {
- if (_untransformedPackages.contains(rootPackage)) return new Set();
-
- if (_transformersNeededByPackages.containsKey(rootPackage)) {
- return _transformersNeededByPackages[rootPackage];
- }
-
- var results = new Set();
- var seen = new Set();
-
- traversePackage(packageName) {
- if (seen.contains(packageName)) return;
- seen.add(packageName);
-
- var package = _graph.packages[packageName];
- for (var phase in package.pubspec.transformers) {
- for (var config in phase) {
- var id = config.id;
- if (id.isBuiltInTransformer) continue;
- if (_loadingPackageComputers.contains(id.package)) {
- throw new CycleException("$packageName is transformed by $id");
- }
- results.add(id);
- }
- }
-
- var dependencies = packageName == _graph.entrypoint.root.name ?
- package.immediateDependencies : package.dependencies;
- for (var dep in dependencies) {
- try {
- traversePackage(dep.name);
- } on CycleException catch (error) {
- throw error.prependStep("$packageName depends on ${dep.name}");
- }
- }
- }
-
- traversePackage(rootPackage);
- _transformersNeededByPackages[rootPackage] = results;
- return results;
- }
-
-
- /// Ensure that a [_PackageDependencyComputer] for [packageName] is loaded.
- ///
- /// If the computer has already been loaded, this does nothing. If the
- /// computer is in the process of being loaded, this throws a
- /// [CycleException].
- void _loadPackageComputer(String packageName) {
- if (_loadingPackageComputers.contains(packageName)) {
- throw new CycleException();
- }
- if (_packageComputers.containsKey(packageName)) return;
- _loadingPackageComputers.add(packageName);
- _packageComputers[packageName] =
- new _PackageDependencyComputer(this, packageName);
- _loadingPackageComputers.remove(packageName);
- }
-}
-
-/// A helper class for [computeTransformersNeededByTransformers] that keeps
-/// package-specific state and caches over the course of the computation.
-class _PackageDependencyComputer {
- /// The parent [DependencyComputer].
- final DependencyComputer _dependencyComputer;
-
- /// The package whose dependencies [this] is computing.
- final Package _package;
-
- /// The set of transformers that currently apply to [this].
- ///
- /// This is added to phase-by-phase while [this] is being initialized. This is
- /// necessary to model the dependencies of a transformer that's applied to its
- /// own package.
- final _applicableTransformers = new Set<TransformerConfig>();
-
- /// A cache of imports and exports parsed from libraries in this package.
- final _directives = new Map<Uri, Set<Uri>>();
-
- /// The set of libraries for which there are currently active
- /// [transformersNeededByLibrary] calls.
- ///
- /// This is used to guard against infinite loops caused by libraries in
- /// different packages importing one another circularly.
- /// [transformersNeededByLibrary] will return an empty set for any active
- /// libraries.
- final _activeLibraries = new Set<String>();
-
- /// A cache of the results of [_transformersNeededByTransformer].
- final _transformersNeededByTransformers =
- new Map<TransformerId, Set<TransformerId>>();
-
- /// A cache of the results of [_getTransitiveExternalDirectives].
- ///
- /// This is invalidated whenever [_applicableTransformers] changes.
- final _transitiveExternalDirectives = new Map<String, Set<Uri>>();
-
- _PackageDependencyComputer(DependencyComputer dependencyComputer,
- String packageName)
- : _dependencyComputer = dependencyComputer,
- _package = dependencyComputer._graph.packages[packageName] {
- var isRootPackage =
- packageName == _dependencyComputer._graph.entrypoint.root.name;
-
- // If [_package] uses its own transformers, there will be fewer transformers
- // running on [_package] while its own transformers are loading than there
- // will be once all its transformers are finished loading. To handle this,
- // we run [_transformersNeededByTransformer] to pre-populate
- // [_transformersNeededByLibraries] while [_applicableTransformers] is
- // smaller.
- for (var phase in _package.pubspec.transformers) {
- for (var config in phase) {
- // Ignore non-root transformers on non-public files.
- if (!isRootPackage && !config.canTransformPublicFiles) continue;
-
- var id = config.id;
- try {
- if (id.package != _package.name) {
- // Probe [id]'s transformer dependencies to ensure that it doesn't
- // depend on this package. If it does, a CycleError will be thrown.
- _dependencyComputer._transformersNeededByTransformer(id);
- } else {
- // Store the transformers needed specifically with the current set
- // of [_applicableTransformers]. When reporting this transformer's
- // dependencies, [computeTransformersNeededByTransformers] will use
- // this stored set of dependencies rather than the potentially wider
- // set that would be recomputed if [transformersNeededByLibrary]
- // were called anew.
- _transformersNeededByTransformers[id] =
- transformersNeededByLibrary(_package.transformerPath(id));
- }
- } on CycleException catch (error) {
- throw error.prependStep("$packageName is transformed by $id");
- }
- }
-
- // Clear the cached imports and exports because the new transformers may
- // start transforming a library whose directives were previously
- // statically analyzable.
- _transitiveExternalDirectives.clear();
- _applicableTransformers.addAll(phase);
- }
- }
-
- /// Returns the set of all transformers that need to be loaded before [id] is
- /// loaded.
- ///
- /// [id] must refer to a transformer in [_package].
- Set<TransformerId> _transformersNeededByTransformer(TransformerId id) {
- assert(id.package == _package.name);
- if (_transformersNeededByTransformers.containsKey(id)) {
- return _transformersNeededByTransformers[id];
- }
-
- _transformersNeededByTransformers[id] =
- transformersNeededByLibrary(_package.transformerPath(id));
- return _transformersNeededByTransformers[id];
- }
-
- /// Returns the set of all transformers that need to be loaded before
- /// [library] is imported.
- ///
- /// If [library] or anything it imports/exports within this package is
- /// transformed by [_applicableTransformers], this will return a conservative
- /// set of transformers (see also
- /// [DependencyComputer._transformersNeededByPackage]).
- Set<TransformerId> transformersNeededByLibrary(String library) {
- library = p.normalize(library);
- if (_activeLibraries.contains(library)) return new Set();
- _activeLibraries.add(library);
-
- try {
- var externalDirectives = _getTransitiveExternalDirectives(library);
- if (externalDirectives == null) {
- var rootName = _dependencyComputer._graph.entrypoint.root.name;
- var dependencies = _package.name == rootName ?
- _package.immediateDependencies : _package.dependencies;
-
- // If anything transitively imported/exported by [library] within this
- // package is modified by a transformer, we don't know what it will
- // load, so we take the conservative approach and say it depends on
- // everything.
- return _applicableTransformers.map((config) => config.id).toSet().union(
- unionAll(dependencies.map((dep) {
- try {
- return _dependencyComputer._transformersNeededByPackage(dep.name);
- } on CycleException catch (error) {
- throw error.prependStep("${_package.name} depends on ${dep.name}");
- }
- })));
- } else {
- // If nothing's transformed, then we only depend on the transformers
- // used by the external packages' libraries that we import or export.
- return unionAll(externalDirectives.map((uri) {
- try {
- return _dependencyComputer._transformersNeededByPackageUri(uri);
- } on CycleException catch (error) {
- var packageName = p.url.split(uri.path).first;
- throw error.prependStep("${_package.name} depends on $packageName");
- }
- }));
- }
- } finally {
- _activeLibraries.remove(library);
- }
- }
-
- /// Returns the set of all external package libraries transitively imported or
- /// exported by [rootLibrary].
- ///
- /// All of the returned URIs will have the "package:" scheme. None of them
- /// will be URIs for this package.
- ///
- /// If [rootLibrary] transitively imports or exports a library that's modified
- /// by a transformer, this will return `null`.
- Set<Uri> _getTransitiveExternalDirectives(String rootLibrary) {
- rootLibrary = p.normalize(rootLibrary);
- if (_transitiveExternalDirectives.containsKey(rootLibrary)) {
- return _transitiveExternalDirectives[rootLibrary];
- }
-
- var results = new Set();
- var seen = new Set();
-
- traverseLibrary(library) {
- library = p.normalize(library);
- if (seen.contains(library)) return true;
- seen.add(library);
-
- var directives = _getDirectives(library);
- if (directives == null) return false;
-
- for (var uri in directives) {
- var path;
- if (uri.scheme == 'package') {
- var components = p.split(p.fromUri(uri.path));
- if (components.first != _package.name) {
- results.add(uri);
- continue;
- }
-
- path = _package.path('lib', p.joinAll(components.skip(1)));
- } else if (uri.scheme == '' || uri.scheme == 'file') {
- path = p.join(p.dirname(library), p.fromUri(uri));
- } else {
- // Ignore "dart:" URIs and theoretically-possible "http:" URIs.
- continue;
- }
-
- if (!traverseLibrary(path)) return false;
- }
-
- return true;
- }
-
- _transitiveExternalDirectives[rootLibrary] =
- traverseLibrary(rootLibrary) ? results : null;
- return _transitiveExternalDirectives[rootLibrary];
- }
-
- /// Returns the set of all imports or exports in [library].
- ///
- /// If [library] is modified by a transformer, this will return `null`.
- Set<Uri> _getDirectives(String library) {
- var libraryUri = p.toUri(p.normalize(library));
- var relative = p.toUri(_package.relative(library)).path;
- if (_applicableTransformers.any((config) =>
- config.canTransform(relative))) {
- _directives[libraryUri] = null;
- return null;
- }
-
- // Check the cache *after* checking [_applicableTransformers] because
- // [_applicableTransformers] changes over time so the directives may be
- // invalidated.
- if (_directives.containsKey(libraryUri)) return _directives[libraryUri];
-
- // If a nonexistent library is imported, it will probably be generated by a
- // transformer.
- if (!fileExists(library)) {
- _directives[libraryUri] = null;
- return null;
- }
-
- _directives[libraryUri] =
- parseImportsAndExports(readTextFile(library), name: library)
- .map((directive) => Uri.parse(directive.uri.stringValue))
- .toSet();
- return _directives[libraryUri];
- }
-}

Powered by Google App Engine
This is Rietveld 408576698