| 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'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/error/listener.dart'; | 8 import 'package:analyzer/error/listener.dart'; |
| 9 import 'package:analyzer/src/dart/scanner/reader.dart'; | 9 import 'package:analyzer/src/dart/scanner/reader.dart'; |
| 10 import 'package:analyzer/src/generated/parser.dart'; | 10 import 'package:analyzer/src/generated/parser.dart'; |
| 11 import 'package:front_end/dependency_grapher.dart'; | 11 import 'package:front_end/dependency_grapher.dart'; |
| 12 import 'package:front_end/file_system.dart'; | |
| 13 import 'package:front_end/src/async_dependency_walker.dart'; | 12 import 'package:front_end/src/async_dependency_walker.dart'; |
| 14 import 'package:front_end/src/base/processed_options.dart'; | 13 import 'package:front_end/src/base/processed_options.dart'; |
| 15 import 'package:front_end/src/base/uri_resolver.dart'; | 14 import 'package:front_end/src/base/uri_resolver.dart'; |
| 16 import 'package:front_end/src/scanner/scanner.dart'; | 15 import 'package:front_end/src/scanner/scanner.dart'; |
| 17 | 16 |
| 18 /// Generates a representation of the dependency graph of a program. | 17 /// Generates a representation of the dependency graph of a program. |
| 19 /// | 18 /// |
| 20 /// Given the Uri of one or more files, this function follows `import`, | 19 /// Given the Uri of one or more files, this function follows `import`, |
| 21 /// `export`, and `part` declarations to discover a graph of all files involved | 20 /// `export`, and `part` declarations to discover a graph of all files involved |
| 22 /// in the program. | 21 /// in the program. |
| 23 /// | 22 /// |
| 23 /// If a [fileReader] is supplied, it is used to read file contents; otherwise |
| 24 /// they are read directly from `options.fileSystem`. |
| 25 /// |
| 24 /// This is intended for internal use by the front end. Clients should use | 26 /// This is intended for internal use by the front end. Clients should use |
| 25 /// package:front_end/dependency_grapher.dart. | 27 /// package:front_end/dependency_grapher.dart. |
| 26 Future<Graph> graphForProgram( | 28 Future<Graph> graphForProgram(List<Uri> sources, ProcessedOptions options, |
| 27 List<Uri> sources, ProcessedOptions options) async { | 29 {FileReader fileReader}) async { |
| 28 var uriResolver = await options.getUriResolver(); | 30 var uriResolver = await options.getUriResolver(); |
| 29 var walker = new _Walker(options.fileSystem, uriResolver, options.compileSdk); | 31 fileReader ??= (originalUri, resolvedUri) => |
| 32 options.fileSystem.entityForUri(resolvedUri).readAsString(); |
| 33 var walker = new _Walker(fileReader, uriResolver, options.compileSdk); |
| 30 var startingPoint = new _StartingPoint(walker, sources); | 34 var startingPoint = new _StartingPoint(walker, sources); |
| 31 await walker.walk(startingPoint); | 35 await walker.walk(startingPoint); |
| 32 return walker.graph; | 36 return walker.graph; |
| 33 } | 37 } |
| 34 | 38 |
| 39 /// Type of the callback function used by [graphForProgram] to read file |
| 40 /// contents. |
| 41 typedef Future<String> FileReader(Uri originalUri, Uri resolvedUri); |
| 42 |
| 35 class _Scanner extends Scanner { | 43 class _Scanner extends Scanner { |
| 36 _Scanner(String contents) : super(new CharSequenceReader(contents)) { | 44 _Scanner(String contents) : super(new CharSequenceReader(contents)) { |
| 37 preserveComments = false; | 45 preserveComments = false; |
| 38 } | 46 } |
| 39 | 47 |
| 40 @override | 48 @override |
| 41 void reportError(errorCode, int offset, List<Object> arguments) { | 49 void reportError(errorCode, int offset, List<Object> arguments) { |
| 42 // TODO(paulberry): report errors. | 50 // TODO(paulberry): report errors. |
| 43 } | 51 } |
| 44 } | 52 } |
| 45 | 53 |
| 46 class _StartingPoint extends _WalkerNode { | 54 class _StartingPoint extends _WalkerNode { |
| 47 final List<Uri> sources; | 55 final List<Uri> sources; |
| 48 | 56 |
| 49 _StartingPoint(_Walker walker, this.sources) : super(walker, null); | 57 _StartingPoint(_Walker walker, this.sources) : super(walker, null); |
| 50 | 58 |
| 51 @override | 59 @override |
| 52 Future<List<_WalkerNode>> computeDependencies() async => | 60 Future<List<_WalkerNode>> computeDependencies() async => |
| 53 sources.map(walker.nodeForUri).toList(); | 61 sources.map(walker.nodeForUri).toList(); |
| 54 } | 62 } |
| 55 | 63 |
| 56 class _Walker extends AsyncDependencyWalker<_WalkerNode> { | 64 class _Walker extends AsyncDependencyWalker<_WalkerNode> { |
| 57 final FileSystem fileSystem; | 65 final FileReader fileReader; |
| 58 final UriResolver uriResolver; | 66 final UriResolver uriResolver; |
| 59 final _nodesByUri = <Uri, _WalkerNode>{}; | 67 final _nodesByUri = <Uri, _WalkerNode>{}; |
| 60 final graph = new Graph(); | 68 final graph = new Graph(); |
| 61 final bool compileSdk; | 69 final bool compileSdk; |
| 62 | 70 |
| 63 _Walker(this.fileSystem, this.uriResolver, this.compileSdk); | 71 _Walker(this.fileReader, this.uriResolver, this.compileSdk); |
| 64 | 72 |
| 65 @override | 73 @override |
| 66 Future<Null> evaluate(_WalkerNode v) { | 74 Future<Null> evaluate(_WalkerNode v) { |
| 67 if (v is _StartingPoint) return new Future.value(); | 75 if (v is _StartingPoint) return new Future.value(); |
| 68 return evaluateScc([v]); | 76 return evaluateScc([v]); |
| 69 } | 77 } |
| 70 | 78 |
| 71 @override | 79 @override |
| 72 Future<Null> evaluateScc(List<_WalkerNode> scc) { | 80 Future<Null> evaluateScc(List<_WalkerNode> scc) { |
| 73 var cycle = new LibraryCycleNode(); | 81 var cycle = new LibraryCycleNode(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 98 @override | 106 @override |
| 99 Future<List<_WalkerNode>> computeDependencies() async { | 107 Future<List<_WalkerNode>> computeDependencies() async { |
| 100 var dependencies = <_WalkerNode>[]; | 108 var dependencies = <_WalkerNode>[]; |
| 101 // TODO(paulberry): add error recovery if the file can't be read. | 109 // TODO(paulberry): add error recovery if the file can't be read. |
| 102 var resolvedUri = walker.uriResolver.resolve(uri); | 110 var resolvedUri = walker.uriResolver.resolve(uri); |
| 103 if (resolvedUri == null) { | 111 if (resolvedUri == null) { |
| 104 // TODO(paulberry): If an error reporter was provided, report the error | 112 // TODO(paulberry): If an error reporter was provided, report the error |
| 105 // in the proper way and continue. | 113 // in the proper way and continue. |
| 106 throw new StateError('Invalid URI: $uri'); | 114 throw new StateError('Invalid URI: $uri'); |
| 107 } | 115 } |
| 108 var contents = | 116 var contents = await walker.fileReader(uri, resolvedUri); |
| 109 await walker.fileSystem.entityForUri(resolvedUri).readAsString(); | |
| 110 var scanner = new _Scanner(contents); | 117 var scanner = new _Scanner(contents); |
| 111 var token = scanner.tokenize(); | 118 var token = scanner.tokenize(); |
| 112 // TODO(paulberry): report errors. | 119 // TODO(paulberry): report errors. |
| 113 var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER); | 120 var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER); |
| 114 var unit = parser.parseDirectives(token); | 121 var unit = parser.parseDirectives(token); |
| 115 bool coreUriFound = false; | 122 bool coreUriFound = false; |
| 116 void handleDependency(Uri referencedUri) { | 123 void handleDependency(Uri referencedUri) { |
| 117 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri); | 124 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri); |
| 118 library.dependencies.add(dependencyNode.library); | 125 library.dependencies.add(dependencyNode.library); |
| 119 if (referencedUri.scheme != 'dart' || walker.compileSdk) { | 126 if (referencedUri.scheme != 'dart' || walker.compileSdk) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 135 handleDependency(referencedUri); | 142 handleDependency(referencedUri); |
| 136 } | 143 } |
| 137 } | 144 } |
| 138 } | 145 } |
| 139 if (!coreUriFound) { | 146 if (!coreUriFound) { |
| 140 handleDependency(dartCoreUri); | 147 handleDependency(dartCoreUri); |
| 141 } | 148 } |
| 142 return dependencies; | 149 return dependencies; |
| 143 } | 150 } |
| 144 } | 151 } |
| OLD | NEW |