Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 import 'dart:async'; | |
| 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/file_system.dart'; | |
| 12 import 'package:front_end/src/async_dependency_walker.dart'; | |
| 13 import 'package:front_end/src/base/uri_resolver.dart'; | |
| 14 import 'package:front_end/src/scanner/scanner.dart'; | |
| 15 | |
| 16 import 'compiler_options.dart'; | |
| 17 | |
| 18 /// Generates a representation of the dependency graph of a program. | |
| 19 /// | |
| 20 /// 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 | |
| 22 /// in the program. | |
| 23 Future<Graph> graphForProgram( | |
| 24 List<Uri> sources, CompilerOptions options) async { | |
| 25 var packages = <String, Uri>{}; // TODO(paulberry): support packages | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
should we have a "digested options" at some point
Paul Berry
2016/12/16 02:46:45
Perhaps, I'm not sure yet. I kind of want to fill
| |
| 26 var sdkLibraries = <String, Uri>{}; // TODO(paulberry): support SDK libraries | |
| 27 var uriResolver = | |
| 28 new UriResolver(packages, sdkLibraries, options.fileSystem.context); | |
| 29 var walker = new _Walker(options.fileSystem, uriResolver); | |
| 30 var startingPoint = new _StartingPoint(walker, sources); | |
| 31 await walker.walk(startingPoint); | |
| 32 return walker.graph; | |
| 33 } | |
| 34 | |
| 35 /// A representation of the dependency graph of a program. | |
| 36 /// | |
| 37 /// Not intended to be extended, implemented, or mixed in by clients. | |
| 38 class Graph { | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
as we start looking into integrating alternative i
Paul Berry
2016/12/16 02:46:45
Acknowledged.
| |
| 39 /// A list of all library cycles in the program, in topologically sorted order | |
| 40 /// (each cycle only depends on libraries in the cycles that precede it). | |
| 41 final topologicallySortedCycles = <LibraryCycleNode>[]; | |
| 42 | |
| 43 Graph._(); | |
| 44 } | |
| 45 | |
| 46 /// A representation of a single library cycle in the dependency graph of a | |
| 47 /// program. | |
| 48 /// | |
| 49 /// Not intended to be extended, implemented, or mixed in by clients. | |
| 50 class LibraryCycleNode { | |
| 51 /// A map of all the libraries in the program, keyed by the URI of their | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
all libraries in the program or in the cycle?
Paul Berry
2016/12/16 02:46:45
Whoops, I meant to say "in the cycle". Fixed.
| |
| 52 /// defining compilation unit. | |
| 53 final libraries = <Uri, LibraryNode>{}; | |
| 54 | |
| 55 LibraryCycleNode._(); | |
| 56 } | |
| 57 | |
| 58 /// A representation of a single library in the dependency graph of a program. | |
| 59 /// | |
| 60 /// Not intended to be extended, implemented, or mixed in by clients. | |
| 61 class LibraryNode { | |
| 62 /// A list of all the other libraries this library directly depends on. | |
| 63 final dependencies = <LibraryNode>[]; | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
do we want to split imports and exports or in gene
Paul Berry
2016/12/16 02:46:45
My intuition is no--any client that needs to disti
| |
| 64 | |
| 65 /// A list of the URIs of all of this library's "part" files. | |
| 66 final parts = <Uri>[]; | |
| 67 | |
| 68 /// The URI of this library's defining compilation unit. | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
you may be using an alphabetic order, but I rather
Paul Berry
2016/12/16 02:46:45
Done.
| |
| 69 final Uri uri; | |
| 70 | |
| 71 LibraryNode._(this.uri); | |
| 72 } | |
| 73 | |
| 74 class _Scanner extends Scanner { | |
| 75 _Scanner(String contents) : super(new CharSequenceReader(contents)) { | |
| 76 preserveComments = false; | |
| 77 } | |
| 78 | |
| 79 @override | |
| 80 void reportError(errorCode, int offset, List<Object> arguments) { | |
| 81 // TODO(paulberry): report errors. | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 class _StartingPoint extends _WalkerNode { | |
| 86 final List<Uri> sources; | |
| 87 | |
| 88 _StartingPoint(_Walker walker, this.sources) : super(walker, null); | |
| 89 | |
| 90 @override | |
| 91 Future<List<_WalkerNode>> computeDependencies() async => | |
| 92 sources.map(walker.nodeForUri).toList(); | |
| 93 } | |
| 94 | |
| 95 class _Walker extends AsyncDependencyWalker<_WalkerNode> { | |
| 96 final FileSystem fileSystem; | |
| 97 final UriResolver uriResolver; | |
| 98 final _nodesByUri = <Uri, _WalkerNode>{}; | |
| 99 final graph = new Graph._(); | |
| 100 | |
| 101 _Walker(this.fileSystem, this.uriResolver); | |
| 102 | |
| 103 @override | |
| 104 Future<Null> evaluate(_WalkerNode v) { | |
| 105 if (v is _StartingPoint) return new Future.value(); | |
| 106 return evaluateScc([v]); | |
| 107 } | |
| 108 | |
| 109 @override | |
| 110 Future<Null> evaluateScc(List<_WalkerNode> scc) { | |
| 111 var cycle = new LibraryCycleNode._(); | |
| 112 for (var walkerNode in scc) { | |
| 113 cycle.libraries[walkerNode.uri] = walkerNode.library; | |
| 114 } | |
| 115 graph.topologicallySortedCycles.add(cycle); | |
| 116 return new Future.value(); | |
| 117 } | |
| 118 | |
| 119 _WalkerNode nodeForUri(Uri referencedUri) { | |
| 120 var dependencyNode = _nodesByUri.putIfAbsent( | |
| 121 referencedUri, () => new _WalkerNode(this, referencedUri)); | |
| 122 return dependencyNode; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 class _WalkerNode extends Node<_WalkerNode> { | |
| 127 final _Walker walker; | |
| 128 final Uri uri; | |
| 129 final LibraryNode library; | |
| 130 | |
| 131 _WalkerNode(this.walker, Uri uri) | |
| 132 : uri = uri, | |
| 133 library = new LibraryNode._(uri); | |
| 134 | |
| 135 @override | |
| 136 Future<List<_WalkerNode>> computeDependencies() async { | |
| 137 var dependencies = <_WalkerNode>[]; | |
| 138 // TODO(paulberry): add error recovery if the file can't be read. | |
| 139 var contents = await walker.fileSystem | |
| 140 .entityForPath(walker.uriResolver.resolve(uri)) | |
| 141 .readAsString(); | |
| 142 var scanner = new _Scanner(contents); | |
| 143 var token = scanner.tokenize(); | |
| 144 // TODO(paulberry): report errors. | |
| 145 var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER); | |
| 146 var unit = parser.parseDirectives(token); | |
|
Siggi Cherem (dart-lang)
2016/12/15 23:51:33
I'm OK delaying this until later to avoid over-eng
Paul Berry
2016/12/16 02:46:45
Acknowledged.
| |
| 147 for (var directive in unit.directives) { | |
| 148 if (directive is UriBasedDirective) { | |
| 149 // TODO(paulberry): when we support SDK libraries, we'll need more | |
| 150 // complex logic here to find SDK parts correctly. | |
| 151 var referencedUri = uri.resolve(directive.uri.stringValue); | |
| 152 if (directive is PartDirective) { | |
| 153 library.parts.add(referencedUri); | |
| 154 } else { | |
| 155 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri); | |
| 156 dependencies.add(dependencyNode); | |
| 157 library.dependencies.add(dependencyNode.library); | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 return dependencies; | |
| 162 } | |
| 163 } | |
| OLD | NEW |