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

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

Issue 23924006: Detect transformer dependency cycles in packages using barback transformers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 7 years, 3 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
« no previous file with comments | « sdk/lib/_internal/pub/lib/src/barback.dart ('k') | sdk/lib/_internal/pub/lib/src/directory_tree.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
index c6205bdec1094692c91a84ee46d58c52bc956475..2f9414b6c8029eea2781815a26d8ceaa8ed68b23 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart
@@ -12,6 +12,7 @@ import 'load_transformers.dart';
import 'rewrite_import_transformer.dart';
import 'server.dart';
import 'watch_sources.dart';
+import '../barback.dart';
import '../utils.dart';
/// Loads all transformers depended on by packages in [graph].
@@ -120,18 +121,27 @@ Future loadAllTransformers(BarbackServer server, PackageGraph graph) {
/// are those packages' ordering dependencies.
Map<String, Set<String>> _computeOrderingDeps(PackageGraph graph) {
var orderingDeps = new Map<String, Set<String>>();
- for (var package in graph.packages.values) {
+ // Iterate through the packages in a deterministic order so that if there are
+ // multiple cycles we choose which to print consistently.
+ var packages = ordered(graph.packages.values.map((package) => package.name));
+ for (var package in packages) {
// This package's transformer dependencies are also ordering dependencies.
- var deps = _transformerDeps(graph, package.name);
- deps.remove(package.name);
+ var deps = _transformerDeps(graph, package);
+ deps.remove(package);
// The transformer dependencies of this package's transitive package
// dependencies are also ordering dependencies for this package.
- for (var packageDep in graph.transitiveDependencies(package.name)) {
- deps.addAll(_transformerDeps(graph, packageDep.name));
+ var transitivePackageDeps = graph.transitiveDependencies(package)
+ .map((package) => package.name);
+ for (var packageDep in ordered(transitivePackageDeps)) {
+ var transformerDeps = _transformerDeps(graph, packageDep);
+ if (transformerDeps.contains(package)) {
+ throw _cycleError(graph, package, packageDep);
+ }
+ deps.addAll(transformerDeps);
}
- orderingDeps[package.name] = deps;
+ orderingDeps[package] = deps;
}
- // TODO(nweiz): check for cycles in orderingDeps.
+
return orderingDeps;
}
@@ -140,6 +150,33 @@ Set<String> _transformerDeps(PackageGraph graph, String package) =>
unionAll(graph.packages[package].pubspec.transformers)
.map((id) => id.package).toSet();
+/// Returns an [ApplicationException] describing an ordering dependency cycle
+/// detected in [graph].
+///
+/// [dependee] and [depender] should be the names of two packages known to be in
+/// the cycle. In addition, [depender] should have a transformer dependency on
+/// [dependee].
+ApplicationException _cycleError(PackageGraph graph, String dependee,
+ String depender) {
+ assert(_transformerDeps(graph, depender).contains(dependee));
+
+ var simpleGraph = mapMapValues(graph.packages,
+ (_, package) => package.dependencies.map((dep) => dep.name).toList());
+ var path = shortestPath(simpleGraph, dependee, depender);
+ path.add(dependee);
+ return new ApplicationException("Transformer cycle detected:\n" +
+ pairs(path).map((pair) {
+ var transformers = unionAll(graph.packages[pair.first].pubspec.transformers)
+ .where((id) => id.package == pair.last)
+ .map(idToLibraryIdentifier).toList();
+ if (transformers.isEmpty) {
+ return " ${pair.first} depends on ${pair.last}";
+ } else {
+ return " ${pair.first} is transformed by ${toSentence(transformers)}";
+ }
+ }).join("\n"));
+}
+
/// Returns a map from each package name in [graph] to the asset ids of all
/// transformers exposed by that package and used by other packages.
Map<String, Set<AssetId>> _computePackageTransformers(PackageGraph graph) {
@@ -166,20 +203,15 @@ class _TransformerLoader {
/// The packages that use each transformer id.
///
/// Used for error reporting.
- final _transformerUsers = new Map<AssetId, List<String>>();
+ final _transformerUsers = new Map<AssetId, Set<String>>();
_TransformerLoader(this._server, PackageGraph graph) {
for (var package in graph.packages.values) {
for (var id in unionAll(package.pubspec.transformers)) {
- _transformerUsers.putIfAbsent(id, () => <String>[]).add(package.name);
+ _transformerUsers.putIfAbsent(id, () => new Set<String>())
+ .add(package.name);
}
}
-
- // Ensure that the transformer users are printed in a deterministic order if
- // an error occurs.
- for (var list in _transformerUsers.values) {
- list.sort();
- }
}
/// Loads the transformer(s) defined in the asset [id].
@@ -196,13 +228,9 @@ class _TransformerLoader {
return;
}
- // The path is parsed from a library identifier in the pubspec, so it
- // should always refer to a library.
- assert(id.path.startsWith('lib/'));
- var path = id.path.replaceFirst('lib/', '');
throw new ApplicationException(
- "No transformers were defined in package:${id.package}/$path,\n"
- "required by ${_transformerUsers[id].join(', ')}.");
+ "No transformers were defined in ${idToPackageUri(id)},\n"
+ "required by ${ordered(_transformerUsers[id]).join(', ')}.");
});
}
« no previous file with comments | « sdk/lib/_internal/pub/lib/src/barback.dart ('k') | sdk/lib/_internal/pub/lib/src/directory_tree.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698