| 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 |