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

Unified Diff: pkg/kernel/lib/lookup_table.dart

Issue 2712983002: Add LookupTable class for finding classes and members by name.
Patch Set: Created 3 years, 10 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 | « pkg/kernel/lib/core_types.dart ('k') | pkg/kernel/lib/transformations/continuation.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/lookup_table.dart
diff --git a/pkg/kernel/lib/lookup_table.dart b/pkg/kernel/lib/lookup_table.dart
new file mode 100644
index 0000000000000000000000000000000000000000..bef64d03b4fa7cdbf7fa40e8ba85b4c447254d0c
--- /dev/null
+++ b/pkg/kernel/lib/lookup_table.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+library kernel.lookup_table;
+
+import 'ast.dart';
+
+/// Provides name-based access to library, class, and member AST nodes.
+///
+/// When constructed, the lookup table indexes a given set of libraries, and
+/// will not be up-to-date with changes made after it was created.
+class LookupTable {
+ static const String getterPrefix = 'get:';
+ static const String setterPrefix = 'set:';
+
+ /// A name that can be used as a class name to access the top-level members
+ /// of a library.
+ static const String topLevel = '::';
+
+ final Map<String, _LibraryIndex> _libraries = <String, _LibraryIndex>{};
+
+ /// Indexes the libraries with the URIs given in [libraryUris].
+ LookupTable(Program program, Iterable<String> libraryUris) {
+ for (var uri in libraryUris) {
+ _libraries[uri] = new _LibraryIndex();
+ }
+ for (var library in program.libraries) {
+ var index = _libraries['${library.importUri}'];
+ if (index != null) {
+ index.build(library);
+ }
+ }
+ }
+
+ /// Indexes the libraries with the URIs given in [libraryUris].
+ LookupTable.byUri(Program program, Iterable<Uri> libraryUris)
+ : this(program, libraryUris.map((uri) => '$uri'));
+
+ /// Indexes the libraries with the URIs given in [libraryUris].
+ LookupTable.coreLibraries(Program program) {
+ for (var library in program.libraries) {
+ if (library.importUri.scheme == 'dart') {
+ _libraries['${library.importUri}'] = new _LibraryIndex()
+ ..build(library);
+ }
+ }
+ }
+
+ /// Indexes the entire program.
+ ///
+ /// Consider using another constructor to only index the libraries that
+ /// are needed.
+ LookupTable.all(Program program) {
+ for (var library in program.libraries) {
+ _libraries['${library.importUri}'] = new _LibraryIndex()..build(library);
+ }
+ }
+
+ _LibraryIndex _getLibraryIndex(String uri) {
+ _LibraryIndex libraryIndex = _libraries[uri];
+ if (libraryIndex == null) {
+ throw "The library '$uri' has not been indexed";
+ }
+ return libraryIndex;
+ }
+
+ Library getLibrary(String uri) => _getLibraryIndex(uri).library;
+
+ /// Returns the class with the given name in the given library.
+ ///
+ /// An error is thrown if the class is not found.
+ Class getClass(String library, String className) {
+ return _getLibraryIndex(library).getClass(className);
+ }
+
+ /// Returns the member with the given name, in the given class, in the
+ /// given library.
+ ///
+ /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
+ /// added in front of the member name.
+ ///
+ /// The special class name `::` can be used to access top-level members.
+ ///
+ /// If the member name is private it is considered private to [library].
+ /// It is not possible with this class to lookup members whose name is private
+ /// to a library other than the one containing it.
+ ///
+ /// An error is thrown if the member is not found.
+ Member getMember(String library, String className, String memberName) {
+ return _getLibraryIndex(library).getMember(className, memberName);
+ }
+
+ /// Returns the top-level member with the given name, in the given library.
+ ///
+ /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
+ /// added in front of the member name.
+ ///
+ /// If the member name is private it is considered private to [library].
+ /// It is not possible with this class to lookup members whose name is private
+ /// to a library other than the one containing it.
+ ///
+ /// An error is thrown if the member is not found.
+ Member getTopLevelMember(String library, String memberName) {
+ return getMember(library, topLevel, memberName);
+ }
+}
+
+class _LibraryIndex {
+ Library library;
+ final Map<String, _ClassIndex> classes = <String, _ClassIndex>{};
+
+ void build(Library library) {
+ this.library = library;
+ classes[LookupTable.topLevel] = new _ClassIndex.topLevel(this);
+ for (var class_ in library.classes) {
+ classes[class_.name] = new _ClassIndex(this, class_);
+ }
+ }
+
+ String get containerName {
+ // It can be helpful to indicate if the library is external, since then
+ // the class might be in the library, but just not seen from this build
+ // unit.
+ return library.isExternal
+ ? "external library '${library.importUri}'"
+ : "library '${library.importUri}'";
+ }
+
+ _ClassIndex _getClassIndex(String name) {
+ var indexer = classes[name];
+ if (indexer == null) {
+ throw "Class '$name' not found in $containerName";
+ }
+ return indexer;
+ }
+
+ Class getClass(String name) {
+ return _getClassIndex(name).class_;
+ }
+
+ Member getMember(String className, String memberName) {
+ return _getClassIndex(className).getMember(memberName);
+ }
+}
+
+class _ClassIndex {
+ final _LibraryIndex parent;
+ final Class class_; // Null for top-level.
+ final Map<String, Member> members = <String, Member>{};
+
+ Library get library => parent.library;
+
+ _ClassIndex(this.parent, this.class_) {
+ class_.procedures.forEach(addMember);
+ class_.fields.forEach(addMember);
+ class_.constructors.forEach(addMember);
+ }
+
+ _ClassIndex.topLevel(this.parent) : class_ = null {
+ library.procedures.forEach(addMember);
+ library.fields.forEach(addMember);
+ }
+
+ String getDisambiguatedName(Member member) {
+ if (member is Procedure) {
+ if (member.isGetter) return LookupTable.getterPrefix + member.name.name;
+ if (member.isSetter) return LookupTable.setterPrefix + member.name.name;
+ }
+ return member.name.name;
+ }
+
+ void addMember(Member member) {
+ if (member.name.isPrivate && member.name.library != library) {
+ // Members whose name is private to other libraries cannot currently
+ // be found with the LookupTable.
+ return;
+ }
+ members[getDisambiguatedName(member)] = member;
+ }
+
+ String get containerName {
+ if (class_ == null) {
+ return "top-level of ${parent.containerName}";
+ } else {
+ return "class '${class_.name}' in ${parent.containerName}";
+ }
+ }
+
+ Member getMember(String name) {
+ var member = members[name];
+ if (member == null) {
+ String message = "A member with disambiguated name '$name' was not found "
+ "in $containerName";
+ var getter = LookupTable.getterPrefix + name;
+ var setter = LookupTable.setterPrefix + name;
+ if (members[getter] != null || members[setter] != null) {
+ throw "$message. Did you mean '$getter' or '$setter'?";
+ }
+ throw message;
+ }
+ return member;
+ }
+}
« no previous file with comments | « pkg/kernel/lib/core_types.dart ('k') | pkg/kernel/lib/transformations/continuation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698