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

Side by Side Diff: pkg/compiler/lib/src/library_loader.dart

Issue 1819053002: Split loader from the rest of the compiler. This adds several abstractions to (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: add environment.dart Created 4 years, 9 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 library dart2js.library_loader; 5 library dart2js.library_loader;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'common.dart'; 9 import 'common.dart';
10 import 'common/names.dart' show 10 import 'common/names.dart' show
(...skipping 12 matching lines...) Expand all
23 import 'elements/modelx.dart' show 23 import 'elements/modelx.dart' show
24 CompilationUnitElementX, 24 CompilationUnitElementX,
25 DeferredLoaderGetterElementX, 25 DeferredLoaderGetterElementX,
26 ErroneousElementX, 26 ErroneousElementX,
27 ExportElementX, 27 ExportElementX,
28 ImportElementX, 28 ImportElementX,
29 LibraryElementX, 29 LibraryElementX,
30 LibraryDependencyElementX, 30 LibraryDependencyElementX,
31 PrefixElementX, 31 PrefixElementX,
32 SyntheticImportElement; 32 SyntheticImportElement;
33 33 import 'environment.dart';
34 import 'script.dart'; 34 import 'script.dart';
35 import 'serialization/serialization.dart' show LibraryDeserializer;
35 import 'tree/tree.dart'; 36 import 'tree/tree.dart';
36 import 'util/util.dart' show 37 import 'util/util.dart' show
37 Link, 38 Link,
38 LinkBuilder; 39 LinkBuilder;
39 40
40 /** 41 /**
41 * [CompilerTask] for loading libraries and setting up the import/export scopes. 42 * [CompilerTask] for loading libraries and setting up the import/export scopes.
42 * 43 *
43 * The library loader uses four different kinds of URIs in different parts of 44 * The library loader uses four different kinds of URIs in different parts of
44 * the loading process. 45 * the loading process.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 * as when loaded through the dart URI. 99 * as when loaded through the dart URI.
99 * 100 *
100 * ## Readable URI ## 101 * ## Readable URI ##
101 * 102 *
102 * A 'readable URI' is an absolute URI whose scheme is either 'package' or 103 * A 'readable URI' is an absolute URI whose scheme is either 'package' or
103 * something supported by the input provider, normally 'file'. Dart URIs such as 104 * something supported by the input provider, normally 'file'. Dart URIs such as
104 * 'dart:core' and 'dart:_js_helper' are not readable themselves but are instead 105 * 'dart:core' and 'dart:_js_helper' are not readable themselves but are instead
105 * resolved into a readable URI using the library root URI provided from the 106 * resolved into a readable URI using the library root URI provided from the
106 * command line and the list of platform libraries found in 107 * command line and the list of platform libraries found in
107 * 'sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'. This is done 108 * 'sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'. This is done
108 * through the [Compiler.translateResolvedUri] method which checks whether a 109 * through a [ResolvedUriTranslator] provided from the compiler. The translator
109 * library by that name exists and in case of internal libraries whether access 110 * checks whether a library by that name exists and in case of internal
110 * is granted. 111 * libraries whether access is granted.
111 * 112 *
112 * ## Resource URI ## 113 * ## Resource URI ##
113 * 114 *
114 * A 'resource URI' is an absolute URI with a scheme supported by the input 115 * A 'resource URI' is an absolute URI with a scheme supported by the input
115 * provider. For the standard implementation this means a URI with the 'file' 116 * provider. For the standard implementation this means a URI with the 'file'
116 * scheme. Readable URIs are converted into resource URIs as part of the 117 * scheme. Readable URIs are converted into resource URIs as part of the
117 * [Compiler.readScript] method. In the standard implementation the package URIs 118 * [Compiler.readScript] method. In the standard implementation the package URIs
118 * are converted to file URIs using the package root URI provided on the 119 * are converted to file URIs using the package root URI provided on the
119 * command line as base. If the package root URI is 120 * command line as base. If the package root URI is
120 * 'file:///current/working/dir/' then the package URI 'package:foo/bar.dart' 121 * 'file:///current/working/dir/' then the package URI 'package:foo/bar.dart'
121 * will be resolved to the resource URI 122 * will be resolved to the resource URI
122 * 'file:///current/working/dir/foo/bar.dart'. 123 * 'file:///current/working/dir/foo/bar.dart'.
123 * 124 *
124 * The distinction between readable URI and resource URI is necessary to ensure 125 * The distinction between readable URI and resource URI is necessary to ensure
125 * that these imports 126 * that these imports
126 * 127 *
127 * import 'package:foo.dart' as a; 128 * import 'package:foo.dart' as a;
128 * import 'packages/foo.dart' as b; 129 * import 'packages/foo.dart' as b;
129 * 130 *
130 * do _not_ resolve to the same library when the package root URI happens to 131 * do _not_ resolve to the same library when the package root URI happens to
131 * point to the 'packages' folder. 132 * point to the 'packages' folder.
132 * 133 *
133 */ 134 */
134 abstract class LibraryLoaderTask implements CompilerTask { 135 abstract class LibraryLoaderTask implements CompilerTask {
135 factory LibraryLoaderTask(Compiler compiler) = _LibraryLoaderTask; 136 factory LibraryLoaderTask(Compiler compiler,
137 ResolvedUriTranslator uriTranslator,
138 ScriptLoader scriptLoader,
139 ElementScanner scriptScanner,
140 LibraryDeserializer deserializer,
141 LibraryLoaderListener listener,
142 Environment environment) = _LibraryLoaderTask;
136 143
137 /// Returns all libraries that have been loaded. 144 /// Returns all libraries that have been loaded.
138 Iterable<LibraryElement> get libraries; 145 Iterable<LibraryElement> get libraries;
139 146
140 /// Looks up the library with the [canonicalUri]. 147 /// Looks up the library with the [canonicalUri].
141 LibraryElement lookupLibrary(Uri canonicalUri); 148 LibraryElement lookupLibrary(Uri canonicalUri);
142 149
143 /// Loads the library specified by the [resolvedUri] and returns its 150 /// Loads the library specified by the [resolvedUri] and returns its
144 /// [LibraryElement]. 151 /// [LibraryElement].
145 /// 152 ///
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 * A list of combinators represented as a list of element names to exclude. 259 * A list of combinators represented as a list of element names to exclude.
253 */ 260 */
254 class HideFilter extends CombinatorFilter { 261 class HideFilter extends CombinatorFilter {
255 final Set<String> excludedNames; 262 final Set<String> excludedNames;
256 263
257 HideFilter(this.excludedNames); 264 HideFilter(this.excludedNames);
258 265
259 bool exclude(Element element) => excludedNames.contains(element.name); 266 bool exclude(Element element) => excludedNames.contains(element.name);
260 } 267 }
261 268
262 /** 269 /// Implementation class for [LibraryLoaderTask]. The distinction between
263 * Implementation class for [LibraryLoader]. The distinction between 270 /// [LibraryLoaderTask] and [_LibraryLoaderTask] is made to hide internal
264 * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from 271 /// members from the [LibraryLoaderTask] interface.
265 * the [LibraryLoader] interface.
266 */
267 class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask { 272 class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
268 _LibraryLoaderTask(Compiler compiler) : super(compiler); 273 /// Translates interal uris (like dart:core) to a disk location.
Harry Terkelsen 2016/03/22 21:49:28 s/interal/internal/
Siggi Cherem (dart-lang) 2016/03/23 22:51:05 Done.
274 final ResolvedUriTranslator uriTranslator;
275
276 /// Loads the contents of a a script file (a .dart file). Used when loading
Harry Terkelsen 2016/03/22 21:49:28 s/a a/a/
Siggi Cherem (dart-lang) 2016/03/23 22:51:05 Done.
277 /// libraries from source.
278 final ScriptLoader scriptLoader;
279
280 /// Provides a diet element model from a script file containing information
281 /// about imports and exports. Used when loading libraries from source.
282 final ElementScanner scanner;
283
284 /// Provides a diet element model for a library. Used when loading libraries
285 /// from a serialized form.
286 final LibraryDeserializer deserializer;
287
288 /// Hooks to inform others about progress done by this loader.
289 // TODO(sigmund): move away from this.
290 final LibraryLoaderListener listener;
291
292 /// Definitions provided via the `-D` command line flags. Used to resolve
293 /// conditional imports.
294 final Environment environment;
295
296 _LibraryLoaderTask(
297 Compiler compiler, this.uriTranslator, this.scriptLoader,
298 this.scanner, this.deserializer, this.listener, this.environment)
299 // TODO(sigmund): make measurements separate from compiler
300 : super(compiler);
269 301
270 String get name => 'LibraryLoader'; 302 String get name => 'LibraryLoader';
271 303
272 final Map<Uri, LibraryElement> libraryCanonicalUriMap = 304 final Map<Uri, LibraryElement> libraryCanonicalUriMap =
273 new Map<Uri, LibraryElement>(); 305 new Map<Uri, LibraryElement>();
274 final Map<Uri, LibraryElement> libraryResourceUriMap = 306 final Map<Uri, LibraryElement> libraryResourceUriMap =
275 new Map<Uri, LibraryElement>(); 307 new Map<Uri, LibraryElement>();
276 final Map<String, LibraryElement> libraryNames = 308 final Map<String, LibraryElement> libraryNames =
277 new Map<String, LibraryElement>(); 309 new Map<String, LibraryElement>();
278 310
279 LibraryDependencyHandler currentHandler; 311 LibraryDependencyHandler currentHandler;
280 312
281 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values; 313 Iterable<LibraryElement> get libraries => libraryCanonicalUriMap.values;
282 314
283 LibraryElement lookupLibrary(Uri canonicalUri) { 315 LibraryElement lookupLibrary(Uri canonicalUri) {
284 return libraryCanonicalUriMap[canonicalUri]; 316 return libraryCanonicalUriMap[canonicalUri];
285 } 317 }
286 318
287 void reset({bool reuseLibrary(LibraryElement library)}) { 319 void reset({bool reuseLibrary(LibraryElement library)}) {
288 measure(() { 320 measure(() {
289 assert(currentHandler == null); 321 assert(currentHandler == null);
290 322
291 Iterable<LibraryElement> reusedLibraries = null; 323 Iterable<LibraryElement> reusedLibraries = null;
292 if (reuseLibrary != null) { 324 if (reuseLibrary != null) {
325 // TODO(sigmund): make measurements separate from compiler
293 reusedLibraries = compiler.reuseLibraryTask.measure(() { 326 reusedLibraries = compiler.reuseLibraryTask.measure(() {
294 // Call [toList] to force eager calls to [reuseLibrary]. 327 // Call [toList] to force eager calls to [reuseLibrary].
295 return libraryCanonicalUriMap.values.where(reuseLibrary).toList(); 328 return libraryCanonicalUriMap.values.where(reuseLibrary).toList();
296 }); 329 });
297 } 330 }
298 331
299 resetImplementation(reusedLibraries); 332 resetImplementation(reusedLibraries);
300 }); 333 });
301 } 334 }
302 335
303 void resetImplementation(Iterable<LibraryElement> reusedLibraries) { 336 void resetImplementation(Iterable<LibraryElement> reusedLibraries) {
304 measure(() { 337 measure(() {
305 libraryCanonicalUriMap.clear(); 338 libraryCanonicalUriMap.clear();
306 libraryResourceUriMap.clear(); 339 libraryResourceUriMap.clear();
307 libraryNames.clear(); 340 libraryNames.clear();
308 341
309 if (reusedLibraries != null) { 342 if (reusedLibraries != null) {
310 reusedLibraries.forEach(mapLibrary); 343 reusedLibraries.forEach(mapLibrary);
311 } 344 }
312 }); 345 });
313 } 346 }
314 347
315 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) { 348 Future resetAsync(Future<bool> reuseLibrary(LibraryElement library)) {
316 return measure(() { 349 return measure(() {
317 assert(currentHandler == null); 350 assert(currentHandler == null);
318 351
319 Future<LibraryElement> wrapper(LibraryElement library) { 352 wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null);
320 try {
321 return reuseLibrary(library).then(
322 (bool reuse) => reuse ? library : null);
323 } catch (exception, trace) {
324 compiler.diagnoseCrashInUserCode(
325 'Uncaught exception in reuseLibrary', exception, trace);
326 rethrow;
327 }
328 }
329
330 List<Future<LibraryElement>> reusedLibrariesFuture = 353 List<Future<LibraryElement>> reusedLibrariesFuture =
354 // TODO(sigmund): make measurements separate from compiler
331 compiler.reuseLibraryTask.measure( 355 compiler.reuseLibraryTask.measure(
332 () => libraryCanonicalUriMap.values.map(wrapper).toList()); 356 () => libraryCanonicalUriMap.values.map(wrapper).toList());
333 357
334 return Future.wait(reusedLibrariesFuture).then( 358 return Future.wait(reusedLibrariesFuture).then(
335 (List<LibraryElement> reusedLibraries) { 359 (List<LibraryElement> reusedLibraries) {
336 resetImplementation(reusedLibraries.where((e) => e != null)); 360 resetImplementation(reusedLibraries.where((e) => e != null));
337 }); 361 });
338 }); 362 });
339 } 363 }
340 364
341 /// Insert [library] in the internal maps. Used for compiler reuse. 365 /// Insert [library] in the internal maps. Used for compiler reuse.
342 void mapLibrary(LibraryElement library) { 366 void mapLibrary(LibraryElement library) {
343 libraryCanonicalUriMap[library.canonicalUri] = library; 367 libraryCanonicalUriMap[library.canonicalUri] = library;
344 368
345 Uri resourceUri = library.entryCompilationUnit.script.resourceUri; 369 Uri resourceUri = library.entryCompilationUnit.script.resourceUri;
346 libraryResourceUriMap[resourceUri] = library; 370 libraryResourceUriMap[resourceUri] = library;
347 371
348 if (library.hasLibraryName) { 372 if (library.hasLibraryName) {
349 String name = library.libraryName; 373 String name = library.libraryName;
350 libraryNames[name] = library; 374 libraryNames[name] = library;
351 } 375 }
352 } 376 }
353 377
354 Future<LibraryElement> loadLibrary( 378 Future<LibraryElement> loadLibrary(Uri resolvedUri,
355 Uri resolvedUri,
356 {bool skipFileWithPartOfTag: false}) { 379 {bool skipFileWithPartOfTag: false}) {
357 return measure(() { 380 return measure(() {
358 assert(currentHandler == null); 381 assert(currentHandler == null);
359 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the 382 // TODO(johnniwinther): Ensure that currentHandler correctly encloses the
360 // loading of a library cluster. 383 // loading of a library cluster.
361 currentHandler = new LibraryDependencyHandler(this); 384 currentHandler = new LibraryDependencyHandler(this);
362 return createLibrary(currentHandler, null, resolvedUri, 385 return createLibrary(currentHandler, null, resolvedUri,
363 skipFileWithPartOfTag: skipFileWithPartOfTag) 386 skipFileWithPartOfTag: skipFileWithPartOfTag)
364 .then((LibraryElement library) { 387 .then((LibraryElement library) {
365 if (library == null) { 388 if (library == null) {
366 currentHandler = null; 389 currentHandler = null;
367 return null; 390 return null;
368 } 391 }
369 return reporter.withCurrentElement(library, () { 392 return reporter.withCurrentElement(library, () {
370 return measure(() { 393 return measure(() {
371 currentHandler.computeExports(); 394 currentHandler.computeExports();
372 LoadedLibraries loadedLibraries = new _LoadedLibraries( 395 LoadedLibraries loadedLibraries = new _LoadedLibraries(
373 library, 396 library,
374 currentHandler.newLibraries, 397 currentHandler.newLibraries,
375 currentHandler.nodeMap, 398 currentHandler.nodeMap,
376 this); 399 this);
377 currentHandler = null; 400 currentHandler = null;
378 return compiler.onLibrariesLoaded(loadedLibraries) 401 return listener.onLibrariesLoaded(loadedLibraries)
379 .then((_) => library); 402 .then((_) => library);
380 }); 403 });
381 }); 404 });
382 }); 405 });
383 }); 406 });
384 } 407 }
385 408
386 /** 409 /**
387 * Processes the library tags in [library]. 410 * Processes the library tags in [library].
388 * 411 *
(...skipping 13 matching lines...) Expand all
402 return reporter.withCurrentElement(library, () { 425 return reporter.withCurrentElement(library, () {
403 426
404 Uri computeUri(LibraryDependency node) { 427 Uri computeUri(LibraryDependency node) {
405 StringNode uriNode = node.uri; 428 StringNode uriNode = node.uri;
406 if (node.conditionalUris != null) { 429 if (node.conditionalUris != null) {
407 for (ConditionalUri conditionalUri in node.conditionalUris) { 430 for (ConditionalUri conditionalUri in node.conditionalUris) {
408 String key = conditionalUri.key.slowNameString; 431 String key = conditionalUri.key.slowNameString;
409 String value = conditionalUri.value == null 432 String value = conditionalUri.value == null
410 ? "true" 433 ? "true"
411 : conditionalUri.value.dartString.slowToString(); 434 : conditionalUri.value.dartString.slowToString();
412 String actual = compiler.fromEnvironment(key); 435 String actual = environment.valueOf(key);
413 if (value == actual) { 436 if (value == actual) {
414 uriNode = conditionalUri.uri; 437 uriNode = conditionalUri.uri;
415 break; 438 break;
416 } 439 }
417 } 440 }
418 } 441 }
419 String tagUriString = uriNode.dartString.slowToString(); 442 String tagUriString = uriNode.dartString.slowToString();
420 try { 443 try {
421 return Uri.parse(tagUriString); 444 return Uri.parse(tagUriString);
422 } on FormatException { 445 } on FormatException {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 Part part = tag; 488 Part part = tag;
466 StringNode uri = part.uri; 489 StringNode uri = part.uri;
467 Uri resolvedUri = base.resolve(uri.dartString.slowToString()); 490 Uri resolvedUri = base.resolve(uri.dartString.slowToString());
468 tagState.checkTag(TagState.PART, part, reporter); 491 tagState.checkTag(TagState.PART, part, reporter);
469 return scanPart(part, resolvedUri, library); 492 return scanPart(part, resolvedUri, library);
470 } else { 493 } else {
471 reporter.internalError(tag, "Unhandled library tag."); 494 reporter.internalError(tag, "Unhandled library tag.");
472 } 495 }
473 }); 496 });
474 }).then((_) { 497 }).then((_) {
475 return compiler.onLibraryScanned(library, handler); 498 return listener.onLibraryScanned(library, handler);
476 }).then((_) { 499 }).then((_) {
477 return reporter.withCurrentElement(library, () { 500 return reporter.withCurrentElement(library, () {
478 checkDuplicatedLibraryName(library); 501 checkDuplicatedLibraryName(library);
479 502
480 // Import dart:core if not already imported. 503 // Import dart:core if not already imported.
481 if (!importsDartCore && library.canonicalUri != Uris.dart_core) { 504 if (!importsDartCore && library.canonicalUri != Uris.dart_core) {
482 return createLibrary(handler, null, Uris.dart_core) 505 return createLibrary(handler, null, Uris.dart_core)
483 .then((LibraryElement coreLibrary) { 506 .then((LibraryElement coreLibrary) {
484 handler.registerDependency(library, 507 handler.registerDependency(library,
485 new SyntheticImportElement( 508 new SyntheticImportElement(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 } 565 }
543 } 566 }
544 } 567 }
545 568
546 /** 569 /**
547 * Handle a part tag in the scope of [library]. The [resolvedUri] given is 570 * Handle a part tag in the scope of [library]. The [resolvedUri] given is
548 * used as is, any URI resolution should be done beforehand. 571 * used as is, any URI resolution should be done beforehand.
549 */ 572 */
550 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) { 573 Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
551 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri); 574 if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
552 Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part); 575 Uri readableUri = uriTranslator.translate(library, resolvedUri, part);
553 if (readableUri == null) return new Future.value(); 576 if (readableUri == null) return new Future.value();
554 return reporter.withCurrentElement(library, () { 577 return reporter.withCurrentElement(library, () {
555 return compiler.readScript(part, readableUri). 578 return scriptLoader.readScript(readableUri, part).then((Script script) {
556 then((Script sourceScript) { 579 if (script == null) return;
557 if (sourceScript == null) return; 580 return createUnitSync(script, library);
558 581 });
559 CompilationUnitElementX unit =
560 new CompilationUnitElementX(sourceScript, library);
561 reporter.withCurrentElement(unit, () {
562 compiler.scanner.scan(unit);
563 if (unit.partTag == null && !sourceScript.isSynthesized) {
564 reporter.reportErrorMessage(
565 unit, MessageKind.MISSING_PART_OF_TAG);
566 }
567 });
568 });
569 }); 582 });
570 } 583 }
571 584
572 /** 585 /**
573 * Handle an import/export tag by loading the referenced library and 586 * Handle an import/export tag by loading the referenced library and
574 * registering its dependency in [handler] for the computation of the import/ 587 * registering its dependency in [handler] for the computation of the import/
575 * export scope. If the tag does not contain a valid URI, then its dependency 588 * export scope. If the tag does not contain a valid URI, then its dependency
576 * is not registered in [handler]. 589 * is not registered in [handler].
577 */ 590 */
578 Future<Null> registerLibraryFromImportExport( 591 Future<Null> registerLibraryFromImportExport(
(...skipping 15 matching lines...) Expand all
594 607
595 /// Loads the deserialized [library] with the [handler]. 608 /// Loads the deserialized [library] with the [handler].
596 /// 609 ///
597 /// All libraries imported or exported transitively from [library] will be 610 /// All libraries imported or exported transitively from [library] will be
598 /// loaded as well. 611 /// loaded as well.
599 Future<LibraryElement> loadDeserializedLibrary( 612 Future<LibraryElement> loadDeserializedLibrary(
600 LibraryDependencyHandler handler, 613 LibraryDependencyHandler handler,
601 LibraryElement library) { 614 LibraryElement library) {
602 libraryCanonicalUriMap[library.canonicalUri] = library; 615 libraryCanonicalUriMap[library.canonicalUri] = library;
603 handler.registerNewLibrary(library); 616 handler.registerNewLibrary(library);
604 return compiler.onLibraryScanned(library, handler).then((_) { 617 return listener.onLibraryScanned(library, handler).then((_) {
605 return Future.forEach(library.imports, (ImportElement import) { 618 return Future.forEach(library.imports, (ImportElement import) {
606 return createLibrary(handler, library, import.uri); 619 return createLibrary(handler, library, import.uri);
607 }).then((_) { 620 }).then((_) {
608 return Future.forEach(library.exports, (ExportElement export) { 621 return Future.forEach(library.exports, (ExportElement export) {
609 return createLibrary(handler, library, export.uri); 622 return createLibrary(handler, library, export.uri);
610 }).then((_) => library); 623 }).then((_) => library);
611 }); 624 });
612 }); 625 });
613 } 626 }
614 627
628 Future<Script> _readScript(Spannable spannable,
629 Uri readableUri, Uri resolvedUri) {
630 if (readableUri == null) {
631 return new Future.value(new Script.synthetic(resolvedUri));
632 } else {
633 return scriptLoader.readScript(readableUri, spannable);
634 }
635 }
636
615 /** 637 /**
616 * Create (or reuse) a library element for the library specified by the 638 * Create (or reuse) a library element for the library specified by the
617 * [resolvedUri]. 639 * [resolvedUri].
618 * 640 *
619 * If a new library is created, the [handler] is notified. 641 * If a new library is created, the [handler] is notified.
620 */ 642 */
621 Future<LibraryElement> createLibrary( 643 Future<LibraryElement> createLibrary(
622 LibraryDependencyHandler handler, 644 LibraryDependencyHandler handler,
623 LibraryElement importingLibrary, 645 LibraryElement importingLibrary,
624 Uri resolvedUri, 646 Uri resolvedUri,
625 {Spannable node, 647 {Spannable node,
626 bool skipFileWithPartOfTag: false}) { 648 bool skipFileWithPartOfTag: false}) {
627 Uri readableUri = 649 Uri readableUri =
628 compiler.translateResolvedUri(importingLibrary, resolvedUri, node); 650 uriTranslator.translate(importingLibrary, resolvedUri, node);
629 LibraryElement library = libraryCanonicalUriMap[resolvedUri]; 651 LibraryElement library = libraryCanonicalUriMap[resolvedUri];
630 if (library != null) { 652 if (library != null) {
631 return new Future.value(library); 653 return new Future.value(library);
632 } 654 }
633 library = compiler.serialization.readLibrary(resolvedUri); 655 library = deserializer.readLibrary(resolvedUri);
634 if (library != null) { 656 if (library != null) {
635 return loadDeserializedLibrary(handler, library); 657 return loadDeserializedLibrary(handler, library);
636 } 658 }
637 var readScript = compiler.readScript;
638 if (readableUri == null) {
639 readableUri = resolvedUri;
640 readScript = compiler.synthesizeScript;
641 }
642 return reporter.withCurrentElement(importingLibrary, () { 659 return reporter.withCurrentElement(importingLibrary, () {
643 return readScript(node, readableUri).then((Script script) { 660 return _readScript(node, readableUri, resolvedUri).then((Script script) {
644 if (script == null) return null; 661 if (script == null) return null;
645 LibraryElement element = 662 LibraryElement element =
646 createLibrarySync(handler, script, resolvedUri); 663 createLibrarySync(handler, script, resolvedUri);
647 CompilationUnitElementX compilationUnit = element.entryCompilationUnit; 664 CompilationUnitElementX compilationUnit = element.entryCompilationUnit;
648 if (compilationUnit.partTag != null) { 665 if (compilationUnit.partTag != null) {
649 if (skipFileWithPartOfTag) { 666 if (skipFileWithPartOfTag) {
650 // TODO(johnniwinther): Avoid calling [Compiler.onLibraryCreated] 667 // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated]
651 // for this library. 668 // for this library.
652 libraryCanonicalUriMap.remove(resolvedUri); 669 libraryCanonicalUriMap.remove(resolvedUri);
653 return null; 670 return null;
654 } 671 }
655 if (importingLibrary == null) { 672 if (importingLibrary == null) {
656 DiagnosticMessage error = reporter.withCurrentElement( 673 DiagnosticMessage error = reporter.withCurrentElement(
657 compilationUnit, 674 compilationUnit,
658 () => reporter.createMessage( 675 () => reporter.createMessage(
659 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF)); 676 compilationUnit.partTag, MessageKind.MAIN_HAS_PART_OF));
660 reporter.reportError(error); 677 reporter.reportError(error);
(...skipping 13 matching lines...) Expand all
674 return processLibraryTags(handler, element).then((_) { 691 return processLibraryTags(handler, element).then((_) {
675 reporter.withCurrentElement(element, () { 692 reporter.withCurrentElement(element, () {
676 handler.registerLibraryExports(element); 693 handler.registerLibraryExports(element);
677 }); 694 });
678 return element; 695 return element;
679 }); 696 });
680 }); 697 });
681 }); 698 });
682 } 699 }
683 700
684 LibraryElement createLibrarySync( 701 LibraryElement createLibrarySync(LibraryDependencyHandler handler,
685 LibraryDependencyHandler handler, 702 Script script, Uri resolvedUri) {
686 Script script,
687 Uri resolvedUri) {
688 LibraryElement element = new LibraryElementX(script, resolvedUri); 703 LibraryElement element = new LibraryElementX(script, resolvedUri);
689 return reporter.withCurrentElement(element, () { 704 return reporter.withCurrentElement(element, () {
690 if (handler != null) { 705 if (handler != null) {
691 handler.registerNewLibrary(element); 706 handler.registerNewLibrary(element);
692 libraryCanonicalUriMap[resolvedUri] = element; 707 libraryCanonicalUriMap[resolvedUri] = element;
693 } 708 }
694 compiler.scanner.scanLibrary(element); 709 scanner.scanLibrary(element);
695 return element; 710 return element;
696 }); 711 });
697 } 712 }
713
714 CompilationUnitElement createUnitSync(Script script, LibraryElement library) {
715 CompilationUnitElementX unit = new CompilationUnitElementX(script, library);
716 reporter.withCurrentElement(unit, () {
717 scanner.scanUnit(unit);
718 if (unit.partTag == null && !script.isSynthesized) {
719 reporter.reportErrorMessage(unit, MessageKind.MISSING_PART_OF_TAG);
720 }
721 });
722 return unit;
723 }
698 } 724 }
699 725
700 726
701 /// A state machine for checking script tags come in the correct order. 727 /// A state machine for checking script tags come in the correct order.
702 class TagState { 728 class TagState {
703 /// Initial state. 729 /// Initial state.
704 static const int NO_TAG_SEEN = 0; 730 static const int NO_TAG_SEEN = 0;
705 731
706 /// Passed to [checkTag] when a library declaration (the syntax "library 732 /// Passed to [checkTag] when a library declaration (the syntax "library
707 /// name;") has been seen. Not an actual state. 733 /// name;") has been seen. Not an actual state.
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1167 * Newly loaded libraries and their corresponding node in the library 1193 * Newly loaded libraries and their corresponding node in the library
1168 * dependency graph. Libraries that have already been fully loaded are not 1194 * dependency graph. Libraries that have already been fully loaded are not
1169 * part of the dependency graph of this handler since their export scopes have 1195 * part of the dependency graph of this handler since their export scopes have
1170 * already been computed. 1196 * already been computed.
1171 */ 1197 */
1172 Map<LibraryElement, LibraryDependencyNode> nodeMap = 1198 Map<LibraryElement, LibraryDependencyNode> nodeMap =
1173 new Map<LibraryElement, LibraryDependencyNode>(); 1199 new Map<LibraryElement, LibraryDependencyNode>();
1174 1200
1175 LibraryDependencyHandler(this.task); 1201 LibraryDependencyHandler(this.task);
1176 1202
1177 Compiler get compiler => task.compiler;
1178
1179 DiagnosticReporter get reporter => task.reporter; 1203 DiagnosticReporter get reporter => task.reporter;
1180 1204
1181 /// The libraries created with this handler. 1205 /// The libraries created with this handler.
1182 Iterable<LibraryElement> get newLibraries => _newLibraries; 1206 Iterable<LibraryElement> get newLibraries => _newLibraries;
1183 1207
1184 /** 1208 /**
1185 * Performs a fixed-point computation on the export scopes of all registered 1209 * Performs a fixed-point computation on the export scopes of all registered
1186 * libraries and creates the import/export of the libraries based on the 1210 * libraries and creates the import/export of the libraries based on the
1187 * fixed-point. 1211 * fixed-point.
1188 */ 1212 */
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 assert(invariant(library, importingNode != null, 1285 assert(invariant(library, importingNode != null,
1262 message: "$library has not been registered")); 1286 message: "$library has not been registered"));
1263 importingNode.registerImportDependency(libraryDependency, loadedLibrary); 1287 importingNode.registerImportDependency(libraryDependency, loadedLibrary);
1264 } 1288 }
1265 } 1289 }
1266 1290
1267 /** 1291 /**
1268 * Registers [library] for the processing of its import/export scope. 1292 * Registers [library] for the processing of its import/export scope.
1269 */ 1293 */
1270 void registerNewLibrary(LibraryElement library) { 1294 void registerNewLibrary(LibraryElement library) {
1271 compiler.onLibraryCreated(library); 1295 task.listener.onLibraryCreated(library);
1272 _newLibraries.add(library); 1296 _newLibraries.add(library);
1273 if (!library.exportsHandled) { 1297 if (!library.exportsHandled) {
1274 nodeMap[library] = new LibraryDependencyNode(library); 1298 nodeMap[library] = new LibraryDependencyNode(library);
1275 } 1299 }
1276 } 1300 }
1277 1301
1278 /** 1302 /**
1279 * Registers all top-level entities of [library] as starting point for the 1303 * Registers all top-level entities of [library] as starting point for the
1280 * fixed-point computation of the import/export scopes. 1304 * fixed-point computation of the import/export scopes.
1281 */ 1305 */
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 } 1437 }
1414 suffixChainMap[library] = suffixes; 1438 suffixChainMap[library] = suffixes;
1415 return; 1439 return;
1416 } 1440 }
1417 1441
1418 computeSuffixes(rootLibrary, const Link<Uri>()); 1442 computeSuffixes(rootLibrary, const Link<Uri>());
1419 } 1443 }
1420 1444
1421 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}'; 1445 String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
1422 } 1446 }
1447
1448 /// API used by the library loader to translate internal SDK uri's into file
Harry Terkelsen 2016/03/22 21:49:28 Be consistent with "uri's" or "URIs"
Siggi Cherem (dart-lang) 2016/03/23 22:51:05 Done.
1449 /// system readable URIs.
1450 abstract class ResolvedUriTranslator {
1451 // TODO(sigmund): move here the comments from library loader.
1452 /// Translate the resolved [uri] in the context of [importingLibrary].
1453 ///
1454 /// Use [spannable] for error reporting.
1455 Uri translate(
1456 LibraryElement importingLibrary, Uri uri, [Spannable spannable]);
1457 }
1458
1459
1460 // TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
1461 // rather low-level. It might be more practical to split the library-loading
1462 // task itself. The task would continue to do the work of recursively loading
1463 // dependencies, but it can delegate to a set of subloaders how to do the actual
1464 // loading. We would then have a list of subloaders that use different
1465 // implementations: in-memory cache, deserialization, scanning from files.
1466 //
1467 // For example, the API might look like this:
1468 //
1469 // /// APIs to create [LibraryElement] and [CompilationUnitElements] given it's
1470 // /// URI.
1471 // abstract class SubLoader {
1472 // /// Return the library corresponding to the script at [uri].
1473 // ///
1474 // /// Use [spannable] for error reporting.
1475 // Future<LibraryElement> createLibrary(Uri uri, [Spannable spannable]);
1476 //
1477 // /// Return the compilation unit at [uri] that is a part of [library].
1478 // Future<CompilationUnitElement> createUnit(Uri uri, LibraryElement library,
1479 // [Spannable spannable]);
1480 // }
1481 //
1482 // /// A [SubLoader] that parses a serialized form of the element model to
1483 // /// produce the results.
1484 // class DeserializingUnitElementCreator implements SubLoader {
1485 // ...
1486 // }
1487 //
1488 // /// A [SubLoader] that finds the script sources and does a diet parse
1489 // /// on them to produces the results.
1490 // class ScanningUnitElementCreator implements SubLoader {
1491 // ...
1492 // }
1493 //
1494 // Each subloader would internally create what they need (a scanner, a
1495 // deserializer), and we wouldn't need to create abstractions to pass in
1496 // something that is only used by the loader.
1497
1498 /// API used by the library loader to request scripts from the compiler system.
1499 abstract class ScriptLoader {
1500 /// Load script from a readable [uri], report any errors using the location of
1501 /// the given [spannable].
1502 Future<Script> readScript(Uri uri, [Spannable spannable]);
1503 }
1504
1505 /// API used byt he library loader to sychronously scan a library or compilation
Harry Terkelsen 2016/03/22 21:49:28 byt he sychronously
Siggi Cherem (dart-lang) 2016/03/23 22:51:05 Done.
1506 /// unit and ensure that their library tags are computed.
1507 abstract class ElementScanner {
1508 void scanLibrary(LibraryElement library);
1509 void scanUnit(CompilationUnitElement unit);
1510 }
1511
1512
1513 /// TODO(sigmund): remove this abstraction. Ideally the loader can produce the
1514 /// LoadedLibraries results once, and the compiler and choose what to do with
1515 /// it instead.
1516 abstract class LibraryLoaderListener {
Harry Terkelsen 2016/03/22 21:49:28 Maybe the loader can just publish a stream of libr
Siggi Cherem (dart-lang) 2016/03/23 22:51:05 Might be worth looking into a similar idea in the
1517 /// Called after a request to load a library. The [results] will include all
1518 /// transitive libraries loaded as a result of the initial request.
1519 Future onLibrariesLoaded(LoadedLibraries results);
1520
1521 /// Called whenever a library element is created.
1522 void onLibraryCreated(LibraryElement library);
1523
1524 /// Called whenever a library is scanned from a script file.
1525 Future onLibraryScanned(LibraryElement library, LibraryLoader loader);
1526 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698