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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4 library kernel.lookup_table;
5
6 import 'ast.dart';
7
8 /// Provides name-based access to library, class, and member AST nodes.
9 ///
10 /// When constructed, the lookup table indexes a given set of libraries, and
11 /// will not be up-to-date with changes made after it was created.
12 class LookupTable {
13 static const String getterPrefix = 'get:';
14 static const String setterPrefix = 'set:';
15
16 /// A name that can be used as a class name to access the top-level members
17 /// of a library.
18 static const String topLevel = '::';
19
20 final Map<String, _LibraryIndex> _libraries = <String, _LibraryIndex>{};
21
22 /// Indexes the libraries with the URIs given in [libraryUris].
23 LookupTable(Program program, Iterable<String> libraryUris) {
24 for (var uri in libraryUris) {
25 _libraries[uri] = new _LibraryIndex();
26 }
27 for (var library in program.libraries) {
28 var index = _libraries['${library.importUri}'];
29 if (index != null) {
30 index.build(library);
31 }
32 }
33 }
34
35 /// Indexes the libraries with the URIs given in [libraryUris].
36 LookupTable.byUri(Program program, Iterable<Uri> libraryUris)
37 : this(program, libraryUris.map((uri) => '$uri'));
38
39 /// Indexes the libraries with the URIs given in [libraryUris].
40 LookupTable.coreLibraries(Program program) {
41 for (var library in program.libraries) {
42 if (library.importUri.scheme == 'dart') {
43 _libraries['${library.importUri}'] = new _LibraryIndex()
44 ..build(library);
45 }
46 }
47 }
48
49 /// Indexes the entire program.
50 ///
51 /// Consider using another constructor to only index the libraries that
52 /// are needed.
53 LookupTable.all(Program program) {
54 for (var library in program.libraries) {
55 _libraries['${library.importUri}'] = new _LibraryIndex()..build(library);
56 }
57 }
58
59 _LibraryIndex _getLibraryIndex(String uri) {
60 _LibraryIndex libraryIndex = _libraries[uri];
61 if (libraryIndex == null) {
62 throw "The library '$uri' has not been indexed";
63 }
64 return libraryIndex;
65 }
66
67 Library getLibrary(String uri) => _getLibraryIndex(uri).library;
68
69 /// Returns the class with the given name in the given library.
70 ///
71 /// An error is thrown if the class is not found.
72 Class getClass(String library, String className) {
73 return _getLibraryIndex(library).getClass(className);
74 }
75
76 /// Returns the member with the given name, in the given class, in the
77 /// given library.
78 ///
79 /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
80 /// added in front of the member name.
81 ///
82 /// The special class name `::` can be used to access top-level members.
83 ///
84 /// If the member name is private it is considered private to [library].
85 /// It is not possible with this class to lookup members whose name is private
86 /// to a library other than the one containing it.
87 ///
88 /// An error is thrown if the member is not found.
89 Member getMember(String library, String className, String memberName) {
90 return _getLibraryIndex(library).getMember(className, memberName);
91 }
92
93 /// Returns the top-level member with the given name, in the given library.
94 ///
95 /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
96 /// added in front of the member name.
97 ///
98 /// If the member name is private it is considered private to [library].
99 /// It is not possible with this class to lookup members whose name is private
100 /// to a library other than the one containing it.
101 ///
102 /// An error is thrown if the member is not found.
103 Member getTopLevelMember(String library, String memberName) {
104 return getMember(library, topLevel, memberName);
105 }
106 }
107
108 class _LibraryIndex {
109 Library library;
110 final Map<String, _ClassIndex> classes = <String, _ClassIndex>{};
111
112 void build(Library library) {
113 this.library = library;
114 classes[LookupTable.topLevel] = new _ClassIndex.topLevel(this);
115 for (var class_ in library.classes) {
116 classes[class_.name] = new _ClassIndex(this, class_);
117 }
118 }
119
120 String get containerName {
121 // It can be helpful to indicate if the library is external, since then
122 // the class might be in the library, but just not seen from this build
123 // unit.
124 return library.isExternal
125 ? "external library '${library.importUri}'"
126 : "library '${library.importUri}'";
127 }
128
129 _ClassIndex _getClassIndex(String name) {
130 var indexer = classes[name];
131 if (indexer == null) {
132 throw "Class '$name' not found in $containerName";
133 }
134 return indexer;
135 }
136
137 Class getClass(String name) {
138 return _getClassIndex(name).class_;
139 }
140
141 Member getMember(String className, String memberName) {
142 return _getClassIndex(className).getMember(memberName);
143 }
144 }
145
146 class _ClassIndex {
147 final _LibraryIndex parent;
148 final Class class_; // Null for top-level.
149 final Map<String, Member> members = <String, Member>{};
150
151 Library get library => parent.library;
152
153 _ClassIndex(this.parent, this.class_) {
154 class_.procedures.forEach(addMember);
155 class_.fields.forEach(addMember);
156 class_.constructors.forEach(addMember);
157 }
158
159 _ClassIndex.topLevel(this.parent) : class_ = null {
160 library.procedures.forEach(addMember);
161 library.fields.forEach(addMember);
162 }
163
164 String getDisambiguatedName(Member member) {
165 if (member is Procedure) {
166 if (member.isGetter) return LookupTable.getterPrefix + member.name.name;
167 if (member.isSetter) return LookupTable.setterPrefix + member.name.name;
168 }
169 return member.name.name;
170 }
171
172 void addMember(Member member) {
173 if (member.name.isPrivate && member.name.library != library) {
174 // Members whose name is private to other libraries cannot currently
175 // be found with the LookupTable.
176 return;
177 }
178 members[getDisambiguatedName(member)] = member;
179 }
180
181 String get containerName {
182 if (class_ == null) {
183 return "top-level of ${parent.containerName}";
184 } else {
185 return "class '${class_.name}' in ${parent.containerName}";
186 }
187 }
188
189 Member getMember(String name) {
190 var member = members[name];
191 if (member == null) {
192 String message = "A member with disambiguated name '$name' was not found "
193 "in $containerName";
194 var getter = LookupTable.getterPrefix + name;
195 var setter = LookupTable.setterPrefix + name;
196 if (members[getter] != null || members[setter] != null) {
197 throw "$message. Did you mean '$getter' or '$setter'?";
198 }
199 throw message;
200 }
201 return member;
202 }
203 }
OLDNEW
« 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