OLD | NEW |
| (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_dart2js; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import '../../compiler.dart' as api; | |
10 import '../elements/elements.dart'; | |
11 import '../apiimpl.dart' as apiimpl; | |
12 import '../scanner/scannerlib.dart'; | |
13 import '../resolution/resolution.dart' show Scope; | |
14 import '../dart2jslib.dart'; | |
15 import '../dart_types.dart'; | |
16 import '../tree/tree.dart'; | |
17 import '../util/util.dart' show Spannable, Link; | |
18 import '../util/characters.dart' show $CR, $LF; | |
19 | |
20 import 'mirrors.dart'; | |
21 import 'mirrors_util.dart'; | |
22 import 'util.dart'; | |
23 | |
24 //------------------------------------------------------------------------------ | |
25 // Utility types and functions for the dart2js mirror system | |
26 //------------------------------------------------------------------------------ | |
27 | |
28 bool _isPrivate(String name) { | |
29 return name.startsWith('_'); | |
30 } | |
31 | |
32 List<ParameterMirror> _parametersFromFunctionSignature( | |
33 Dart2JsMirrorSystem system, | |
34 Dart2JsMethodMirror method, | |
35 FunctionSignature signature) { | |
36 var parameters = <ParameterMirror>[]; | |
37 Link<Element> link = signature.requiredParameters; | |
38 while (!link.isEmpty) { | |
39 parameters.add(new Dart2JsParameterMirror( | |
40 system, method, link.head, isOptional: false, isNamed: false)); | |
41 link = link.tail; | |
42 } | |
43 link = signature.optionalParameters; | |
44 bool isNamed = signature.optionalParametersAreNamed; | |
45 while (!link.isEmpty) { | |
46 parameters.add(new Dart2JsParameterMirror( | |
47 system, method, link.head, isOptional: true, isNamed: isNamed)); | |
48 link = link.tail; | |
49 } | |
50 return parameters; | |
51 } | |
52 | |
53 Dart2JsTypeMirror _convertTypeToTypeMirror( | |
54 Dart2JsMirrorSystem system, | |
55 DartType type, | |
56 InterfaceType defaultType, | |
57 [FunctionSignature functionSignature]) { | |
58 if (type == null) { | |
59 return new Dart2JsInterfaceTypeMirror(system, defaultType); | |
60 } else if (type is InterfaceType) { | |
61 if (type == system.compiler.types.dynamicType) { | |
62 return new Dart2JsDynamicMirror(system, type); | |
63 } else { | |
64 return new Dart2JsInterfaceTypeMirror(system, type); | |
65 } | |
66 } else if (type is TypeVariableType) { | |
67 return new Dart2JsTypeVariableMirror(system, type); | |
68 } else if (type is FunctionType) { | |
69 return new Dart2JsFunctionTypeMirror(system, type, functionSignature); | |
70 } else if (type is VoidType) { | |
71 return new Dart2JsVoidMirror(system, type); | |
72 } else if (type is TypedefType) { | |
73 return new Dart2JsTypedefMirror(system, type); | |
74 } else if (type is MalformedType) { | |
75 // TODO(johnniwinther): We need a mirror on malformed types. | |
76 return system.dynamicType; | |
77 } | |
78 system.compiler.internalError("Unexpected type $type of kind ${type.kind}"); | |
79 } | |
80 | |
81 Iterable<Dart2JsMemberMirror> _convertElementMemberToMemberMirrors( | |
82 Dart2JsContainerMirror library, Element element) { | |
83 if (element.isSynthesized) { | |
84 return const <Dart2JsMemberMirror>[]; | |
85 } else if (element is VariableElement) { | |
86 return <Dart2JsMemberMirror>[new Dart2JsFieldMirror(library, element)]; | |
87 } else if (element is FunctionElement) { | |
88 return <Dart2JsMemberMirror>[new Dart2JsMethodMirror(library, element)]; | |
89 } else if (element is AbstractFieldElement) { | |
90 var members = <Dart2JsMemberMirror>[]; | |
91 AbstractFieldElement field = element; | |
92 if (field.getter != null) { | |
93 members.add(new Dart2JsMethodMirror(library, field.getter)); | |
94 } | |
95 if (field.setter != null) { | |
96 members.add(new Dart2JsMethodMirror(library, field.setter)); | |
97 } | |
98 return members; | |
99 } | |
100 library.mirrors.compiler.internalError( | |
101 "Unexpected member type $element ${element.kind}"); | |
102 } | |
103 | |
104 MethodMirror _convertElementMethodToMethodMirror(Dart2JsContainerMirror library, | |
105 Element element) { | |
106 if (element is FunctionElement) { | |
107 return new Dart2JsMethodMirror(library, element); | |
108 } else { | |
109 return null; | |
110 } | |
111 } | |
112 | |
113 InstanceMirror _convertConstantToInstanceMirror(Dart2JsMirrorSystem mirrors, | |
114 Constant constant) { | |
115 if (constant is BoolConstant) { | |
116 return new Dart2JsBoolConstantMirror(mirrors, constant); | |
117 } else if (constant is NumConstant) { | |
118 return new Dart2JsNumConstantMirror(mirrors, constant); | |
119 } else if (constant is StringConstant) { | |
120 return new Dart2JsStringConstantMirror(mirrors, constant); | |
121 } else if (constant is ListConstant) { | |
122 return new Dart2JsListConstantMirror(mirrors, constant); | |
123 } else if (constant is MapConstant) { | |
124 return new Dart2JsMapConstantMirror(mirrors, constant); | |
125 } else if (constant is TypeConstant) { | |
126 return new Dart2JsTypeConstantMirror(mirrors, constant); | |
127 } else if (constant is FunctionConstant) { | |
128 return new Dart2JsConstantMirror(mirrors, constant); | |
129 } else if (constant is NullConstant) { | |
130 return new Dart2JsNullConstantMirror(mirrors, constant); | |
131 } else if (constant is ConstructedConstant) { | |
132 return new Dart2JsConstructedConstantMirror(mirrors, constant); | |
133 } | |
134 mirrors.compiler.internalError("Unexpected constant $constant"); | |
135 } | |
136 | |
137 class Dart2JsMethodKind { | |
138 static const Dart2JsMethodKind REGULAR = const Dart2JsMethodKind("regular"); | |
139 static const Dart2JsMethodKind GENERATIVE = | |
140 const Dart2JsMethodKind("generative"); | |
141 static const Dart2JsMethodKind REDIRECTING = | |
142 const Dart2JsMethodKind("redirecting"); | |
143 static const Dart2JsMethodKind CONST = const Dart2JsMethodKind("const"); | |
144 static const Dart2JsMethodKind FACTORY = const Dart2JsMethodKind("factory"); | |
145 static const Dart2JsMethodKind GETTER = const Dart2JsMethodKind("getter"); | |
146 static const Dart2JsMethodKind SETTER = const Dart2JsMethodKind("setter"); | |
147 static const Dart2JsMethodKind OPERATOR = const Dart2JsMethodKind("operator"); | |
148 | |
149 final String text; | |
150 | |
151 const Dart2JsMethodKind(this.text); | |
152 | |
153 String toString() => text; | |
154 } | |
155 | |
156 | |
157 String _getOperatorFromOperatorName(String name) { | |
158 Map<String, String> mapping = const { | |
159 'eq': '==', | |
160 'not': '~', | |
161 'index': '[]', | |
162 'indexSet': '[]=', | |
163 'mul': '*', | |
164 'div': '/', | |
165 'mod': '%', | |
166 'tdiv': '~/', | |
167 'add': '+', | |
168 'sub': '-', | |
169 'shl': '<<', | |
170 'shr': '>>', | |
171 'ge': '>=', | |
172 'gt': '>', | |
173 'le': '<=', | |
174 'lt': '<', | |
175 'and': '&', | |
176 'xor': '^', | |
177 'or': '|', | |
178 }; | |
179 String newName = mapping[name]; | |
180 if (newName == null) { | |
181 throw new Exception('Unhandled operator name: $name'); | |
182 } | |
183 return newName; | |
184 } | |
185 | |
186 //------------------------------------------------------------------------------ | |
187 // Analysis entry point. | |
188 //------------------------------------------------------------------------------ | |
189 | |
190 /** | |
191 * Analyzes set of libraries and provides a mirror system which can be used for | |
192 * static inspection of the source code. | |
193 */ | |
194 // TODO(johnniwinther): Move this to [compiler/compiler.dart]. | |
195 Future<MirrorSystem> analyze(List<Uri> libraries, | |
196 Uri libraryRoot, | |
197 Uri packageRoot, | |
198 api.CompilerInputProvider inputProvider, | |
199 api.DiagnosticHandler diagnosticHandler, | |
200 [List<String> options = const <String>[]]) { | |
201 if (!libraryRoot.path.endsWith("/")) { | |
202 throw new ArgumentError("libraryRoot must end with a /"); | |
203 } | |
204 if (packageRoot != null && !packageRoot.path.endsWith("/")) { | |
205 throw new ArgumentError("packageRoot must end with a /"); | |
206 } | |
207 options = new List<String>.from(options); | |
208 options.add('--analyze-only'); | |
209 options.add('--analyze-signatures-only'); | |
210 options.add('--analyze-all'); | |
211 options.add('--categories=Client,Server'); | |
212 | |
213 bool compilationFailed = false; | |
214 void internalDiagnosticHandler(Uri uri, int begin, int end, | |
215 String message, api.Diagnostic kind) { | |
216 if (kind == api.Diagnostic.ERROR || | |
217 kind == api.Diagnostic.CRASH) { | |
218 compilationFailed = true; | |
219 } | |
220 diagnosticHandler(uri, begin, end, message, kind); | |
221 } | |
222 | |
223 Compiler compiler = new apiimpl.Compiler(inputProvider, | |
224 null, | |
225 internalDiagnosticHandler, | |
226 libraryRoot, packageRoot, | |
227 options, | |
228 const {}); | |
229 compiler.librariesToAnalyzeWhenRun = libraries; | |
230 return compiler.run(null).then((bool success) { | |
231 if (success && !compilationFailed) { | |
232 return new Dart2JsMirrorSystem(compiler); | |
233 } else { | |
234 throw new StateError('Failed to create mirror system.'); | |
235 } | |
236 }); | |
237 } | |
238 | |
239 //------------------------------------------------------------------------------ | |
240 // Dart2Js specific extensions of mirror interfaces | |
241 //------------------------------------------------------------------------------ | |
242 | |
243 abstract class Dart2JsMirror implements Mirror { | |
244 Dart2JsMirrorSystem get mirrors; | |
245 } | |
246 | |
247 abstract class Dart2JsDeclarationMirror extends Dart2JsMirror | |
248 implements DeclarationMirror { | |
249 | |
250 bool get isTopLevel => owner != null && owner is LibraryMirror; | |
251 | |
252 bool get isPrivate => _isPrivate(simpleName); | |
253 | |
254 /** | |
255 * Returns the first token for the source of this declaration, not including | |
256 * metadata annotations. | |
257 */ | |
258 Token getBeginToken(); | |
259 | |
260 /** | |
261 * Returns the last token for the source of this declaration. | |
262 */ | |
263 Token getEndToken(); | |
264 | |
265 /** | |
266 * Returns the script for the source of this declaration. | |
267 */ | |
268 Script getScript(); | |
269 } | |
270 | |
271 abstract class Dart2JsTypeMirror extends Dart2JsDeclarationMirror | |
272 implements TypeMirror { | |
273 } | |
274 | |
275 abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror { | |
276 final Dart2JsMirrorSystem mirrors; | |
277 final Element _element; | |
278 List<InstanceMirror> _metadata; | |
279 | |
280 Dart2JsElementMirror(this.mirrors, this._element) { | |
281 assert (mirrors != null); | |
282 assert (_element != null); | |
283 } | |
284 | |
285 /** | |
286 * Returns the element to be used to determine the begin token of this | |
287 * declaration and the metadata associated with this declaration. | |
288 * | |
289 * This indirection is needed to use the [VariableListElement] as the location | |
290 * for type and metadata information on a [VariableElement]. | |
291 */ | |
292 Element get _beginElement => _element; | |
293 | |
294 String get simpleName => _element.name; | |
295 | |
296 bool get isNameSynthetic => false; | |
297 | |
298 /** | |
299 * Computes the first token for this declaration using the begin token of the | |
300 * element node or element position as indicator. | |
301 */ | |
302 Token getBeginToken() { | |
303 // TODO(johnniwinther): Avoid calling [parseNode]. | |
304 Node node = _beginElement.parseNode(mirrors.compiler); | |
305 if (node == null) { | |
306 return _beginElement.position(); | |
307 } | |
308 return node.getBeginToken(); | |
309 } | |
310 | |
311 /** | |
312 * Computes the last token for this declaration using the end token of the | |
313 * element node or element position as indicator. | |
314 */ | |
315 Token getEndToken() { | |
316 // TODO(johnniwinther): Avoid calling [parseNode]. | |
317 Node node = _element.parseNode(mirrors.compiler); | |
318 if (node == null) { | |
319 return _element.position(); | |
320 } | |
321 return node.getEndToken(); | |
322 } | |
323 | |
324 /** | |
325 * Returns the first token for the source of this declaration, including | |
326 * metadata annotations. | |
327 */ | |
328 Token getFirstToken() { | |
329 if (!_beginElement.metadata.isEmpty) { | |
330 for (MetadataAnnotation metadata in _beginElement.metadata) { | |
331 if (metadata.beginToken != null) { | |
332 return metadata.beginToken; | |
333 } | |
334 } | |
335 } | |
336 return getBeginToken(); | |
337 } | |
338 | |
339 Script getScript() => _element.getCompilationUnit().script; | |
340 | |
341 SourceLocation get location { | |
342 Token beginToken = getFirstToken(); | |
343 Script script = getScript(); | |
344 SourceSpan span; | |
345 if (beginToken == null) { | |
346 span = new SourceSpan(script.uri, 0, 0); | |
347 } else { | |
348 Token endToken = getEndToken(); | |
349 span = mirrors.compiler.spanFromTokens(beginToken, endToken, script.uri); | |
350 } | |
351 return new Dart2JsSourceLocation(script, span); | |
352 } | |
353 | |
354 String toString() => _element.toString(); | |
355 | |
356 void _appendCommentTokens(Token commentToken) { | |
357 while (commentToken != null && commentToken.kind == COMMENT_TOKEN) { | |
358 _metadata.add(new Dart2JsCommentInstanceMirror( | |
359 mirrors, commentToken.value)); | |
360 commentToken = commentToken.next; | |
361 } | |
362 } | |
363 | |
364 List<InstanceMirror> get metadata { | |
365 if (_metadata == null) { | |
366 _metadata = <InstanceMirror>[]; | |
367 for (MetadataAnnotation metadata in _element.metadata) { | |
368 _appendCommentTokens(mirrors.compiler.commentMap[metadata.beginToken]); | |
369 metadata.ensureResolved(mirrors.compiler); | |
370 _metadata.add( | |
371 _convertConstantToInstanceMirror(mirrors, metadata.value)); | |
372 } | |
373 _appendCommentTokens(mirrors.compiler.commentMap[getBeginToken()]); | |
374 } | |
375 // TODO(johnniwinther): Return an unmodifiable list instead. | |
376 return new List<InstanceMirror>.from(_metadata); | |
377 } | |
378 | |
379 DeclarationMirror lookupInScope(String name) { | |
380 // TODO(11653): Support lookup of constructors. | |
381 Scope scope = _element.buildScope(); | |
382 Element result; | |
383 int index = name.indexOf('.'); | |
384 if (index != -1) { | |
385 // Lookup [: prefix.id :]. | |
386 String prefix = name.substring(0, index); | |
387 String id = name.substring(index+1); | |
388 result = scope.lookup(prefix); | |
389 if (result != null && result.isPrefix()) { | |
390 PrefixElement prefix = result; | |
391 result = prefix.lookupLocalMember(id); | |
392 } else { | |
393 result = null; | |
394 } | |
395 } else { | |
396 // Lookup [: id :]. | |
397 result = scope.lookup(name); | |
398 } | |
399 if (result == null || result.isPrefix()) return null; | |
400 return _convertElementToDeclarationMirror(mirrors, result); | |
401 } | |
402 | |
403 bool operator ==(var other) { | |
404 if (identical(this, other)) return true; | |
405 if (other == null) return false; | |
406 if (other is! Dart2JsElementMirror) return false; | |
407 return _element == other._element && | |
408 owner == other.owner; | |
409 } | |
410 | |
411 int get hashCode { | |
412 return 13 * _element.hashCode + 17 * owner.hashCode; | |
413 } | |
414 } | |
415 | |
416 abstract class Dart2JsMemberMirror extends Dart2JsElementMirror | |
417 implements MemberMirror { | |
418 | |
419 Dart2JsMemberMirror(Dart2JsMirrorSystem system, Element element) | |
420 : super(system, element); | |
421 | |
422 bool get isConstructor => false; | |
423 | |
424 bool get isVariable => false; | |
425 | |
426 bool get isMethod => false; | |
427 | |
428 bool get isStatic => false; | |
429 | |
430 bool get isParameter => false; | |
431 } | |
432 | |
433 //------------------------------------------------------------------------------ | |
434 // Mirror system implementation. | |
435 //------------------------------------------------------------------------------ | |
436 | |
437 class Dart2JsMirrorSystem extends MirrorSystem { | |
438 final Compiler compiler; | |
439 Map<Uri, Dart2JsLibraryMirror> _libraries; | |
440 Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap; | |
441 | |
442 Dart2JsMirrorSystem(this.compiler) | |
443 : _libraryMap = new Map<LibraryElement, Dart2JsLibraryMirror>(); | |
444 | |
445 void _ensureLibraries() { | |
446 if (_libraries == null) { | |
447 _libraries = new Map<Uri, Dart2JsLibraryMirror>(); | |
448 compiler.libraries.forEach((_, LibraryElement v) { | |
449 var mirror = new Dart2JsLibraryMirror(mirrors, v); | |
450 _libraries[mirror.uri] = mirror; | |
451 _libraryMap[v] = mirror; | |
452 }); | |
453 } | |
454 } | |
455 | |
456 Map<Uri, LibraryMirror> get libraries { | |
457 _ensureLibraries(); | |
458 return new FilteredImmutableMap<Uri, LibraryMirror>(_libraries, | |
459 (library) => new bool.fromEnvironment("list_all_libraries") || | |
460 !library._element.isInternalLibrary); | |
461 } | |
462 | |
463 Dart2JsLibraryMirror _getLibrary(LibraryElement element) => | |
464 _libraryMap[element]; | |
465 | |
466 Dart2JsMirrorSystem get mirrors => this; | |
467 | |
468 TypeMirror get dynamicType => | |
469 _convertTypeToTypeMirror(this, compiler.types.dynamicType, null); | |
470 | |
471 TypeMirror get voidType => | |
472 _convertTypeToTypeMirror(this, compiler.types.voidType, null); | |
473 } | |
474 | |
475 abstract class Dart2JsContainerMirror extends Dart2JsElementMirror | |
476 implements ContainerMirror { | |
477 Map<String, MemberMirror> _members; | |
478 | |
479 Dart2JsContainerMirror(Dart2JsMirrorSystem system, Element element) | |
480 : super(system, element); | |
481 | |
482 void _ensureMembers(); | |
483 | |
484 Map<String, MemberMirror> get members { | |
485 _ensureMembers(); | |
486 return new ImmutableMapWrapper<String, MemberMirror>(_members); | |
487 } | |
488 | |
489 Map<String, MethodMirror> get functions { | |
490 _ensureMembers(); | |
491 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
492 _members, | |
493 (MemberMirror member) => member is MethodMirror ? member : null); | |
494 } | |
495 | |
496 Map<String, MethodMirror> get getters { | |
497 _ensureMembers(); | |
498 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
499 _members, | |
500 (MemberMirror member) => | |
501 member is MethodMirror && member.isGetter ? member : null); | |
502 } | |
503 | |
504 Map<String, MethodMirror> get setters { | |
505 _ensureMembers(); | |
506 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
507 _members, | |
508 (MemberMirror member) => | |
509 member is MethodMirror && member.isSetter ? member : null); | |
510 } | |
511 | |
512 Map<String, VariableMirror> get variables { | |
513 _ensureMembers(); | |
514 return new AsFilteredImmutableMap<String, MemberMirror, VariableMirror>( | |
515 _members, | |
516 (MemberMirror member) => member is VariableMirror ? member : null); | |
517 } | |
518 } | |
519 | |
520 class Dart2JsLibraryMirror extends Dart2JsContainerMirror | |
521 implements LibraryMirror { | |
522 Map<String, ClassMirror> _classes; | |
523 List<LibraryDependencyMirror> _libraryDependencies; | |
524 | |
525 | |
526 Dart2JsLibraryMirror(Dart2JsMirrorSystem system, LibraryElement library) | |
527 : super(system, library); | |
528 | |
529 LibraryElement get _library => _element; | |
530 | |
531 Uri get uri => _library.canonicalUri; | |
532 | |
533 DeclarationMirror get owner => null; | |
534 | |
535 bool get isPrivate => false; | |
536 | |
537 LibraryMirror library() => this; | |
538 | |
539 /** | |
540 * Returns the library name (for libraries with a library tag) or the script | |
541 * file name (for scripts without a library tag). The latter case is used to | |
542 * provide a 'library name' for scripts, to use for instance in dartdoc. | |
543 */ | |
544 String get simpleName { | |
545 if (_library.libraryTag != null) { | |
546 return _library.libraryTag.name.toString(); | |
547 } else { | |
548 // Use the file name as script name. | |
549 String path = _library.canonicalUri.path; | |
550 return path.substring(path.lastIndexOf('/') + 1); | |
551 } | |
552 } | |
553 | |
554 String get qualifiedName => simpleName; | |
555 | |
556 void _ensureClasses() { | |
557 if (_classes == null) { | |
558 _classes = <String, ClassMirror>{}; | |
559 _library.forEachLocalMember((Element e) { | |
560 if (e.isClass()) { | |
561 ClassElement classElement = e; | |
562 classElement.ensureResolved(mirrors.compiler); | |
563 var type = new Dart2JsClassMirror.fromLibrary(this, classElement); | |
564 assert(invariant(_library, !_classes.containsKey(type.simpleName), | |
565 message: "Type name '${type.simpleName}' " | |
566 "is not unique in $_library.")); | |
567 _classes[type.simpleName] = type; | |
568 } else if (e.isTypedef()) { | |
569 var type = new Dart2JsTypedefMirror.fromLibrary(this, | |
570 e.computeType(mirrors.compiler)); | |
571 assert(invariant(_library, !_classes.containsKey(type.simpleName), | |
572 message: "Type name '${type.simpleName}' " | |
573 "is not unique in $_library.")); | |
574 _classes[type.simpleName] = type; | |
575 } | |
576 }); | |
577 } | |
578 } | |
579 | |
580 void _ensureMembers() { | |
581 if (_members == null) { | |
582 _members = <String, MemberMirror>{}; | |
583 _library.forEachLocalMember((Element e) { | |
584 if (!e.isClass() && !e.isTypedef()) { | |
585 // TODO(ahe): I think it is incorrect to filter out classes | |
586 // and typedefs. See http://dartbug.com/10371. | |
587 for (var member in _convertElementMemberToMemberMirrors(this, e)) { | |
588 assert(!_members.containsKey(member.simpleName)); | |
589 _members[member.simpleName] = member; | |
590 } | |
591 } | |
592 }); | |
593 } | |
594 } | |
595 | |
596 Map<String, ClassMirror> get classes { | |
597 _ensureClasses(); | |
598 return new ImmutableMapWrapper<String, ClassMirror>(_classes); | |
599 } | |
600 | |
601 /** | |
602 * Computes the first token of this library using the first library tag as | |
603 * indicator. | |
604 */ | |
605 Token getBeginToken() { | |
606 if (_library.libraryTag != null) { | |
607 return _library.libraryTag.getBeginToken(); | |
608 } else if (!_library.tags.isEmpty) { | |
609 return _library.tags.reverse().head.getBeginToken(); | |
610 } | |
611 return null; | |
612 } | |
613 | |
614 /** | |
615 * Computes the first token of this library using the last library tag as | |
616 * indicator. | |
617 */ | |
618 Token getEndToken() { | |
619 if (!_library.tags.isEmpty) { | |
620 return _library.tags.head.getEndToken(); | |
621 } | |
622 return null; | |
623 } | |
624 | |
625 void _ensureLibraryDependenciesAnalyzed() { | |
626 if (_libraryDependencies == null) { | |
627 _libraryDependencies = <LibraryDependencyMirror>[]; | |
628 for (LibraryTag node in _library.tags.reverse()) { | |
629 LibraryDependency libraryDependency = node.asLibraryDependency(); | |
630 if (libraryDependency != null) { | |
631 LibraryElement targetLibraryElement = | |
632 _library.getLibraryFromTag(libraryDependency); | |
633 assert(targetLibraryElement != null); | |
634 LibraryMirror targetLibrary = | |
635 mirrors._getLibrary(targetLibraryElement); | |
636 _libraryDependencies.add(new Dart2JsLibraryDependencyMirror( | |
637 libraryDependency, this, targetLibrary)); | |
638 } | |
639 } | |
640 } | |
641 } | |
642 | |
643 List<LibraryDependencyMirror> get libraryDependencies { | |
644 _ensureLibraryDependenciesAnalyzed(); | |
645 return _libraryDependencies; | |
646 } | |
647 } | |
648 | |
649 class Dart2JsLibraryDependencyMirror implements LibraryDependencyMirror { | |
650 final LibraryDependency _node; | |
651 final Dart2JsLibraryMirror _sourceLibrary; | |
652 final Dart2JsLibraryMirror _targetLibrary; | |
653 List<CombinatorMirror> _combinators; | |
654 | |
655 Dart2JsLibraryDependencyMirror(this._node, | |
656 this._sourceLibrary, | |
657 this._targetLibrary); | |
658 | |
659 SourceLocation get location { | |
660 return new Dart2JsSourceLocation( | |
661 _sourceLibrary._library.entryCompilationUnit.script, | |
662 _sourceLibrary.mirrors.compiler.spanFromNode(_node)); | |
663 } | |
664 | |
665 List<CombinatorMirror> get combinators { | |
666 if (_combinators == null) { | |
667 _combinators = <CombinatorMirror>[]; | |
668 if (_node.combinators != null) { | |
669 for (Combinator combinator in _node.combinators.nodes) { | |
670 List<String> identifiers = <String>[]; | |
671 for (Identifier identifier in combinator.identifiers.nodes) { | |
672 identifiers.add(identifier.source); | |
673 } | |
674 _combinators.add(new Dart2JsCombinatorMirror( | |
675 identifiers, isShow: combinator.isShow)); | |
676 } | |
677 } | |
678 } | |
679 return _combinators; | |
680 } | |
681 | |
682 LibraryMirror get sourceLibrary => _sourceLibrary; | |
683 | |
684 LibraryMirror get targetLibrary => _targetLibrary; | |
685 | |
686 String get prefix { | |
687 Import import = _node.asImport(); | |
688 if (import != null && import.prefix != null) { | |
689 return import.prefix.source; | |
690 } | |
691 return null; | |
692 } | |
693 | |
694 bool get isImport => _node.asImport() != null; | |
695 | |
696 bool get isExport => _node.asExport() != null; | |
697 } | |
698 | |
699 class Dart2JsCombinatorMirror implements CombinatorMirror { | |
700 final List<String> identifiers; | |
701 final bool isShow; | |
702 | |
703 Dart2JsCombinatorMirror(this.identifiers, {bool isShow: true}) | |
704 : this.isShow = isShow; | |
705 | |
706 bool get isHide => !isShow; | |
707 } | |
708 | |
709 class Dart2JsSourceLocation implements SourceLocation { | |
710 final Script _script; | |
711 final SourceSpan _span; | |
712 int _line; | |
713 int _column; | |
714 | |
715 Dart2JsSourceLocation(this._script, this._span); | |
716 | |
717 int _computeLine() { | |
718 var sourceFile = _script.file; | |
719 if (sourceFile != null) { | |
720 return sourceFile.getLine(offset) + 1; | |
721 } | |
722 var index = 0; | |
723 var lineNumber = 0; | |
724 while (index <= offset && index < sourceText.length) { | |
725 index = sourceText.indexOf('\n', index) + 1; | |
726 if (index <= 0) break; | |
727 lineNumber++; | |
728 } | |
729 return lineNumber; | |
730 } | |
731 | |
732 int get line { | |
733 if (_line == null) { | |
734 _line = _computeLine(); | |
735 } | |
736 return _line; | |
737 } | |
738 | |
739 int _computeColumn() { | |
740 if (length == 0) return 0; | |
741 | |
742 var sourceFile = _script.file; | |
743 if (sourceFile != null) { | |
744 return sourceFile.getColumn(sourceFile.getLine(offset), offset) + 1; | |
745 } | |
746 int index = offset - 1; | |
747 var columnNumber = 0; | |
748 while (0 <= index && index < sourceText.length) { | |
749 columnNumber++; | |
750 var codeUnit = sourceText.codeUnitAt(index); | |
751 if (codeUnit == $CR || codeUnit == $LF) { | |
752 break; | |
753 } | |
754 index--; | |
755 } | |
756 return columnNumber; | |
757 } | |
758 | |
759 int get column { | |
760 if (_column == null) { | |
761 _column = _computeColumn(); | |
762 } | |
763 return _column; | |
764 } | |
765 | |
766 int get offset => _span.begin; | |
767 | |
768 int get length => _span.end - _span.begin; | |
769 | |
770 String get text => _script.text.substring(_span.begin, _span.end); | |
771 | |
772 Uri get sourceUri => _script.uri; | |
773 | |
774 String get sourceText => _script.text; | |
775 } | |
776 | |
777 class Dart2JsParameterMirror extends Dart2JsMemberMirror | |
778 implements ParameterMirror { | |
779 final MethodMirror _method; | |
780 final bool isOptional; | |
781 final bool isNamed; | |
782 | |
783 factory Dart2JsParameterMirror(Dart2JsMirrorSystem system, | |
784 MethodMirror method, | |
785 VariableElement element, | |
786 {bool isOptional: false, | |
787 bool isNamed: false}) { | |
788 if (element is FieldParameterElement) { | |
789 return new Dart2JsFieldParameterMirror(system, | |
790 method, element, isOptional, isNamed); | |
791 } | |
792 return new Dart2JsParameterMirror._normal(system, | |
793 method, element, isOptional, isNamed); | |
794 } | |
795 | |
796 Dart2JsParameterMirror._normal(Dart2JsMirrorSystem system, | |
797 this._method, | |
798 VariableElement element, | |
799 this.isOptional, | |
800 this.isNamed) | |
801 : super(system, element); | |
802 | |
803 Element get _beginElement => _variableElement.variables; | |
804 | |
805 DeclarationMirror get owner => _method; | |
806 | |
807 VariableElement get _variableElement => _element; | |
808 | |
809 String get qualifiedName => '${_method.qualifiedName}#${simpleName}'; | |
810 | |
811 TypeMirror get type => _convertTypeToTypeMirror(mirrors, | |
812 _variableElement.computeType(mirrors.compiler), | |
813 mirrors.compiler.types.dynamicType, | |
814 _variableElement.variables.functionSignature); | |
815 | |
816 | |
817 bool get isFinal => false; | |
818 | |
819 bool get isConst => false; | |
820 | |
821 String get defaultValue { | |
822 if (hasDefaultValue) { | |
823 SendSet expression = _variableElement.cachedNode.asSendSet(); | |
824 return unparse(expression.arguments.head); | |
825 } | |
826 return null; | |
827 } | |
828 | |
829 bool get hasDefaultValue { | |
830 return _variableElement.cachedNode != null && | |
831 _variableElement.cachedNode is SendSet; | |
832 } | |
833 | |
834 bool get isInitializingFormal => false; | |
835 | |
836 VariableMirror get initializedField => null; | |
837 } | |
838 | |
839 class Dart2JsFieldParameterMirror extends Dart2JsParameterMirror { | |
840 | |
841 Dart2JsFieldParameterMirror(Dart2JsMirrorSystem system, | |
842 MethodMirror method, | |
843 FieldParameterElement element, | |
844 bool isOptional, | |
845 bool isNamed) | |
846 : super._normal(system, method, element, isOptional, isNamed); | |
847 | |
848 FieldParameterElement get _fieldParameterElement => _element; | |
849 | |
850 TypeMirror get type { | |
851 VariableListElement variables = _fieldParameterElement.variables; | |
852 VariableDefinitions node = variables.parseNode(mirrors.compiler); | |
853 if (node.type != null) { | |
854 return super.type; | |
855 } | |
856 // Use the field type for initializing formals with no type annotation. | |
857 return _convertTypeToTypeMirror(mirrors, | |
858 _fieldParameterElement.fieldElement.computeType(mirrors.compiler), | |
859 mirrors.compiler.types.dynamicType, | |
860 _variableElement.variables.functionSignature); | |
861 } | |
862 | |
863 bool get isInitializingFormal => true; | |
864 | |
865 VariableMirror get initializedField => new Dart2JsFieldMirror( | |
866 _method.owner, _fieldParameterElement.fieldElement); | |
867 } | |
868 | |
869 //------------------------------------------------------------------------------ | |
870 // Declarations | |
871 //------------------------------------------------------------------------------ | |
872 class Dart2JsClassMirror extends Dart2JsContainerMirror | |
873 implements Dart2JsTypeMirror, ClassMirror { | |
874 final Dart2JsLibraryMirror library; | |
875 List<TypeVariableMirror> _typeVariables; | |
876 | |
877 Dart2JsClassMirror(Dart2JsMirrorSystem system, ClassElement _class) | |
878 : this.library = system._getLibrary(_class.getLibrary()), | |
879 super(system, _class); | |
880 | |
881 ClassElement get _class => _element; | |
882 | |
883 Dart2JsClassMirror.fromLibrary(Dart2JsLibraryMirror library, | |
884 ClassElement _class) | |
885 : this.library = library, | |
886 super(library.mirrors, _class); | |
887 | |
888 DeclarationMirror get owner => library; | |
889 | |
890 String get qualifiedName => '${library.qualifiedName}.${simpleName}'; | |
891 | |
892 void _ensureMembers() { | |
893 if (_members == null) { | |
894 _members = <String, Dart2JsMemberMirror>{}; | |
895 _class.forEachMember((_, e) { | |
896 for (var member in _convertElementMemberToMemberMirrors(this, e)) { | |
897 assert(!_members.containsKey(member.simpleName)); | |
898 _members[member.simpleName] = member; | |
899 } | |
900 }); | |
901 } | |
902 } | |
903 | |
904 Map<String, MethodMirror> get methods => functions; | |
905 | |
906 Map<String, MethodMirror> get constructors { | |
907 _ensureMembers(); | |
908 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
909 _members, (m) => m.isConstructor ? m : null); | |
910 } | |
911 | |
912 bool get isObject => _class == mirrors.compiler.objectClass; | |
913 | |
914 bool get isDynamic => false; | |
915 | |
916 bool get isVoid => false; | |
917 | |
918 bool get isTypeVariable => false; | |
919 | |
920 bool get isTypedef => false; | |
921 | |
922 bool get isFunction => false; | |
923 | |
924 ClassMirror get originalDeclaration => this; | |
925 | |
926 ClassMirror get superclass { | |
927 if (_class.supertype != null) { | |
928 return new Dart2JsInterfaceTypeMirror(mirrors, _class.supertype); | |
929 } | |
930 return null; | |
931 } | |
932 | |
933 ClassMirror get mixin { | |
934 if (_class.isMixinApplication) { | |
935 MixinApplicationElement mixinApplication = _class; | |
936 return new Dart2JsInterfaceTypeMirror(mirrors, | |
937 mixinApplication.mixinType); | |
938 } | |
939 return this; | |
940 } | |
941 | |
942 bool get isNameSynthetic { | |
943 if (_class.isMixinApplication) { | |
944 MixinApplicationElement mixinApplication = _class; | |
945 return mixinApplication.isUnnamedMixinApplication; | |
946 } | |
947 return false; | |
948 } | |
949 | |
950 List<ClassMirror> get superinterfaces { | |
951 var list = <ClassMirror>[]; | |
952 Link<DartType> link = _class.interfaces; | |
953 while (!link.isEmpty) { | |
954 var type = _convertTypeToTypeMirror(mirrors, link.head, | |
955 mirrors.compiler.types.dynamicType); | |
956 list.add(type); | |
957 link = link.tail; | |
958 } | |
959 return list; | |
960 } | |
961 | |
962 bool get isClass => true; | |
963 | |
964 bool get isAbstract => _class.modifiers.isAbstract(); | |
965 | |
966 bool get isOriginalDeclaration => true; | |
967 | |
968 List<TypeMirror> get typeArguments { | |
969 throw new UnsupportedError( | |
970 'Declarations do not have type arguments'); | |
971 } | |
972 | |
973 List<TypeVariableMirror> get typeVariables { | |
974 if (_typeVariables == null) { | |
975 _typeVariables = <TypeVariableMirror>[]; | |
976 _class.ensureResolved(mirrors.compiler); | |
977 for (TypeVariableType typeVariable in _class.typeVariables) { | |
978 _typeVariables.add( | |
979 new Dart2JsTypeVariableMirror(mirrors, typeVariable)); | |
980 } | |
981 } | |
982 return _typeVariables; | |
983 } | |
984 | |
985 bool operator ==(other) { | |
986 if (identical(this, other)) { | |
987 return true; | |
988 } | |
989 if (other is! ClassMirror) { | |
990 return false; | |
991 } | |
992 if (library != other.library) { | |
993 return false; | |
994 } | |
995 if (!identical(isOriginalDeclaration, other.isOriginalDeclaration)) { | |
996 return false; | |
997 } | |
998 return qualifiedName == other.qualifiedName; | |
999 } | |
1000 } | |
1001 | |
1002 class Dart2JsTypedefMirror extends Dart2JsTypeElementMirror | |
1003 implements Dart2JsTypeMirror, TypedefMirror { | |
1004 final Dart2JsLibraryMirror _library; | |
1005 List<TypeVariableMirror> _typeVariables; | |
1006 TypeMirror _definition; | |
1007 | |
1008 Dart2JsTypedefMirror(Dart2JsMirrorSystem system, TypedefType _typedef) | |
1009 : this._library = system._getLibrary(_typedef.element.getLibrary()), | |
1010 super(system, _typedef); | |
1011 | |
1012 Dart2JsTypedefMirror.fromLibrary(Dart2JsLibraryMirror library, | |
1013 TypedefType _typedef) | |
1014 : this._library = library, | |
1015 super(library.mirrors, _typedef); | |
1016 | |
1017 TypedefType get _typedef => _type; | |
1018 | |
1019 String get qualifiedName => '${library.qualifiedName}.${simpleName}'; | |
1020 | |
1021 LibraryMirror get library => _library; | |
1022 | |
1023 bool get isTypedef => true; | |
1024 | |
1025 List<TypeMirror> get typeArguments { | |
1026 throw new UnsupportedError( | |
1027 'Declarations do not have type arguments'); | |
1028 } | |
1029 | |
1030 List<TypeVariableMirror> get typeVariables { | |
1031 if (_typeVariables == null) { | |
1032 _typeVariables = <TypeVariableMirror>[]; | |
1033 for (TypeVariableType typeVariable in _typedef.typeArguments) { | |
1034 _typeVariables.add( | |
1035 new Dart2JsTypeVariableMirror(mirrors, typeVariable)); | |
1036 } | |
1037 } | |
1038 return _typeVariables; | |
1039 } | |
1040 | |
1041 TypeMirror get value { | |
1042 if (_definition == null) { | |
1043 // TODO(johnniwinther): Should be [ensureResolved]. | |
1044 mirrors.compiler.resolveTypedef(_typedef.element); | |
1045 _definition = _convertTypeToTypeMirror( | |
1046 mirrors, | |
1047 _typedef.element.alias, | |
1048 mirrors.compiler.types.dynamicType, | |
1049 _typedef.element.functionSignature); | |
1050 } | |
1051 return _definition; | |
1052 } | |
1053 | |
1054 ClassMirror get originalDeclaration => this; | |
1055 | |
1056 // TODO(johnniwinther): How should a typedef respond to these? | |
1057 ClassMirror get superclass => null; | |
1058 | |
1059 List<ClassMirror> get superinterfaces => const <ClassMirror>[]; | |
1060 | |
1061 // TODO(johnniwinther): Refactor [TypedefMirror] to not extend [ClassMirror] | |
1062 // and remove this. | |
1063 ClassMirror get mixin => this; | |
1064 | |
1065 bool get isClass => false; | |
1066 | |
1067 bool get isOriginalDeclaration => true; | |
1068 | |
1069 bool get isAbstract => false; | |
1070 } | |
1071 | |
1072 class Dart2JsTypeVariableMirror extends Dart2JsTypeElementMirror | |
1073 implements TypeVariableMirror { | |
1074 final TypeVariableType _typeVariableType; | |
1075 ClassMirror _declarer; | |
1076 | |
1077 Dart2JsTypeVariableMirror(Dart2JsMirrorSystem system, | |
1078 TypeVariableType typeVariableType) | |
1079 : this._typeVariableType = typeVariableType, | |
1080 super(system, typeVariableType) { | |
1081 assert(_typeVariableType != null); | |
1082 } | |
1083 | |
1084 | |
1085 String get qualifiedName => '${declarer.qualifiedName}.${simpleName}'; | |
1086 | |
1087 ClassMirror get declarer { | |
1088 if (_declarer == null) { | |
1089 if (_typeVariableType.element.enclosingElement.isClass()) { | |
1090 _declarer = new Dart2JsClassMirror(mirrors, | |
1091 _typeVariableType.element.enclosingElement); | |
1092 } else if (_typeVariableType.element.enclosingElement.isTypedef()) { | |
1093 _declarer = new Dart2JsTypedefMirror(mirrors, | |
1094 _typeVariableType.element.enclosingElement.computeType( | |
1095 mirrors.compiler)); | |
1096 } | |
1097 } | |
1098 return _declarer; | |
1099 } | |
1100 | |
1101 LibraryMirror get library => declarer.library; | |
1102 | |
1103 DeclarationMirror get owner => declarer; | |
1104 | |
1105 bool get isTypeVariable => true; | |
1106 | |
1107 TypeMirror get upperBound => _convertTypeToTypeMirror( | |
1108 mirrors, | |
1109 _typeVariableType.element.bound, | |
1110 mirrors.compiler.objectClass.computeType(mirrors.compiler)); | |
1111 | |
1112 bool operator ==(var other) { | |
1113 if (identical(this, other)) { | |
1114 return true; | |
1115 } | |
1116 if (other is! TypeVariableMirror) { | |
1117 return false; | |
1118 } | |
1119 if (declarer != other.declarer) { | |
1120 return false; | |
1121 } | |
1122 return qualifiedName == other.qualifiedName; | |
1123 } | |
1124 } | |
1125 | |
1126 | |
1127 //------------------------------------------------------------------------------ | |
1128 // Types | |
1129 //------------------------------------------------------------------------------ | |
1130 | |
1131 abstract class Dart2JsTypeElementMirror extends Dart2JsElementMirror | |
1132 implements Dart2JsTypeMirror { | |
1133 final DartType _type; | |
1134 | |
1135 Dart2JsTypeElementMirror(Dart2JsMirrorSystem system, DartType type) | |
1136 : super(system, type.element), | |
1137 this._type = type; | |
1138 | |
1139 String get simpleName => _type.name; | |
1140 | |
1141 DeclarationMirror get owner => library; | |
1142 | |
1143 LibraryMirror get library { | |
1144 return mirrors._getLibrary(_type.element.getLibrary()); | |
1145 } | |
1146 | |
1147 bool get isObject => false; | |
1148 | |
1149 bool get isVoid => false; | |
1150 | |
1151 bool get isDynamic => false; | |
1152 | |
1153 bool get isTypeVariable => false; | |
1154 | |
1155 bool get isTypedef => false; | |
1156 | |
1157 bool get isFunction => false; | |
1158 | |
1159 String toString() => _type.toString(); | |
1160 | |
1161 Map<String, MemberMirror> get members => const <String, MemberMirror>{}; | |
1162 | |
1163 Map<String, MethodMirror> get constructors => const <String, MethodMirror>{}; | |
1164 | |
1165 Map<String, MethodMirror> get methods => const <String, MethodMirror>{}; | |
1166 | |
1167 Map<String, MethodMirror> get getters => const <String, MethodMirror>{}; | |
1168 | |
1169 Map<String, MethodMirror> get setters => const <String, MethodMirror>{}; | |
1170 | |
1171 Map<String, VariableMirror> get variables => const <String, VariableMirror>{}; | |
1172 } | |
1173 | |
1174 class Dart2JsInterfaceTypeMirror extends Dart2JsTypeElementMirror | |
1175 implements ClassMirror { | |
1176 List<TypeMirror> _typeArguments; | |
1177 | |
1178 Dart2JsInterfaceTypeMirror(Dart2JsMirrorSystem system, | |
1179 InterfaceType interfaceType) | |
1180 : super(system, interfaceType); | |
1181 | |
1182 InterfaceType get _interfaceType => _type; | |
1183 | |
1184 bool get isNameSynthetic => originalDeclaration.isNameSynthetic; | |
1185 | |
1186 String get qualifiedName => originalDeclaration.qualifiedName; | |
1187 | |
1188 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1189 Map<String, MemberMirror> get members => originalDeclaration.members; | |
1190 | |
1191 bool get isObject => mirrors.compiler.objectClass == _type.element; | |
1192 | |
1193 // TODO(johnniwinther): How to show malformed types? | |
1194 bool get isDynamic => _type.isDynamic; | |
1195 | |
1196 ClassMirror get originalDeclaration | |
1197 => new Dart2JsClassMirror(mirrors, _type.element); | |
1198 | |
1199 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1200 ClassMirror get superclass => originalDeclaration.superclass; | |
1201 | |
1202 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1203 List<ClassMirror> get superinterfaces => originalDeclaration.superinterfaces; | |
1204 | |
1205 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1206 ClassMirror get mixin { | |
1207 if (originalDeclaration.mixin == originalDeclaration) { | |
1208 return this; | |
1209 } | |
1210 return originalDeclaration.mixin; | |
1211 } | |
1212 | |
1213 bool get isClass => originalDeclaration.isClass; | |
1214 | |
1215 bool get isAbstract => originalDeclaration.isAbstract; | |
1216 | |
1217 bool get isPrivate => originalDeclaration.isPrivate; | |
1218 | |
1219 bool get isOriginalDeclaration => false; | |
1220 | |
1221 List<TypeMirror> get typeArguments { | |
1222 if (_typeArguments == null) { | |
1223 _typeArguments = <TypeMirror>[]; | |
1224 if (!_interfaceType.isRaw) { | |
1225 Link<DartType> type = _interfaceType.typeArguments; | |
1226 while (type != null && type.head != null) { | |
1227 _typeArguments.add(_convertTypeToTypeMirror(mirrors, type.head, | |
1228 mirrors.compiler.types.dynamicType)); | |
1229 type = type.tail; | |
1230 } | |
1231 } | |
1232 } | |
1233 return _typeArguments; | |
1234 } | |
1235 | |
1236 List<TypeVariableMirror> get typeVariables => | |
1237 originalDeclaration.typeVariables; | |
1238 | |
1239 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1240 Map<String, MethodMirror> get constructors => | |
1241 originalDeclaration.constructors; | |
1242 | |
1243 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1244 Map<String, MethodMirror> get methods => originalDeclaration.methods; | |
1245 | |
1246 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1247 Map<String, MethodMirror> get setters => originalDeclaration.setters; | |
1248 | |
1249 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1250 Map<String, MethodMirror> get getters => originalDeclaration.getters; | |
1251 | |
1252 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1253 Map<String, VariableMirror> get variables => originalDeclaration.variables; | |
1254 | |
1255 bool operator ==(other) { | |
1256 if (identical(this, other)) { | |
1257 return true; | |
1258 } | |
1259 if (other is! ClassMirror) { | |
1260 return false; | |
1261 } | |
1262 if (other.isOriginalDeclaration) { | |
1263 return false; | |
1264 } | |
1265 if (originalDeclaration != other.originalDeclaration) { | |
1266 return false; | |
1267 } | |
1268 var thisTypeArguments = typeArguments.iterator; | |
1269 var otherTypeArguments = other.typeArguments.iterator; | |
1270 while (thisTypeArguments.moveNext()) { | |
1271 if (!otherTypeArguments.moveNext()) return false; | |
1272 if (thisTypeArguments.current != otherTypeArguments.current) { | |
1273 return false; | |
1274 } | |
1275 } | |
1276 return !otherTypeArguments.moveNext(); | |
1277 } | |
1278 } | |
1279 | |
1280 | |
1281 class Dart2JsFunctionTypeMirror extends Dart2JsTypeElementMirror | |
1282 implements FunctionTypeMirror { | |
1283 final FunctionSignature _functionSignature; | |
1284 List<ParameterMirror> _parameters; | |
1285 | |
1286 Dart2JsFunctionTypeMirror(Dart2JsMirrorSystem system, | |
1287 FunctionType functionType, this._functionSignature) | |
1288 : super(system, functionType) { | |
1289 assert (_functionSignature != null); | |
1290 } | |
1291 | |
1292 FunctionType get _functionType => _type; | |
1293 | |
1294 // TODO(johnniwinther): Is this the qualified name of a function type? | |
1295 String get qualifiedName => originalDeclaration.qualifiedName; | |
1296 | |
1297 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1298 Map<String, MemberMirror> get members { | |
1299 var method = callMethod; | |
1300 if (method != null) { | |
1301 var map = new Map<String, MemberMirror>.from( | |
1302 originalDeclaration.members); | |
1303 var name = method.qualifiedName; | |
1304 assert(!map.containsKey(name)); | |
1305 map[name] = method; | |
1306 return new ImmutableMapWrapper<String, MemberMirror>(map); | |
1307 } | |
1308 return originalDeclaration.members; | |
1309 } | |
1310 | |
1311 bool get isFunction => true; | |
1312 | |
1313 MethodMirror get callMethod => _convertElementMethodToMethodMirror( | |
1314 mirrors._getLibrary(_functionType.element.getLibrary()), | |
1315 _functionType.element); | |
1316 | |
1317 ClassMirror get originalDeclaration | |
1318 => new Dart2JsClassMirror(mirrors, mirrors.compiler.functionClass); | |
1319 | |
1320 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1321 ClassMirror get superclass => originalDeclaration.superclass; | |
1322 | |
1323 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1324 List<ClassMirror> get superinterfaces => originalDeclaration.superinterfaces; | |
1325 | |
1326 ClassMirror get mixin => this; | |
1327 | |
1328 bool get isClass => originalDeclaration.isClass; | |
1329 | |
1330 bool get isPrivate => originalDeclaration.isPrivate; | |
1331 | |
1332 bool get isOriginalDeclaration => false; | |
1333 | |
1334 bool get isAbstract => false; | |
1335 | |
1336 List<TypeMirror> get typeArguments => const <TypeMirror>[]; | |
1337 | |
1338 List<TypeVariableMirror> get typeVariables => | |
1339 originalDeclaration.typeVariables; | |
1340 | |
1341 TypeMirror get returnType { | |
1342 return _convertTypeToTypeMirror(mirrors, _functionType.returnType, | |
1343 mirrors.compiler.types.dynamicType); | |
1344 } | |
1345 | |
1346 List<ParameterMirror> get parameters { | |
1347 if (_parameters == null) { | |
1348 _parameters = _parametersFromFunctionSignature(mirrors, callMethod, | |
1349 _functionSignature); | |
1350 } | |
1351 return _parameters; | |
1352 } | |
1353 } | |
1354 | |
1355 class Dart2JsVoidMirror extends Dart2JsTypeElementMirror { | |
1356 | |
1357 Dart2JsVoidMirror(Dart2JsMirrorSystem system, VoidType voidType) | |
1358 : super(system, voidType); | |
1359 | |
1360 VoidType get _voidType => _type; | |
1361 | |
1362 String get qualifiedName => simpleName; | |
1363 | |
1364 /** | |
1365 * The void type has no location. | |
1366 */ | |
1367 SourceLocation get location => null; | |
1368 | |
1369 /** | |
1370 * The void type has no library. | |
1371 */ | |
1372 LibraryMirror get library => null; | |
1373 | |
1374 bool get isVoid => true; | |
1375 | |
1376 bool operator ==(other) { | |
1377 if (identical(this, other)) { | |
1378 return true; | |
1379 } | |
1380 if (other is! TypeMirror) { | |
1381 return false; | |
1382 } | |
1383 return other.isVoid; | |
1384 } | |
1385 } | |
1386 | |
1387 | |
1388 class Dart2JsDynamicMirror extends Dart2JsTypeElementMirror { | |
1389 Dart2JsDynamicMirror(Dart2JsMirrorSystem system, InterfaceType voidType) | |
1390 : super(system, voidType); | |
1391 | |
1392 InterfaceType get _dynamicType => _type; | |
1393 | |
1394 String get qualifiedName => simpleName; | |
1395 | |
1396 /** | |
1397 * The dynamic type has no location. | |
1398 */ | |
1399 SourceLocation get location => null; | |
1400 | |
1401 /** | |
1402 * The dynamic type has no library. | |
1403 */ | |
1404 LibraryMirror get library => null; | |
1405 | |
1406 bool get isDynamic => true; | |
1407 | |
1408 bool operator ==(other) { | |
1409 if (identical(this, other)) { | |
1410 return true; | |
1411 } | |
1412 if (other is! TypeMirror) { | |
1413 return false; | |
1414 } | |
1415 return other.isDynamic; | |
1416 } | |
1417 } | |
1418 | |
1419 //------------------------------------------------------------------------------ | |
1420 // Member mirrors implementation. | |
1421 //------------------------------------------------------------------------------ | |
1422 | |
1423 class Dart2JsMethodMirror extends Dart2JsMemberMirror | |
1424 implements MethodMirror { | |
1425 final Dart2JsContainerMirror _objectMirror; | |
1426 final String simpleName; | |
1427 final Dart2JsMethodKind _kind; | |
1428 | |
1429 Dart2JsMethodMirror._internal(Dart2JsContainerMirror objectMirror, | |
1430 FunctionElement function, | |
1431 String this.simpleName, | |
1432 Dart2JsMethodKind this._kind) | |
1433 : this._objectMirror = objectMirror, | |
1434 super(objectMirror.mirrors, function); | |
1435 | |
1436 factory Dart2JsMethodMirror(Dart2JsContainerMirror objectMirror, | |
1437 FunctionElement function) { | |
1438 String realName = function.name; | |
1439 // TODO(ahe): This method should not be calling | |
1440 // Elements.operatorNameToIdentifier. | |
1441 String simpleName = | |
1442 Elements.operatorNameToIdentifier(function.name); | |
1443 Dart2JsMethodKind kind; | |
1444 if (function.kind == ElementKind.GETTER) { | |
1445 kind = Dart2JsMethodKind.GETTER; | |
1446 } else if (function.kind == ElementKind.SETTER) { | |
1447 kind = Dart2JsMethodKind.SETTER; | |
1448 simpleName = '$simpleName='; | |
1449 } else if (function.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
1450 // TODO(johnniwinther): Support detection of redirecting constructors. | |
1451 if (function.modifiers.isConst()) { | |
1452 kind = Dart2JsMethodKind.CONST; | |
1453 } else { | |
1454 kind = Dart2JsMethodKind.GENERATIVE; | |
1455 } | |
1456 } else if (function.modifiers.isFactory()) { | |
1457 kind = Dart2JsMethodKind.FACTORY; | |
1458 } else if (realName == 'unary-') { | |
1459 kind = Dart2JsMethodKind.OPERATOR; | |
1460 // Simple name is 'unary-'. | |
1461 simpleName = Mirror.UNARY_MINUS; | |
1462 } else if (simpleName.startsWith('operator\$')) { | |
1463 String str = simpleName.substring(9); | |
1464 simpleName = 'operator'; | |
1465 kind = Dart2JsMethodKind.OPERATOR; | |
1466 simpleName = _getOperatorFromOperatorName(str); | |
1467 } else { | |
1468 kind = Dart2JsMethodKind.REGULAR; | |
1469 } | |
1470 return new Dart2JsMethodMirror._internal(objectMirror, function, | |
1471 simpleName, kind); | |
1472 } | |
1473 | |
1474 FunctionElement get _function => _element; | |
1475 | |
1476 String get qualifiedName | |
1477 => '${owner.qualifiedName}.$simpleName'; | |
1478 | |
1479 DeclarationMirror get owner => _objectMirror; | |
1480 | |
1481 bool get isTopLevel => _objectMirror is LibraryMirror; | |
1482 | |
1483 bool get isConstructor | |
1484 => isGenerativeConstructor || isConstConstructor || | |
1485 isFactoryConstructor || isRedirectingConstructor; | |
1486 | |
1487 bool get isMethod => !isConstructor; | |
1488 | |
1489 bool get isStatic => _function.modifiers.isStatic(); | |
1490 | |
1491 List<ParameterMirror> get parameters { | |
1492 return _parametersFromFunctionSignature(mirrors, this, | |
1493 _function.computeSignature(mirrors.compiler)); | |
1494 } | |
1495 | |
1496 TypeMirror get returnType => _convertTypeToTypeMirror( | |
1497 mirrors, _function.computeSignature(mirrors.compiler).returnType, | |
1498 mirrors.compiler.types.dynamicType); | |
1499 | |
1500 bool get isAbstract => _function.isAbstract; | |
1501 | |
1502 bool get isRegularMethod => !(isGetter || isSetter || isConstructor); | |
1503 | |
1504 bool get isConstConstructor => _kind == Dart2JsMethodKind.CONST; | |
1505 | |
1506 bool get isGenerativeConstructor => _kind == Dart2JsMethodKind.GENERATIVE; | |
1507 | |
1508 bool get isRedirectingConstructor => _kind == Dart2JsMethodKind.REDIRECTING; | |
1509 | |
1510 bool get isFactoryConstructor => _kind == Dart2JsMethodKind.FACTORY; | |
1511 | |
1512 bool get isGetter => _kind == Dart2JsMethodKind.GETTER; | |
1513 | |
1514 bool get isSetter => _kind == Dart2JsMethodKind.SETTER; | |
1515 | |
1516 bool get isOperator => _kind == Dart2JsMethodKind.OPERATOR; | |
1517 | |
1518 DeclarationMirror lookupInScope(String name) { | |
1519 for (ParameterMirror parameter in parameters) { | |
1520 if (parameter.simpleName == name) { | |
1521 return parameter; | |
1522 } | |
1523 } | |
1524 return super.lookupInScope(name); | |
1525 } | |
1526 } | |
1527 | |
1528 class Dart2JsFieldMirror extends Dart2JsMemberMirror implements VariableMirror { | |
1529 Dart2JsContainerMirror _objectMirror; | |
1530 VariableElement _variable; | |
1531 | |
1532 Dart2JsFieldMirror(Dart2JsContainerMirror objectMirror, | |
1533 VariableElement variable) | |
1534 : this._objectMirror = objectMirror, | |
1535 this._variable = variable, | |
1536 super(objectMirror.mirrors, variable); | |
1537 | |
1538 Element get _beginElement => _variable.variables; | |
1539 | |
1540 String get qualifiedName | |
1541 => '${owner.qualifiedName}.$simpleName'; | |
1542 | |
1543 DeclarationMirror get owner => _objectMirror; | |
1544 | |
1545 bool get isTopLevel => _objectMirror is LibraryMirror; | |
1546 | |
1547 bool get isVariable => true; | |
1548 | |
1549 bool get isStatic => _variable.modifiers.isStatic(); | |
1550 | |
1551 bool get isFinal => _variable.modifiers.isFinal(); | |
1552 | |
1553 bool get isConst => _variable.modifiers.isConst(); | |
1554 | |
1555 TypeMirror get type => _convertTypeToTypeMirror(mirrors, | |
1556 _variable.computeType(mirrors.compiler), | |
1557 mirrors.compiler.types.dynamicType); | |
1558 } | |
1559 | |
1560 //////////////////////////////////////////////////////////////////////////////// | |
1561 // Mirrors on constant values used for metadata. | |
1562 //////////////////////////////////////////////////////////////////////////////// | |
1563 | |
1564 class Dart2JsConstantMirror extends InstanceMirror { | |
1565 final Dart2JsMirrorSystem mirrors; | |
1566 final Constant _constant; | |
1567 | |
1568 Dart2JsConstantMirror(this.mirrors, this._constant); | |
1569 | |
1570 ClassMirror get type { | |
1571 return new Dart2JsClassMirror(mirrors, | |
1572 _constant.computeType(mirrors.compiler).element); | |
1573 } | |
1574 | |
1575 bool get hasReflectee => false; | |
1576 | |
1577 get reflectee { | |
1578 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1579 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1580 } | |
1581 | |
1582 InstanceMirror getField(String fieldName) { | |
1583 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1584 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1585 } | |
1586 } | |
1587 | |
1588 class Dart2JsNullConstantMirror extends Dart2JsConstantMirror { | |
1589 Dart2JsNullConstantMirror(Dart2JsMirrorSystem mirrors, NullConstant constant) | |
1590 : super(mirrors, constant); | |
1591 | |
1592 NullConstant get _constant => super._constant; | |
1593 | |
1594 bool get hasReflectee => true; | |
1595 | |
1596 get reflectee => null; | |
1597 } | |
1598 | |
1599 class Dart2JsBoolConstantMirror extends Dart2JsConstantMirror { | |
1600 Dart2JsBoolConstantMirror(Dart2JsMirrorSystem mirrors, BoolConstant constant) | |
1601 : super(mirrors, constant); | |
1602 | |
1603 Dart2JsBoolConstantMirror.fromBool(Dart2JsMirrorSystem mirrors, bool value) | |
1604 : super(mirrors, value ? new TrueConstant() : new FalseConstant()); | |
1605 | |
1606 BoolConstant get _constant => super._constant; | |
1607 | |
1608 bool get hasReflectee => true; | |
1609 | |
1610 get reflectee => _constant is TrueConstant; | |
1611 } | |
1612 | |
1613 class Dart2JsStringConstantMirror extends Dart2JsConstantMirror { | |
1614 Dart2JsStringConstantMirror(Dart2JsMirrorSystem mirrors, | |
1615 StringConstant constant) | |
1616 : super(mirrors, constant); | |
1617 | |
1618 Dart2JsStringConstantMirror.fromString(Dart2JsMirrorSystem mirrors, | |
1619 String text) | |
1620 : super(mirrors, new StringConstant(new DartString.literal(text))); | |
1621 | |
1622 StringConstant get _constant => super._constant; | |
1623 | |
1624 bool get hasReflectee => true; | |
1625 | |
1626 get reflectee => _constant.value.slowToString(); | |
1627 } | |
1628 | |
1629 class Dart2JsNumConstantMirror extends Dart2JsConstantMirror { | |
1630 Dart2JsNumConstantMirror(Dart2JsMirrorSystem mirrors, | |
1631 NumConstant constant) | |
1632 : super(mirrors, constant); | |
1633 | |
1634 NumConstant get _constant => super._constant; | |
1635 | |
1636 bool get hasReflectee => true; | |
1637 | |
1638 get reflectee => _constant.value; | |
1639 } | |
1640 | |
1641 class Dart2JsListConstantMirror extends Dart2JsConstantMirror | |
1642 implements ListInstanceMirror { | |
1643 Dart2JsListConstantMirror(Dart2JsMirrorSystem mirrors, | |
1644 ListConstant constant) | |
1645 : super(mirrors, constant); | |
1646 | |
1647 ListConstant get _constant => super._constant; | |
1648 | |
1649 int get length => _constant.length; | |
1650 | |
1651 InstanceMirror operator[](int index) { | |
1652 if (index < 0) throw new RangeError('Negative index'); | |
1653 if (index >= _constant.length) throw new RangeError('Index out of bounds'); | |
1654 return _convertConstantToInstanceMirror(mirrors, _constant.entries[index]); | |
1655 } | |
1656 } | |
1657 | |
1658 class Dart2JsMapConstantMirror extends Dart2JsConstantMirror | |
1659 implements MapInstanceMirror { | |
1660 List<String> _listCache; | |
1661 | |
1662 Dart2JsMapConstantMirror(Dart2JsMirrorSystem mirrors, | |
1663 MapConstant constant) | |
1664 : super(mirrors, constant); | |
1665 | |
1666 MapConstant get _constant => super._constant; | |
1667 | |
1668 List<String> get _list { | |
1669 if (_listCache == null) { | |
1670 _listCache = new List<String>(_constant.keys.entries.length); | |
1671 int index = 0; | |
1672 for (StringConstant keyConstant in _constant.keys.entries) { | |
1673 _listCache[index] = keyConstant.value.slowToString(); | |
1674 index++; | |
1675 } | |
1676 } | |
1677 return _listCache; | |
1678 } | |
1679 | |
1680 int get length => _constant.length; | |
1681 | |
1682 Iterable<String> get keys { | |
1683 // TODO(johnniwinther): Return an unmodifiable list instead. | |
1684 return new List<String>.from(_list); | |
1685 } | |
1686 | |
1687 InstanceMirror operator[](String key) { | |
1688 int index = _list.indexOf(key); | |
1689 if (index == -1) return null; | |
1690 return _convertConstantToInstanceMirror(mirrors, _constant.values[index]); | |
1691 } | |
1692 } | |
1693 | |
1694 class Dart2JsTypeConstantMirror extends Dart2JsConstantMirror | |
1695 implements TypeInstanceMirror { | |
1696 | |
1697 Dart2JsTypeConstantMirror(Dart2JsMirrorSystem mirrors, | |
1698 TypeConstant constant) | |
1699 : super(mirrors, constant); | |
1700 | |
1701 TypeConstant get _constant => super._constant; | |
1702 | |
1703 TypeMirror get representedType => _convertTypeToTypeMirror( | |
1704 mirrors, _constant.representedType, mirrors.compiler.types.dynamicType); | |
1705 } | |
1706 | |
1707 class Dart2JsConstructedConstantMirror extends Dart2JsConstantMirror { | |
1708 Map<String,Constant> _fieldMapCache; | |
1709 | |
1710 Dart2JsConstructedConstantMirror(Dart2JsMirrorSystem mirrors, | |
1711 ConstructedConstant constant) | |
1712 : super(mirrors, constant); | |
1713 | |
1714 ConstructedConstant get _constant => super._constant; | |
1715 | |
1716 Map<String,Constant> get _fieldMap { | |
1717 if (_fieldMapCache == null) { | |
1718 _fieldMapCache = new Map<String,Constant>(); | |
1719 if (identical(_constant.type.element.kind, ElementKind.CLASS)) { | |
1720 var index = 0; | |
1721 ClassElement element = _constant.type.element; | |
1722 element.forEachInstanceField((_, Element field) { | |
1723 String fieldName = field.name; | |
1724 _fieldMapCache.putIfAbsent(fieldName, () => _constant.fields[index]); | |
1725 index++; | |
1726 }, includeSuperAndInjectedMembers: true); | |
1727 } | |
1728 } | |
1729 return _fieldMapCache; | |
1730 } | |
1731 | |
1732 InstanceMirror getField(String fieldName) { | |
1733 Constant fieldConstant = _fieldMap[fieldName]; | |
1734 if (fieldConstant != null) { | |
1735 return _convertConstantToInstanceMirror(mirrors, fieldConstant); | |
1736 } | |
1737 return super.getField(fieldName); | |
1738 } | |
1739 } | |
1740 | |
1741 class Dart2JsCommentInstanceMirror implements CommentInstanceMirror { | |
1742 final Dart2JsMirrorSystem mirrors; | |
1743 final String text; | |
1744 String _trimmedText; | |
1745 | |
1746 Dart2JsCommentInstanceMirror(this.mirrors, this.text); | |
1747 | |
1748 ClassMirror get type { | |
1749 return new Dart2JsClassMirror(mirrors, mirrors.compiler.documentClass); | |
1750 } | |
1751 | |
1752 bool get isDocComment => text.startsWith('/**') || text.startsWith('///'); | |
1753 | |
1754 String get trimmedText { | |
1755 if (_trimmedText == null) { | |
1756 _trimmedText = stripComment(text); | |
1757 } | |
1758 return _trimmedText; | |
1759 } | |
1760 | |
1761 bool get hasReflectee => false; | |
1762 | |
1763 get reflectee { | |
1764 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1765 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1766 } | |
1767 | |
1768 InstanceMirror getField(String fieldName) { | |
1769 if (fieldName == 'isDocComment') { | |
1770 return new Dart2JsBoolConstantMirror.fromBool(mirrors, isDocComment); | |
1771 } else if (fieldName == 'text') { | |
1772 return new Dart2JsStringConstantMirror.fromString(mirrors, text); | |
1773 } else if (fieldName == 'trimmedText') { | |
1774 return new Dart2JsStringConstantMirror.fromString(mirrors, trimmedText); | |
1775 } | |
1776 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1777 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1778 } | |
1779 } | |
1780 | |
1781 _convertElementToMembers(Dart2JsLibraryMirror library, Element e) { | |
1782 // TODO(ahe): This method creates new mirror objects which is not correct. | |
1783 if (e.isClass()) { | |
1784 ClassElement classElement = e; | |
1785 classElement.ensureResolved(library.mirrors.compiler); | |
1786 return [new Dart2JsClassMirror.fromLibrary(library, classElement)]; | |
1787 } else if (e.isTypedef()) { | |
1788 return [new Dart2JsTypedefMirror.fromLibrary( | |
1789 library, e.computeType(library.mirrors.compiler))]; | |
1790 } else { | |
1791 return _convertElementMemberToMemberMirrors(library, e); | |
1792 } | |
1793 } | |
1794 | |
1795 /** | |
1796 * Converts [element] into its corresponding [DeclarationMirror], if any. | |
1797 * | |
1798 * If [element] is an [AbstractFieldElement] the mirror for its getter is | |
1799 * returned or, if not present, the mirror for its setter. | |
1800 */ | |
1801 DeclarationMirror _convertElementToDeclarationMirror(Dart2JsMirrorSystem system, | |
1802 Element element) { | |
1803 if (element.isTypeVariable()) { | |
1804 return new Dart2JsTypeVariableMirror( | |
1805 system, element.computeType(system.compiler)); | |
1806 } | |
1807 | |
1808 Dart2JsLibraryMirror library = system._libraryMap[element.getLibrary()]; | |
1809 if (element.isLibrary()) return library; | |
1810 if (element.isTypedef()) { | |
1811 return new Dart2JsTypedefMirror.fromLibrary( | |
1812 library, element.computeType(system.compiler)); | |
1813 } | |
1814 | |
1815 Dart2JsContainerMirror container = library; | |
1816 if (element.getEnclosingClass() != null) { | |
1817 container = new Dart2JsClassMirror.fromLibrary( | |
1818 library, element.getEnclosingClass()); | |
1819 } | |
1820 if (element.isClass()) return container; | |
1821 if (element.isParameter()) { | |
1822 MethodMirror method = _convertElementMethodToMethodMirror( | |
1823 container, element.getOutermostEnclosingMemberOrTopLevel()); | |
1824 // TODO(johnniwinther): Find the right info for [isOptional] and [isNamed]. | |
1825 return new Dart2JsParameterMirror( | |
1826 system, method, element, isOptional: false, isNamed: false); | |
1827 } | |
1828 Iterable<MemberMirror> members = | |
1829 _convertElementMemberToMemberMirrors(container, element); | |
1830 if (members.isEmpty) return null; | |
1831 return members.first; | |
1832 } | |
1833 | |
1834 /** | |
1835 * Experimental API for accessing compilation units defined in a | |
1836 * library. | |
1837 */ | |
1838 // TODO(ahe): Superclasses? Is this really a mirror? | |
1839 class Dart2JsCompilationUnitMirror extends Dart2JsMirror { | |
1840 final Dart2JsLibraryMirror _library; | |
1841 final CompilationUnitElement _element; | |
1842 | |
1843 Dart2JsCompilationUnitMirror(this._element, this._library); | |
1844 | |
1845 Dart2JsMirrorSystem get mirrors => _library.mirrors; | |
1846 | |
1847 List<DeclarationMirror> get members { | |
1848 // TODO(ahe): Should return an immutable List. | |
1849 // TODO(johnniwinther): make sure that these are returned in declaration | |
1850 // order. | |
1851 List<DeclarationMirror> members= <DeclarationMirror>[]; | |
1852 _element.forEachLocalMember((m) { | |
1853 members.addAll(_convertElementToMembers(_library, m)); | |
1854 }); | |
1855 return members; | |
1856 } | |
1857 | |
1858 Uri get uri => _element.script.uri; | |
1859 } | |
1860 | |
1861 /** | |
1862 * Transitional class that allows access to features that have not yet | |
1863 * made it to the mirror API. | |
1864 * | |
1865 * All API in this class is experimental. | |
1866 */ | |
1867 class BackDoor { | |
1868 /// Return the compilation units comprising [library]. | |
1869 static List<Mirror> compilationUnitsOf(Dart2JsLibraryMirror library) { | |
1870 return library._library.compilationUnits.toList().map( | |
1871 (cu) => new Dart2JsCompilationUnitMirror(cu, library)).toList(); | |
1872 } | |
1873 } | |
OLD | NEW |