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

Side by Side Diff: pkg/kernel/lib/library_index.dart

Issue 2706243011: Add LibraryIndex class for finding classes and members by name. (Closed)
Patch Set: Update fasta, and add methods for tolerating missing libaries 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.library_index;
5
6 import 'ast.dart';
7
8 /// Provides name-based access to library, class, and member AST nodes.
9 ///
10 /// When constructed, a given set of libraries are indexed immediately, and
11 /// will not be up-to-date with changes made after it was created.
12 class LibraryIndex {
13 static const String getterPrefix = 'get:';
14 static const String setterPrefix = 'set:';
15
16 /// A special class name that can be used to access the top-level members
17 /// of a library.
18 static const String topLevel = '::';
19
20 final Map<String, _ClassTable> _libraries = <String, _ClassTable>{};
21
22 /// Indexes the libraries with the URIs given in [libraryUris].
23 LibraryIndex(Program program, Iterable<String> libraryUris) {
24 for (var uri in libraryUris) {
25 _libraries[uri] = new _ClassTable();
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 LibraryIndex.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 LibraryIndex.coreLibraries(Program program) {
41 for (var library in program.libraries) {
42 if (library.importUri.scheme == 'dart') {
43 _libraries['${library.importUri}'] = new _ClassTable()..build(library);
44 }
45 }
46 }
47
48 /// Indexes the entire program.
49 ///
50 /// Consider using another constructor to only index the libraries that
51 /// are needed.
52 LibraryIndex.all(Program program) {
53 for (var library in program.libraries) {
54 _libraries['${library.importUri}'] = new _ClassTable()..build(library);
55 }
56 }
57
58 _ClassTable _getLibraryIndex(String uri) {
59 _ClassTable libraryIndex = _libraries[uri];
60 if (libraryIndex == null) {
61 throw "The library '$uri' has not been indexed";
62 }
63 return libraryIndex;
64 }
65
66 /// Returns the library with the given URI.
67 ///
68 /// Throws an error if it does not exist.
69 Library getLibrary(String uri) => _getLibraryIndex(uri).library;
70
71 /// Like [getLibrary] but returns `null` if not found.
72 Library tryGetLibrary(String uri) => _libraries[uri]?.library;
73
74 /// True if the library with the given URI exists and was indexed.
75 bool containsLibrary(String uri) => _libraries.containsKey(uri);
76
77 /// Returns the class with the given name in the given library.
78 ///
79 /// An error is thrown if the class is not found.
80 Class getClass(String library, String className) {
81 return _getLibraryIndex(library).getClass(className);
82 }
83
84 /// Like [getClass] but returns `null` if not found.
85 Class tryGetClass(String library, String className) {
86 return _libraries[library]?.tryGetClass(className);
87 }
88
89 /// Returns the member with the given name, in the given class, in the
90 /// given library.
91 ///
92 /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
93 /// added in front of the member name.
94 ///
95 /// The special class name `::` can be used to access top-level members.
96 ///
97 /// If the member name is private it is considered private to [library].
98 /// It is not possible with this class to lookup members whose name is private
99 /// to a library other than the one containing it.
100 ///
101 /// An error is thrown if the member is not found.
102 Member getMember(String library, String className, String memberName) {
103 return _getLibraryIndex(library).getMember(className, memberName);
104 }
105
106 /// Like [getMember] but returns `null` if not found.
107 Member tryGetMember(String library, String className, String memberName) {
108 return _libraries[library]?.tryGetMember(className, memberName);
109 }
110
111 /// Returns the top-level member with the given name, in the given library.
112 ///
113 /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
114 /// added in front of the member name.
115 ///
116 /// If the member name is private it is considered private to [library].
117 /// It is not possible with this class to lookup members whose name is private
118 /// to a library other than the one containing it.
119 ///
120 /// An error is thrown if the member is not found.
121 Member getTopLevelMember(String library, String memberName) {
122 return getMember(library, topLevel, memberName);
123 }
124
125 /// Like [getTopLevelMember] but returns `null` if not found.
126 Member tryGetTopLevelMember(
127 String library, String className, String memberName) {
128 return tryGetMember(library, topLevel, memberName);
129 }
130 }
131
132 class _ClassTable {
133 Library library;
134 final Map<String, _MemberTable> classes = <String, _MemberTable>{};
135
136 void build(Library library) {
137 this.library = library;
138 classes[LibraryIndex.topLevel] = new _MemberTable.topLevel(this);
139 for (var class_ in library.classes) {
140 classes[class_.name] = new _MemberTable(this, class_);
141 }
142 }
143
144 String get containerName {
145 // For useful error messages, it can be helpful to indicate if the library
146 // is external. If a class or member was not found in an external library,
147 // it might be that it exists in the actual library, but its interface was
148 // not included in this build unit.
149 return library.isExternal
150 ? "external library '${library.importUri}'"
151 : "library '${library.importUri}'";
152 }
153
154 _MemberTable _getClassIndex(String name) {
155 var indexer = classes[name];
156 if (indexer == null) {
157 throw "Class '$name' not found in $containerName";
158 }
159 return indexer;
160 }
161
162 Class getClass(String name) {
163 return _getClassIndex(name).class_;
164 }
165
166 Class tryGetClass(String name) {
167 return classes[name]?.class_;
168 }
169
170 Member getMember(String className, String memberName) {
171 return _getClassIndex(className).getMember(memberName);
172 }
173
174 Member tryGetMember(String className, String memberName) {
175 return classes[className]?.tryGetMember(memberName);
176 }
177 }
178
179 class _MemberTable {
180 final _ClassTable parent;
181 final Class class_; // Null for top-level.
182 final Map<String, Member> members = <String, Member>{};
183
184 Library get library => parent.library;
185
186 _MemberTable(this.parent, this.class_) {
187 class_.procedures.forEach(addMember);
188 class_.fields.forEach(addMember);
189 class_.constructors.forEach(addMember);
190 }
191
192 _MemberTable.topLevel(this.parent) : class_ = null {
193 library.procedures.forEach(addMember);
194 library.fields.forEach(addMember);
195 }
196
197 String getDisambiguatedName(Member member) {
198 if (member is Procedure) {
199 if (member.isGetter) return LibraryIndex.getterPrefix + member.name.name;
200 if (member.isSetter) return LibraryIndex.setterPrefix + member.name.name;
201 }
202 return member.name.name;
203 }
204
205 void addMember(Member member) {
206 if (member.name.isPrivate && member.name.library != library) {
207 // Members whose name is private to other libraries cannot currently
208 // be found with the LibraryIndex class.
209 return;
210 }
211 members[getDisambiguatedName(member)] = member;
212 }
213
214 String get containerName {
215 if (class_ == null) {
216 return "top-level of ${parent.containerName}";
217 } else {
218 return "class '${class_.name}' in ${parent.containerName}";
219 }
220 }
221
222 Member getMember(String name) {
223 var member = members[name];
224 if (member == null) {
225 String message = "A member with disambiguated name '$name' was not found "
226 "in $containerName";
227 var getter = LibraryIndex.getterPrefix + name;
228 var setter = LibraryIndex.setterPrefix + name;
229 if (members[getter] != null || members[setter] != null) {
230 throw "$message. Did you mean '$getter' or '$setter'?";
231 }
232 throw message;
233 }
234 return member;
235 }
236
237 Member tryGetMember(String name) => members[name];
238 }
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