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

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: Rebased 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(Dart2JsDeclarationMirror librar y,
Emily Fortuna 2014/01/30 19:33:10 80 char. :-P
Johnni Winther 2014/02/03 08:22:48 Done.
56 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 mirrors;
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 mirrors._convertTypeToTypeMirror(type, signature);
113 }
114
115 /// Returns a list of the declaration mirrors 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 mirrors.compiler.internalError(
135 "Unexpected member type $element ${element.kind}");
136 }
137
138 }
139
140 abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror {
141 final Dart2JsMirrorSystem mirrors;
142 final Element _element;
143 List<InstanceMirror> _metadata;
144
145 Dart2JsElementMirror(this.mirrors, this._element) {
146 assert (mirrors != 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(mirrors.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(mirrors.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 = mirrors.compiler.spanFromTokens(beginToken, endToken, script.uri);
215 }
216 return new Dart2JsSourceLocation(script, span);
217 }
218
219 String toString() => _element.toString();
220
221 void _appendCommentTokens(Token commentToken) {
222 while (commentToken != null && commentToken.kind == COMMENT_TOKEN) {
223 _metadata.add(new Dart2JsCommentInstanceMirror(
224 mirrors, commentToken.value));
225 commentToken = commentToken.next;
226 }
227 }
228
229 List<InstanceMirror> get metadata {
230 if (_metadata == null) {
231 _metadata = <InstanceMirror>[];
232 for (MetadataAnnotation metadata in _element.metadata) {
233 _appendCommentTokens(mirrors.compiler.commentMap[metadata.beginToken]);
234 metadata.ensureResolved(mirrors.compiler);
235 _metadata.add(
236 _convertConstantToInstanceMirror(mirrors, metadata.value));
237 }
238 _appendCommentTokens(mirrors.compiler.commentMap[getBeginToken()]);
239 }
240 // TODO(johnniwinther): Return an unmodifiable list instead.
241 return new List<InstanceMirror>.from(_metadata);
242 }
243
244 DeclarationMirror lookupInScope(String name) {
245 // TODO(11653): Support lookup of constructors.
246 Scope scope = _element.buildScope();
247 Element result;
248 int index = name.indexOf('.');
249 if (index != -1) {
250 // Lookup [: prefix.id :].
251 String prefix = name.substring(0, index);
252 String id = name.substring(index+1);
253 result = scope.lookup(prefix);
254 if (result != null && result.isPrefix()) {
255 PrefixElement prefix = result;
256 result = prefix.lookupLocalMember(id);
257 } else {
258 result = null;
259 }
260 } else {
261 // Lookup [: id :].
262 result = scope.lookup(name);
263 }
264 if (result == null || result.isPrefix()) return null;
265 return _convertElementToDeclarationMirror(mirrors, result);
266 }
267
268 bool operator ==(var other) {
269 if (identical(this, other)) return true;
270 if (other == null) return false;
271 if (other is! Dart2JsElementMirror) return false;
272 return _element == other._element &&
273 owner == other.owner;
274 }
275
276 int get hashCode {
277 return 13 * _element.hashCode + 17 * owner.hashCode;
278 }
279 }
280
281 //------------------------------------------------------------------------------
282 // Mirror system implementation.
283 //------------------------------------------------------------------------------
284
285 class Dart2JsMirrorSystem extends MirrorSystem {
286 final Compiler compiler;
287 Map<Uri, Dart2JsLibraryMirror> _libraries;
288 Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap;
289
290 Dart2JsMirrorSystem(this.compiler)
291 : _libraryMap = new Map<LibraryElement, Dart2JsLibraryMirror>();
292
293 IsolateMirror get isolate => null;
294
295 void _ensureLibraries() {
296 if (_libraries == null) {
297 _libraries = new Map<Uri, Dart2JsLibraryMirror>();
298 compiler.libraries.forEach((_, LibraryElement v) {
299 var mirror = new Dart2JsLibraryMirror(mirrors, v);
300 _libraries[mirror.uri] = mirror;
301 _libraryMap[v] = mirror;
302 });
303 }
304 }
305
306 Map<Uri, LibraryMirror> get libraries {
307 _ensureLibraries();
308 return new FilteredImmutableMap<Uri, LibraryMirror>(_libraries,
309 (library) => new bool.fromEnvironment("list_all_libraries") ||
310 !library._element.isInternalLibrary);
311 }
312
313 Dart2JsLibraryMirror _getLibrary(LibraryElement element) =>
314 _libraryMap[element];
315
316 Dart2JsMirrorSystem get mirrors => this;
317
318 TypeMirror get dynamicType =>
319 _convertTypeToTypeMirror(compiler.types.dynamicType);
320
321 TypeMirror get voidType =>
322 _convertTypeToTypeMirror(compiler.types.voidType);
323
324 TypeMirror _convertTypeToTypeMirror(DartType type,
325 [FunctionSignature signature]) {
326 assert(type != null);
327 if (type.treatAsDynamic) {
328 return new Dart2JsDynamicMirror(this, type);
329 } else if (type is InterfaceType) {
330 if (type.typeArguments.isEmpty) {
331 return _getTypeDeclarationMirror(type.element);
332 } else {
333 return new Dart2JsInterfaceTypeMirror(this, type);
334 }
335 } else if (type is TypeVariableType) {
336 return new Dart2JsTypeVariableMirror(this, type);
337 } else if (type is FunctionType) {
338 return new Dart2JsFunctionTypeMirror(this, type, signature);
339 } else if (type is VoidType) {
340 return new Dart2JsVoidMirror(this, type);
341 } else if (type is TypedefType) {
342 if (type.typeArguments.isEmpty) {
343 return _getTypeDeclarationMirror(type.element);
344 } else {
345 return new Dart2JsTypedefMirror(this, type);
346 }
347 }
348 compiler.internalError("Unexpected type $type of kind ${type.kind}");
349 }
350
351 DeclarationMirror _getTypeDeclarationMirror(Element element) {
352 if (element.isClass()) {
353 return new Dart2JsClassDeclarationMirror(
354 this, element.computeType(compiler));
355 } else if (element.isTypedef()) {
356 return new Dart2JsTypedefDeclarationMirror(this,
357 element.computeType(compiler));
358 }
359 }
360 }
361
362 abstract class ContainerMixin {
363 Map<Symbol, DeclarationMirror> _declarations;
364
365 void _ensureDeclarations() {
366 if (_declarations == null) {
367 _declarations = <Symbol, DeclarationMirror>{};
368 _forEachElement((Element element) {
369 for (DeclarationMirror mirror in _getDeclarationMirrors(element)) {
370 assert(invariant(_element,
371 !_declarations.containsKey(mirror.simpleName),
372 message: "Declaration name '${nameOf(mirror)}' "
373 "is not unique in $_element."));
374 _declarations[mirror.simpleName] = mirror;
375 }
376 });
377 }
378 }
379
380 Element get _element;
381
382 void _forEachElement(f(Element element));
383
384 Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element);
385
386 Map<Symbol, DeclarationMirror> get declarations {
387 _ensureDeclarations();
388 return new ImmutableMapWrapper<Symbol, DeclarationMirror>(_declarations);
389 }
390 }
391
392 /**
393 * Converts [element] into its corresponding [DeclarationMirror], if any.
394 *
395 * If [element] is an [AbstractFieldElement] the mirror for its getter is
396 * returned or, if not present, the mirror for its setter.
397 */
398 DeclarationMirror _convertElementToDeclarationMirror(Dart2JsMirrorSystem system,
399 Element element) {
400 if (element.isTypeVariable()) {
401 return new Dart2JsTypeVariableMirror(
402 system, element.computeType(system.compiler));
403 }
404
405 Dart2JsLibraryMirror library = system._libraryMap[element.getLibrary()];
406 if (element.isLibrary()) return library;
407 if (element.isTypedef()) {
408 return new Dart2JsTypedefMirror.fromLibrary(
409 library, element.computeType(system.compiler));
410 }
411
412 Dart2JsDeclarationMirror container = library;
413 if (element.getEnclosingClass() != null) {
414 container = system._getTypeDeclarationMirror(element.getEnclosingClass());
415 }
416 if (element.isClass()) return container;
417 if (element.isParameter()) {
418 var method = _convertElementMethodToMethodMirror(
floitsch 2014/01/30 18:18:20 Why the change (removing the type "MethodMirror").
Johnni Winther 2014/02/03 08:22:48 Done.
419 container, element.getOutermostEnclosingMemberOrTopLevel());
420 // TODO(johnniwinther): Find the right info for [isOptional] and [isNamed].
421 return new Dart2JsParameterMirror(
422 method, element, isOptional: false, isNamed: false);
423 }
424 Iterable<DeclarationMirror> members =
425 container._getDeclarationMirrors(element);
426 if (members.isEmpty) return null;
427 return members.first;
428 }
429
430 /**
431 * Experimental API for accessing compilation units defined in a
432 * library.
433 */
434 // TODO(ahe): Superclasses? Is this really a mirror?
435 class Dart2JsCompilationUnitMirror extends Dart2JsMirror
436 with ContainerMixin {
437 final Dart2JsLibraryMirror _library;
438 final CompilationUnitElement _element;
439
440 Dart2JsCompilationUnitMirror(this._element, this._library);
441
442 Dart2JsMirrorSystem get mirrors => _library.mirrors;
443
444 // TODO(johnniwinther): make sure that these are returned in declaration
445 // order.
446 void _forEachElement(f(Element element)) => _element.forEachLocalMember(f);
447
448 Iterable<DeclarationMirror> _getDeclarationMirrors(Element element) =>
449 _library._getDeclarationMirrors(element);
450
451 Uri get uri => _element.script.uri;
452 }
453
454 /**
455 * Transitional class that allows access to features that have not yet
456 * made it to the mirror API.
457 *
458 * All API in this class is experimental.
459 */
460 class BackDoor {
461 /// Return the compilation units comprising [library].
462 static List<Mirror> compilationUnitsOf(Dart2JsLibraryMirror library) {
463 return library._element.compilationUnits.toList().map(
464 (cu) => new Dart2JsCompilationUnitMirror(cu, library)).toList();
465 }
466 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698