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

Unified Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 1017743003: Task: Create Export Namespace. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/task/dart.dart
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index f9e7705febc1ae21bb2e94b6ea19c0f83288e798..0ccb28d5502f22890d488e573e3326de47a5e4c8 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -49,6 +49,14 @@ final ResultDescriptor<List<AnalysisError>> BUILD_LIBRARY_ERRORS =
contributesTo: DART_ERRORS);
/**
+ * The export [Namespace] of a library.
+ *
+ * The result is only available for targets representing a Dart library.
+ */
+final ResultDescriptor<Namespace> EXPORT_NAMESPACE =
+ new ResultDescriptor<Namespace>('EXPORT_NAMESPACE', null);
+
+/**
* The sources representing the export closure of a library.
*
* The result is only available for targets representing a Dart library.
@@ -79,6 +87,17 @@ final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT2 =
new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT2', null);
/**
+ * The partial [LibraryElement] associated with a library.
+ *
+ * In addition to [LIBRARY_ELEMENT2] `entryPoint` is set, if the library does
+ * not declare one already and one of the exported libraries exports one.
+ *
+ * The result is only available for targets representing a Dart library.
+ */
+final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT3 =
+ new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT3', null);
+
+/**
* The partially resolved [CompilationUnit] associated with a unit.
*
* All declarations bound to the element defined by the declaration.
@@ -369,15 +388,6 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
//
libraryElement.imports = imports;
libraryElement.exports = exports;
- // TODO(scheglov) move after EXPORT_NAMESPACE or just this task
-// if (libraryElement.entryPoint == null) {
-// Namespace namespace = new NamespaceBuilder()
-// .createExportNamespaceForLibrary(libraryElement);
-// Element element = namespace.get(FunctionElement.MAIN_FUNCTION_NAME);
-// if (element is FunctionElement) {
-// libraryElement.entryPoint = element;
-// }
-// }
//
// Record outputs.
//
@@ -521,6 +531,87 @@ class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
}
/**
+ * A task that builds [EXPORT_NAMESPACE] and [LIBRARY_ELEMENT3] for a library.
+ */
+class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
+ /**
+ * The name of the input for [LIBRARY_ELEMENT2] of a library.
+ */
+ static const String LIBRARY2_ELEMENT_INPUT = 'LIBRARY2_ELEMENT_INPUT';
+
+ /**
+ * The a [Source] to [PUBLIC_NAMESPACE] map input.
+ */
+ static const String PUBLIC_NAMESPACES_INPUT = 'PUBLIC_NAMESPACES_INPUT';
+
+ /**
+ * The task descriptor describing this kind of task.
+ */
+ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+ 'BuildExportNamespaceTask', createTask, buildInputs, <ResultDescriptor>[
+ EXPORT_NAMESPACE,
+ LIBRARY_ELEMENT3
+ ]);
+
+ BuildExportNamespaceTask(
+ InternalAnalysisContext context, AnalysisTarget target)
+ : super(context, target);
+
+ @override
+ TaskDescriptor get descriptor => DESCRIPTOR;
+
+ @override
+ void internalPerform() {
+ LibraryElementImpl library = getRequiredInput(LIBRARY2_ELEMENT_INPUT);
+ Map<Source, Namespace> publicNamespaces =
+ getRequiredInput(PUBLIC_NAMESPACES_INPUT);
+ //
+ // Compute export namespace.
+ //
+ ExportNamespaceBuilder builder =
+ new ExportNamespaceBuilder(publicNamespaces);
+ Namespace namespace = builder.build(library);
+ //
+ // Update entry point.
+ //
+ if (library.entryPoint == null) {
+ Iterable<Element> exportedElements = namespace.definedNames.values;
+ library.entryPoint = exportedElements.firstWhere(
+ (element) => element is FunctionElement && element.isEntryPoint,
+ orElse: () => null);
+ }
+ //
+ // Record outputs.
+ //
+ outputs[EXPORT_NAMESPACE] = namespace;
+ outputs[LIBRARY_ELEMENT3] = library;
+ }
+
+ /**
+ * Return a map from the names of the inputs of this kind of task to the task
+ * input descriptors describing those inputs for a task with the
+ * given library [source].
+ */
+ static Map<String, TaskInput> buildInputs(Source source) {
+ return <String, TaskInput>{
+ LIBRARY2_ELEMENT_INPUT: LIBRARY_ELEMENT2.inputFor(source),
+ PUBLIC_NAMESPACES_INPUT: new ListToMapTaskInput<Source, Namespace>(
+ EXPORT_SOURCE_CLOSURE.inputFor(source),
+ (Source source) => PUBLIC_NAMESPACE.inputFor(source))
+ };
+ }
+
+ /**
+ * Create a [BuildExportNamespaceTask] based on the given [target] in
+ * the given [context].
+ */
+ static BuildExportNamespaceTask createTask(
+ AnalysisContext context, AnalysisTarget target) {
+ return new BuildExportNamespaceTask(context, target);
+ }
+}
+
+/**
* A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
*/
class BuildExportSourceClosureTask extends SourceBasedAnalysisTask {
@@ -975,6 +1066,113 @@ class BuildTypeProviderTask extends SourceBasedAnalysisTask {
}
/**
+ * The helper for building the export [Namespace] of a [LibraryElement].
+ */
+class ExportNamespaceBuilder {
+ final Map<Source, Namespace> _publicNamespaces;
+
+ ExportNamespaceBuilder(this._publicNamespaces);
+
+ /**
+ * Build the export [Namespace] of the given [LibraryElement].
+ */
+ Namespace build(LibraryElement library) {
+ return new Namespace(
+ _createExportMapping(library, new HashSet<LibraryElement>()));
+ }
+
+ /**
+ * Create a mapping table representing the export namespace of the given
+ * [library].
+ *
+ * The given [visitedElements] a set of libraries that do not need to be
+ * visited when processing the export directives of the given library because
+ * all of the names defined by them will be added by another library.
+ */
+ HashMap<String, Element> _createExportMapping(
+ LibraryElement library, HashSet<LibraryElement> visitedElements) {
+ visitedElements.add(library);
+ try {
+ HashMap<String, Element> definedNames = new HashMap<String, Element>();
+ // Add names of the export directives.
+ for (ExportElement element in library.exports) {
+ LibraryElement exportedLibrary = element.exportedLibrary;
+ if (exportedLibrary != null &&
+ !visitedElements.contains(exportedLibrary)) {
+ //
+ // The exported library will be null if the URI does not reference a
+ // valid library.
+ //
+ HashMap<String, Element> exportedNames =
+ _createExportMapping(exportedLibrary, visitedElements);
+ exportedNames = _applyCombinators(exportedNames, element.combinators);
+ definedNames.addAll(exportedNames);
+ }
+ }
+ // Add names of the public namespace.
+ {
+ Namespace publicNamespace = _publicNamespaces[library.source];
+ if (publicNamespace != null) {
+ definedNames.addAll(publicNamespace.definedNames);
+ }
+ }
+ return definedNames;
+ } finally {
+ visitedElements.remove(library);
+ }
+ }
+
+ /**
+ * Apply the given [combinators] to all of the names in [definedNames].
+ */
+ static HashMap<String, Element> _applyCombinators(
+ HashMap<String, Element> definedNames,
+ List<NamespaceCombinator> combinators) {
+ for (NamespaceCombinator combinator in combinators) {
+ if (combinator is HideElementCombinator) {
+ _hide(definedNames, combinator.hiddenNames);
+ } else if (combinator is ShowElementCombinator) {
+ definedNames = _show(definedNames, combinator.shownNames);
+ }
+ }
+ return definedNames;
+ }
+
+ /**
+ * Hide all of the [hiddenNames] by removing them from the given
+ * [definedNames].
+ */
+ static void _hide(
+ HashMap<String, Element> definedNames, List<String> hiddenNames) {
+ for (String name in hiddenNames) {
+ definedNames.remove(name);
+ definedNames.remove('$name=');
+ }
+ }
+
+ /**
+ * Show only the given [shownNames] by removing all other names from the given
+ * [definedNames].
+ */
+ static HashMap<String, Element> _show(
+ HashMap<String, Element> definedNames, List<String> shownNames) {
+ HashMap<String, Element> newNames = new HashMap<String, Element>();
+ for (String name in shownNames) {
+ Element element = definedNames[name];
+ if (element != null) {
+ newNames[name] = element;
+ }
+ String setterName = '$name=';
+ element = definedNames[setterName];
+ if (element != null) {
+ newNames[setterName] = element;
+ }
+ }
+ return newNames;
+ }
+}
+
+/**
* A pair of a library [Source] and a unit [Source] in this library.
*/
class LibraryUnitTarget implements AnalysisTarget {
@@ -1073,7 +1271,7 @@ class ParseDartTask extends SourceBasedAnalysisTask {
}
} else {
throw new AnalysisException(
- "$runtimeType failed to handle a ${directive.runtimeType}");
+ '$runtimeType failed to handle a ${directive.runtimeType}');
}
}
}
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698