Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: pkg/front_end/lib/dependency_grapher.dart

Issue 2617483007: Extract code from dependency_grapher.dart for easier re-use elsewhere in the front end. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/front_end/lib/src/dependency_grapher_impl.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 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 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:front_end/compiler_options.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/processed_options.dart'; 8 import 'package:front_end/src/base/processed_options.dart';
14 import 'package:front_end/src/base/uri_resolver.dart'; 9 import 'package:front_end/src/dependency_grapher_impl.dart' as impl;
15 import 'package:front_end/src/scanner/scanner.dart';
16
17 import 'compiler_options.dart';
18 10
19 /// Generates a representation of the dependency graph of a program. 11 /// Generates a representation of the dependency graph of a program.
20 /// 12 ///
21 /// Given the Uri of one or more files, this function follows `import`, 13 /// Given the Uri of one or more files, this function follows `import`,
22 /// `export`, and `part` declarations to discover a graph of all files involved 14 /// `export`, and `part` declarations to discover a graph of all files involved
23 /// in the program. 15 /// in the program.
24 Future<Graph> graphForProgram( 16 Future<Graph> graphForProgram(List<Uri> sources, CompilerOptions options) {
25 List<Uri> sources, CompilerOptions options) async {
26 var processedOptions = new ProcessedOptions(options); 17 var processedOptions = new ProcessedOptions(options);
27 var uriResolver = await processedOptions.getUriResolver(); 18 return impl.graphForProgram(sources, processedOptions);
28 var walker = new _Walker(processedOptions.fileSystem, uriResolver, processedOp tions.compileSdk);
29 var startingPoint = new _StartingPoint(walker, sources);
30 await walker.walk(startingPoint);
31 return walker.graph;
32 } 19 }
33 20
34 /// A representation of the dependency graph of a program. 21 /// A representation of the dependency graph of a program.
35 /// 22 ///
36 /// Not intended to be extended, implemented, or mixed in by clients. 23 /// Not intended to be extended, implemented, or mixed in by clients.
37 class Graph { 24 class Graph {
38 /// A list of all library cycles in the program, in topologically sorted order 25 /// A list of all library cycles in the program, in topologically sorted order
39 /// (each cycle only depends on libraries in the cycles that precede it). 26 /// (each cycle only depends on libraries in the cycles that precede it).
40 final topologicallySortedCycles = <LibraryCycleNode>[]; 27 final topologicallySortedCycles = <LibraryCycleNode>[];
41
42 Graph._();
43 } 28 }
44 29
45 /// A representation of a single library cycle in the dependency graph of a 30 /// A representation of a single library cycle in the dependency graph of a
46 /// program. 31 /// program.
47 /// 32 ///
48 /// Not intended to be extended, implemented, or mixed in by clients. 33 /// Not intended to be extended, implemented, or mixed in by clients.
49 class LibraryCycleNode { 34 class LibraryCycleNode {
50 /// A map of all the libraries in the cycle, keyed by the URI of their 35 /// A map of all the libraries in the cycle, keyed by the URI of their
51 /// defining compilation unit. 36 /// defining compilation unit.
52 final libraries = <Uri, LibraryNode>{}; 37 final libraries = <Uri, LibraryNode>{};
53
54 LibraryCycleNode._();
55 } 38 }
56 39
57 /// A representation of a single library in the dependency graph of a program. 40 /// A representation of a single library in the dependency graph of a program.
58 /// 41 ///
59 /// Not intended to be extended, implemented, or mixed in by clients. 42 /// Not intended to be extended, implemented, or mixed in by clients.
60 class LibraryNode { 43 class LibraryNode {
61 /// The URI of this library's defining compilation unit. 44 /// The URI of this library's defining compilation unit.
62 final Uri uri; 45 final Uri uri;
63 46
64 /// A list of the URIs of all of this library's "part" files. 47 /// A list of the URIs of all of this library's "part" files.
65 final parts = <Uri>[]; 48 final parts = <Uri>[];
66 49
67 /// A list of all the other libraries this library directly depends on. 50 /// A list of all the other libraries this library directly depends on.
68 final dependencies = <LibraryNode>[]; 51 final dependencies = <LibraryNode>[];
69 52
70 LibraryNode._(this.uri); 53 LibraryNode(this.uri);
71 } 54 }
72
73 class _Scanner extends Scanner {
74 _Scanner(String contents) : super(new CharSequenceReader(contents)) {
75 preserveComments = false;
76 }
77
78 @override
79 void reportError(errorCode, int offset, List<Object> arguments) {
80 // TODO(paulberry): report errors.
81 }
82 }
83
84 class _StartingPoint extends _WalkerNode {
85 final List<Uri> sources;
86
87 _StartingPoint(_Walker walker, this.sources) : super(walker, null);
88
89 @override
90 Future<List<_WalkerNode>> computeDependencies() async =>
91 sources.map(walker.nodeForUri).toList();
92 }
93
94 class _Walker extends AsyncDependencyWalker<_WalkerNode> {
95 final FileSystem fileSystem;
96 final UriResolver uriResolver;
97 final _nodesByUri = <Uri, _WalkerNode>{};
98 final graph = new Graph._();
99 final bool compileSdk;
100
101 _Walker(this.fileSystem, this.uriResolver, this.compileSdk);
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 static final dartCoreUri = Uri.parse('dart:core');
128 final _Walker walker;
129 final Uri uri;
130 final LibraryNode library;
131
132 _WalkerNode(this.walker, Uri uri)
133 : uri = uri,
134 library = new LibraryNode._(uri);
135
136 @override
137 Future<List<_WalkerNode>> computeDependencies() async {
138 var dependencies = <_WalkerNode>[];
139 // TODO(paulberry): add error recovery if the file can't be read.
140 var path = walker.uriResolver.resolve(uri);
141 if (path == null) {
142 // TODO(paulberry): If an error reporter was provided, report the error
143 // in the proper way and continue.
144 throw new StateError('Invalid URI: $uri');
145 }
146 var contents = await walker.fileSystem.entityForPath(path).readAsString();
147 var scanner = new _Scanner(contents);
148 var token = scanner.tokenize();
149 // TODO(paulberry): report errors.
150 var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
151 var unit = parser.parseDirectives(token);
152 bool coreUriFound = false;
153 void handleDependency(Uri referencedUri) {
154 _WalkerNode dependencyNode = walker.nodeForUri(referencedUri);
155 library.dependencies.add(dependencyNode.library);
156 if (referencedUri.scheme != 'dart' || walker.compileSdk) {
157 dependencies.add(dependencyNode);
158 }
159 if (referencedUri == dartCoreUri) {
160 coreUriFound = true;
161 }
162 }
163
164 for (var directive in unit.directives) {
165 if (directive is UriBasedDirective) {
166 // TODO(paulberry): when we support SDK libraries, we'll need more
167 // complex logic here to find SDK parts correctly.
168 var referencedUri = uri.resolve(directive.uri.stringValue);
169 if (directive is PartDirective) {
170 library.parts.add(referencedUri);
171 } else {
172 handleDependency(referencedUri);
173 }
174 }
175 }
176 if (!coreUriFound) {
177 handleDependency(dartCoreUri);
178 }
179 return dependencies;
180 }
181 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/lib/src/dependency_grapher_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698