| 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:front_end/dependency_grapher.dart'; | 7 import 'package:front_end/dependency_grapher.dart'; |
| 8 import 'package:front_end/src/async_dependency_walker.dart'; | 8 import 'package:front_end/src/async_dependency_walker.dart'; |
| 9 import 'package:front_end/src/base/processed_options.dart'; | 9 import 'package:front_end/src/base/processed_options.dart'; |
| 10 import 'package:front_end/src/base/uri_resolver.dart'; | |
| 11 import 'package:front_end/src/fasta/parser.dart'; | 10 import 'package:front_end/src/fasta/parser.dart'; |
| 12 import 'package:front_end/src/fasta/scanner.dart'; | 11 import 'package:front_end/src/fasta/scanner.dart'; |
| 13 import 'package:front_end/src/fasta/source/directive_listener.dart'; | 12 import 'package:front_end/src/fasta/source/directive_listener.dart'; |
| 13 import 'package:front_end/src/fasta/translate_uri.dart'; |
| 14 | 14 |
| 15 /// Generates a representation of the dependency graph of a program. | 15 /// Generates a representation of the dependency graph of a program. |
| 16 /// | 16 /// |
| 17 /// 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`, |
| 18 /// `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 |
| 19 /// in the program. | 19 /// in the program. |
| 20 /// | 20 /// |
| 21 /// 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 |
| 22 /// they are read directly from `options.fileSystem`. | 22 /// they are read directly from `options.fileSystem`. |
| 23 /// | 23 /// |
| 24 /// 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 |
| 25 /// package:front_end/dependency_grapher.dart. | 25 /// package:front_end/dependency_grapher.dart. |
| 26 Future<Graph> graphForProgram(List<Uri> sources, ProcessedOptions options, | 26 Future<Graph> graphForProgram(List<Uri> sources, ProcessedOptions options, |
| 27 {FileReader fileReader}) async { | 27 {FileReader fileReader}) async { |
| 28 var uriResolver = await options.getUriResolver(); | 28 TranslateUri uriTranslator = await options.getUriTranslator(); |
| 29 fileReader ??= (originalUri, resolvedUri) => | 29 fileReader ??= (originalUri, resolvedUri) => |
| 30 options.fileSystem.entityForUri(resolvedUri).readAsString(); | 30 options.fileSystem.entityForUri(resolvedUri).readAsString(); |
| 31 var walker = new _Walker(fileReader, uriResolver, options.compileSdk); | 31 var walker = new _Walker(fileReader, uriTranslator, options.compileSdk); |
| 32 var startingPoint = new _StartingPoint(walker, sources); | 32 var startingPoint = new _StartingPoint(walker, sources); |
| 33 await walker.walk(startingPoint); | 33 await walker.walk(startingPoint); |
| 34 return walker.graph; | 34 return walker.graph; |
| 35 } | 35 } |
| 36 | 36 |
| 37 /// Type of the callback function used by [graphForProgram] to read file | 37 /// Type of the callback function used by [graphForProgram] to read file |
| 38 /// contents. | 38 /// contents. |
| 39 typedef Future<String> FileReader(Uri originalUri, Uri resolvedUri); | 39 typedef Future<String> FileReader(Uri originalUri, Uri resolvedUri); |
| 40 | 40 |
| 41 class _StartingPoint extends _WalkerNode { | 41 class _StartingPoint extends _WalkerNode { |
| 42 final List<Uri> sources; | 42 final List<Uri> sources; |
| 43 | 43 |
| 44 _StartingPoint(_Walker walker, this.sources) : super(walker, null); | 44 _StartingPoint(_Walker walker, this.sources) : super(walker, null); |
| 45 | 45 |
| 46 @override | 46 @override |
| 47 Future<List<_WalkerNode>> computeDependencies() async => | 47 Future<List<_WalkerNode>> computeDependencies() async => |
| 48 sources.map(walker.nodeForUri).toList(); | 48 sources.map(walker.nodeForUri).toList(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 class _Walker extends AsyncDependencyWalker<_WalkerNode> { | 51 class _Walker extends AsyncDependencyWalker<_WalkerNode> { |
| 52 final FileReader fileReader; | 52 final FileReader fileReader; |
| 53 final UriResolver uriResolver; | 53 final TranslateUri uriTranslator; |
| 54 final _nodesByUri = <Uri, _WalkerNode>{}; | 54 final _nodesByUri = <Uri, _WalkerNode>{}; |
| 55 final graph = new Graph(); | 55 final graph = new Graph(); |
| 56 final bool compileSdk; | 56 final bool compileSdk; |
| 57 | 57 |
| 58 _Walker(this.fileReader, this.uriResolver, this.compileSdk); | 58 _Walker(this.fileReader, this.uriTranslator, this.compileSdk); |
| 59 | 59 |
| 60 @override | 60 @override |
| 61 Future<Null> evaluate(_WalkerNode v) { | 61 Future<Null> evaluate(_WalkerNode v) { |
| 62 if (v is _StartingPoint) return new Future.value(); | 62 if (v is _StartingPoint) return new Future.value(); |
| 63 return evaluateScc([v]); | 63 return evaluateScc([v]); |
| 64 } | 64 } |
| 65 | 65 |
| 66 @override | 66 @override |
| 67 Future<Null> evaluateScc(List<_WalkerNode> scc) { | 67 Future<Null> evaluateScc(List<_WalkerNode> scc) { |
| 68 var cycle = new LibraryCycleNode(); | 68 var cycle = new LibraryCycleNode(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 87 final LibraryNode library; | 87 final LibraryNode library; |
| 88 | 88 |
| 89 _WalkerNode(this.walker, Uri uri) | 89 _WalkerNode(this.walker, Uri uri) |
| 90 : uri = uri, | 90 : uri = uri, |
| 91 library = new LibraryNode(uri); | 91 library = new LibraryNode(uri); |
| 92 | 92 |
| 93 @override | 93 @override |
| 94 Future<List<_WalkerNode>> computeDependencies() async { | 94 Future<List<_WalkerNode>> computeDependencies() async { |
| 95 var dependencies = <_WalkerNode>[]; | 95 var dependencies = <_WalkerNode>[]; |
| 96 // 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. |
| 97 var resolvedUri = walker.uriResolver.resolve(uri); | 97 var resolvedUri = |
| 98 uri.scheme == 'file' ? uri : walker.uriTranslator.translate(uri); |
| 98 if (resolvedUri == null) { | 99 if (resolvedUri == null) { |
| 99 // TODO(paulberry): If an error reporter was provided, report the error | 100 // TODO(paulberry): If an error reporter was provided, report the error |
| 100 // in the proper way and continue. | 101 // in the proper way and continue. |
| 101 throw new StateError('Invalid URI: $uri'); | 102 throw new StateError('Invalid URI: $uri'); |
| 102 } | 103 } |
| 103 var contents = await walker.fileReader(uri, resolvedUri); | 104 var contents = await walker.fileReader(uri, resolvedUri); |
| 104 var scannerResults = scanString(contents); | 105 var scannerResults = scanString(contents); |
| 105 // TODO(paulberry): report errors. | 106 // TODO(paulberry): report errors. |
| 106 var listener = new DirectiveListener(); | 107 var listener = new DirectiveListener(); |
| 107 new TopLevelParser(listener).parseUnit(scannerResults.tokens); | 108 new TopLevelParser(listener).parseUnit(scannerResults.tokens); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 130 for (var dep in listener.exports) { | 131 for (var dep in listener.exports) { |
| 131 handleDependency(uri.resolve(dep)); | 132 handleDependency(uri.resolve(dep)); |
| 132 } | 133 } |
| 133 | 134 |
| 134 if (!coreUriFound) { | 135 if (!coreUriFound) { |
| 135 handleDependency(dartCoreUri); | 136 handleDependency(dartCoreUri); |
| 136 } | 137 } |
| 137 return dependencies; | 138 return dependencies; |
| 138 } | 139 } |
| 139 } | 140 } |
| OLD | NEW |