OLD | NEW |
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 analyzer.tool.task_dependency_graph.generate; | 18 library analyzer.tool.task_dependency_graph.generate; |
19 | 19 |
| 20 import 'dart:async'; |
20 import 'dart:io' hide File; | 21 import 'dart:io' hide File; |
21 import 'dart:io' as io; | 22 import 'dart:io' as io; |
22 | 23 |
23 import 'package:analyzer/analyzer.dart'; | 24 import 'package:analyzer/analyzer.dart'; |
24 import 'package:analyzer/dart/element/element.dart'; | 25 import 'package:analyzer/dart/element/element.dart'; |
25 import 'package:analyzer/dart/element/type.dart'; | 26 import 'package:analyzer/dart/element/type.dart'; |
26 import 'package:analyzer/file_system/file_system.dart'; | 27 import 'package:analyzer/file_system/file_system.dart'; |
27 import 'package:analyzer/file_system/physical_file_system.dart'; | 28 import 'package:analyzer/file_system/physical_file_system.dart'; |
28 import 'package:analyzer/source/package_map_resolver.dart'; | 29 import 'package:analyzer/source/package_map_resolver.dart'; |
29 import 'package:analyzer/src/context/builder.dart'; | 30 import 'package:analyzer/src/context/builder.dart'; |
| 31 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 32 import 'package:analyzer/src/dart/analysis/file_state.dart'; |
30 import 'package:analyzer/src/dart/sdk/sdk.dart'; | 33 import 'package:analyzer/src/dart/sdk/sdk.dart'; |
31 import 'package:analyzer/src/generated/constant.dart'; | 34 import 'package:analyzer/src/generated/constant.dart'; |
32 import 'package:analyzer/src/generated/engine.dart'; | 35 import 'package:analyzer/src/generated/engine.dart'; |
| 36 import 'package:analyzer/src/generated/resolver.dart'; |
33 import 'package:analyzer/src/generated/sdk.dart'; | 37 import 'package:analyzer/src/generated/sdk.dart'; |
34 import 'package:analyzer/src/generated/source.dart'; | 38 import 'package:analyzer/src/generated/source.dart'; |
35 import 'package:analyzer/src/generated/source_io.dart'; | 39 import 'package:analyzer/src/generated/source_io.dart'; |
| 40 import 'package:front_end/src/base/performace_logger.dart'; |
| 41 import 'package:front_end/src/byte_store/byte_store.dart'; |
36 import 'package:front_end/src/codegen/tools.dart'; | 42 import 'package:front_end/src/codegen/tools.dart'; |
37 import 'package:path/path.dart' as path; | 43 import 'package:path/path.dart' as path; |
38 import 'package:path/path.dart'; | 44 import 'package:path/path.dart'; |
39 | 45 |
40 /** | 46 /** |
41 * Generate the target .dot file. | 47 * Generate the target .dot file. |
42 */ | 48 */ |
43 main() { | 49 main() async { |
44 String script = Platform.script.toFilePath(windows: Platform.isWindows); | 50 String script = Platform.script.toFilePath(windows: Platform.isWindows); |
45 String pkgPath = normalize(join(dirname(script), '..', '..')); | 51 String pkgPath = normalize(join(dirname(script), '..', '..')); |
46 GeneratedContent.generateAll(pkgPath, <GeneratedContent>[target, htmlTarget]); | 52 await GeneratedContent |
| 53 .generateAll(pkgPath, <GeneratedContent>[target, htmlTarget]); |
47 } | 54 } |
48 | 55 |
49 final GeneratedFile htmlTarget = new GeneratedFile( | 56 final GeneratedFile htmlTarget = new GeneratedFile( |
50 'doc/tasks.html', (String pkgPath) => new Driver(pkgPath).generateHtml()); | 57 'doc/tasks.html', (String pkgPath) => new Driver(pkgPath).generateHtml()); |
51 | 58 |
52 final GeneratedFile target = new GeneratedFile( | 59 final GeneratedFile target = new GeneratedFile( |
53 'tool/task_dependency_graph/tasks.dot', | 60 'tool/task_dependency_graph/tasks.dot', |
54 (String pkgPath) => new Driver(pkgPath).generateFileContents()); | 61 (String pkgPath) => new Driver(pkgPath).generateFileContents()); |
55 | 62 |
56 typedef void GetterFinderCallback(PropertyAccessorElement element); | 63 typedef void GetterFinderCallback(PropertyAccessorElement element); |
57 | 64 |
58 class Driver { | 65 class Driver { |
59 static bool hasInitializedPlugins = false; | 66 static bool hasInitializedPlugins = false; |
60 PhysicalResourceProvider resourceProvider; | 67 PhysicalResourceProvider resourceProvider; |
61 AnalysisContext context; | 68 AnalysisDriver driver; |
62 InterfaceType resultDescriptorType; | 69 InterfaceType resultDescriptorType; |
63 InterfaceType listOfResultDescriptorType; | 70 InterfaceType listOfResultDescriptorType; |
64 ClassElement enginePluginClass; | 71 ClassElement enginePluginClass; |
65 CompilationUnitElement taskUnitElement; | 72 CompilationUnitElement taskUnitElement; |
66 InterfaceType extensionPointIdType; | 73 InterfaceType extensionPointIdType; |
67 | 74 |
68 final String rootDir; | 75 final String rootDir; |
69 | 76 |
70 Driver(String pkgPath) : rootDir = new Directory(pkgPath).absolute.path; | 77 Driver(String pkgPath) : rootDir = new Directory(pkgPath).absolute.path; |
71 | 78 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 new Set<PropertyAccessorElement>(); | 126 new Set<PropertyAccessorElement>(); |
120 node.accept(new GetterFinder(resultDescriptorType, resultDescriptors.add)); | 127 node.accept(new GetterFinder(resultDescriptorType, resultDescriptors.add)); |
121 for (PropertyAccessorElement resultDescriptor in resultDescriptors) { | 128 for (PropertyAccessorElement resultDescriptor in resultDescriptors) { |
122 callback(resultDescriptor.name); | 129 callback(resultDescriptor.name); |
123 } | 130 } |
124 } | 131 } |
125 | 132 |
126 /** | 133 /** |
127 * Generate the task dependency graph and return it as a [String]. | 134 * Generate the task dependency graph and return it as a [String]. |
128 */ | 135 */ |
129 String generateFileContents() { | 136 Future<String> generateFileContents() async { |
| 137 String data = await generateGraphData(); |
130 return ''' | 138 return ''' |
131 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 139 // 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 | 140 // 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. | 141 // BSD-style license that can be found in the LICENSE file. |
134 // | 142 // |
135 // This file has been automatically generated. Please do not edit it manually. | 143 // This file has been automatically generated. Please do not edit it manually. |
136 // To regenerate the file, use the script | 144 // To regenerate the file, use the script |
137 // "pkg/analyzer/tool/task_dependency_graph/generate.dart". | 145 // "pkg/analyzer/tool/task_dependency_graph/generate.dart". |
138 // | 146 // |
139 // To render this graph using Graphviz (www.graphviz.org) use the command: | 147 // To render this graph using Graphviz (www.graphviz.org) use the command: |
140 // "dot tasks.dot -Tpdf -O". | 148 // "dot tasks.dot -Tpdf -O". |
141 digraph G { | 149 digraph G { |
142 ${generateGraphData()} | 150 $data |
143 } | 151 } |
144 '''; | 152 '''; |
145 } | 153 } |
146 | 154 |
147 String generateGraphData() { | 155 Future<String> generateGraphData() async { |
148 if (!hasInitializedPlugins) { | 156 if (!hasInitializedPlugins) { |
149 AnalysisEngine.instance.processRequiredPlugins(); | 157 AnalysisEngine.instance.processRequiredPlugins(); |
150 hasInitializedPlugins = true; | 158 hasInitializedPlugins = true; |
151 } | 159 } |
152 List<String> lines = <String>[]; | 160 List<String> lines = <String>[]; |
153 resourceProvider = PhysicalResourceProvider.INSTANCE; | 161 resourceProvider = PhysicalResourceProvider.INSTANCE; |
154 DartSdk sdk = new FolderBasedDartSdk(resourceProvider, | 162 DartSdk sdk = new FolderBasedDartSdk(resourceProvider, |
155 FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)); | 163 FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)); |
156 context = AnalysisEngine.instance.createAnalysisContext(); | 164 |
157 ContextBuilderOptions builderOptions = new ContextBuilderOptions(); | 165 ContextBuilderOptions builderOptions = new ContextBuilderOptions(); |
158 if (Platform.packageRoot != null) { | 166 if (Platform.packageRoot != null) { |
159 builderOptions.defaultPackagesDirectoryPath = | 167 builderOptions.defaultPackagesDirectoryPath = |
160 Uri.parse(Platform.packageRoot).toFilePath(); | 168 Uri.parse(Platform.packageRoot).toFilePath(); |
161 } else if (Platform.packageConfig != null) { | 169 } else if (Platform.packageConfig != null) { |
162 builderOptions.defaultPackageFilePath = | 170 builderOptions.defaultPackageFilePath = |
163 Uri.parse(Platform.packageConfig).toFilePath(); | 171 Uri.parse(Platform.packageConfig).toFilePath(); |
164 } else { | 172 } else { |
165 // Let the context builder use the default algorithm for package | 173 // Let the context builder use the default algorithm for package |
166 // resolution. | 174 // resolution. |
167 } | 175 } |
| 176 |
168 ContextBuilder builder = new ContextBuilder(resourceProvider, null, null, | 177 ContextBuilder builder = new ContextBuilder(resourceProvider, null, null, |
169 options: builderOptions); | 178 options: builderOptions); |
170 List<UriResolver> uriResolvers = [ | 179 List<UriResolver> uriResolvers = [ |
171 new DartUriResolver(sdk), | 180 new DartUriResolver(sdk), |
172 new PackageMapUriResolver(resourceProvider, | 181 new PackageMapUriResolver(resourceProvider, |
173 builder.convertPackagesToMap(builder.createPackageMap(''))), | 182 builder.convertPackagesToMap(builder.createPackageMap(''))), |
174 new ResourceUriResolver(PhysicalResourceProvider.INSTANCE) | 183 new ResourceUriResolver(resourceProvider) |
175 ]; | 184 ]; |
176 context.sourceFactory = new SourceFactory(uriResolvers); | 185 |
177 Source dartDartSource = | 186 var logger = new PerformanceLog(null); |
178 setupSource(path.join('lib', 'src', 'task', 'dart.dart')); | 187 var scheduler = new AnalysisDriverScheduler(logger); |
179 Source taskSource = setupSource(path.join('lib', 'plugin', 'task.dart')); | 188 driver = new AnalysisDriver( |
180 Source modelSource = setupSource(path.join('lib', 'task', 'model.dart')); | 189 scheduler, |
181 Source enginePluginSource = | 190 logger, |
182 setupSource(path.join('lib', 'src', 'plugin', 'engine_plugin.dart')); | 191 resourceProvider, |
183 CompilationUnitElement modelElement = getUnit(modelSource).element; | 192 new MemoryByteStore(), |
| 193 new FileContentOverlay(), |
| 194 null, |
| 195 new SourceFactory(uriResolvers), |
| 196 new AnalysisOptionsImpl()); |
| 197 scheduler.start(); |
| 198 |
| 199 TypeProvider typeProvider = await driver.currentSession.typeProvider; |
| 200 |
| 201 String dartDartPath = path.join(rootDir, 'lib', 'src', 'task', 'dart.dart'); |
| 202 String taskPath = path.join(rootDir, 'lib', 'plugin', 'task.dart'); |
| 203 String modelPath = path.join(rootDir, 'lib', 'task', 'model.dart'); |
| 204 String enginePluginPath = |
| 205 path.join(rootDir, 'lib', 'src', 'plugin', 'engine_plugin.dart'); |
| 206 |
| 207 CompilationUnitElement modelElement = await getUnitElement(modelPath); |
184 InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type; | 208 InterfaceType analysisTaskType = modelElement.getType('AnalysisTask').type; |
185 DartType dynamicType = context.typeProvider.dynamicType; | 209 DartType dynamicType = typeProvider.dynamicType; |
186 resultDescriptorType = modelElement | 210 resultDescriptorType = modelElement |
187 .getType('ResultDescriptor') | 211 .getType('ResultDescriptor') |
188 .type | 212 .type |
189 .instantiate([dynamicType]); | 213 .instantiate([dynamicType]); |
190 listOfResultDescriptorType = | 214 listOfResultDescriptorType = |
191 context.typeProvider.listType.instantiate([resultDescriptorType]); | 215 typeProvider.listType.instantiate([resultDescriptorType]); |
192 CompilationUnit enginePluginUnit = getUnit(enginePluginSource); | 216 CompilationUnit enginePluginUnit = await getUnit(enginePluginPath); |
193 enginePluginClass = enginePluginUnit.element.getType('EnginePlugin'); | 217 enginePluginClass = enginePluginUnit.element.getType('EnginePlugin'); |
194 extensionPointIdType = | 218 extensionPointIdType = |
195 enginePluginUnit.element.getType('ExtensionPointId').type; | 219 enginePluginUnit.element.getType('ExtensionPointId').type; |
196 CompilationUnit dartDartUnit = getUnit(dartDartSource); | 220 CompilationUnit dartDartUnit = await getUnit(dartDartPath); |
197 CompilationUnit taskUnit = getUnit(taskSource); | 221 CompilationUnit taskUnit = await getUnit(taskPath); |
198 taskUnitElement = taskUnit.element; | 222 taskUnitElement = taskUnit.element; |
199 Set<String> results = new Set<String>(); | 223 Set<String> results = new Set<String>(); |
200 Set<String> resultLists = new Set<String>(); | 224 Set<String> resultLists = new Set<String>(); |
201 for (CompilationUnitMember dartUnitMember in dartDartUnit.declarations) { | 225 for (CompilationUnitMember dartUnitMember in dartDartUnit.declarations) { |
202 if (dartUnitMember is ClassDeclaration) { | 226 if (dartUnitMember is ClassDeclaration) { |
203 ClassDeclaration clazz = dartUnitMember; | 227 ClassDeclaration clazz = dartUnitMember; |
204 if (!clazz.isAbstract && | 228 if (!clazz.isAbstract && |
205 clazz.element.type.isSubtypeOf(analysisTaskType)) { | 229 clazz.element.type.isSubtypeOf(analysisTaskType)) { |
206 String task = clazz.name.name; | 230 String task = clazz.name.name; |
207 | 231 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 lines.add(' $extension -> $resultList'); | 268 lines.add(' $extension -> $resultList'); |
245 }); | 269 }); |
246 } | 270 } |
247 for (String result in results) { | 271 for (String result in results) { |
248 lines.add(' $result [shape=box]'); | 272 lines.add(' $result [shape=box]'); |
249 } | 273 } |
250 lines.sort(); | 274 lines.sort(); |
251 return lines.join('\n'); | 275 return lines.join('\n'); |
252 } | 276 } |
253 | 277 |
254 String generateHtml() { | 278 Future<String> generateHtml() async { |
| 279 var data = await generateGraphData(); |
255 return ''' | 280 return ''' |
256 <!DOCTYPE html> | 281 <!DOCTYPE html> |
257 <html> | 282 <html> |
258 <head> | 283 <head> |
259 <title>Analysis Task Dependency Graph</title> | 284 <title>Analysis Task Dependency Graph</title> |
260 <link rel="stylesheet" href="support/style.css"> | 285 <link rel="stylesheet" href="support/style.css"> |
261 <script src="support/viz.js"></script> | 286 <script src="support/viz.js"></script> |
262 <script type="application/dart" src="support/web_app.dart.js"></script> | 287 <script type="application/dart" src="support/web_app.dart.js"></script> |
263 <script src="support/dart.js"></script> | 288 <script src="support/dart.js"></script> |
264 </head> | 289 </head> |
265 <body> | 290 <body> |
266 <button id="zoomBtn">Zoom</button> | 291 <button id="zoomBtn">Zoom</button> |
267 <script type="text/vnd.graphviz" id="dot"> | 292 <script type="text/vnd.graphviz" id="dot"> |
268 digraph G { | 293 digraph G { |
269 tooltip="Analysis Task Dependency Graph"; | 294 tooltip="Analysis Task Dependency Graph"; |
270 node [fontname=Helvetica]; | 295 node [fontname=Helvetica]; |
271 edge [fontname=Helvetica, fontcolor=gray]; | 296 edge [fontname=Helvetica, fontcolor=gray]; |
272 ${generateGraphData()} | 297 $data |
273 } | 298 } |
274 </script> | 299 </script> |
275 </body> | 300 </body> |
276 </html> | 301 </html> |
277 '''; | 302 '''; |
278 } | 303 } |
279 | 304 |
280 CompilationUnit getUnit(Source source) => | 305 Future<CompilationUnit> getUnit(String path) async { |
281 context.resolveCompilationUnit2(source, source); | 306 var result = await driver.getResult(path); |
| 307 return result.unit; |
| 308 } |
282 | 309 |
283 Source setupSource(String filename) { | 310 Future<CompilationUnitElement> getUnitElement(String path) async { |
284 String filePath = path.join(rootDir, filename); | 311 UnitElementResult result = await driver.getUnitElement(path); |
285 File file = resourceProvider.getResource(filePath); | 312 return result.element; |
286 Source source = file.createSource(); | |
287 Uri restoredUri = context.sourceFactory.restoreUri(source); | |
288 if (restoredUri != null) { | |
289 source = file.createSource(restoredUri); | |
290 } | |
291 ChangeSet changeSet = new ChangeSet(); | |
292 changeSet.addedSource(source); | |
293 context.applyChanges(changeSet); | |
294 return source; | |
295 } | 313 } |
296 | 314 |
297 /** | 315 /** |
298 * Find the result list getter having name [resultListGetterName] in the | 316 * Find the result list getter having name [resultListGetterName] in the |
299 * [EnginePlugin] class, and use the [ExtensionPointId] annotation on that | 317 * [EnginePlugin] class, and use the [ExtensionPointId] annotation on that |
300 * getter to find the associated [TopLevelVariableElement] which can be used | 318 * getter to find the associated [TopLevelVariableElement] which can be used |
301 * to register extensions for that getter. | 319 * to register extensions for that getter. |
302 */ | 320 */ |
303 TopLevelVariableElement _getExtensionId(String resultListGetterName) { | 321 TopLevelVariableElement _getExtensionId(String resultListGetterName) { |
304 PropertyAccessorElement getter = | 322 PropertyAccessorElement getter = |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 @override | 392 @override |
375 visitIdentifier(Identifier node) { | 393 visitIdentifier(Identifier node) { |
376 Element element = node.staticElement; | 394 Element element = node.staticElement; |
377 if (element is PropertyAccessorElement && | 395 if (element is PropertyAccessorElement && |
378 element.isGetter && | 396 element.isGetter && |
379 element.returnType.isSubtypeOf(type)) { | 397 element.returnType.isSubtypeOf(type)) { |
380 callback(element); | 398 callback(element); |
381 } | 399 } |
382 } | 400 } |
383 } | 401 } |
OLD | NEW |