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

Unified Diff: pkg/analyzer/tool/task_dependency_graph.dart

Issue 1235963002: Add a tool to generate a graph of tasks and their dependencies. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/tool/task_dependency_graph.dart
diff --git a/pkg/analyzer/tool/task_dependency_graph.dart b/pkg/analyzer/tool/task_dependency_graph.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0d2f2d398c94e358bbded20f01baa34ff65b26cf
--- /dev/null
+++ b/pkg/analyzer/tool/task_dependency_graph.dart
@@ -0,0 +1,150 @@
+// 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.
+
+/**
+ * This file contains code to output a description of tasks and their
+ * dependencies in ".dot" format. Prior to running, the user should run "pub
+ * get" in the analyzer directory to ensure that a "packages" folder exists.
+ *
+ * The ".dot" file is output to standard out. To convert it to a pdf, store it
+ * in a file (e.g. "tasks.dot"), and post-process it with
+ * "dot tasks.dart -Tpdf -O".
+ *
+ * TODO(paulberry):
+ * - Add general.dart and html.dart for completeness.
+ * - Use Graphviz's "record" feature to produce more compact output
+ * (http://www.graphviz.org/content/node-shapes#record)
+ * - Produce a warning if a result descriptor is found which isn't the output
+ * of exactly one task.
Brian Wilkerson 2015/07/13 15:01:19 One more todo: convert this to use package_config
+ */
+library task_dependency_graph;
+
+import 'dart:io' hide File;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:path/path.dart' as path;
+
+main() {
+ new Driver().run();
+}
+
+typedef void ResultDescriptorFinderCallback(PropertyAccessorElement element);
+
+class Driver {
+ PhysicalResourceProvider resourceProvider;
+ AnalysisContext context;
+ InterfaceType resultDescriptorType;
+ String rootDir;
+
+ void findResultDescriptors(
+ AstNode node, void callback(String descriptorName)) {
+ Set<PropertyAccessorElement> resultDescriptors =
+ new Set<PropertyAccessorElement>();
+ node.accept(new ResultDescriptorFinder(
+ resultDescriptorType, resultDescriptors.add));
+ for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
+ callback(resultDescriptor.name);
+ }
+ }
+
+ /**
+ * Find the root directory of the analyzer package by proceeding
+ * upward to the 'tool' dir, and then going up one more directory.
+ */
+ String findRoot(String pathname) {
+ while (path.basename(pathname) != 'tool') {
+ String parent = path.dirname(pathname);
+ if (parent.length >= pathname.length) {
+ throw new Exception("Can't find root directory");
+ }
+ pathname = parent;
+ }
+ return path.dirname(pathname);
+ }
+
+ CompilationUnit getUnit(Source source) =>
+ context.resolveCompilationUnit2(source, source);
+
+ void run() {
+ rootDir = findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
+ resourceProvider = PhysicalResourceProvider.INSTANCE;
+ DartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
+ context = AnalysisEngine.instance.createAnalysisContext();
+ JavaFile packagesDir = new JavaFile(path.join(rootDir, 'packages'));
+ List<UriResolver> uriResolvers = [
+ new FileUriResolver(),
+ new DartUriResolver(sdk),
+ new PackageUriResolver(<JavaFile>[packagesDir])
+ ];
+ context.sourceFactory = new SourceFactory(uriResolvers);
+ Source taskSource =
+ setupSource(path.join('lib', 'src', 'task', 'dart.dart'));
+ Source modelSource = setupSource(path.join('lib', 'task', 'model.dart'));
+ CompilationUnitElement modelElement = getUnit(modelSource).element;
+ InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type;
+ DartType dynamicType = context.typeProvider.dynamicType;
+ resultDescriptorType = modelElement.getType('ResultDescriptor').type
+ .substitute4([dynamicType]);
+ CompilationUnit taskUnit = getUnit(taskSource);
+ CompilationUnitElement taskUnitElement = taskUnit.element;
+ print('digraph G {');
+ Set<String> results = new Set<String>();
+ for (ClassElement cls in taskUnitElement.types) {
+ if (!cls.isAbstract && cls.type.isSubtypeOf(analysisTaskType)) {
+ String task = cls.name;
+ // TODO(paulberry): node is deprecated. What am I supposed to do
+ // instead?
+ findResultDescriptors(cls.getMethod('buildInputs').node,
+ (String input) {
+ results.add(input);
+ print(' $input -> $task');
+ });
+ findResultDescriptors(cls.getField('DESCRIPTOR').node, (String output) {
+ results.add(output);
+ print(' $task -> $output');
+ });
+ }
+ }
+ for (String result in results) {
+ print(' $result [shape=box]');
+ }
+ print('}');
+ }
+
+ Source setupSource(String filename) {
+ String filePath = path.join(rootDir, filename);
+ File file = resourceProvider.getResource(filePath);
+ Source source = file.createSource();
+ ChangeSet changeSet = new ChangeSet();
+ changeSet.addedSource(source);
+ context.applyChanges(changeSet);
+ return source;
+ }
+}
+
+class ResultDescriptorFinder extends GeneralizingAstVisitor {
+ final InterfaceType resultDescriptorType;
+ final ResultDescriptorFinderCallback callback;
+
+ ResultDescriptorFinder(this.resultDescriptorType, this.callback);
+
+ @override
+ visitIdentifier(Identifier node) {
+ Element element = node.staticElement;
+ if (element is PropertyAccessorElement &&
+ element.isGetter &&
+ element.returnType.isSubtypeOf(resultDescriptorType)) {
+ callback(element);
+ }
+ }
+}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698