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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/library_loader.dart
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 68f6008b2728f4784c58bd5ca9efa7d743e6d453..15edd79efe46fab574b341900f6d5b33b9d11fe1 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -30,8 +30,9 @@ import 'elements/modelx.dart' show
LibraryDependencyElementX,
PrefixElementX,
SyntheticImportElement;
-
+import 'environment.dart';
import 'script.dart';
+import 'serialization/serialization.dart' show LibraryDeserializer;
import 'tree/tree.dart';
import 'util/util.dart' show
Link,
@@ -105,9 +106,9 @@ import 'util/util.dart' show
* resolved into a readable URI using the library root URI provided from the
* command line and the list of platform libraries found in
* 'sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart'. This is done
- * through the [Compiler.translateResolvedUri] method which checks whether a
- * library by that name exists and in case of internal libraries whether access
- * is granted.
+ * through a [ResolvedUriTranslator] provided from the compiler. The translator
+ * checks whether a library by that name exists and in case of internal
+ * libraries whether access is granted.
*
* ## Resource URI ##
*
@@ -132,7 +133,13 @@ import 'util/util.dart' show
*
*/
abstract class LibraryLoaderTask implements CompilerTask {
- factory LibraryLoaderTask(Compiler compiler) = _LibraryLoaderTask;
+ factory LibraryLoaderTask(Compiler compiler,
+ ResolvedUriTranslator uriTranslator,
+ ScriptLoader scriptLoader,
+ ElementScanner scriptScanner,
+ LibraryDeserializer deserializer,
+ LibraryLoaderListener listener,
+ Environment environment) = _LibraryLoaderTask;
/// Returns all libraries that have been loaded.
Iterable<LibraryElement> get libraries;
@@ -259,13 +266,38 @@ class HideFilter extends CombinatorFilter {
bool exclude(Element element) => excludedNames.contains(element.name);
}
-/**
- * Implementation class for [LibraryLoader]. The distinction between
- * [LibraryLoader] and [LibraryLoaderTask] is made to hide internal members from
- * the [LibraryLoader] interface.
- */
+/// Implementation class for [LibraryLoaderTask]. The distinction between
+/// [LibraryLoaderTask] and [_LibraryLoaderTask] is made to hide internal
+/// members from the [LibraryLoaderTask] interface.
class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
- _LibraryLoaderTask(Compiler compiler) : super(compiler);
+ /// 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.
+ final ResolvedUriTranslator uriTranslator;
+
+ /// 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.
+ /// libraries from source.
+ final ScriptLoader scriptLoader;
+
+ /// Provides a diet element model from a script file containing information
+ /// about imports and exports. Used when loading libraries from source.
+ final ElementScanner scanner;
+
+ /// Provides a diet element model for a library. Used when loading libraries
+ /// from a serialized form.
+ final LibraryDeserializer deserializer;
+
+ /// Hooks to inform others about progress done by this loader.
+ // TODO(sigmund): move away from this.
+ final LibraryLoaderListener listener;
+
+ /// Definitions provided via the `-D` command line flags. Used to resolve
+ /// conditional imports.
+ final Environment environment;
+
+ _LibraryLoaderTask(
+ Compiler compiler, this.uriTranslator, this.scriptLoader,
+ this.scanner, this.deserializer, this.listener, this.environment)
+ // TODO(sigmund): make measurements separate from compiler
+ : super(compiler);
String get name => 'LibraryLoader';
@@ -290,6 +322,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
Iterable<LibraryElement> reusedLibraries = null;
if (reuseLibrary != null) {
+ // TODO(sigmund): make measurements separate from compiler
reusedLibraries = compiler.reuseLibraryTask.measure(() {
// Call [toList] to force eager calls to [reuseLibrary].
return libraryCanonicalUriMap.values.where(reuseLibrary).toList();
@@ -316,18 +349,9 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
return measure(() {
assert(currentHandler == null);
- Future<LibraryElement> wrapper(LibraryElement library) {
- try {
- return reuseLibrary(library).then(
- (bool reuse) => reuse ? library : null);
- } catch (exception, trace) {
- compiler.diagnoseCrashInUserCode(
- 'Uncaught exception in reuseLibrary', exception, trace);
- rethrow;
- }
- }
-
+ wrapper(lib) => reuseLibrary(lib).then((reuse) => reuse ? lib : null);
List<Future<LibraryElement>> reusedLibrariesFuture =
+ // TODO(sigmund): make measurements separate from compiler
compiler.reuseLibraryTask.measure(
() => libraryCanonicalUriMap.values.map(wrapper).toList());
@@ -351,8 +375,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
}
}
- Future<LibraryElement> loadLibrary(
- Uri resolvedUri,
+ Future<LibraryElement> loadLibrary(Uri resolvedUri,
{bool skipFileWithPartOfTag: false}) {
return measure(() {
assert(currentHandler == null);
@@ -375,7 +398,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
currentHandler.nodeMap,
this);
currentHandler = null;
- return compiler.onLibrariesLoaded(loadedLibraries)
+ return listener.onLibrariesLoaded(loadedLibraries)
.then((_) => library);
});
});
@@ -409,7 +432,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
String value = conditionalUri.value == null
? "true"
: conditionalUri.value.dartString.slowToString();
- String actual = compiler.fromEnvironment(key);
+ String actual = environment.valueOf(key);
if (value == actual) {
uriNode = conditionalUri.uri;
break;
@@ -472,7 +495,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
}
});
}).then((_) {
- return compiler.onLibraryScanned(library, handler);
+ return listener.onLibraryScanned(library, handler);
}).then((_) {
return reporter.withCurrentElement(library, () {
checkDuplicatedLibraryName(library);
@@ -549,23 +572,13 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
*/
Future scanPart(Part part, Uri resolvedUri, LibraryElement library) {
if (!resolvedUri.isAbsolute) throw new ArgumentError(resolvedUri);
- Uri readableUri = compiler.translateResolvedUri(library, resolvedUri, part);
+ Uri readableUri = uriTranslator.translate(library, resolvedUri, part);
if (readableUri == null) return new Future.value();
return reporter.withCurrentElement(library, () {
- return compiler.readScript(part, readableUri).
- then((Script sourceScript) {
- if (sourceScript == null) return;
-
- CompilationUnitElementX unit =
- new CompilationUnitElementX(sourceScript, library);
- reporter.withCurrentElement(unit, () {
- compiler.scanner.scan(unit);
- if (unit.partTag == null && !sourceScript.isSynthesized) {
- reporter.reportErrorMessage(
- unit, MessageKind.MISSING_PART_OF_TAG);
- }
- });
- });
+ return scriptLoader.readScript(readableUri, part).then((Script script) {
+ if (script == null) return;
+ return createUnitSync(script, library);
+ });
});
}
@@ -601,7 +614,7 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
LibraryElement library) {
libraryCanonicalUriMap[library.canonicalUri] = library;
handler.registerNewLibrary(library);
- return compiler.onLibraryScanned(library, handler).then((_) {
+ return listener.onLibraryScanned(library, handler).then((_) {
return Future.forEach(library.imports, (ImportElement import) {
return createLibrary(handler, library, import.uri);
}).then((_) {
@@ -612,6 +625,15 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
});
}
+ Future<Script> _readScript(Spannable spannable,
+ Uri readableUri, Uri resolvedUri) {
+ if (readableUri == null) {
+ return new Future.value(new Script.synthetic(resolvedUri));
+ } else {
+ return scriptLoader.readScript(readableUri, spannable);
+ }
+ }
+
/**
* Create (or reuse) a library element for the library specified by the
* [resolvedUri].
@@ -625,29 +647,24 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
{Spannable node,
bool skipFileWithPartOfTag: false}) {
Uri readableUri =
- compiler.translateResolvedUri(importingLibrary, resolvedUri, node);
+ uriTranslator.translate(importingLibrary, resolvedUri, node);
LibraryElement library = libraryCanonicalUriMap[resolvedUri];
if (library != null) {
return new Future.value(library);
}
- library = compiler.serialization.readLibrary(resolvedUri);
+ library = deserializer.readLibrary(resolvedUri);
if (library != null) {
return loadDeserializedLibrary(handler, library);
}
- var readScript = compiler.readScript;
- if (readableUri == null) {
- readableUri = resolvedUri;
- readScript = compiler.synthesizeScript;
- }
return reporter.withCurrentElement(importingLibrary, () {
- return readScript(node, readableUri).then((Script script) {
+ return _readScript(node, readableUri, resolvedUri).then((Script script) {
if (script == null) return null;
LibraryElement element =
createLibrarySync(handler, script, resolvedUri);
CompilationUnitElementX compilationUnit = element.entryCompilationUnit;
if (compilationUnit.partTag != null) {
if (skipFileWithPartOfTag) {
- // TODO(johnniwinther): Avoid calling [Compiler.onLibraryCreated]
+ // TODO(johnniwinther): Avoid calling [listener.onLibraryCreated]
// for this library.
libraryCanonicalUriMap.remove(resolvedUri);
return null;
@@ -681,20 +698,29 @@ class _LibraryLoaderTask extends CompilerTask implements LibraryLoaderTask {
});
}
- LibraryElement createLibrarySync(
- LibraryDependencyHandler handler,
- Script script,
- Uri resolvedUri) {
+ LibraryElement createLibrarySync(LibraryDependencyHandler handler,
+ Script script, Uri resolvedUri) {
LibraryElement element = new LibraryElementX(script, resolvedUri);
return reporter.withCurrentElement(element, () {
if (handler != null) {
handler.registerNewLibrary(element);
libraryCanonicalUriMap[resolvedUri] = element;
}
- compiler.scanner.scanLibrary(element);
+ scanner.scanLibrary(element);
return element;
});
}
+
+ CompilationUnitElement createUnitSync(Script script, LibraryElement library) {
+ CompilationUnitElementX unit = new CompilationUnitElementX(script, library);
+ reporter.withCurrentElement(unit, () {
+ scanner.scanUnit(unit);
+ if (unit.partTag == null && !script.isSynthesized) {
+ reporter.reportErrorMessage(unit, MessageKind.MISSING_PART_OF_TAG);
+ }
+ });
+ return unit;
+ }
}
@@ -1174,8 +1200,6 @@ class LibraryDependencyHandler implements LibraryLoader {
LibraryDependencyHandler(this.task);
- Compiler get compiler => task.compiler;
-
DiagnosticReporter get reporter => task.reporter;
/// The libraries created with this handler.
@@ -1268,7 +1292,7 @@ class LibraryDependencyHandler implements LibraryLoader {
* Registers [library] for the processing of its import/export scope.
*/
void registerNewLibrary(LibraryElement library) {
- compiler.onLibraryCreated(library);
+ task.listener.onLibraryCreated(library);
_newLibraries.add(library);
if (!library.exportsHandled) {
nodeMap[library] = new LibraryDependencyNode(library);
@@ -1420,3 +1444,83 @@ class _LoadedLibraries implements LoadedLibraries {
String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
}
+
+/// 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.
+/// system readable URIs.
+abstract class ResolvedUriTranslator {
+ // TODO(sigmund): move here the comments from library loader.
+ /// Translate the resolved [uri] in the context of [importingLibrary].
+ ///
+ /// Use [spannable] for error reporting.
+ Uri translate(
+ LibraryElement importingLibrary, Uri uri, [Spannable spannable]);
+}
+
+
+// TODO(sigmund): remove ScriptLoader & ElementScanner. Such abstraction seems
+// rather low-level. It might be more practical to split the library-loading
+// task itself. The task would continue to do the work of recursively loading
+// dependencies, but it can delegate to a set of subloaders how to do the actual
+// loading. We would then have a list of subloaders that use different
+// implementations: in-memory cache, deserialization, scanning from files.
+//
+// For example, the API might look like this:
+//
+// /// APIs to create [LibraryElement] and [CompilationUnitElements] given it's
+// /// URI.
+// abstract class SubLoader {
+// /// Return the library corresponding to the script at [uri].
+// ///
+// /// Use [spannable] for error reporting.
+// Future<LibraryElement> createLibrary(Uri uri, [Spannable spannable]);
+//
+// /// Return the compilation unit at [uri] that is a part of [library].
+// Future<CompilationUnitElement> createUnit(Uri uri, LibraryElement library,
+// [Spannable spannable]);
+// }
+//
+// /// A [SubLoader] that parses a serialized form of the element model to
+// /// produce the results.
+// class DeserializingUnitElementCreator implements SubLoader {
+// ...
+// }
+//
+// /// A [SubLoader] that finds the script sources and does a diet parse
+// /// on them to produces the results.
+// class ScanningUnitElementCreator implements SubLoader {
+// ...
+// }
+//
+// Each subloader would internally create what they need (a scanner, a
+// deserializer), and we wouldn't need to create abstractions to pass in
+// something that is only used by the loader.
+
+/// API used by the library loader to request scripts from the compiler system.
+abstract class ScriptLoader {
+ /// Load script from a readable [uri], report any errors using the location of
+ /// the given [spannable].
+ Future<Script> readScript(Uri uri, [Spannable spannable]);
+}
+
+/// 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.
+/// unit and ensure that their library tags are computed.
+abstract class ElementScanner {
+ void scanLibrary(LibraryElement library);
+ void scanUnit(CompilationUnitElement unit);
+}
+
+
+/// TODO(sigmund): remove this abstraction. Ideally the loader can produce the
+/// LoadedLibraries results once, and the compiler and choose what to do with
+/// it instead.
+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
+ /// Called after a request to load a library. The [results] will include all
+ /// transitive libraries loaded as a result of the initial request.
+ Future onLibrariesLoaded(LoadedLibraries results);
+
+ /// Called whenever a library element is created.
+ void onLibraryCreated(LibraryElement library);
+
+ /// Called whenever a library is scanned from a script file.
+ Future onLibraryScanned(LibraryElement library, LibraryLoader loader);
+}

Powered by Google App Engine
This is Rietveld 408576698