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

Unified Diff: lib/compiler/implementation/library_loader.dart

Issue 11087073: Show and hide combinators supported. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Status updated. Created 8 years, 2 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 | tests/co19/co19-dart2dart.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/library_loader.dart
diff --git a/lib/compiler/implementation/library_loader.dart b/lib/compiler/implementation/library_loader.dart
index c1011760eeba1efff8c72b5510934bc288db8bcb..ac3da854895119436051e34bbe84711fdf3e6fd7 100644
--- a/lib/compiler/implementation/library_loader.dart
+++ b/lib/compiler/implementation/library_loader.dart
@@ -37,6 +37,87 @@ abstract class LibraryLoader extends CompilerTask {
}
/**
+ * [CombinatorFilter] is a succinct representation of a list of combinators from
+ * a library dependency tag.
+ */
+class CombinatorFilter {
+ const CombinatorFilter();
+
+ /**
+ * Returns [:true:] if [element] is excluded by this filter.
+ */
+ bool exclude(Element element) => false;
+
+ /**
+ * Creates a filter based on the combinators of [tag].
+ */
+ factory CombinatorFilter.fromTag(LibraryDependency tag) {
+ if (tag == null || tag.combinators == null) {
+ return const CombinatorFilter();
+ }
+
+ // If the list of combinators contain at least one [:show:] we can create
+ // a positive list of elements to include, otherwise we create a negative
+ // list of elements to exclude.
+ bool show = false;
+ Set<SourceString> nameSet;
+ for (Combinator combinator in tag.combinators) {
+ if (combinator.isShow) {
+ show = true;
+ var set = new Set<SourceString>();
+ for (Identifier identifier in combinator.identifiers) {
+ set.add(identifier.source);
+ }
+ if (nameSet == null) {
+ nameSet = set;
+ } else {
+ nameSet = nameSet.intersection(set);
+ }
+ }
+ }
+ if (nameSet == null) {
+ nameSet = new Set<SourceString>();
+ }
+ for (Combinator combinator in tag.combinators) {
+ if (combinator.isHide) {
+ for (Identifier identifier in combinator.identifiers) {
+ if (show) {
+ // We have a positive list => Remove hidden elements.
+ nameSet.remove(identifier.source);
+ } else {
+ // We have no positive list => Accumulate hidden elements.
+ nameSet.add(identifier.source);
+ }
+ }
+ }
+ }
+ return show ? new ShowFilter(nameSet) : new HideFilter(nameSet);
+ }
+}
+
+/**
+ * A list of combinators represented as a list of element names to include.
+ */
+class ShowFilter extends CombinatorFilter {
+ final Set<SourceString> includedNames;
+
+ ShowFilter(this.includedNames);
+
+ bool exclude(Element element) => !includedNames.contains(element.name);
+}
+
+/**
+ * A list of combinators represented as a list of element names to exclude.
+ */
+class HideFilter extends CombinatorFilter {
+ final Set<SourceString> excludedNames;
+
+ HideFilter(this.excludedNames);
+
+ 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.
@@ -91,9 +172,6 @@ class LibraryLoaderTask extends LibraryLoader {
for (LibraryTag tag in library.tags.reverse()) {
if (tag.isImport) {
tagState = checkTag(TagState.IMPORT_OR_EXPORT, tag);
- if (tag.combinators != null) {
- compiler.unimplemented('combinators', node: tag.combinators);
- }
if (tag.uri.dartString.slowToString() == 'dart:core') {
importsDartCore = true;
}
@@ -291,6 +369,7 @@ class ImportLink {
assert(invariant(importingLibrary,
importedLibrary.exportsHandled,
message: 'Exports not handled on $importedLibrary'));
+ var combinatorFilter = new CombinatorFilter.fromTag(import);
if (import !== null && import.prefix !== null) {
SourceString prefix = import.prefix.source;
Element e = importingLibrary.find(prefix);
@@ -308,7 +387,7 @@ class ImportLink {
}
PrefixElement prefixElement = e;
importedLibrary.forEachExport((Element element) {
- // TODO(johnniwinther): Handle show and hide combinators.
+ if (combinatorFilter.exclude(element)) return;
// TODO(johnniwinther): Clean-up like [checkDuplicateLibraryName].
Element existing =
prefixElement.imported.putIfAbsent(element.name, () => element);
@@ -326,7 +405,7 @@ class ImportLink {
} else {
importedLibrary.forEachExport((Element element) {
compiler.withCurrentElement(element, () {
- // TODO(johnniwinther): Handle show and hide combinators.
+ if (combinatorFilter.exclude(element)) return;
importingLibrary.addImport(element, compiler);
});
});
@@ -335,6 +414,29 @@ class ImportLink {
}
/**
+ * The combinator filter computed from an export tag and the library dependency
+ * node for the library that declared the export tag. This represents an edge in
+ * the library dependency graph.
+ */
+class ExportLink {
+ final CombinatorFilter combinatorFilter;
+ final LibraryDependencyNode exportNode;
+
+ ExportLink(Export export, LibraryDependencyNode this.exportNode)
+ : this.combinatorFilter = new CombinatorFilter.fromTag(export);
+
+ /**
+ * Exports [element] to the dependent library unless [element] is filtered by
+ * the export combinators. Returns [:true:] if the set pending exports of the
+ * dependent library was modified.
+ */
+ bool exportElement(Element element) {
+ if (combinatorFilter.exclude(element)) return false;
+ return exportNode.addElementToPendingExports(element);
+ }
+}
+
+/**
* A node in the library dependency graph.
*
* This class is used to collect the library dependencies expressed through
@@ -352,12 +454,10 @@ class LibraryDependencyNode {
Link<ImportLink> imports = const EmptyLink<ImportLink>();
/**
- * The export tags that export [library] mapped to the nodes for the libraries
- * that declared each export tag. This is used to propagete exports during the
- * computation of export scopes.
+ * A linked list of the export tags the dependent upon this node library.
+ * This is used to propagate exports during the computation of export scopes.
*/
- Map<Export, LibraryDependencyNode> dependencyMap =
- new Map<Export, LibraryDependencyNode>();
+ Link<ExportLink> dependencies = const EmptyLink<ExportLink>();
/**
* The export scope for [library] which is gradually computed by the work-list
@@ -389,7 +489,8 @@ class LibraryDependencyNode {
*/
void registerExportDependency(Export export,
LibraryDependencyNode exportingLibraryNode) {
- dependencyMap[export] = exportingLibraryNode;
+ dependencies =
+ dependencies.prepend(new ExportLink(export, exportingLibraryNode));
}
/**
@@ -433,7 +534,7 @@ class LibraryDependencyNode {
/**
* Adds [element] to the export scope for this node. If the [element] name
- * is a duplicate, an error element is inserted into the exscope.
+ * is a duplicate, an error element is inserted into the export scope.
*/
Element addElementToExportScope(Compiler compiler, Element element) {
SourceString name = element.name;
@@ -457,11 +558,11 @@ class LibraryDependencyNode {
*/
bool propagateElement(Element element) {
bool change = false;
- dependencyMap.forEach((Export export, LibraryDependencyNode exportNode) {
- if (exportNode.addElementToPendingExports(export, element)) {
+ for (ExportLink link in dependencies) {
+ if (link.exportElement(element)) {
change = true;
}
- });
+ }
return change;
}
@@ -470,8 +571,7 @@ class LibraryDependencyNode {
* the pending export set was modified. The combinators of [export] are used
* to filter the element.
*/
- bool addElementToPendingExports(Export export, Element element) {
- // TODO(johnniwinther): Use [export] to handle show and hide combinators.
+ bool addElementToPendingExports(Element element) {
if (exportScope[element.name] !== element) {
if (!pendingExportSet.contains(element)) {
pendingExportSet.add(element);
« no previous file with comments | « no previous file | tests/co19/co19-dart2dart.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698