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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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
5 library mirrors_util;
6
7 import 'dart:collection' show Queue, IterableBase;
8
9 import 'source_mirrors.dart';
10
11 //------------------------------------------------------------------------------
12 // Utility functions for using the Mirror API
13 //------------------------------------------------------------------------------
14
15 String nameOf(DeclarationMirror mirror) =>
16 MirrorSystem.getName(mirror.simpleName);
17
18 String qualifiedNameOf(DeclarationMirror mirror) =>
19 MirrorSystem.getName(mirror.qualifiedName);
20
21 // TODO(johnniwinther): Handle private names.
22 Symbol symbolOf(String name, [LibraryMirror library]) => new Symbol(name);
23
24 /**
25 * Return the display name for [mirror].
26 *
27 * The display name is the normal representation of the entity name. In most
28 * cases the display name is the simple name, but for a setter 'foo=' the
29 * display name is simply 'foo' and for the unary minus operator the display
30 * name is 'operator -'. For 'dart:' libraries the display name is the URI and
31 * not the library name, for instance 'dart:core' instead of 'dart.core'.
32 *
33 * The display name is not unique.
34 */
35 String displayName(DeclarationMirror mirror) {
36 if (mirror is LibraryMirror) {
37 LibraryMirror library = mirror;
38 if (library.uri.scheme == 'dart') {
39 return library.uri.toString();
40 }
41 } else if (mirror is MethodMirror) {
42 String simpleName = nameOf(mirror);
43 if (mirror.isSetter) {
44 // Remove trailing '='.
45 return simpleName.substring(0, simpleName.length-1);
46 } else if (mirror.isOperator) {
47 return 'operator ${operatorName(mirror)}';
48 } else if (mirror.isConstructor) {
49 String className = displayName(mirror.owner);
50 if (simpleName == '') {
51 return className;
52 } else {
53 return '$className.$simpleName';
54 }
55 }
56 }
57 return MirrorSystem.getName(mirror.simpleName);
58 }
59
60 /**
61 * Returns the operator name if [methodMirror] is an operator method,
62 * for instance [:'<':] for [:operator <:] and [:'-':] for the unary minus
63 * operator. Return [:null:] if [methodMirror] is not an operator method.
64 */
65 String operatorName(MethodMirror methodMirror) {
66 if (methodMirror.isOperator) {
67 if (methodMirror.simpleName == const Symbol('unary-')) {
68 return '-';
69 } else {
70 return nameOf(methodMirror);
71 }
72 }
73 return null;
74 }
75
76 /**
77 * Returns an iterable over the type declarations directly inheriting from
78 * the declaration of [type] within [mirrors].
79 */
80 Iterable<ClassMirror> computeSubdeclarations(MirrorSystem mirrors,
81 ClassMirror type) {
82 type = type.originalDeclaration;
83 var subtypes = <ClassMirror>[];
84 mirrors.libraries.forEach((_, library) {
85 library.declarations.values
86 .where((mirror) => mirror is ClassMirror)
87 .forEach((ClassMirror otherType) {
88 var superClass = otherType.superclass;
89 if (superClass != null) {
90 superClass = superClass.originalDeclaration;
91 if (superClass == type) {
92 subtypes.add(otherType);
93 }
94 }
95 final superInterfaces = otherType.superinterfaces;
96 for (ClassMirror superInterface in superInterfaces) {
97 superInterface = superInterface.originalDeclaration;
98 if (superInterface == type) {
99 subtypes.add(otherType);
100 }
101 }
102 });
103 });
104 return subtypes;
105 }
106
107 class HierarchyIterable extends IterableBase<ClassMirror> {
108 final bool includeType;
109 final ClassMirror type;
110
111 HierarchyIterable(this.type, {bool includeType})
112 : this.includeType = includeType;
113
114 Iterator<ClassMirror> get iterator =>
115 new HierarchyIterator(type, includeType: includeType);
116 }
117
118 /**
119 * [HierarchyIterator] iterates through the class hierarchy of the provided
120 * type.
121 *
122 * First the superclass relation is traversed, skipping [Object], next the
123 * superinterface relation and finally is [Object] visited. The supertypes are
124 * visited in breadth first order and a superinterface is visited more than once
125 * if implemented through multiple supertypes.
126 */
127 class HierarchyIterator implements Iterator<ClassMirror> {
128 final Queue<ClassMirror> queue = new Queue<ClassMirror>();
129 ClassMirror object;
130 ClassMirror _current;
131
132 HierarchyIterator(ClassMirror type, {bool includeType}) {
133 if (includeType) {
134 queue.add(type);
135 } else {
136 push(type);
137 }
138 }
139
140 ClassMirror push(ClassMirror type) {
141 if (type.superclass != null) {
142 if (isObject(type.superclass)) {
143 object = type.superclass;
144 } else {
145 queue.addFirst(type.superclass);
146 }
147 }
148 queue.addAll(type.superinterfaces);
149 return type;
150 }
151
152 ClassMirror get current => _current;
153
154 bool moveNext() {
155 _current = null;
156 if (queue.isEmpty) {
157 if (object == null) return false;
158 _current = object;
159 object = null;
160 return true;
161 } else {
162 _current = push(queue.removeFirst());
163 return true;
164 }
165 }
166 }
167
168 LibraryMirror getLibrary(DeclarationMirror declaration) {
169 while (declaration != null && declaration is! LibraryMirror) {
170 declaration = declaration.owner;
171 }
172 return declaration;
173 }
174
175 Iterable<DeclarationMirror> membersOf(
176 Map<Symbol, DeclarationMirror> declarations) {
177 return declarations.values.where(
178 (mirror) => mirror is MethodMirror || mirror is VariableMirror);
179 }
180
181 Iterable<TypeMirror> classesOf(
182 Map<Symbol, DeclarationMirror> declarations) {
183 return new _TypeOfIterable<ClassMirror>(declarations.values);
184 }
185
186 Iterable<TypeMirror> typesOf(
187 Map<Symbol, DeclarationMirror> declarations) {
188 return new _TypeOfIterable<TypeMirror>(declarations.values);
189 }
190
191 Iterable<MethodMirror> methodsOf(
192 Map<Symbol, DeclarationMirror> declarations) {
193 return anyMethodOf(declarations).where((mirror) => mirror.isRegularMethod);
194 }
195
196 Iterable<MethodMirror> constructorsOf(
197 Map<Symbol, DeclarationMirror> declarations) {
198 return anyMethodOf(declarations).where((mirror) => mirror.isConstructor);
199 }
200
201 Iterable<MethodMirror> settersOf(
202 Map<Symbol, DeclarationMirror> declarations) {
203 return anyMethodOf(declarations).where((mirror) => mirror.isSetter);
204 }
205
206 Iterable<MethodMirror> gettersOf(
207 Map<Symbol, DeclarationMirror> declarations) {
208 return anyMethodOf(declarations).where((mirror) => mirror.isGetter);
209 }
210
211 Iterable<MethodMirror> anyMethodOf(
212 Map<Symbol, DeclarationMirror> declarations) {
213 return new _TypeOfIterable<MethodMirror>(declarations.values);
214 }
215
216 Iterable<VariableMirror> variablesOf(
217 Map<Symbol, DeclarationMirror> declarations) {
218 return new _TypeOfIterable<VariableMirror>(declarations.values);
219 }
220
221 class _TypeOfIterable<T> extends IterableBase<T> {
222 final Iterable _source;
223
224 _TypeOfIterable(this._source);
225
226 Iterator<T> get iterator => new _TypeOfIterator<T>(_source.iterator);
227 }
228
229 class _TypeOfIterator<T> implements Iterator<T> {
230 final Iterator _source;
231
232 T get current => _source.current;
233
234 _TypeOfIterator(this._source);
235
236 bool moveNext() {
237 while(_source.moveNext()) {
238 if (_source.current is T) {
239 return true;
240 }
241 }
242 return false;
243 }
244 }
245
246 bool isObject(TypeMirror mirror) =>
247 mirror is ClassMirror && mirror.superclass == null;
248
249 /// Returns `true` if [cls] is declared in a private dart library.
250 bool isFromPrivateDartLibrary(ClassMirror cls) {
251 if (isMixinApplication(cls)) cls = cls.mixin;
252 var uri = getLibrary(cls).uri;
253 return uri.scheme == 'dart' && uri.path.startsWith('_');
254 }
255
256 /// Returns `true` if [mirror] reflects a mixin application.
257 bool isMixinApplication(Mirror mirror) {
258 return mirror is ClassMirror && mirror.mixin != mirror;
259 }
260
261 /**
262 * Returns the superclass of [cls] skipping unnamed mixin applications.
263 *
264 * For instance, for all of the following definitions this method returns [:B:].
265 *
266 * class A extends B {}
267 * class A extends B with C1, C2 {}
268 * class A extends B implements D1, D2 {}
269 * class A extends B with C1, C2 implements D1, D2 {}
270 * class A = B with C1, C2;
271 * abstract class A = B with C1, C2 implements D1, D2;
272 */
273 ClassSourceMirror getSuperclass(ClassSourceMirror cls) {
274 ClassSourceMirror superclass = cls.superclass;
275 while (isMixinApplication(superclass) && superclass.isNameSynthetic) {
276 superclass = superclass.superclass;
277 }
278 return superclass;
279 }
280
281 /**
282 * Returns the mixins directly applied to [cls].
283 *
284 * For instance, for all of the following definitions this method returns
285 * [:C1, C2:].
286 *
287 * class A extends B with C1, C2 {}
288 * class A extends B with C1, C2 implements D1, D2 {}
289 * class A = B with C1, C2;
290 * abstract class A = B with C1, C2 implements D1, D2;
291 */
292 Iterable<ClassSourceMirror> getAppliedMixins(ClassSourceMirror cls) {
293 List<ClassSourceMirror> mixins = <ClassSourceMirror>[];
294 ClassSourceMirror superclass = cls.superclass;
295 while (isMixinApplication(superclass) && superclass.isNameSynthetic) {
296 mixins.add(superclass.mixin);
297 superclass = superclass.superclass;
298 }
299 if (mixins.length > 1) {
300 mixins = new List<ClassSourceMirror>.from(mixins.reversed);
301 }
302 if (isMixinApplication(cls)) {
303 mixins.add(cls.mixin);
304 }
305 return mixins;
306 }
307
308 /**
309 * Returns the superinterfaces directly and explicitly implemented by [cls].
310 *
311 * For instance, for all of the following definitions this method returns
312 * [:D1, D2:].
313 *
314 * class A extends B implements D1, D2 {}
315 * class A extends B with C1, C2 implements D1, D2 {}
316 * abstract class A = B with C1, C2 implements D1, D2;
317 */
318 Iterable<ClassMirror> getExplicitInterfaces(ClassMirror cls) {
319 if (isMixinApplication(cls)) {
320 bool first = true;
321 ClassMirror mixin = cls.mixin;
322 bool filter(ClassMirror superinterface) {
323 if (first && superinterface == mixin) {
324 first = false;
325 return false;
326 }
327 return true;
328 }
329 return cls.superinterfaces.where(filter);
330 }
331 return cls.superinterfaces;
332 }
333
334 final RegExp _singleLineCommentStart = new RegExp(r'^///? ?(.*)');
335 final RegExp _multiLineCommentStartEnd =
336 new RegExp(r'^/\*\*? ?([\s\S]*)\*/$', multiLine: true);
337 final RegExp _multiLineCommentLineStart = new RegExp(r'^[ \t]*\* ?(.*)');
338
339 /**
340 * Pulls the raw text out of a comment (i.e. removes the comment
341 * characters).
342 */
343 String stripComment(String comment) {
344 Match match = _singleLineCommentStart.firstMatch(comment);
345 if (match != null) {
346 return match[1];
347 }
348 match = _multiLineCommentStartEnd.firstMatch(comment);
349 if (match != null) {
350 comment = match[1];
351 var sb = new StringBuffer();
352 List<String> lines = comment.split('\n');
353 for (int index = 0 ; index < lines.length ; index++) {
354 String line = lines[index];
355 if (index == 0) {
356 sb.write(line); // Add the first line unprocessed.
357 continue;
358 }
359 sb.write('\n');
360 match = _multiLineCommentLineStart.firstMatch(line);
361 if (match != null) {
362 sb.write(match[1]);
363 } else if (index < lines.length-1 || !line.trim().isEmpty) {
364 // Do not add the last line if it only contains white space.
365 // This interprets cases like
366 // /*
367 // * Foo
368 // */
369 // as "\nFoo\n" and not as "\nFoo\n ".
370 sb.write(line);
371 }
372 }
373 return sb.toString();
374 }
375 throw new ArgumentError('Invalid comment $comment');
376 }
377
378 /**
379 * Looks up [name] in the scope [declaration].
380 *
381 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of
382 * [declaration] and if unresolved 'a.b' is looked in the scope of
383 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is
384 * then looked up in the local scope of the previous result.
385 *
386 * For instance, assumming that [:Iterable:] is imported into the scope of
387 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type
388 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the
389 * [:element:] parameter of the [:contains:] method on [:Iterable:].
390 */
391 DeclarationMirror lookupQualifiedInScope(DeclarationSourceMirror declaration,
392 String name) {
393 // TODO(11653): Support lookup of constructors using the [:new Foo:]
394 // syntax.
395 int offset = 1;
396 List<String> parts = name.split('.');
397 DeclarationMirror result = declaration.lookupInScope(parts[0]);
398 if (result == null && parts.length > 1) {
399 // Try lookup of `prefix.id`.
400 result = declaration.lookupInScope('${parts[0]}.${parts[1]}');
401 offset = 2;
402 }
403 if (result == null) return null;
404 LibraryMirror library = getLibrary(result);
405 while (result != null && offset < parts.length) {
406 result = _lookupLocal(result, symbolOf(parts[offset++], library));
407 }
408 return result;
409 }
410
411 DeclarationMirror _lookupLocal(Mirror mirror, Symbol id) {
412 DeclarationMirror result;
413 if (mirror is LibraryMirror) {
414 // Try member lookup.
415 result = mirror.declarations[id];
416 } else if (mirror is ClassMirror) {
417 // Try member lookup.
418 result = mirror.declarations[id];
419 if (result != null) return result;
420 // Try type variables.
421 result = mirror.typeVariables.firstWhere(
422 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null);
423 } else if (mirror is MethodMirror) {
424 result = mirror.parameters.firstWhere(
425 (ParameterMirror p) => p.simpleName == id, orElse: () => null);
426 }
427 return result;
428
429 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698