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) => !library._element.isInternalLibrary); | |
460 } | |
461 | |
462 Dart2JsLibraryMirror _getLibrary(LibraryElement element) => | |
463 _libraryMap[element]; | |
464 | |
465 Dart2JsMirrorSystem get mirrors => this; | |
466 | |
467 TypeMirror get dynamicType => | |
468 _convertTypeToTypeMirror(this, compiler.types.dynamicType, null); | |
469 | |
470 TypeMirror get voidType => | |
471 _convertTypeToTypeMirror(this, compiler.types.voidType, null); | |
472 } | |
473 | |
474 abstract class Dart2JsContainerMirror extends Dart2JsElementMirror | |
475 implements ContainerMirror { | |
476 Map<String, MemberMirror> _members; | |
477 | |
478 Dart2JsContainerMirror(Dart2JsMirrorSystem system, Element element) | |
479 : super(system, element); | |
480 | |
481 void _ensureMembers(); | |
482 | |
483 Map<String, MemberMirror> get members { | |
484 _ensureMembers(); | |
485 return new ImmutableMapWrapper<String, MemberMirror>(_members); | |
486 } | |
487 | |
488 Map<String, MethodMirror> get functions { | |
489 _ensureMembers(); | |
490 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
491 _members, | |
492 (MemberMirror member) => member is MethodMirror ? member : null); | |
493 } | |
494 | |
495 Map<String, MethodMirror> get getters { | |
496 _ensureMembers(); | |
497 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
498 _members, | |
499 (MemberMirror member) => | |
500 member is MethodMirror && member.isGetter ? member : null); | |
501 } | |
502 | |
503 Map<String, MethodMirror> get setters { | |
504 _ensureMembers(); | |
505 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
506 _members, | |
507 (MemberMirror member) => | |
508 member is MethodMirror && member.isSetter ? member : null); | |
509 } | |
510 | |
511 Map<String, VariableMirror> get variables { | |
512 _ensureMembers(); | |
513 return new AsFilteredImmutableMap<String, MemberMirror, VariableMirror>( | |
514 _members, | |
515 (MemberMirror member) => member is VariableMirror ? member : null); | |
516 } | |
517 } | |
518 | |
519 class Dart2JsLibraryMirror extends Dart2JsContainerMirror | |
520 implements LibraryMirror { | |
521 Map<String, ClassMirror> _classes; | |
522 List<LibraryDependencyMirror> _libraryDependencies; | |
523 | |
524 | |
525 Dart2JsLibraryMirror(Dart2JsMirrorSystem system, LibraryElement library) | |
526 : super(system, library); | |
527 | |
528 LibraryElement get _library => _element; | |
529 | |
530 Uri get uri => _library.canonicalUri; | |
531 | |
532 DeclarationMirror get owner => null; | |
533 | |
534 bool get isPrivate => false; | |
535 | |
536 LibraryMirror library() => this; | |
537 | |
538 /** | |
539 * Returns the library name (for libraries with a library tag) or the script | |
540 * file name (for scripts without a library tag). The latter case is used to | |
541 * provide a 'library name' for scripts, to use for instance in dartdoc. | |
542 */ | |
543 String get simpleName { | |
544 if (_library.libraryTag != null) { | |
545 return _library.libraryTag.name.toString(); | |
546 } else { | |
547 // Use the file name as script name. | |
548 String path = _library.canonicalUri.path; | |
549 return path.substring(path.lastIndexOf('/') + 1); | |
550 } | |
551 } | |
552 | |
553 String get qualifiedName => simpleName; | |
554 | |
555 void _ensureClasses() { | |
556 if (_classes == null) { | |
557 _classes = <String, ClassMirror>{}; | |
558 _library.forEachLocalMember((Element e) { | |
559 if (e.isClass()) { | |
560 ClassElement classElement = e; | |
561 classElement.ensureResolved(mirrors.compiler); | |
562 var type = new Dart2JsClassMirror.fromLibrary(this, classElement); | |
563 assert(invariant(_library, !_classes.containsKey(type.simpleName), | |
564 message: "Type name '${type.simpleName}' " | |
565 "is not unique in $_library.")); | |
566 _classes[type.simpleName] = type; | |
567 } else if (e.isTypedef()) { | |
568 var type = new Dart2JsTypedefMirror.fromLibrary(this, | |
569 e.computeType(mirrors.compiler)); | |
570 assert(invariant(_library, !_classes.containsKey(type.simpleName), | |
571 message: "Type name '${type.simpleName}' " | |
572 "is not unique in $_library.")); | |
573 _classes[type.simpleName] = type; | |
574 } | |
575 }); | |
576 } | |
577 } | |
578 | |
579 void _ensureMembers() { | |
580 if (_members == null) { | |
581 _members = <String, MemberMirror>{}; | |
582 _library.forEachLocalMember((Element e) { | |
583 if (!e.isClass() && !e.isTypedef()) { | |
584 // TODO(ahe): I think it is incorrect to filter out classes | |
585 // and typedefs. See http://dartbug.com/10371. | |
586 for (var member in _convertElementMemberToMemberMirrors(this, e)) { | |
587 assert(!_members.containsKey(member.simpleName)); | |
588 _members[member.simpleName] = member; | |
589 } | |
590 } | |
591 }); | |
592 } | |
593 } | |
594 | |
595 Map<String, ClassMirror> get classes { | |
596 _ensureClasses(); | |
597 return new ImmutableMapWrapper<String, ClassMirror>(_classes); | |
598 } | |
599 | |
600 /** | |
601 * Computes the first token of this library using the first library tag as | |
602 * indicator. | |
603 */ | |
604 Token getBeginToken() { | |
605 if (_library.libraryTag != null) { | |
606 return _library.libraryTag.getBeginToken(); | |
607 } else if (!_library.tags.isEmpty) { | |
608 return _library.tags.reverse().head.getBeginToken(); | |
609 } | |
610 return null; | |
611 } | |
612 | |
613 /** | |
614 * Computes the first token of this library using the last library tag as | |
615 * indicator. | |
616 */ | |
617 Token getEndToken() { | |
618 if (!_library.tags.isEmpty) { | |
619 return _library.tags.head.getEndToken(); | |
620 } | |
621 return null; | |
622 } | |
623 | |
624 void _ensureLibraryDependenciesAnalyzed() { | |
625 if (_libraryDependencies == null) { | |
626 _libraryDependencies = <LibraryDependencyMirror>[]; | |
627 for (LibraryTag node in _library.tags.reverse()) { | |
628 LibraryDependency libraryDependency = node.asLibraryDependency(); | |
629 if (libraryDependency != null) { | |
630 LibraryElement targetLibraryElement = | |
631 _library.getLibraryFromTag(libraryDependency); | |
632 assert(targetLibraryElement != null); | |
633 LibraryMirror targetLibrary = | |
634 mirrors._getLibrary(targetLibraryElement); | |
635 _libraryDependencies.add(new Dart2JsLibraryDependencyMirror( | |
636 libraryDependency, this, targetLibrary)); | |
637 } | |
638 } | |
639 } | |
640 } | |
641 | |
642 List<LibraryDependencyMirror> get libraryDependencies { | |
643 _ensureLibraryDependenciesAnalyzed(); | |
644 return _libraryDependencies; | |
645 } | |
646 } | |
647 | |
648 class Dart2JsLibraryDependencyMirror implements LibraryDependencyMirror { | |
649 final LibraryDependency _node; | |
650 final Dart2JsLibraryMirror _sourceLibrary; | |
651 final Dart2JsLibraryMirror _targetLibrary; | |
652 List<CombinatorMirror> _combinators; | |
653 | |
654 Dart2JsLibraryDependencyMirror(this._node, | |
655 this._sourceLibrary, | |
656 this._targetLibrary); | |
657 | |
658 SourceLocation get location { | |
659 return new Dart2JsSourceLocation( | |
660 _sourceLibrary._library.entryCompilationUnit.script, | |
661 _sourceLibrary.mirrors.compiler.spanFromNode(_node)); | |
662 } | |
663 | |
664 List<CombinatorMirror> get combinators { | |
665 if (_combinators == null) { | |
666 _combinators = <CombinatorMirror>[]; | |
667 if (_node.combinators != null) { | |
668 for (Combinator combinator in _node.combinators.nodes) { | |
669 List<String> identifiers = <String>[]; | |
670 for (Identifier identifier in combinator.identifiers.nodes) { | |
671 identifiers.add(identifier.source); | |
672 } | |
673 _combinators.add(new Dart2JsCombinatorMirror( | |
674 identifiers, isShow: combinator.isShow)); | |
675 } | |
676 } | |
677 } | |
678 return _combinators; | |
679 } | |
680 | |
681 LibraryMirror get sourceLibrary => _sourceLibrary; | |
682 | |
683 LibraryMirror get targetLibrary => _targetLibrary; | |
684 | |
685 String get prefix { | |
686 Import import = _node.asImport(); | |
687 if (import != null && import.prefix != null) { | |
688 return import.prefix.source; | |
689 } | |
690 return null; | |
691 } | |
692 | |
693 bool get isImport => _node.asImport() != null; | |
694 | |
695 bool get isExport => _node.asExport() != null; | |
696 } | |
697 | |
698 class Dart2JsCombinatorMirror implements CombinatorMirror { | |
699 final List<String> identifiers; | |
700 final bool isShow; | |
701 | |
702 Dart2JsCombinatorMirror(this.identifiers, {bool isShow: true}) | |
703 : this.isShow = isShow; | |
704 | |
705 bool get isHide => !isShow; | |
706 } | |
707 | |
708 class Dart2JsSourceLocation implements SourceLocation { | |
709 final Script _script; | |
710 final SourceSpan _span; | |
711 int _line; | |
712 int _column; | |
713 | |
714 Dart2JsSourceLocation(this._script, this._span); | |
715 | |
716 int _computeLine() { | |
717 var sourceFile = _script.file; | |
718 if (sourceFile != null) { | |
719 return sourceFile.getLine(offset) + 1; | |
720 } | |
721 var index = 0; | |
722 var lineNumber = 0; | |
723 while (index <= offset && index < sourceText.length) { | |
724 index = sourceText.indexOf('\n', index) + 1; | |
725 if (index <= 0) break; | |
726 lineNumber++; | |
727 } | |
728 return lineNumber; | |
729 } | |
730 | |
731 int get line { | |
732 if (_line == null) { | |
733 _line = _computeLine(); | |
734 } | |
735 return _line; | |
736 } | |
737 | |
738 int _computeColumn() { | |
739 if (length == 0) return 0; | |
740 | |
741 var sourceFile = _script.file; | |
742 if (sourceFile != null) { | |
743 return sourceFile.getColumn(sourceFile.getLine(offset), offset) + 1; | |
744 } | |
745 int index = offset - 1; | |
746 var columnNumber = 0; | |
747 while (0 <= index && index < sourceText.length) { | |
748 columnNumber++; | |
749 var codeUnit = sourceText.codeUnitAt(index); | |
750 if (codeUnit == $CR || codeUnit == $LF) { | |
751 break; | |
752 } | |
753 index--; | |
754 } | |
755 return columnNumber; | |
756 } | |
757 | |
758 int get column { | |
759 if (_column == null) { | |
760 _column = _computeColumn(); | |
761 } | |
762 return _column; | |
763 } | |
764 | |
765 int get offset => _span.begin; | |
766 | |
767 int get length => _span.end - _span.begin; | |
768 | |
769 String get text => _script.text.substring(_span.begin, _span.end); | |
770 | |
771 Uri get sourceUri => _script.uri; | |
772 | |
773 String get sourceText => _script.text; | |
774 } | |
775 | |
776 class Dart2JsParameterMirror extends Dart2JsMemberMirror | |
777 implements ParameterMirror { | |
778 final MethodMirror _method; | |
779 final bool isOptional; | |
780 final bool isNamed; | |
781 | |
782 factory Dart2JsParameterMirror(Dart2JsMirrorSystem system, | |
783 MethodMirror method, | |
784 VariableElement element, | |
785 {bool isOptional: false, | |
786 bool isNamed: false}) { | |
787 if (element is FieldParameterElement) { | |
788 return new Dart2JsFieldParameterMirror(system, | |
789 method, element, isOptional, isNamed); | |
790 } | |
791 return new Dart2JsParameterMirror._normal(system, | |
792 method, element, isOptional, isNamed); | |
793 } | |
794 | |
795 Dart2JsParameterMirror._normal(Dart2JsMirrorSystem system, | |
796 this._method, | |
797 VariableElement element, | |
798 this.isOptional, | |
799 this.isNamed) | |
800 : super(system, element); | |
801 | |
802 Element get _beginElement => _variableElement.variables; | |
803 | |
804 DeclarationMirror get owner => _method; | |
805 | |
806 VariableElement get _variableElement => _element; | |
807 | |
808 String get qualifiedName => '${_method.qualifiedName}#${simpleName}'; | |
809 | |
810 TypeMirror get type => _convertTypeToTypeMirror(mirrors, | |
811 _variableElement.computeType(mirrors.compiler), | |
812 mirrors.compiler.types.dynamicType, | |
813 _variableElement.variables.functionSignature); | |
814 | |
815 | |
816 bool get isFinal => false; | |
817 | |
818 bool get isConst => false; | |
819 | |
820 String get defaultValue { | |
821 if (hasDefaultValue) { | |
822 SendSet expression = _variableElement.cachedNode.asSendSet(); | |
823 return unparse(expression.arguments.head); | |
824 } | |
825 return null; | |
826 } | |
827 | |
828 bool get hasDefaultValue { | |
829 return _variableElement.cachedNode != null && | |
830 _variableElement.cachedNode is SendSet; | |
831 } | |
832 | |
833 bool get isInitializingFormal => false; | |
834 | |
835 VariableMirror get initializedField => null; | |
836 } | |
837 | |
838 class Dart2JsFieldParameterMirror extends Dart2JsParameterMirror { | |
839 | |
840 Dart2JsFieldParameterMirror(Dart2JsMirrorSystem system, | |
841 MethodMirror method, | |
842 FieldParameterElement element, | |
843 bool isOptional, | |
844 bool isNamed) | |
845 : super._normal(system, method, element, isOptional, isNamed); | |
846 | |
847 FieldParameterElement get _fieldParameterElement => _element; | |
848 | |
849 TypeMirror get type { | |
850 VariableListElement variables = _fieldParameterElement.variables; | |
851 VariableDefinitions node = variables.parseNode(mirrors.compiler); | |
852 if (node.type != null) { | |
853 return super.type; | |
854 } | |
855 // Use the field type for initializing formals with no type annotation. | |
856 return _convertTypeToTypeMirror(mirrors, | |
857 _fieldParameterElement.fieldElement.computeType(mirrors.compiler), | |
858 mirrors.compiler.types.dynamicType, | |
859 _variableElement.variables.functionSignature); | |
860 } | |
861 | |
862 bool get isInitializingFormal => true; | |
863 | |
864 VariableMirror get initializedField => new Dart2JsFieldMirror( | |
865 _method.owner, _fieldParameterElement.fieldElement); | |
866 } | |
867 | |
868 //------------------------------------------------------------------------------ | |
869 // Declarations | |
870 //------------------------------------------------------------------------------ | |
871 class Dart2JsClassMirror extends Dart2JsContainerMirror | |
872 implements Dart2JsTypeMirror, ClassMirror { | |
873 final Dart2JsLibraryMirror library; | |
874 List<TypeVariableMirror> _typeVariables; | |
875 | |
876 Dart2JsClassMirror(Dart2JsMirrorSystem system, ClassElement _class) | |
877 : this.library = system._getLibrary(_class.getLibrary()), | |
878 super(system, _class); | |
879 | |
880 ClassElement get _class => _element; | |
881 | |
882 Dart2JsClassMirror.fromLibrary(Dart2JsLibraryMirror library, | |
883 ClassElement _class) | |
884 : this.library = library, | |
885 super(library.mirrors, _class); | |
886 | |
887 DeclarationMirror get owner => library; | |
888 | |
889 String get qualifiedName => '${library.qualifiedName}.${simpleName}'; | |
890 | |
891 void _ensureMembers() { | |
892 if (_members == null) { | |
893 _members = <String, Dart2JsMemberMirror>{}; | |
894 _class.forEachMember((_, e) { | |
895 for (var member in _convertElementMemberToMemberMirrors(this, e)) { | |
896 assert(!_members.containsKey(member.simpleName)); | |
897 _members[member.simpleName] = member; | |
898 } | |
899 }); | |
900 } | |
901 } | |
902 | |
903 Map<String, MethodMirror> get methods => functions; | |
904 | |
905 Map<String, MethodMirror> get constructors { | |
906 _ensureMembers(); | |
907 return new AsFilteredImmutableMap<String, MemberMirror, MethodMirror>( | |
908 _members, (m) => m.isConstructor ? m : null); | |
909 } | |
910 | |
911 bool get isObject => _class == mirrors.compiler.objectClass; | |
912 | |
913 bool get isDynamic => false; | |
914 | |
915 bool get isVoid => false; | |
916 | |
917 bool get isTypeVariable => false; | |
918 | |
919 bool get isTypedef => false; | |
920 | |
921 bool get isFunction => false; | |
922 | |
923 ClassMirror get originalDeclaration => this; | |
924 | |
925 ClassMirror get superclass { | |
926 if (_class.supertype != null) { | |
927 return new Dart2JsInterfaceTypeMirror(mirrors, _class.supertype); | |
928 } | |
929 return null; | |
930 } | |
931 | |
932 ClassMirror get mixin { | |
933 if (_class.isMixinApplication) { | |
934 MixinApplicationElement mixinApplication = _class; | |
935 return new Dart2JsInterfaceTypeMirror(mirrors, | |
936 mixinApplication.mixinType); | |
937 } | |
938 return this; | |
939 } | |
940 | |
941 bool get isNameSynthetic { | |
942 if (_class.isMixinApplication) { | |
943 MixinApplicationElement mixinApplication = _class; | |
944 return mixinApplication.isUnnamedMixinApplication; | |
945 } | |
946 return false; | |
947 } | |
948 | |
949 List<ClassMirror> get superinterfaces { | |
950 var list = <ClassMirror>[]; | |
951 Link<DartType> link = _class.interfaces; | |
952 while (!link.isEmpty) { | |
953 var type = _convertTypeToTypeMirror(mirrors, link.head, | |
954 mirrors.compiler.types.dynamicType); | |
955 list.add(type); | |
956 link = link.tail; | |
957 } | |
958 return list; | |
959 } | |
960 | |
961 bool get isClass => true; | |
962 | |
963 bool get isAbstract => _class.modifiers.isAbstract(); | |
964 | |
965 bool get isOriginalDeclaration => true; | |
966 | |
967 List<TypeMirror> get typeArguments { | |
968 throw new UnsupportedError( | |
969 'Declarations do not have type arguments'); | |
970 } | |
971 | |
972 List<TypeVariableMirror> get typeVariables { | |
973 if (_typeVariables == null) { | |
974 _typeVariables = <TypeVariableMirror>[]; | |
975 _class.ensureResolved(mirrors.compiler); | |
976 for (TypeVariableType typeVariable in _class.typeVariables) { | |
977 _typeVariables.add( | |
978 new Dart2JsTypeVariableMirror(mirrors, typeVariable)); | |
979 } | |
980 } | |
981 return _typeVariables; | |
982 } | |
983 | |
984 bool operator ==(other) { | |
985 if (identical(this, other)) { | |
986 return true; | |
987 } | |
988 if (other is! ClassMirror) { | |
989 return false; | |
990 } | |
991 if (library != other.library) { | |
992 return false; | |
993 } | |
994 if (!identical(isOriginalDeclaration, other.isOriginalDeclaration)) { | |
995 return false; | |
996 } | |
997 return qualifiedName == other.qualifiedName; | |
998 } | |
999 } | |
1000 | |
1001 class Dart2JsTypedefMirror extends Dart2JsTypeElementMirror | |
1002 implements Dart2JsTypeMirror, TypedefMirror { | |
1003 final Dart2JsLibraryMirror _library; | |
1004 List<TypeVariableMirror> _typeVariables; | |
1005 TypeMirror _definition; | |
1006 | |
1007 Dart2JsTypedefMirror(Dart2JsMirrorSystem system, TypedefType _typedef) | |
1008 : this._library = system._getLibrary(_typedef.element.getLibrary()), | |
1009 super(system, _typedef); | |
1010 | |
1011 Dart2JsTypedefMirror.fromLibrary(Dart2JsLibraryMirror library, | |
1012 TypedefType _typedef) | |
1013 : this._library = library, | |
1014 super(library.mirrors, _typedef); | |
1015 | |
1016 TypedefType get _typedef => _type; | |
1017 | |
1018 String get qualifiedName => '${library.qualifiedName}.${simpleName}'; | |
1019 | |
1020 LibraryMirror get library => _library; | |
1021 | |
1022 bool get isTypedef => true; | |
1023 | |
1024 List<TypeMirror> get typeArguments { | |
1025 throw new UnsupportedError( | |
1026 'Declarations do not have type arguments'); | |
1027 } | |
1028 | |
1029 List<TypeVariableMirror> get typeVariables { | |
1030 if (_typeVariables == null) { | |
1031 _typeVariables = <TypeVariableMirror>[]; | |
1032 for (TypeVariableType typeVariable in _typedef.typeArguments) { | |
1033 _typeVariables.add( | |
1034 new Dart2JsTypeVariableMirror(mirrors, typeVariable)); | |
1035 } | |
1036 } | |
1037 return _typeVariables; | |
1038 } | |
1039 | |
1040 TypeMirror get value { | |
1041 if (_definition == null) { | |
1042 // TODO(johnniwinther): Should be [ensureResolved]. | |
1043 mirrors.compiler.resolveTypedef(_typedef.element); | |
1044 _definition = _convertTypeToTypeMirror( | |
1045 mirrors, | |
1046 _typedef.element.alias, | |
1047 mirrors.compiler.types.dynamicType, | |
1048 _typedef.element.functionSignature); | |
1049 } | |
1050 return _definition; | |
1051 } | |
1052 | |
1053 ClassMirror get originalDeclaration => this; | |
1054 | |
1055 // TODO(johnniwinther): How should a typedef respond to these? | |
1056 ClassMirror get superclass => null; | |
1057 | |
1058 List<ClassMirror> get superinterfaces => const <ClassMirror>[]; | |
1059 | |
1060 // TODO(johnniwinther): Refactor [TypedefMirror] to not extend [ClassMirror] | |
1061 // and remove this. | |
1062 ClassMirror get mixin => this; | |
1063 | |
1064 bool get isClass => false; | |
1065 | |
1066 bool get isOriginalDeclaration => true; | |
1067 | |
1068 bool get isAbstract => false; | |
1069 } | |
1070 | |
1071 class Dart2JsTypeVariableMirror extends Dart2JsTypeElementMirror | |
1072 implements TypeVariableMirror { | |
1073 final TypeVariableType _typeVariableType; | |
1074 ClassMirror _declarer; | |
1075 | |
1076 Dart2JsTypeVariableMirror(Dart2JsMirrorSystem system, | |
1077 TypeVariableType typeVariableType) | |
1078 : this._typeVariableType = typeVariableType, | |
1079 super(system, typeVariableType) { | |
1080 assert(_typeVariableType != null); | |
1081 } | |
1082 | |
1083 | |
1084 String get qualifiedName => '${declarer.qualifiedName}.${simpleName}'; | |
1085 | |
1086 ClassMirror get declarer { | |
1087 if (_declarer == null) { | |
1088 if (_typeVariableType.element.enclosingElement.isClass()) { | |
1089 _declarer = new Dart2JsClassMirror(mirrors, | |
1090 _typeVariableType.element.enclosingElement); | |
1091 } else if (_typeVariableType.element.enclosingElement.isTypedef()) { | |
1092 _declarer = new Dart2JsTypedefMirror(mirrors, | |
1093 _typeVariableType.element.enclosingElement.computeType( | |
1094 mirrors.compiler)); | |
1095 } | |
1096 } | |
1097 return _declarer; | |
1098 } | |
1099 | |
1100 LibraryMirror get library => declarer.library; | |
1101 | |
1102 DeclarationMirror get owner => declarer; | |
1103 | |
1104 bool get isTypeVariable => true; | |
1105 | |
1106 TypeMirror get upperBound => _convertTypeToTypeMirror( | |
1107 mirrors, | |
1108 _typeVariableType.element.bound, | |
1109 mirrors.compiler.objectClass.computeType(mirrors.compiler)); | |
1110 | |
1111 bool operator ==(var other) { | |
1112 if (identical(this, other)) { | |
1113 return true; | |
1114 } | |
1115 if (other is! TypeVariableMirror) { | |
1116 return false; | |
1117 } | |
1118 if (declarer != other.declarer) { | |
1119 return false; | |
1120 } | |
1121 return qualifiedName == other.qualifiedName; | |
1122 } | |
1123 } | |
1124 | |
1125 | |
1126 //------------------------------------------------------------------------------ | |
1127 // Types | |
1128 //------------------------------------------------------------------------------ | |
1129 | |
1130 abstract class Dart2JsTypeElementMirror extends Dart2JsElementMirror | |
1131 implements Dart2JsTypeMirror { | |
1132 final DartType _type; | |
1133 | |
1134 Dart2JsTypeElementMirror(Dart2JsMirrorSystem system, DartType type) | |
1135 : super(system, type.element), | |
1136 this._type = type; | |
1137 | |
1138 String get simpleName => _type.name; | |
1139 | |
1140 DeclarationMirror get owner => library; | |
1141 | |
1142 LibraryMirror get library { | |
1143 return mirrors._getLibrary(_type.element.getLibrary()); | |
1144 } | |
1145 | |
1146 bool get isObject => false; | |
1147 | |
1148 bool get isVoid => false; | |
1149 | |
1150 bool get isDynamic => false; | |
1151 | |
1152 bool get isTypeVariable => false; | |
1153 | |
1154 bool get isTypedef => false; | |
1155 | |
1156 bool get isFunction => false; | |
1157 | |
1158 String toString() => _type.toString(); | |
1159 | |
1160 Map<String, MemberMirror> get members => const <String, MemberMirror>{}; | |
1161 | |
1162 Map<String, MethodMirror> get constructors => const <String, MethodMirror>{}; | |
1163 | |
1164 Map<String, MethodMirror> get methods => const <String, MethodMirror>{}; | |
1165 | |
1166 Map<String, MethodMirror> get getters => const <String, MethodMirror>{}; | |
1167 | |
1168 Map<String, MethodMirror> get setters => const <String, MethodMirror>{}; | |
1169 | |
1170 Map<String, VariableMirror> get variables => const <String, VariableMirror>{}; | |
1171 } | |
1172 | |
1173 class Dart2JsInterfaceTypeMirror extends Dart2JsTypeElementMirror | |
1174 implements ClassMirror { | |
1175 List<TypeMirror> _typeArguments; | |
1176 | |
1177 Dart2JsInterfaceTypeMirror(Dart2JsMirrorSystem system, | |
1178 InterfaceType interfaceType) | |
1179 : super(system, interfaceType); | |
1180 | |
1181 InterfaceType get _interfaceType => _type; | |
1182 | |
1183 bool get isNameSynthetic => originalDeclaration.isNameSynthetic; | |
1184 | |
1185 String get qualifiedName => originalDeclaration.qualifiedName; | |
1186 | |
1187 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1188 Map<String, MemberMirror> get members => originalDeclaration.members; | |
1189 | |
1190 bool get isObject => mirrors.compiler.objectClass == _type.element; | |
1191 | |
1192 // TODO(johnniwinther): How to show malformed types? | |
1193 bool get isDynamic => _type.isDynamic; | |
1194 | |
1195 ClassMirror get originalDeclaration | |
1196 => new Dart2JsClassMirror(mirrors, _type.element); | |
1197 | |
1198 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1199 ClassMirror get superclass => originalDeclaration.superclass; | |
1200 | |
1201 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1202 List<ClassMirror> get superinterfaces => originalDeclaration.superinterfaces; | |
1203 | |
1204 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1205 ClassMirror get mixin { | |
1206 if (originalDeclaration.mixin == originalDeclaration) { | |
1207 return this; | |
1208 } | |
1209 return originalDeclaration.mixin; | |
1210 } | |
1211 | |
1212 bool get isClass => originalDeclaration.isClass; | |
1213 | |
1214 bool get isAbstract => originalDeclaration.isAbstract; | |
1215 | |
1216 bool get isPrivate => originalDeclaration.isPrivate; | |
1217 | |
1218 bool get isOriginalDeclaration => false; | |
1219 | |
1220 List<TypeMirror> get typeArguments { | |
1221 if (_typeArguments == null) { | |
1222 _typeArguments = <TypeMirror>[]; | |
1223 if (!_interfaceType.isRaw) { | |
1224 Link<DartType> type = _interfaceType.typeArguments; | |
1225 while (type != null && type.head != null) { | |
1226 _typeArguments.add(_convertTypeToTypeMirror(mirrors, type.head, | |
1227 mirrors.compiler.types.dynamicType)); | |
1228 type = type.tail; | |
1229 } | |
1230 } | |
1231 } | |
1232 return _typeArguments; | |
1233 } | |
1234 | |
1235 List<TypeVariableMirror> get typeVariables => | |
1236 originalDeclaration.typeVariables; | |
1237 | |
1238 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1239 Map<String, MethodMirror> get constructors => | |
1240 originalDeclaration.constructors; | |
1241 | |
1242 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1243 Map<String, MethodMirror> get methods => originalDeclaration.methods; | |
1244 | |
1245 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1246 Map<String, MethodMirror> get setters => originalDeclaration.setters; | |
1247 | |
1248 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1249 Map<String, MethodMirror> get getters => originalDeclaration.getters; | |
1250 | |
1251 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1252 Map<String, VariableMirror> get variables => originalDeclaration.variables; | |
1253 | |
1254 bool operator ==(other) { | |
1255 if (identical(this, other)) { | |
1256 return true; | |
1257 } | |
1258 if (other is! ClassMirror) { | |
1259 return false; | |
1260 } | |
1261 if (other.isOriginalDeclaration) { | |
1262 return false; | |
1263 } | |
1264 if (originalDeclaration != other.originalDeclaration) { | |
1265 return false; | |
1266 } | |
1267 var thisTypeArguments = typeArguments.iterator; | |
1268 var otherTypeArguments = other.typeArguments.iterator; | |
1269 while (thisTypeArguments.moveNext()) { | |
1270 if (!otherTypeArguments.moveNext()) return false; | |
1271 if (thisTypeArguments.current != otherTypeArguments.current) { | |
1272 return false; | |
1273 } | |
1274 } | |
1275 return !otherTypeArguments.moveNext(); | |
1276 } | |
1277 } | |
1278 | |
1279 | |
1280 class Dart2JsFunctionTypeMirror extends Dart2JsTypeElementMirror | |
1281 implements FunctionTypeMirror { | |
1282 final FunctionSignature _functionSignature; | |
1283 List<ParameterMirror> _parameters; | |
1284 | |
1285 Dart2JsFunctionTypeMirror(Dart2JsMirrorSystem system, | |
1286 FunctionType functionType, this._functionSignature) | |
1287 : super(system, functionType) { | |
1288 assert (_functionSignature != null); | |
1289 } | |
1290 | |
1291 FunctionType get _functionType => _type; | |
1292 | |
1293 // TODO(johnniwinther): Is this the qualified name of a function type? | |
1294 String get qualifiedName => originalDeclaration.qualifiedName; | |
1295 | |
1296 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1297 Map<String, MemberMirror> get members { | |
1298 var method = callMethod; | |
1299 if (method != null) { | |
1300 var map = new Map<String, MemberMirror>.from( | |
1301 originalDeclaration.members); | |
1302 var name = method.qualifiedName; | |
1303 assert(!map.containsKey(name)); | |
1304 map[name] = method; | |
1305 return new ImmutableMapWrapper<String, MemberMirror>(map); | |
1306 } | |
1307 return originalDeclaration.members; | |
1308 } | |
1309 | |
1310 bool get isFunction => true; | |
1311 | |
1312 MethodMirror get callMethod => _convertElementMethodToMethodMirror( | |
1313 mirrors._getLibrary(_functionType.element.getLibrary()), | |
1314 _functionType.element); | |
1315 | |
1316 ClassMirror get originalDeclaration | |
1317 => new Dart2JsClassMirror(mirrors, mirrors.compiler.functionClass); | |
1318 | |
1319 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1320 ClassMirror get superclass => originalDeclaration.superclass; | |
1321 | |
1322 // TODO(johnniwinther): Substitute type arguments for type variables. | |
1323 List<ClassMirror> get superinterfaces => originalDeclaration.superinterfaces; | |
1324 | |
1325 ClassMirror get mixin => this; | |
1326 | |
1327 bool get isClass => originalDeclaration.isClass; | |
1328 | |
1329 bool get isPrivate => originalDeclaration.isPrivate; | |
1330 | |
1331 bool get isOriginalDeclaration => false; | |
1332 | |
1333 bool get isAbstract => false; | |
1334 | |
1335 List<TypeMirror> get typeArguments => const <TypeMirror>[]; | |
1336 | |
1337 List<TypeVariableMirror> get typeVariables => | |
1338 originalDeclaration.typeVariables; | |
1339 | |
1340 TypeMirror get returnType { | |
1341 return _convertTypeToTypeMirror(mirrors, _functionType.returnType, | |
1342 mirrors.compiler.types.dynamicType); | |
1343 } | |
1344 | |
1345 List<ParameterMirror> get parameters { | |
1346 if (_parameters == null) { | |
1347 _parameters = _parametersFromFunctionSignature(mirrors, callMethod, | |
1348 _functionSignature); | |
1349 } | |
1350 return _parameters; | |
1351 } | |
1352 } | |
1353 | |
1354 class Dart2JsVoidMirror extends Dart2JsTypeElementMirror { | |
1355 | |
1356 Dart2JsVoidMirror(Dart2JsMirrorSystem system, VoidType voidType) | |
1357 : super(system, voidType); | |
1358 | |
1359 VoidType get _voidType => _type; | |
1360 | |
1361 String get qualifiedName => simpleName; | |
1362 | |
1363 /** | |
1364 * The void type has no location. | |
1365 */ | |
1366 SourceLocation get location => null; | |
1367 | |
1368 /** | |
1369 * The void type has no library. | |
1370 */ | |
1371 LibraryMirror get library => null; | |
1372 | |
1373 bool get isVoid => true; | |
1374 | |
1375 bool operator ==(other) { | |
1376 if (identical(this, other)) { | |
1377 return true; | |
1378 } | |
1379 if (other is! TypeMirror) { | |
1380 return false; | |
1381 } | |
1382 return other.isVoid; | |
1383 } | |
1384 } | |
1385 | |
1386 | |
1387 class Dart2JsDynamicMirror extends Dart2JsTypeElementMirror { | |
1388 Dart2JsDynamicMirror(Dart2JsMirrorSystem system, InterfaceType voidType) | |
1389 : super(system, voidType); | |
1390 | |
1391 InterfaceType get _dynamicType => _type; | |
1392 | |
1393 String get qualifiedName => simpleName; | |
1394 | |
1395 /** | |
1396 * The dynamic type has no location. | |
1397 */ | |
1398 SourceLocation get location => null; | |
1399 | |
1400 /** | |
1401 * The dynamic type has no library. | |
1402 */ | |
1403 LibraryMirror get library => null; | |
1404 | |
1405 bool get isDynamic => true; | |
1406 | |
1407 bool operator ==(other) { | |
1408 if (identical(this, other)) { | |
1409 return true; | |
1410 } | |
1411 if (other is! TypeMirror) { | |
1412 return false; | |
1413 } | |
1414 return other.isDynamic; | |
1415 } | |
1416 } | |
1417 | |
1418 //------------------------------------------------------------------------------ | |
1419 // Member mirrors implementation. | |
1420 //------------------------------------------------------------------------------ | |
1421 | |
1422 class Dart2JsMethodMirror extends Dart2JsMemberMirror | |
1423 implements MethodMirror { | |
1424 final Dart2JsContainerMirror _objectMirror; | |
1425 final String simpleName; | |
1426 final Dart2JsMethodKind _kind; | |
1427 | |
1428 Dart2JsMethodMirror._internal(Dart2JsContainerMirror objectMirror, | |
1429 FunctionElement function, | |
1430 String this.simpleName, | |
1431 Dart2JsMethodKind this._kind) | |
1432 : this._objectMirror = objectMirror, | |
1433 super(objectMirror.mirrors, function); | |
1434 | |
1435 factory Dart2JsMethodMirror(Dart2JsContainerMirror objectMirror, | |
1436 FunctionElement function) { | |
1437 String realName = function.name; | |
1438 // TODO(ahe): This method should not be calling | |
1439 // Elements.operatorNameToIdentifier. | |
1440 String simpleName = | |
1441 Elements.operatorNameToIdentifier(function.name); | |
1442 Dart2JsMethodKind kind; | |
1443 if (function.kind == ElementKind.GETTER) { | |
1444 kind = Dart2JsMethodKind.GETTER; | |
1445 } else if (function.kind == ElementKind.SETTER) { | |
1446 kind = Dart2JsMethodKind.SETTER; | |
1447 simpleName = '$simpleName='; | |
1448 } else if (function.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
1449 // TODO(johnniwinther): Support detection of redirecting constructors. | |
1450 if (function.modifiers.isConst()) { | |
1451 kind = Dart2JsMethodKind.CONST; | |
1452 } else { | |
1453 kind = Dart2JsMethodKind.GENERATIVE; | |
1454 } | |
1455 } else if (function.modifiers.isFactory()) { | |
1456 kind = Dart2JsMethodKind.FACTORY; | |
1457 } else if (realName == 'unary-') { | |
1458 kind = Dart2JsMethodKind.OPERATOR; | |
1459 // Simple name is 'unary-'. | |
1460 simpleName = Mirror.UNARY_MINUS; | |
1461 } else if (simpleName.startsWith('operator\$')) { | |
1462 String str = simpleName.substring(9); | |
1463 simpleName = 'operator'; | |
1464 kind = Dart2JsMethodKind.OPERATOR; | |
1465 simpleName = _getOperatorFromOperatorName(str); | |
1466 } else { | |
1467 kind = Dart2JsMethodKind.REGULAR; | |
1468 } | |
1469 return new Dart2JsMethodMirror._internal(objectMirror, function, | |
1470 simpleName, kind); | |
1471 } | |
1472 | |
1473 FunctionElement get _function => _element; | |
1474 | |
1475 String get qualifiedName | |
1476 => '${owner.qualifiedName}.$simpleName'; | |
1477 | |
1478 DeclarationMirror get owner => _objectMirror; | |
1479 | |
1480 bool get isTopLevel => _objectMirror is LibraryMirror; | |
1481 | |
1482 bool get isConstructor | |
1483 => isGenerativeConstructor || isConstConstructor || | |
1484 isFactoryConstructor || isRedirectingConstructor; | |
1485 | |
1486 bool get isMethod => !isConstructor; | |
1487 | |
1488 bool get isStatic => _function.modifiers.isStatic(); | |
1489 | |
1490 List<ParameterMirror> get parameters { | |
1491 return _parametersFromFunctionSignature(mirrors, this, | |
1492 _function.computeSignature(mirrors.compiler)); | |
1493 } | |
1494 | |
1495 TypeMirror get returnType => _convertTypeToTypeMirror( | |
1496 mirrors, _function.computeSignature(mirrors.compiler).returnType, | |
1497 mirrors.compiler.types.dynamicType); | |
1498 | |
1499 bool get isAbstract => _function.isAbstract(mirrors.compiler); | |
1500 | |
1501 bool get isRegularMethod => !(isGetter || isSetter || isConstructor); | |
1502 | |
1503 bool get isConstConstructor => _kind == Dart2JsMethodKind.CONST; | |
1504 | |
1505 bool get isGenerativeConstructor => _kind == Dart2JsMethodKind.GENERATIVE; | |
1506 | |
1507 bool get isRedirectingConstructor => _kind == Dart2JsMethodKind.REDIRECTING; | |
1508 | |
1509 bool get isFactoryConstructor => _kind == Dart2JsMethodKind.FACTORY; | |
1510 | |
1511 bool get isGetter => _kind == Dart2JsMethodKind.GETTER; | |
1512 | |
1513 bool get isSetter => _kind == Dart2JsMethodKind.SETTER; | |
1514 | |
1515 bool get isOperator => _kind == Dart2JsMethodKind.OPERATOR; | |
1516 | |
1517 DeclarationMirror lookupInScope(String name) { | |
1518 for (ParameterMirror parameter in parameters) { | |
1519 if (parameter.simpleName == name) { | |
1520 return parameter; | |
1521 } | |
1522 } | |
1523 return super.lookupInScope(name); | |
1524 } | |
1525 } | |
1526 | |
1527 class Dart2JsFieldMirror extends Dart2JsMemberMirror implements VariableMirror { | |
1528 Dart2JsContainerMirror _objectMirror; | |
1529 VariableElement _variable; | |
1530 | |
1531 Dart2JsFieldMirror(Dart2JsContainerMirror objectMirror, | |
1532 VariableElement variable) | |
1533 : this._objectMirror = objectMirror, | |
1534 this._variable = variable, | |
1535 super(objectMirror.mirrors, variable); | |
1536 | |
1537 Element get _beginElement => _variable.variables; | |
1538 | |
1539 String get qualifiedName | |
1540 => '${owner.qualifiedName}.$simpleName'; | |
1541 | |
1542 DeclarationMirror get owner => _objectMirror; | |
1543 | |
1544 bool get isTopLevel => _objectMirror is LibraryMirror; | |
1545 | |
1546 bool get isVariable => true; | |
1547 | |
1548 bool get isStatic => _variable.modifiers.isStatic(); | |
1549 | |
1550 bool get isFinal => _variable.modifiers.isFinal(); | |
1551 | |
1552 bool get isConst => _variable.modifiers.isConst(); | |
1553 | |
1554 TypeMirror get type => _convertTypeToTypeMirror(mirrors, | |
1555 _variable.computeType(mirrors.compiler), | |
1556 mirrors.compiler.types.dynamicType); | |
1557 } | |
1558 | |
1559 //////////////////////////////////////////////////////////////////////////////// | |
1560 // Mirrors on constant values used for metadata. | |
1561 //////////////////////////////////////////////////////////////////////////////// | |
1562 | |
1563 class Dart2JsConstantMirror extends InstanceMirror { | |
1564 final Dart2JsMirrorSystem mirrors; | |
1565 final Constant _constant; | |
1566 | |
1567 Dart2JsConstantMirror(this.mirrors, this._constant); | |
1568 | |
1569 ClassMirror get type { | |
1570 return new Dart2JsClassMirror(mirrors, | |
1571 _constant.computeType(mirrors.compiler).element); | |
1572 } | |
1573 | |
1574 bool get hasReflectee => false; | |
1575 | |
1576 get reflectee { | |
1577 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1578 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1579 } | |
1580 | |
1581 InstanceMirror getField(String fieldName) { | |
1582 // TODO(johnniwinther): Which exception/error should be thrown here? | |
1583 throw new UnsupportedError('InstanceMirror does not have a reflectee'); | |
1584 } | |
1585 } | |
1586 | |
1587 class Dart2JsNullConstantMirror extends Dart2JsConstantMirror { | |
1588 Dart2JsNullConstantMirror(Dart2JsMirrorSystem mirrors, NullConstant constant) | |
1589 : super(mirrors, constant); | |
1590 | |
1591 NullConstant get _constant => super._constant; | |
1592 | |
1593 bool get hasReflectee => true; | |
1594 | |
1595 get reflectee => null; | |
1596 } | |
1597 | |
1598 class Dart2JsBoolConstantMirror extends Dart2JsConstantMirror { | |
1599 Dart2JsBoolConstantMirror(Dart2JsMirrorSystem mirrors, BoolConstant constant) | |
1600 : super(mirrors, constant); | |
1601 | |
1602 Dart2JsBoolConstantMirror.fromBool(Dart2JsMirrorSystem mirrors, bool value) | |
1603 : super(mirrors, value ? new TrueConstant() : new FalseConstant()); | |
1604 | |
1605 BoolConstant get _constant => super._constant; | |
1606 | |
1607 bool get hasReflectee => true; | |
1608 | |
1609 get reflectee => _constant is TrueConstant; | |
1610 } | |
1611 | |
1612 class Dart2JsStringConstantMirror extends Dart2JsConstantMirror { | |
1613 Dart2JsStringConstantMirror(Dart2JsMirrorSystem mirrors, | |
1614 StringConstant constant) | |
1615 : super(mirrors, constant); | |
1616 | |
1617 Dart2JsStringConstantMirror.fromString(Dart2JsMirrorSystem mirrors, | |
1618 String text) | |
1619 : super(mirrors, | |
1620 new StringConstant(new DartString.literal(text), null)); | |
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 |