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

Side by Side Diff: pkg/fasta/lib/src/source/source_loader.dart

Issue 2623033007: Fasta targets and loaders. (Closed)
Patch Set: Address review comments. 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 | « pkg/fasta/lib/src/loader.dart ('k') | pkg/fasta/lib/testing/suite.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 library fasta.source_loader;
6
7 import 'dart:async' show
8 Future;
9
10 import 'dart:io' show
11 FileSystemException;
12
13 import 'package:dart_scanner/io.dart' show
14 readBytesFromFile;
15
16 import 'package:dart_scanner/src/token.dart' show
17 Token;
18
19 import 'package:dart_scanner/dart_scanner.dart' show
20 scan;
21
22 import 'package:dart_parser/src/class_member_parser.dart' show
23 ClassMemberParser;
24
25 import 'package:kernel/ast.dart' show
26 Program;
27
28 import 'package:kernel/class_hierarchy.dart' show
29 ClassHierarchy;
30
31 import 'package:kernel/core_types.dart' show
32 CoreTypes;
33
34 import '../errors.dart' show
35 inputError;
36
37 import '../export.dart' show
38 Export;
39
40 import '../analyzer/element_store.dart' show
41 ElementStore;
42
43 import '../builder/builder.dart' show
44 Builder,
45 ClassBuilder,
46 LibraryBuilder;
47
48 import 'outline_builder.dart' show
49 OutlineBuilder;
50
51 import '../loader.dart' show
52 Loader;
53
54 import '../target_implementation.dart' show
55 TargetImplementation;
56
57 import 'diet_listener.dart' show
58 DietListener;
59
60 import 'diet_parser.dart' show
61 DietParser;
62
63 import 'source_library_builder.dart' show
64 SourceLibraryBuilder;
65
66 import '../ast_kind.dart' show
67 AstKind;
68
69 class SourceLoader<L> extends Loader<L> {
70 // Used when building directly to kernel.
71 ClassHierarchy hierarchy;
72 CoreTypes coreTypes;
73
74 // Used when building analyzer ASTs.
75 ElementStore elementStore;
76
77 SourceLoader(TargetImplementation target)
78 : super(target);
79
80 Future<Token> tokenize(SourceLibraryBuilder library) async {
81 Uri uri = library.uri;
82 if (uri.scheme != "file") {
83 uri = target.translateUri(uri);
84 if (uri == null) {
85 print("Skipping ${library.uri}");
86 return null;
87 }
88 library.fileUri = uri;
89 }
90 try {
91 List<int> bytes = await readBytesFromFile(uri);
92 byteCount += bytes.length - 1;
93 return scan(bytes).tokens;
94 } on FileSystemException catch (e) {
95 String message = e.message;
96 String osMessage = e.osError?.message;
97 if (osMessage != null && osMessage.isNotEmpty) {
98 message = osMessage;
99 }
100 return inputError(uri, -1, message);
101 }
102 }
103
104 Future<Null> buildOutline(SourceLibraryBuilder library) async {
105 Token tokens = await tokenize(library);
106 if (tokens == null) return;
107 OutlineBuilder listener = new OutlineBuilder(library);
108 new ClassMemberParser(listener).parseUnit(tokens);
109 }
110
111 Future<Null> buildBody(LibraryBuilder library, AstKind astKind) async {
112 if (library is SourceLibraryBuilder) {
113 Token tokens = await tokenize(library);
114 if (tokens == null) return;
115 DietListener listener = new DietListener(
116 library, elementStore, hierarchy, coreTypes, astKind);
117 DietParser parser = new DietParser(listener);
118 parser.parseUnit(tokens);
119 for (SourceLibraryBuilder part in library.parts) {
120 Token tokens = await tokenize(part);
121 if (tokens != null) {
122 parser.parseUnit(tokens);
123 }
124 }
125 }
126 }
127
128 void resolveParts() {
129 List<Uri> parts = <Uri>[];
130 builders.forEach((Uri uri, LibraryBuilder library) {
131 if (library is SourceLibraryBuilder) {
132 if (library.isPart) {
133 library.validatePart();
134 parts.add(uri);
135 } else {
136 library.includeParts();
137 }
138 }
139 });
140 parts.forEach(builders.remove);
141 ticker.logMs("Resolved parts");
142 }
143
144 void computeLibraryScopes() {
145 Set<LibraryBuilder> exporters = new Set<LibraryBuilder>();
146 Set<LibraryBuilder> exportees = new Set<LibraryBuilder>();
147 builders.forEach((Uri uri, LibraryBuilder library) {
148 if (library is SourceLibraryBuilder) {
149 library.buildInitialScopes();
150 }
151 if (library.exporters.isNotEmpty) {
152 exportees.add(library);
153 for (Export exporter in library.exporters) {
154 exporters.add(exporter.exporter);
155 }
156 }
157 });
158 Set<SourceLibraryBuilder> both = new Set<SourceLibraryBuilder>();
159 for (LibraryBuilder exported in exportees) {
160 if (exporters.contains(exported)) {
161 both.add(exported);
162 }
163 for (Export export in exported.exporters) {
164 exported.exports.forEach(export.addToExportScope);
165 }
166 }
167 bool wasChanged = false;
168 do {
169 wasChanged = false;
170 for (SourceLibraryBuilder exported in both) {
171 for (Export export in exported.exporters) {
172 SourceLibraryBuilder exporter = export.exporter;
173 exported.exports.forEach((String name, Builder member) {
174 if (exporter.addToExportScope(name, member)) {
175 wasChanged = true;
176 }
177 });
178 }
179 }
180 } while (wasChanged);
181 builders.forEach((Uri uri, LibraryBuilder library) {
182 if (library is SourceLibraryBuilder) {
183 library.addImportsToScope();
184 }
185 });
186 ticker.logMs("Computed library scopes");
187 // debugPrintExports();
188 }
189
190 void debugPrintExports() {
191 builders.forEach((Uri uri, SourceLibraryBuilder library) {
192 Set<Builder> members = new Set<Builder>();
193 library.members.forEach((String name, Builder member) {
194 while (member != null) {
195 members.add(member);
196 member = member.next;
197 }
198 });
199 List<String> exports = <String>[];
200 library.exports.forEach((String name, Builder member) {
201 while (member != null) {
202 if (!members.contains(member)) {
203 exports.add(name);
204 }
205 member = member.next;
206 }
207 });
208 if (exports.isNotEmpty) {
209 print("$uri exports $exports");
210 }
211 });
212 }
213
214 void resolveTypes() {
215 int typeCount = 0;
216 builders.forEach((Uri uri, LibraryBuilder library) {
217 typeCount += library.resolveTypes(null);
218 });
219 ticker.logMs("Resolved $typeCount types");
220 }
221
222 void convertConstructors() {
223 int count = 0;
224 builders.forEach((Uri uri, LibraryBuilder library) {
225 count += library.convertConstructors(null);
226 });
227 ticker.logMs("Converted $count constructors");
228 }
229
230 void finishStaticInvocations() {
231 int count = 0;
232 builders.forEach((Uri uri, LibraryBuilder library) {
233 count += library.finishStaticInvocations();
234 });
235 ticker.logMs("Finished static invocations $count");
236 }
237
238 void resolveConstructors() {
239 int count = 0;
240 builders.forEach((Uri uri, LibraryBuilder library) {
241 count += library.resolveConstructors(null);
242 });
243 ticker.logMs("Resolved $count constructors");
244 }
245
246 /// Returns all the supertypes (including interfaces) of [cls]
247 /// transitively. Includes [cls].
248 Set<ClassBuilder> allSupertypes(ClassBuilder cls) {
249 int length = 0;
250 Set<ClassBuilder> result = new Set<ClassBuilder>()..add(cls);
251 while (length != result.length) {
252 length = result.length;
253 result.addAll(directSupertypes(result));
254 }
255 return result;
256 }
257
258 /// Returns the direct supertypes (including interface) of [classes]. A class
259 /// from [classes] is only included if it is a supertype of one of the other
260 /// classes in [classes].
261 Set<ClassBuilder> directSupertypes(Iterable<ClassBuilder> classes) {
262 Set<ClassBuilder> result = new Set<ClassBuilder>();
263 for (ClassBuilder cls in classes) {
264 target.addDirectSupertype(cls, result);
265 }
266 return result;
267 }
268
269 /// Computes a set of classes that may have cycles. The set is empty if there
270 /// are no cycles. If the set isn't empty, it will include supertypes of
271 /// classes with cycles, as well as the classes with cycles.
272 ///
273 /// It is assumed that [classes] is a transitive closure with respect to
274 /// supertypes.
275 Iterable<ClassBuilder> cyclicCandidates(Iterable<ClassBuilder> classes) {
276 // The candidates are found by a fixed-point computation.
277 //
278 // On each iteration, the classes that have no supertypes in the input set
279 // will be removed.
280 //
281 // If there are no cycles, eventually, the set will converge on Object, and
282 // the next iteration will make the set empty (as Object has no
283 // supertypes).
284 //
285 // On the other hand, if there is a cycle, the cycle will remain in the
286 // set, and so will its supertypes, and eventually the input and output set
287 // will have the same length.
288 Iterable<ClassBuilder> input = const [];
289 Iterable<ClassBuilder> output = classes;
290 while (input.length != output.length) {
291 input = output;
292 output = directSupertypes(input);
293 }
294 return output;
295 }
296
297 void checkSemantics() {
298 List<ClassBuilder> allClasses = target.collectAllClasses();
299 Iterable<ClassBuilder> candidates = cyclicCandidates(allClasses);
300 Map<ClassBuilder, Set<ClassBuilder>> realCycles =
301 <ClassBuilder, Set<ClassBuilder>>{};
302 for (ClassBuilder cls in candidates) {
303 Set<ClassBuilder> cycles = cyclicCandidates(allSupertypes(cls));
304 if (cycles.isNotEmpty) {
305 realCycles[cls] = cycles;
306 }
307 }
308 Set<ClassBuilder> reported = new Set<ClassBuilder>();
309 realCycles.forEach((ClassBuilder cls, Set<ClassBuilder> cycles) {
310 target.breakCycle(cls);
311 if (reported.add(cls)) {
312 List<ClassBuilder> involved = <ClassBuilder>[];
313 for (ClassBuilder cls in cycles) {
314 if (realCycles.containsKey(cls)) {
315 involved.add(cls);
316 reported.add(cls);
317 }
318 }
319 print("${cls.name} is a supertype of itself via "
320 "${involved.map((c) => c.name).join(' ')}");
321 }
322 });
323 ticker.logMs("Found cycles");
324 }
325
326 void buildProgram() {
327 builders.forEach((Uri uri, LibraryBuilder library) {
328 if (library is SourceLibraryBuilder) {
329 libraries.add(library.build());
330 }
331 });
332 ticker.logMs("Built program");
333 }
334
335 void buildElementStore() {
336 elementStore = new ElementStore(coreLibrary, builders);
337 ticker.logMs("Built analyzer element model.");
338 }
339
340 void computeHierarchy(Program program) {
341 hierarchy = new ClassHierarchy(program);
342 ticker.logMs("Computed class hierarchy");
343 coreTypes = new CoreTypes(program);
344 ticker.logMs("Computed core types");
345 }
346 }
OLDNEW
« no previous file with comments | « pkg/fasta/lib/src/loader.dart ('k') | pkg/fasta/lib/testing/suite.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698