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

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

Issue 119913002: Align source mirrors with runtime mirrors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments + small fix. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js.mirrors;
6
7 import 'dart:collection' show UnmodifiableListView;
8
9 import '../elements/elements.dart';
10 import '../scanner/scannerlib.dart';
11 import '../resolution/resolution.dart' show Scope;
12 import '../dart2jslib.dart';
13 import '../dart_types.dart';
14 import '../tree/tree.dart';
15 import '../util/util.dart' show Spannable, Link, LinkBuilder;
16 import '../util/characters.dart' show $CR, $LF;
17
18 import 'source_mirrors.dart';
19 import 'mirrors_util.dart';
20 import 'util.dart';
21
22 part 'dart2js_library_mirror.dart';
23 part 'dart2js_type_mirrors.dart';
24 part 'dart2js_member_mirrors.dart';
25 part 'dart2js_instance_mirrors.dart';
26
27 //------------------------------------------------------------------------------
28 // Utility types and functions for the dart2js mirror system
29 //------------------------------------------------------------------------------
30
31 bool _isPrivate(String name) {
32 return name.startsWith('_');
33 }
34
35 List<ParameterMirror> _parametersFromFunctionSignature(
36 Dart2JsDeclarationMirror owner,
37 FunctionSignature signature) {
38 var parameters = <ParameterMirror>[];
39 Link<Element> link = signature.requiredParameters;
40 while (!link.isEmpty) {
41 parameters.add(new Dart2JsParameterMirror(
42 owner, link.head, isOptional: false, isNamed: false));
43 link = link.tail;
44 }
45 link = signature.optionalParameters;
46 bool isNamed = signature.optionalParametersAreNamed;
47 while (!link.isEmpty) {
48 parameters.add(new Dart2JsParameterMirror(
49 owner, link.head, isOptional: true, isNamed: isNamed));
50 link = link.tail;
51 }
52 return parameters;
53 }
54
55 MethodMirror _convertElementMethodToMethodMirror(
56 Dart2JsDeclarationMirror library, Element element) {
57 if (element is FunctionElement) {
58 return new Dart2JsMethodMirror(library, element);
59 } else {
60 return null;
61 }
62 }
63
64 //------------------------------------------------------------------------------
65 // Dart2Js specific extensions of mirror interfaces
66 //------------------------------------------------------------------------------
67
68 abstract class Dart2JsMirror implements Mirror {
69 Dart2JsMirrorSystem get mirrorSystem;
70 }
71
72 abstract class Dart2JsDeclarationMirror extends Dart2JsMirror
73 implements DeclarationSourceMirror {
74
75 bool get isTopLevel => owner != null && owner is LibraryMirror;
76
77 bool get isPrivate => _isPrivate(_simpleNameString);
78
79 String get _simpleNameString;
80
81 String get _qualifiedNameString {
82 var parent = owner;
83 if (parent is Dart2JsDeclarationMirror) {
84 return '${parent._qualifiedNameString}.${_simpleNameString}';
85 }
86 assert(parent == null);
87 return _simpleNameString;
88 }
89
90 Symbol get simpleName => symbolOf(_simpleNameString, getLibrary(this));
91
92 Symbol get qualifiedName => symbolOf(_qualifiedNameString, getLibrary(this));
93
94 /**
95 * Returns the first token for the source of this declaration, not including
96 * metadata annotations.
97 */
98 Token getBeginToken();
99
100 /**
101 * Returns the last token for the source of this declaration.
102 */
103 Token getEndToken();
104
105 /**
106 * Returns the script for the source of this declaration.
107 */
108 Script getScript();
109
110 /// Returns the type mirror for [type] in the context of this declaration.
111 TypeMirror _getTypeMirror(DartType type, [FunctionSignature signature]) {
112 return mirrorSystem._convertTypeToTypeMirror(type, signature);
113 }
114
115 /// Returns a list of the declaration mirrorSystem for [element].
116 Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element) {
117 if (element.isSynthesized) {
118 return const <Dart2JsMemberMirror>[];
119 } else if (element is VariableElement) {
120 return <Dart2JsMemberMirror>[new Dart2JsFieldMirror(this, element)];
121 } else if (element is FunctionElement) {
122 return <Dart2JsMemberMirror>[new Dart2JsMethodMirror(this, element)];
123 } else if (element is AbstractFieldElement) {
124 var members = <Dart2JsMemberMirror>[];
125 AbstractFieldElement field = element;
126 if (field.getter != null) {
127 members.add(new Dart2JsMethodMirror(this, field.getter));
128 }
129 if (field.setter != null) {
130 members.add(new Dart2JsMethodMirror(this, field.setter));
131 }
132 return members;
133 }
134 mirrorSystem.compiler.internalError(
135 "Unexpected member type $element ${element.kind}");
136 }
137
138 }
139
140 abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror {
141 final Dart2JsMirrorSystem mirrorSystem;
142 final Element _element;
143 List<InstanceMirror> _metadata;
144
145 Dart2JsElementMirror(this.mirrorSystem, this._element) {
146 assert (mirrorSystem != null);
147 assert (_element != null);
148 }
149
150 /**
151 * Returns the element to be used to determine the begin token of this
152 * declaration and the metadata associated with this declaration.
153 *
154 * This indirection is needed to use the [VariableListElement] as the location
155 * for type and metadata information on a [VariableElement].
156 */
157 Element get _beginElement => _element;
158
159 String get _simpleNameString => _element.name;
160
161 bool get isNameSynthetic => false;
162
163 /**
164 * Computes the first token for this declaration using the begin token of the
165 * element node or element position as indicator.
166 */
167 Token getBeginToken() {
168 // TODO(johnniwinther): Avoid calling [parseNode].
169 Node node = _beginElement.parseNode(mirrorSystem.compiler);
170 if (node == null) {
171 return _beginElement.position();
172 }
173 return node.getBeginToken();
174 }
175
176 /**
177 * Computes the last token for this declaration using the end token of the
178 * element node or element position as indicator.
179 */
180 Token getEndToken() {
181 // TODO(johnniwinther): Avoid calling [parseNode].
182 Node node = _element.parseNode(mirrorSystem.compiler);
183 if (node == null) {
184 return _element.position();
185 }
186 return node.getEndToken();
187 }
188
189 /**
190 * Returns the first token for the source of this declaration, including
191 * metadata annotations.
192 */
193 Token getFirstToken() {
194 if (!_beginElement.metadata.isEmpty) {
195 for (MetadataAnnotation metadata in _beginElement.metadata) {
196 if (metadata.beginToken != null) {
197 return metadata.beginToken;
198 }
199 }
200 }
201 return getBeginToken();
202 }
203
204 Script getScript() => _element.getCompilationUnit().script;
205
206 SourceLocation get location {
207 Token beginToken = getFirstToken();
208 Script script = getScript();
209 SourceSpan span;
210 if (beginToken == null) {
211 span = new SourceSpan(script.uri, 0, 0);
212 } else {
213 Token endToken = getEndToken();
214 span = mirrorSystem.compiler.spanFromTokens(
215 beginToken, endToken, script.uri);
216 }
217 return new Dart2JsSourceLocation(script, span);
218 }
219
220 String toString() => _element.toString();
221
222 void _appendCommentTokens(Token commentToken) {
223 while (commentToken != null && commentToken.kind == COMMENT_TOKEN) {
224 _metadata.add(new Dart2JsCommentInstanceMirror(
225 mirrorSystem, commentToken.value));
226 commentToken = commentToken.next;
227 }
228 }
229
230 List<InstanceMirror> get metadata {
231 if (_metadata == null) {
232 _metadata = <InstanceMirror>[];
233 for (MetadataAnnotation metadata in _element.metadata) {
234 _appendCommentTokens(
235 mirrorSystem.compiler.commentMap[metadata.beginToken]);
236 metadata.ensureResolved(mirrorSystem.compiler);
237 _metadata.add(
238 _convertConstantToInstanceMirror(mirrorSystem, metadata.value));
239 }
240 _appendCommentTokens(mirrorSystem.compiler.commentMap[getBeginToken()]);
241 }
242 // TODO(johnniwinther): Return an unmodifiable list instead.
243 return new List<InstanceMirror>.from(_metadata);
244 }
245
246 DeclarationMirror lookupInScope(String name) {
247 // TODO(11653): Support lookup of constructors.
248 Scope scope = _element.buildScope();
249 Element result;
250 int index = name.indexOf('.');
251 if (index != -1) {
252 // Lookup [: prefix.id :].
253 String prefix = name.substring(0, index);
254 String id = name.substring(index+1);
255 result = scope.lookup(prefix);
256 if (result != null && result.isPrefix()) {
257 PrefixElement prefix = result;
258 result = prefix.lookupLocalMember(id);
259 } else {
260 result = null;
261 }
262 } else {
263 // Lookup [: id :].
264 result = scope.lookup(name);
265 }
266 if (result == null || result.isPrefix()) return null;
267 return _convertElementToDeclarationMirror(mirrorSystem, result);
268 }
269
270 bool operator ==(var other) {
271 if (identical(this, other)) return true;
272 if (other == null) return false;
273 if (other is! Dart2JsElementMirror) return false;
274 return _element == other._element &&
275 owner == other.owner;
276 }
277
278 int get hashCode {
279 return 13 * _element.hashCode + 17 * owner.hashCode;
280 }
281 }
282
283 //------------------------------------------------------------------------------
284 // Mirror system implementation.
285 //------------------------------------------------------------------------------
286
287 class Dart2JsMirrorSystem extends MirrorSystem {
288 final Compiler compiler;
289 Map<Uri, Dart2JsLibraryMirror> _libraries;
290 Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap;
291
292 Dart2JsMirrorSystem(this.compiler)
293 : _libraryMap = new Map<LibraryElement, Dart2JsLibraryMirror>();
294
295 IsolateMirror get isolate => null;
296
297 void _ensureLibraries() {
298 if (_libraries == null) {
299 _libraries = new Map<Uri, Dart2JsLibraryMirror>();
300 compiler.libraries.forEach((_, LibraryElement v) {
301 var mirror = new Dart2JsLibraryMirror(mirrorSystem, v);
302 _libraries[mirror.uri] = mirror;
303 _libraryMap[v] = mirror;
304 });
305 }
306 }
307
308 Map<Uri, LibraryMirror> get libraries {
309 _ensureLibraries();
310 return new FilteredImmutableMap<Uri, LibraryMirror>(_libraries,
311 (library) => new bool.fromEnvironment("list_all_libraries") ||
312 !library._element.isInternalLibrary);
313 }
314
315 Dart2JsLibraryMirror _getLibrary(LibraryElement element) =>
316 _libraryMap[element];
317
318 Dart2JsMirrorSystem get mirrorSystem => this;
319
320 TypeMirror get dynamicType =>
321 _convertTypeToTypeMirror(compiler.types.dynamicType);
322
323 TypeMirror get voidType =>
324 _convertTypeToTypeMirror(compiler.types.voidType);
325
326 TypeMirror _convertTypeToTypeMirror(DartType type,
327 [FunctionSignature signature]) {
328 assert(type != null);
329 if (type.treatAsDynamic) {
330 return new Dart2JsDynamicMirror(this, type);
331 } else if (type is InterfaceType) {
332 if (type.typeArguments.isEmpty) {
333 return _getTypeDeclarationMirror(type.element);
334 } else {
335 return new Dart2JsInterfaceTypeMirror(this, type);
336 }
337 } else if (type is TypeVariableType) {
338 return new Dart2JsTypeVariableMirror(this, type);
339 } else if (type is FunctionType) {
340 return new Dart2JsFunctionTypeMirror(this, type, signature);
341 } else if (type is VoidType) {
342 return new Dart2JsVoidMirror(this, type);
343 } else if (type is TypedefType) {
344 if (type.typeArguments.isEmpty) {
345 return _getTypeDeclarationMirror(type.element);
346 } else {
347 return new Dart2JsTypedefMirror(this, type);
348 }
349 }
350 compiler.internalError("Unexpected type $type of kind ${type.kind}");
351 }
352
353 DeclarationMirror _getTypeDeclarationMirror(Element element) {
354 if (element.isClass()) {
355 return new Dart2JsClassDeclarationMirror(
356 this, element.computeType(compiler));
357 } else if (element.isTypedef()) {
358 return new Dart2JsTypedefDeclarationMirror(this,
359 element.computeType(compiler));
360 }
361 }
362 }
363
364 abstract class ContainerMixin {
365 Map<Symbol, DeclarationMirror> _declarations;
366
367 void _ensureDeclarations() {
368 if (_declarations == null) {
369 _declarations = <Symbol, DeclarationMirror>{};
370 _forEachElement((Element element) {
371 for (DeclarationMirror mirror in _getDeclarationMirrors(element)) {
372 assert(invariant(_element,
373 !_declarations.containsKey(mirror.simpleName),
374 message: "Declaration name '${nameOf(mirror)}' "
375 "is not unique in $_element."));
376 _declarations[mirror.simpleName] = mirror;
377 }
378 });
379 }
380 }
381
382 Element get _element;
383
384 void _forEachElement(f(Element element));
385
386 Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element);
387
388 Map<Symbol, DeclarationMirror> get declarations {
389 _ensureDeclarations();
390 return new ImmutableMapWrapper<Symbol, DeclarationMirror>(_declarations);
391 }
392 }
393
394 /**
395 * Converts [element] into its corresponding [DeclarationMirror], if any.
396 *
397 * If [element] is an [AbstractFieldElement] the mirror for its getter is
398 * returned or, if not present, the mirror for its setter.
399 */
400 DeclarationMirror _convertElementToDeclarationMirror(Dart2JsMirrorSystem system,
401 Element element) {
402 if (element.isTypeVariable()) {
403 return new Dart2JsTypeVariableMirror(
404 system, element.computeType(system.compiler));
405 }
406
407 Dart2JsLibraryMirror library = system._libraryMap[element.getLibrary()];
408 if (element.isLibrary()) return library;
409 if (element.isTypedef()) {
410 return new Dart2JsTypedefMirror.fromLibrary(
411 library, element.computeType(system.compiler));
412 }
413
414 Dart2JsDeclarationMirror container = library;
415 if (element.getEnclosingClass() != null) {
416 container = system._getTypeDeclarationMirror(element.getEnclosingClass());
417 }
418 if (element.isClass()) return container;
419 if (element.isParameter()) {
420 Dart2JsMethodMirror method = _convertElementMethodToMethodMirror(
421 container, element.getOutermostEnclosingMemberOrTopLevel());
422 // TODO(johnniwinther): Find the right info for [isOptional] and [isNamed].
423 return new Dart2JsParameterMirror(
424 method, element, isOptional: false, isNamed: false);
425 }
426 Iterable<DeclarationMirror> members =
427 container._getDeclarationMirrors(element);
428 if (members.isEmpty) return null;
429 return members.first;
430 }
431
432 /**
433 * Experimental API for accessing compilation units defined in a
434 * library.
435 */
436 // TODO(ahe): Superclasses? Is this really a mirror?
437 class Dart2JsCompilationUnitMirror extends Dart2JsMirror
438 with ContainerMixin {
439 final Dart2JsLibraryMirror _library;
440 final CompilationUnitElement _element;
441
442 Dart2JsCompilationUnitMirror(this._element, this._library);
443
444 Dart2JsMirrorSystem get mirrorSystem => _library.mirrorSystem;
445
446 // TODO(johnniwinther): make sure that these are returned in declaration
447 // order.
448 void _forEachElement(f(Element element)) => _element.forEachLocalMember(f);
449
450 Iterable<DeclarationMirror> _getDeclarationMirrors(Element element) =>
451 _library._getDeclarationMirrors(element);
452
453 Uri get uri => _element.script.uri;
454 }
455
456 /**
457 * Transitional class that allows access to features that have not yet
458 * made it to the mirror API.
459 *
460 * All API in this class is experimental.
461 */
462 class BackDoor {
463 /// Return the compilation units comprising [library].
464 static List<Mirror> compilationUnitsOf(Dart2JsLibraryMirror library) {
465 return library._element.compilationUnits.toList().map(
466 (cu) => new Dart2JsCompilationUnitMirror(cu, library)).toList();
467 }
468 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698