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

Side by Side Diff: packages/analyzer/tool/task_dependency_graph/generate.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * This file contains code to output a description of tasks and their 6 * This file contains code to output a description of tasks and their
7 * dependencies in ".dot" format. Prior to running, the user should run "pub 7 * dependencies in ".dot" format. Prior to running, the user should run "pub
8 * get" in the analyzer directory to ensure that a "packages" folder exists. 8 * get" in the analyzer directory to ensure that a "packages" folder exists.
9 * 9 *
10 * TODO(paulberry): 10 * TODO(paulberry):
11 * - Add general.dart and html.dart for completeness. 11 * - Add general.dart and html.dart for completeness.
12 * - Use Graphviz's "record" feature to produce more compact output 12 * - Use Graphviz's "record" feature to produce more compact output
13 * (http://www.graphviz.org/content/node-shapes#record) 13 * (http://www.graphviz.org/content/node-shapes#record)
14 * - Produce a warning if a result descriptor is found which isn't the output 14 * - Produce a warning if a result descriptor is found which isn't the output
15 * of exactly one task. 15 * of exactly one task.
16 * - Convert this tool to use package_config to find the package map. 16 * - Convert this tool to use package_config to find the package map.
17 */ 17 */
18 library task_dependency_graph.generate; 18 library analyzer.tool.task_dependency_graph.generate;
19 19
20 import 'dart:io' hide File; 20 import 'dart:io' hide File;
21 import 'dart:io' as io; 21 import 'dart:io' as io;
22 22
23 import 'package:analyzer/analyzer.dart'; 23 import 'package:analyzer/analyzer.dart';
24 import 'package:analyzer/dart/element/element.dart';
25 import 'package:analyzer/dart/element/type.dart';
24 import 'package:analyzer/file_system/file_system.dart'; 26 import 'package:analyzer/file_system/file_system.dart';
25 import 'package:analyzer/file_system/physical_file_system.dart'; 27 import 'package:analyzer/file_system/physical_file_system.dart';
28 import 'package:analyzer/source/package_map_resolver.dart';
29 import 'package:analyzer/src/codegen/tools.dart';
30 import 'package:analyzer/src/context/builder.dart';
31 import 'package:analyzer/src/dart/sdk/sdk.dart';
26 import 'package:analyzer/src/generated/constant.dart'; 32 import 'package:analyzer/src/generated/constant.dart';
27 import 'package:analyzer/src/generated/element.dart';
28 import 'package:analyzer/src/generated/engine.dart'; 33 import 'package:analyzer/src/generated/engine.dart';
29 import 'package:analyzer/src/generated/java_io.dart';
30 import 'package:analyzer/src/generated/sdk.dart'; 34 import 'package:analyzer/src/generated/sdk.dart';
31 import 'package:analyzer/src/generated/sdk_io.dart';
32 import 'package:analyzer/src/generated/source.dart'; 35 import 'package:analyzer/src/generated/source.dart';
33 import 'package:analyzer/src/generated/source_io.dart'; 36 import 'package:analyzer/src/generated/source_io.dart';
34 import 'package:path/path.dart' as path; 37 import 'package:path/path.dart' as path;
38 import 'package:path/path.dart';
35 39
36 /** 40 /**
37 * Generate the target .dot file. 41 * Generate the target .dot file.
38 */ 42 */
39 main() { 43 main() {
40 new Driver().generateFile(); 44 String script = Platform.script.toFilePath(windows: Platform.isWindows);
45 String pkgPath = normalize(join(dirname(script), '..', '..'));
46 GeneratedContent.generateAll(pkgPath, <GeneratedContent>[target, htmlTarget]);
41 } 47 }
42 48
49 final GeneratedFile htmlTarget = new GeneratedFile(
50 'doc/tasks.html', (String pkgPath) => new Driver(pkgPath).generateHtml());
51
52 final GeneratedFile target = new GeneratedFile(
53 'tool/task_dependency_graph/tasks.dot',
54 (String pkgPath) => new Driver(pkgPath).generateFileContents());
55
43 typedef void GetterFinderCallback(PropertyAccessorElement element); 56 typedef void GetterFinderCallback(PropertyAccessorElement element);
44 57
45 class Driver { 58 class Driver {
59 static bool hasInitializedPlugins = false;
46 PhysicalResourceProvider resourceProvider; 60 PhysicalResourceProvider resourceProvider;
47 AnalysisContext context; 61 AnalysisContext context;
48 InterfaceType resultDescriptorType; 62 InterfaceType resultDescriptorType;
49 InterfaceType listOfResultDescriptorType; 63 InterfaceType listOfResultDescriptorType;
50 ClassElement enginePluginClass; 64 ClassElement enginePluginClass;
51 CompilationUnitElement taskUnitElement; 65 CompilationUnitElement taskUnitElement;
52 InterfaceType extensionPointIdType; 66 InterfaceType extensionPointIdType;
67
53 final String rootDir; 68 final String rootDir;
54 69
55 Driver() 70 Driver(String pkgPath) : rootDir = new Directory(pkgPath).absolute.path;
56 : rootDir =
57 findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
58 71
59 /** 72 /**
60 * Get an [io.File] object corresponding to the file in which the generated 73 * Get an [io.File] object corresponding to the file in which the generated
61 * graph should be output. 74 * graph should be output.
62 */ 75 */
63 io.File get file => new io.File( 76 io.File get file => new io.File(
64 path.join(rootDir, 'tool', 'task_dependency_graph', 'tasks.dot')); 77 path.join(rootDir, 'tool', 'task_dependency_graph', 'tasks.dot'));
65 78
66 /** 79 /**
67 * Determine if the output [file] contains the expected contents.
68 */
69 bool checkFile() {
70 String expectedContents = generateFileContents();
71 String actualContents = file.readAsStringSync();
72 // Normalize Windows line endings to Unix line endings so that the
73 // comparison doesn't fail on Windows.
74 actualContents = actualContents.replaceAll('\r\n', '\n');
75 return expectedContents == actualContents;
76 }
77
78 /**
79 * Starting at [node], find all calls to registerExtension() which refer to 80 * Starting at [node], find all calls to registerExtension() which refer to
80 * the given [extensionIdVariable], and execute [callback] for the associated 81 * the given [extensionIdVariable], and execute [callback] for the associated
81 * result descriptors. 82 * result descriptors.
82 */ 83 */
83 void findExtensions(AstNode node, TopLevelVariableElement extensionIdVariable, 84 void findExtensions(AstNode node, TopLevelVariableElement extensionIdVariable,
84 void callback(descriptorName)) { 85 void callback(descriptorName)) {
85 Set<PropertyAccessorElement> resultDescriptors = 86 Set<PropertyAccessorElement> resultDescriptors =
86 new Set<PropertyAccessorElement>(); 87 new Set<PropertyAccessorElement>();
87 node.accept(new ExtensionFinder( 88 node.accept(new ExtensionFinder(
88 resultDescriptorType, extensionIdVariable, resultDescriptors.add)); 89 resultDescriptorType, extensionIdVariable, resultDescriptors.add));
(...skipping 27 matching lines...) Expand all
116 AstNode node, void callback(String descriptorName)) { 117 AstNode node, void callback(String descriptorName)) {
117 Set<PropertyAccessorElement> resultDescriptors = 118 Set<PropertyAccessorElement> resultDescriptors =
118 new Set<PropertyAccessorElement>(); 119 new Set<PropertyAccessorElement>();
119 node.accept(new GetterFinder(resultDescriptorType, resultDescriptors.add)); 120 node.accept(new GetterFinder(resultDescriptorType, resultDescriptors.add));
120 for (PropertyAccessorElement resultDescriptor in resultDescriptors) { 121 for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
121 callback(resultDescriptor.name); 122 callback(resultDescriptor.name);
122 } 123 }
123 } 124 }
124 125
125 /** 126 /**
126 * Generate the task dependency graph and write it to the output [file].
127 */
128 void generateFile() {
129 String fileContents = generateFileContents();
130 file.writeAsStringSync(fileContents);
131 }
132
133 /**
134 * Generate the task dependency graph and return it as a [String]. 127 * Generate the task dependency graph and return it as a [String].
135 */ 128 */
136 String generateFileContents() { 129 String generateFileContents() {
130 return '''
131 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
132 // for details. All rights reserved. Use of this source code is governed by a
133 // BSD-style license that can be found in the LICENSE file.
134 //
135 // This file has been automatically generated. Please do not edit it manually.
136 // To regenerate the file, use the script
137 // "pkg/analyzer/tool/task_dependency_graph/generate.dart".
138 //
139 // To render this graph using Graphviz (www.graphviz.org) use the command:
140 // "dot tasks.dot -Tpdf -O".
141 digraph G {
142 ${generateGraphData()}
143 }
144 ''';
145 }
146
147 String generateGraphData() {
148 if (!hasInitializedPlugins) {
149 AnalysisEngine.instance.processRequiredPlugins();
150 hasInitializedPlugins = true;
151 }
137 List<String> lines = <String>[]; 152 List<String> lines = <String>[];
138 resourceProvider = PhysicalResourceProvider.INSTANCE; 153 resourceProvider = PhysicalResourceProvider.INSTANCE;
139 DartSdk sdk = DirectoryBasedDartSdk.defaultSdk; 154 DartSdk sdk = new FolderBasedDartSdk(resourceProvider,
155 FolderBasedDartSdk.defaultSdkDirectory(resourceProvider));
140 context = AnalysisEngine.instance.createAnalysisContext(); 156 context = AnalysisEngine.instance.createAnalysisContext();
141 String packageRootPath; 157 ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
142 if (Platform.packageRoot.isNotEmpty) { 158 if (Platform.packageRoot != null) {
143 packageRootPath = Platform.packageRoot; 159 builder.defaultPackagesDirectoryPath =
160 Uri.parse(Platform.packageRoot).toFilePath();
161 } else if (Platform.packageConfig != null) {
162 builder.defaultPackageFilePath =
163 Uri.parse(Platform.packageConfig).toFilePath();
144 } else { 164 } else {
145 packageRootPath = path.join(rootDir, 'packages'); 165 // Let the context builder use the default algorithm for package
166 // resolution.
146 } 167 }
147 JavaFile packagesDir = new JavaFile(packageRootPath);
148 List<UriResolver> uriResolvers = [ 168 List<UriResolver> uriResolvers = [
149 new DartUriResolver(sdk), 169 new DartUriResolver(sdk),
150 new PackageUriResolver(<JavaFile>[packagesDir]), 170 new PackageMapUriResolver(resourceProvider,
151 new FileUriResolver() 171 builder.convertPackagesToMap(builder.createPackageMap(''))),
172 new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)
152 ]; 173 ];
153 context.sourceFactory = new SourceFactory(uriResolvers); 174 context.sourceFactory = new SourceFactory(uriResolvers);
154 Source dartDartSource = 175 Source dartDartSource =
155 setupSource(path.join('lib', 'src', 'task', 'dart.dart')); 176 setupSource(path.join('lib', 'src', 'task', 'dart.dart'));
156 Source taskSource = setupSource(path.join('lib', 'plugin', 'task.dart')); 177 Source taskSource = setupSource(path.join('lib', 'plugin', 'task.dart'));
157 Source modelSource = setupSource(path.join('lib', 'task', 'model.dart')); 178 Source modelSource = setupSource(path.join('lib', 'task', 'model.dart'));
158 Source enginePluginSource = 179 Source enginePluginSource =
159 setupSource(path.join('lib', 'src', 'plugin', 'engine_plugin.dart')); 180 setupSource(path.join('lib', 'src', 'plugin', 'engine_plugin.dart'));
160 CompilationUnitElement modelElement = getUnit(modelSource).element; 181 CompilationUnitElement modelElement = getUnit(modelSource).element;
161 InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type; 182 InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type;
162 DartType dynamicType = context.typeProvider.dynamicType; 183 DartType dynamicType = context.typeProvider.dynamicType;
163 resultDescriptorType = modelElement 184 resultDescriptorType = modelElement
164 .getType('ResultDescriptor') 185 .getType('ResultDescriptor')
165 .type 186 .type
166 .substitute4([dynamicType]); 187 .instantiate([dynamicType]);
167 listOfResultDescriptorType = 188 listOfResultDescriptorType =
168 context.typeProvider.listType.substitute4([resultDescriptorType]); 189 context.typeProvider.listType.instantiate([resultDescriptorType]);
169 CompilationUnitElement enginePluginUnitElement = 190 CompilationUnitElement enginePluginUnitElement =
170 getUnit(enginePluginSource).element; 191 getUnit(enginePluginSource).element;
171 enginePluginClass = enginePluginUnitElement.getType('EnginePlugin'); 192 enginePluginClass = enginePluginUnitElement.getType('EnginePlugin');
172 extensionPointIdType = 193 extensionPointIdType =
173 enginePluginUnitElement.getType('ExtensionPointId').type; 194 enginePluginUnitElement.getType('ExtensionPointId').type;
174 CompilationUnit dartDartUnit = getUnit(dartDartSource); 195 CompilationUnit dartDartUnit = getUnit(dartDartSource);
175 CompilationUnitElement dartDartUnitElement = dartDartUnit.element; 196 CompilationUnitElement dartDartUnitElement = dartDartUnit.element;
176 CompilationUnit taskUnit = getUnit(taskSource); 197 CompilationUnit taskUnit = getUnit(taskSource);
177 taskUnitElement = taskUnit.element; 198 taskUnitElement = taskUnit.element;
178 Set<String> results = new Set<String>(); 199 Set<String> results = new Set<String>();
179 Set<String> resultLists = new Set<String>(); 200 Set<String> resultLists = new Set<String>();
180 for (ClassElement cls in dartDartUnitElement.types) { 201 for (ClassElement cls in dartDartUnitElement.types) {
181 if (!cls.isAbstract && cls.type.isSubtypeOf(analysisTaskType)) { 202 if (!cls.isAbstract && cls.type.isSubtypeOf(analysisTaskType)) {
182 String task = cls.name; 203 String task = cls.name;
183 AstNode buildInputsAst = cls.getMethod('buildInputs').computeNode(); 204 AstNode buildInputsAst = cls.getMethod('buildInputs').computeNode();
184 findResultDescriptors(buildInputsAst, (String input) { 205 findResultDescriptors(buildInputsAst, (String input) {
185 results.add(input); 206 results.add(input);
186 lines.add(' $input -> $task'); 207 lines.add(' $input -> $task');
187 }); 208 });
188 findResultDescriptorLists(buildInputsAst, (String input) { 209 findResultDescriptorLists(buildInputsAst, (String input) {
189 resultLists.add(input); 210 resultLists.add(input);
190 lines.add(' $input -> $task'); 211 lines.add(' $input -> $task');
191 }); 212 });
192 findResultDescriptors(cls.getField('DESCRIPTOR').computeNode(), (String out) { 213 findResultDescriptors(cls.getField('DESCRIPTOR').computeNode(),
214 (String out) {
193 results.add(out); 215 results.add(out);
194 lines.add(' $task -> $out'); 216 lines.add(' $task -> $out');
195 }); 217 });
196 } 218 }
197 } 219 }
198 AstNode enginePluginAst = enginePluginUnitElement.computeNode(); 220 AstNode enginePluginAst = enginePluginUnitElement.computeNode();
199 for (String resultList in resultLists) { 221 for (String resultList in resultLists) {
200 lines.add(' $resultList [shape=hexagon]'); 222 lines.add(' $resultList [shape=hexagon]');
201 TopLevelVariableElement extensionIdVariable = _getExtensionId(resultList); 223 TopLevelVariableElement extensionIdVariable = _getExtensionId(resultList);
202 findExtensions(enginePluginAst, extensionIdVariable, (String extension) { 224 findExtensions(enginePluginAst, extensionIdVariable, (String extension) {
203 results.add(extension); 225 results.add(extension);
204 lines.add(' $extension -> $resultList'); 226 lines.add(' $extension -> $resultList');
205 }); 227 });
206 } 228 }
207 for (String result in results) { 229 for (String result in results) {
208 lines.add(' $result [shape=box]'); 230 lines.add(' $result [shape=box]');
209 } 231 }
210 lines.sort(); 232 lines.sort();
233 return lines.join('\n');
234 }
235
236 String generateHtml() {
211 return ''' 237 return '''
212 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 238 <!DOCTYPE html>
213 // for details. All rights reserved. Use of this source code is governed by a 239 <html>
214 // BSD-style license that can be found in the LICENSE file. 240 <head>
215 // 241 <title>Analysis Task Dependency Graph</title>
216 // This file has been automatically generated. Please do not edit it manually. 242 <link rel="stylesheet" href="support/style.css">
217 // To regenerate the file, use the script 243 <script src="support/viz.js"></script>
218 // "pkg/analyzer/tool/task_dependency_graph/generate.dart". 244 <script type="application/dart" src="support/web_app.dart.js"></script>
219 // 245 <script src="support/dart.js"></script>
220 // To render this graph using Graphviz (www.graphviz.org) use the command: 246 </head>
221 // "dot tasks.dot -Tpdf -O". 247 <body>
248 <button id="zoomBtn">Zoom</button>
249 <script type="text/vnd.graphviz" id="dot">
222 digraph G { 250 digraph G {
223 ${lines.join('\n')} 251 tooltip="Analysis Task Dependency Graph";
252 node [fontname=Helvetica];
253 edge [fontname=Helvetica, fontcolor=gray];
254 ${generateGraphData()}
224 } 255 }
256 </script>
257 </body>
258 </html>
225 '''; 259 ''';
226 } 260 }
227 261
228 CompilationUnit getUnit(Source source) => 262 CompilationUnit getUnit(Source source) =>
229 context.resolveCompilationUnit2(source, source); 263 context.resolveCompilationUnit2(source, source);
230 264
231 Source setupSource(String filename) { 265 Source setupSource(String filename) {
232 String filePath = path.join(rootDir, filename); 266 String filePath = path.join(rootDir, filename);
233 File file = resourceProvider.getResource(filePath); 267 File file = resourceProvider.getResource(filePath);
234 Source source = file.createSource(); 268 Source source = file.createSource();
(...skipping 25 matching lines...) Expand all
260 in taskUnitElement.topLevelVariables) { 294 in taskUnitElement.topLevelVariables) {
261 if (variable.name == extensionPointId) { 295 if (variable.name == extensionPointId) {
262 return variable; 296 return variable;
263 } 297 }
264 } 298 }
265 } 299 }
266 } 300 }
267 throw new Exception( 301 throw new Exception(
268 'Could not find extension ID corresponding to $resultListGetterName'); 302 'Could not find extension ID corresponding to $resultListGetterName');
269 } 303 }
270
271 /**
272 * Find the root directory of the analyzer package by proceeding
273 * upward to the 'tool' dir, and then going up one more directory.
274 */
275 static String findRoot(String pathname) {
276 while (path.basename(pathname) != 'tool') {
277 String parent = path.dirname(pathname);
278 if (parent.length >= pathname.length) {
279 throw new Exception("Can't find root directory");
280 }
281 pathname = parent;
282 }
283 return path.dirname(pathname);
284 }
285 } 304 }
286 305
287 /** 306 /**
288 * Visitor that finds calls that register extension points. Specifically, we 307 * Visitor that finds calls that register extension points. Specifically, we
289 * look for calls of the form `method(extensionIdVariable, resultDescriptor)`, 308 * look for calls of the form `method(extensionIdVariable, resultDescriptor)`,
290 * where `resultDescriptor` has type [resultDescriptorType], and we pass the 309 * where `resultDescriptor` has type [resultDescriptorType], and we pass the
291 * corresponding result descriptor names to [callback]. 310 * corresponding result descriptor names to [callback].
292 */ 311 */
293 class ExtensionFinder extends GeneralizingAstVisitor { 312 class ExtensionFinder extends GeneralizingAstVisitor {
294 final InterfaceType resultDescriptorType; 313 final InterfaceType resultDescriptorType;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 @override 356 @override
338 visitIdentifier(Identifier node) { 357 visitIdentifier(Identifier node) {
339 Element element = node.staticElement; 358 Element element = node.staticElement;
340 if (element is PropertyAccessorElement && 359 if (element is PropertyAccessorElement &&
341 element.isGetter && 360 element.isGetter &&
342 element.returnType.isSubtypeOf(type)) { 361 element.returnType.isSubtypeOf(type)) {
343 callback(element); 362 callback(element);
344 } 363 }
345 } 364 }
346 } 365 }
OLDNEW
« no previous file with comments | « packages/analyzer/tool/task_dependency_graph/check_test.dart ('k') | packages/analyzer/tool/task_dependency_graph/tasks.dot » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698