| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; | |
| 8 import 'package:analyzer/error/listener.dart'; | |
| 9 import 'package:analyzer/src/dart/scanner/reader.dart'; | |
| 10 import 'package:analyzer/src/generated/parser.dart'; | |
| 11 import 'package:front_end/dependency_grapher.dart'; | 7 import 'package:front_end/dependency_grapher.dart'; |
| 12 import 'package:front_end/src/async_dependency_walker.dart'; | 8 import 'package:front_end/src/async_dependency_walker.dart'; |
| 13 import 'package:front_end/src/base/processed_options.dart'; | 9 import 'package:front_end/src/base/processed_options.dart'; |
| 14 import 'package:front_end/src/base/uri_resolver.dart'; | 10 import 'package:front_end/src/base/uri_resolver.dart'; |
| 15 import 'package:front_end/src/scanner/scanner.dart'; | 11 import 'package:front_end/src/fasta/parser.dart'; |
| 12 import 'package:front_end/src/fasta/scanner.dart'; |
| 13 import 'package:front_end/src/fasta/source/directive_listener.dart'; |
| 16 | 14 |
| 17 /// Generates a representation of the dependency graph of a program. | 15 /// Generates a representation of the dependency graph of a program. |
| 18 /// | 16 /// |
| 19 /// Given the Uri of one or more files, this function follows `import`, | 17 /// Given the Uri of one or more files, this function follows `import`, |
| 20 /// `export`, and `part` declarations to discover a graph of all files involved | 18 /// `export`, and `part` declarations to discover a graph of all files involved |
| 21 /// in the program. | 19 /// in the program. |
| 22 /// | 20 /// |
| 23 /// If a [fileReader] is supplied, it is used to read file contents; otherwise | 21 /// If a [fileReader] is supplied, it is used to read file contents; otherwise |
| 24 /// they are read directly from `options.fileSystem`. | 22 /// they are read directly from `options.fileSystem`. |
| 25 /// | 23 /// |
| 26 /// This is intended for internal use by the front end. Clients should use | 24 /// This is intended for internal use by the front end. Clients should use |
| 27 /// package:front_end/dependency_grapher.dart. | 25 /// package:front_end/dependency_grapher.dart. |
| 28 Future<Graph> graphForProgram(List<Uri> sources, ProcessedOptions options, | 26 Future<Graph> graphForProgram(List<Uri> sources, ProcessedOptions options, |
| 29 {FileReader fileReader}) async { | 27 {FileReader fileReader}) async { |
| 30 var uriResolver = await options.getUriResolver(); | 28 var uriResolver = await options.getUriResolver(); |
| 31 fileReader ??= (originalUri, resolvedUri) => | 29 fileReader ??= (originalUri, resolvedUri) => |
| 32 options.fileSystem.entityForUri(resolvedUri).readAsString(); | 30 options.fileSystem.entityForUri(resolvedUri).readAsString(); |
| 33 var walker = new _Walker(fileReader, uriResolver, options.compileSdk); | 31 var walker = new _Walker(fileReader, uriResolver, options.compileSdk); |
| 34 var startingPoint = new _StartingPoint(walker, sources); | 32 var startingPoint = new _StartingPoint(walker, sources); |
| 35 await walker.walk(startingPoint); | 33 await walker.walk(startingPoint); |
| 36 return walker.graph; | 34 return walker.graph; |
| 37 } | 35 } |
| 38 | 36 |
| 39 /// Type of the callback function used by [graphForProgram] to read file | 37 /// Type of the callback function used by [graphForProgram] to read file |
| 40 /// contents. | 38 /// contents. |
| 41 typedef Future<String> FileReader(Uri originalUri, Uri resolvedUri); | 39 typedef Future<String> FileReader(Uri originalUri, Uri resolvedUri); |
| 42 | 40 |
| 43 class _Scanner extends Scanner { | |
| 44 _Scanner(String contents) : super.create(new CharSequenceReader(contents)) { | |
| 45 preserveComments = false; | |
| 46 } | |
| 47 | |
| 48 @override | |
| 49 void reportError(errorCode, int offset, List<Object> arguments) { | |
| 50 // TODO(paulberry): report errors. | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 class _StartingPoint extends _WalkerNode { | 41 class _StartingPoint extends _WalkerNode { |
| 55 final List<Uri> sources; | 42 final List<Uri> sources; |
| 56 | 43 |
| 57 _StartingPoint(_Walker walker, this.sources) : super(walker, null); | 44 _StartingPoint(_Walker walker, this.sources) : super(walker, null); |
| 58 | 45 |
| 59 @override | 46 @override |
| 60 Future<List<_WalkerNode>> computeDependencies() async => | 47 Future<List<_WalkerNode>> computeDependencies() async => |
| 61 sources.map(walker.nodeForUri).toList(); | 48 sources.map(walker.nodeForUri).toList(); |
| 62 } | 49 } |
| 63 | 50 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 Future<List<_WalkerNode>> computeDependencies() async { | 94 Future<List<_WalkerNode>> computeDependencies() async { |
| 108 var dependencies = <_WalkerNode>[]; | 95 var dependencies = <_WalkerNode>[]; |
| 109 // TODO(paulberry): add error recovery if the file can't be read. | 96 // TODO(paulberry): add error recovery if the file can't be read. |
| 110 var resolvedUri = walker.uriResolver.resolve(uri); | 97 var resolvedUri = walker.uriResolver.resolve(uri); |
| 111 if (resolvedUri == null) { | 98 if (resolvedUri == null) { |
| 112 // TODO(paulberry): If an error reporter was provided, report the error | 99 // TODO(paulberry): If an error reporter was provided, report the error |
| 113 // in the proper way and continue. | 100 // in the proper way and continue. |
| 114 throw new StateError('Invalid URI: $uri'); | 101 throw new StateError('Invalid URI: $uri'); |
| 115 } | 102 } |
| 116 var contents = await walker.fileReader(uri, resolvedUri); | 103 var contents = await walker.fileReader(uri, resolvedUri); |
| 117 var scanner = new _Scanner(contents); | 104 var scannerResults = scanString(contents); |
| 118 var token = scanner.tokenize(); | |
| 119 // TODO(paulberry): report errors. | 105 // TODO(paulberry): report errors. |
| 120 var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER); | 106 var listener = new DirectiveListener(); |
| 121 var unit = parser.parseDirectives(token); | 107 new TopLevelParser(listener).parseUnit(scannerResults.tokens); |
| 122 bool coreUriFound = false; | 108 bool coreUriFound = false; |
| 123 void handleDependency(Uri referencedUri) { | 109 void handleDependency(Uri referencedUri) { |
| 124 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri); | 110 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri); |
| 125 library.dependencies.add(dependencyNode.library); | 111 library.dependencies.add(dependencyNode.library); |
| 126 if (referencedUri.scheme != 'dart' || walker.compileSdk) { | 112 if (referencedUri.scheme != 'dart' || walker.compileSdk) { |
| 127 dependencies.add(dependencyNode); | 113 dependencies.add(dependencyNode); |
| 128 } | 114 } |
| 129 if (referencedUri == dartCoreUri) { | 115 if (referencedUri == dartCoreUri) { |
| 130 coreUriFound = true; | 116 coreUriFound = true; |
| 131 } | 117 } |
| 132 } | 118 } |
| 133 | 119 |
| 134 for (var directive in unit.directives) { | 120 for (var part in listener.parts) { |
| 135 if (directive is UriBasedDirective) { | 121 // TODO(paulberry): when we support SDK libraries, we'll need more |
| 136 // TODO(paulberry): when we support SDK libraries, we'll need more | 122 // complex logic here to find SDK parts correctly. |
| 137 // complex logic here to find SDK parts correctly. | 123 library.parts.add(uri.resolve(part)); |
| 138 var referencedUri = uri.resolve(directive.uri.stringValue); | |
| 139 if (directive is PartDirective) { | |
| 140 library.parts.add(referencedUri); | |
| 141 } else { | |
| 142 handleDependency(referencedUri); | |
| 143 } | |
| 144 } | |
| 145 } | 124 } |
| 125 |
| 126 for (var dep in listener.imports) { |
| 127 handleDependency(uri.resolve(dep)); |
| 128 } |
| 129 |
| 130 for (var dep in listener.exports) { |
| 131 handleDependency(uri.resolve(dep)); |
| 132 } |
| 133 |
| 146 if (!coreUriFound) { | 134 if (!coreUriFound) { |
| 147 handleDependency(dartCoreUri); | 135 handleDependency(dartCoreUri); |
| 148 } | 136 } |
| 149 return dependencies; | 137 return dependencies; |
| 150 } | 138 } |
| 151 } | 139 } |
| OLD | NEW |