| 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('../../compiler/compiler.dart', prefix: 'diagnostics'); |
| 8 #import('../../compiler/implementation/elements/elements.dart'); |
| 9 #import('../../compiler/implementation/apiimpl.dart', prefix: 'api'); |
| 10 #import('../../compiler/implementation/scanner/scannerlib.dart'); |
| 11 #import('../../compiler/implementation/leg.dart'); |
| 12 #import('../../compiler/implementation/filenames.dart'); |
| 13 #import('../../compiler/implementation/source_file.dart'); |
| 14 #import('../../compiler/implementation/tree/tree.dart'); |
| 15 #import('../../compiler/implementation/util/util.dart'); |
| 16 #import('../../compiler/implementation/util/uri_extras.dart'); |
| 17 #import('../../compiler/implementation/dart2js.dart'); |
| 18 #import('mirrors.dart'); |
| 19 #import('util.dart'); |
| 20 #import('dart:io'); |
| 21 #import('dart:uri'); |
| 22 |
| 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(system, method, |
| 40 link.head, false)); |
| 41 link = link.tail; |
| 42 } |
| 43 link = signature.optionalParameters; |
| 44 while (!link.isEmpty()) { |
| 45 parameters.add(new Dart2jsParameterMirror(system, method, |
| 46 link.head, true)); |
| 47 link = link.tail; |
| 48 } |
| 49 return parameters; |
| 50 } |
| 51 |
| 52 Dart2jsTypeMirror _convertTypeToTypeMirror( |
| 53 Dart2jsMirrorSystem system, |
| 54 Type type, |
| 55 InterfaceType defaultType, |
| 56 [FunctionSignature functionSignature]) { |
| 57 if (type === null) { |
| 58 return new Dart2jsInterfaceTypeMirror(system, defaultType); |
| 59 } else if (type is InterfaceType) { |
| 60 return new Dart2jsInterfaceTypeMirror(system, type); |
| 61 } else if (type is TypeVariableType) { |
| 62 return new Dart2jsTypeVariableMirror(system, type); |
| 63 } else if (type is FunctionType) { |
| 64 if (type.element is TypedefElement) { |
| 65 return new Dart2jsTypedefMirror(system, type.element); |
| 66 } else { |
| 67 return new Dart2jsFunctionTypeMirror(system, type, functionSignature); |
| 68 } |
| 69 } else if (type is VoidType) { |
| 70 return new Dart2jsVoidMirror(system, type); |
| 71 } |
| 72 throw new IllegalArgumentException("Unexpected interface type $type"); |
| 73 } |
| 74 |
| 75 Collection<Dart2jsMemberMirror> _convertElementMemberToMemberMirrors( |
| 76 Dart2jsObjectMirror library, Element element) { |
| 77 if (element is SynthesizedConstructorElement) { |
| 78 return const <Dart2jsMemberMirror>[]; |
| 79 } else if (element is VariableElement) { |
| 80 return <Dart2jsMemberMirror>[new Dart2jsFieldMirror(library, element)]; |
| 81 } else if (element is FunctionElement) { |
| 82 return <Dart2jsMemberMirror>[new Dart2jsMethodMirror(library, element)]; |
| 83 } else if (element is AbstractFieldElement) { |
| 84 var members = <Dart2jsMemberMirror>[]; |
| 85 if (element.getter !== null) { |
| 86 members.add(new Dart2jsMethodMirror(library, element.getter, |
| 87 Dart2jsMethodKind.GETTER)); |
| 88 } |
| 89 if (element.setter !== null) { |
| 90 members.add(new Dart2jsMethodMirror(library, element.setter, |
| 91 Dart2jsMethodKind.SETTER)); |
| 92 } |
| 93 return members; |
| 94 } |
| 95 throw new IllegalArgumentException( |
| 96 "Unexpected member type $element ${element.kind}"); |
| 97 } |
| 98 |
| 99 MethodMirror _convertElementMethodToMethodMirror(Dart2jsObjectMirror library, |
| 100 Element element) { |
| 101 if (element is FunctionElement) { |
| 102 return new Dart2jsMethodMirror(library, element); |
| 103 } else { |
| 104 return null; |
| 105 } |
| 106 } |
| 107 |
| 108 class Dart2jsMethodKind { |
| 109 static final Dart2jsMethodKind NORMAL = const Dart2jsMethodKind("normal"); |
| 110 static final Dart2jsMethodKind CONSTRUCTOR |
| 111 = const Dart2jsMethodKind("constructor"); |
| 112 static final Dart2jsMethodKind CONST = const Dart2jsMethodKind("const"); |
| 113 static final Dart2jsMethodKind FACTORY = const Dart2jsMethodKind("factory"); |
| 114 static final Dart2jsMethodKind GETTER = const Dart2jsMethodKind("getter"); |
| 115 static final Dart2jsMethodKind SETTER = const Dart2jsMethodKind("setter"); |
| 116 static final Dart2jsMethodKind OPERATOR = const Dart2jsMethodKind("operator"); |
| 117 |
| 118 final String text; |
| 119 |
| 120 const Dart2jsMethodKind(this.text); |
| 121 |
| 122 String toString() => text; |
| 123 } |
| 124 |
| 125 |
| 126 String _getOperatorFromOperatorName(String name) { |
| 127 Map<String, String> mapping = const { |
| 128 'eq': '==', |
| 129 'not': '~', |
| 130 'negate': 'negate', // Will change. |
| 131 'index': '[]', |
| 132 'indexSet': '[]=', |
| 133 'mul': '*', |
| 134 'div': '/', |
| 135 'mod': '%', |
| 136 'tdiv': '~/', |
| 137 'add': '+', |
| 138 'sub': '-', |
| 139 'shl': '<<', |
| 140 'shr': '>>', |
| 141 'ge': '>=', |
| 142 'gt': '>', |
| 143 'le': '<=', |
| 144 'lt': '<', |
| 145 'and': '&', |
| 146 'xor': '^', |
| 147 'or': '|', |
| 148 }; |
| 149 String newName = mapping[name]; |
| 150 if (newName === null) { |
| 151 throw new Exception('Unhandled operator name: $name'); |
| 152 } |
| 153 return newName; |
| 154 } |
| 155 |
| 156 DiagnosticListener get _diagnosticListener() { |
| 157 return const Dart2jsDiagnosticListener(); |
| 158 } |
| 159 |
| 160 class Dart2jsDiagnosticListener implements DiagnosticListener { |
| 161 const Dart2jsDiagnosticListener(); |
| 162 |
| 163 void cancel([String reason, node, token, instruction, element]) { |
| 164 print(reason); |
| 165 } |
| 166 |
| 167 void log(message) { |
| 168 print(message); |
| 169 } |
| 170 } |
| 171 |
| 172 //------------------------------------------------------------------------------ |
| 173 // Compilation implementation |
| 174 //------------------------------------------------------------------------------ |
| 175 |
| 176 class Dart2jsCompilation implements Compilation { |
| 177 api.Compiler _compiler; |
| 178 Uri cwd; |
| 179 bool isAborting = false; |
| 180 Map<String, SourceFile> sourceFiles; |
| 181 |
| 182 Future<String> provider(Uri uri) { |
| 183 if (uri.scheme != 'file') { |
| 184 throw new IllegalArgumentException(uri); |
| 185 } |
| 186 String source; |
| 187 try { |
| 188 source = readAll(uriPathToNative(uri.path)); |
| 189 } catch (FileIOException ex) { |
| 190 throw 'Error: Cannot read "${relativize(cwd, uri)}" (${ex.osError}).'; |
| 191 } |
| 192 sourceFiles[uri.toString()] = |
| 193 new SourceFile(relativize(cwd, uri), source); |
| 194 return new Future.immediate(source); |
| 195 } |
| 196 |
| 197 void handler(Uri uri, int begin, int end, |
| 198 String message, diagnostics.Diagnostic kind) { |
| 199 if (isAborting) return; |
| 200 bool fatal = |
| 201 kind === diagnostics.Diagnostic.CRASH || |
| 202 kind === diagnostics.Diagnostic.ERROR; |
| 203 if (uri === null) { |
| 204 if (!fatal) { |
| 205 return; |
| 206 } |
| 207 print(message); |
| 208 throw message; |
| 209 } else if (fatal) { |
| 210 SourceFile file = sourceFiles[uri.toString()]; |
| 211 print(file.getLocationMessage(message, begin, end, true, (s) => s)); |
| 212 throw message; |
| 213 } |
| 214 } |
| 215 |
| 216 Dart2jsCompilation(String script, String libraryRoot, |
| 217 [String packageRoot, List<String> opts = const <String>[]]) |
| 218 : cwd = getCurrentDirectory(), sourceFiles = <SourceFile>{} { |
| 219 var libraryUri = cwd.resolve(nativeToUriPath(libraryRoot)); |
| 220 var packageUri; |
| 221 if (packageRoot !== null) { |
| 222 packageUri = cwd.resolve(nativeToUriPath(packageRoot)); |
| 223 } else { |
| 224 packageUri = libraryUri; |
| 225 } |
| 226 _compiler = new api.Compiler(provider, handler, |
| 227 libraryUri, packageUri, <String>[]); |
| 228 var scriptUri = cwd.resolve(nativeToUriPath(script)); |
| 229 // TODO(johnniwinther): Detect file not found |
| 230 _compiler.run(scriptUri); |
| 231 } |
| 232 |
| 233 void addLibrary(String path) { |
| 234 var uri = cwd.resolve(nativeToUriPath(path)); |
| 235 _compiler.scanner.loadLibrary(uri, null); |
| 236 } |
| 237 |
| 238 MirrorSystem mirrors() => new Dart2jsMirrorSystem(_compiler); |
| 239 } |
| 240 |
| 241 |
| 242 //------------------------------------------------------------------------------ |
| 243 // Dart2js specific extensions of mirror interfaces |
| 244 //------------------------------------------------------------------------------ |
| 245 |
| 246 interface Dart2jsMirror extends Mirror { |
| 247 /** |
| 248 * A unique name used as the key in maps. |
| 249 */ |
| 250 final String canonicalName; |
| 251 final Dart2jsMirrorSystem system; |
| 252 } |
| 253 |
| 254 interface Dart2jsMemberMirror extends Dart2jsMirror, MemberMirror { |
| 255 |
| 256 } |
| 257 |
| 258 interface Dart2jsTypeMirror extends Dart2jsMirror, TypeMirror { |
| 259 |
| 260 } |
| 261 |
| 262 abstract class Dart2jsElementMirror implements Dart2jsMirror { |
| 263 final Dart2jsMirrorSystem system; |
| 264 final Element _element; |
| 265 |
| 266 Dart2jsElementMirror(this.system, this._element) { |
| 267 assert (system !== null); |
| 268 assert (_element !== null); |
| 269 } |
| 270 |
| 271 String simpleName() => _element.name.slowToString(); |
| 272 |
| 273 Location location() => new Dart2jsLocation( |
| 274 _element.getCompilationUnit().script, |
| 275 system.compiler.spanFromElement(_element)); |
| 276 |
| 277 String toString() => _element.toString(); |
| 278 } |
| 279 |
| 280 abstract class Dart2jsProxyMirror implements Dart2jsMirror { |
| 281 final Dart2jsMirrorSystem system; |
| 282 |
| 283 Dart2jsProxyMirror(this.system); |
| 284 } |
| 285 |
| 286 /////////////////////////////////////////////////////// |
| 287 // implementation |
| 288 /////////////////////////////////////////////////////// |
| 289 |
| 290 class Dart2jsMirrorSystem implements MirrorSystem, Dart2jsMirror { |
| 291 final api.Compiler compiler; |
| 292 Map<String, Dart2jsLibraryMirror> _libraries; |
| 293 Map<LibraryElement, Dart2jsLibraryMirror> _libraryMap; |
| 294 |
| 295 Dart2jsMirrorSystem(this.compiler) |
| 296 : _libraryMap = new Map<LibraryElement, Dart2jsLibraryMirror>(); |
| 297 |
| 298 void _ensureLibraries() { |
| 299 if (_libraries == null) { |
| 300 _libraries = <Dart2jsLibraryMirror>{}; |
| 301 compiler.libraries.forEach((_, LibraryElement v) { |
| 302 var mirror = new Dart2jsLibraryMirror(system, v); |
| 303 _libraries[mirror.canonicalName] = mirror; |
| 304 _libraryMap[v] = mirror; |
| 305 }); |
| 306 } |
| 307 } |
| 308 |
| 309 Map<Object, LibraryMirror> libraries() { |
| 310 _ensureLibraries(); |
| 311 return new ImmutableMapWrapper<Object, LibraryMirror>(_libraries); |
| 312 } |
| 313 |
| 314 Dart2jsLibraryMirror getLibrary(LibraryElement element) { |
| 315 return _libraryMap[element]; |
| 316 } |
| 317 |
| 318 Dart2jsMirrorSystem get system() => this; |
| 319 |
| 320 String simpleName() => "mirror"; |
| 321 String qualifiedName() => simpleName(); |
| 322 |
| 323 String get canonicalName() => simpleName(); |
| 324 } |
| 325 |
| 326 abstract class Dart2jsObjectMirror extends Dart2jsElementMirror |
| 327 implements ObjectMirror { |
| 328 Dart2jsObjectMirror(Dart2jsMirrorSystem system, Element element) |
| 329 : super(system, element); |
| 330 } |
| 331 |
| 332 class Dart2jsLibraryMirror extends Dart2jsObjectMirror |
| 333 implements LibraryMirror { |
| 334 Map<String, InterfaceMirror> _types; |
| 335 Map<String, MemberMirror> _members; |
| 336 |
| 337 Dart2jsLibraryMirror(Dart2jsMirrorSystem system, LibraryElement library) |
| 338 : super(system, library); |
| 339 |
| 340 LibraryElement get _library() => _element; |
| 341 |
| 342 String get canonicalName() => simpleName(); |
| 343 |
| 344 /** |
| 345 * Returns the library name (for libraries with a #library tag) or the script |
| 346 * file name (for scripts without a #library tag). The latter case is used to |
| 347 * provide a 'library name' for scripts, to use for instance in dartdoc. |
| 348 */ |
| 349 String simpleName() { |
| 350 if (_library.libraryTag !== null) { |
| 351 return _library.libraryTag.argument.dartString.slowToString(); |
| 352 } else { |
| 353 // Use the file name as script name. |
| 354 String path = _library.script.uri.path; |
| 355 return path.substring(path.lastIndexOf('/') + 1); |
| 356 } |
| 357 } |
| 358 |
| 359 String qualifiedName() => simpleName(); |
| 360 |
| 361 void _ensureTypes() { |
| 362 if (_types == null) { |
| 363 _types = <InterfaceMirror>{}; |
| 364 _library.forEachExport((Element e) { |
| 365 if (e.getLibrary() == _library) { |
| 366 if (e.isClass()) { |
| 367 var type = new Dart2jsInterfaceMirror.fromLibrary(this, e); |
| 368 _types[type.canonicalName] = type; |
| 369 } else if (e.isTypedef()) { |
| 370 var type = new Dart2jsTypedefMirror.fromLibrary(this, e); |
| 371 _types[type.canonicalName] = type; |
| 372 } |
| 373 } |
| 374 }); |
| 375 } |
| 376 } |
| 377 |
| 378 void _ensureMembers() { |
| 379 if (_members == null) { |
| 380 _members = <MemberMirror>{}; |
| 381 _library.forEachExport((Element e) { |
| 382 if (!e.isClass() && !e.isTypedef()) { |
| 383 for (var member in _convertElementMemberToMemberMirrors(this, e)) { |
| 384 _members[member.canonicalName] = member; |
| 385 } |
| 386 } |
| 387 }); |
| 388 } |
| 389 } |
| 390 |
| 391 Map<Object, MemberMirror> declaredMembers() { |
| 392 _ensureMembers(); |
| 393 return new ImmutableMapWrapper<Object, MemberMirror>(_members); |
| 394 } |
| 395 |
| 396 Map<Object, InterfaceMirror> types() { |
| 397 _ensureTypes(); |
| 398 return new ImmutableMapWrapper<Object, InterfaceMirror>(_types); |
| 399 } |
| 400 |
| 401 Location location() { |
| 402 var script = _library.getCompilationUnit().script; |
| 403 return new Dart2jsLocation( |
| 404 script, |
| 405 new SourceSpan(script.uri, 0, script.text.length)); |
| 406 } |
| 407 } |
| 408 |
| 409 class Dart2jsLocation implements Location { |
| 410 Script _script; |
| 411 SourceSpan _span; |
| 412 |
| 413 Dart2jsLocation(this._script, this._span); |
| 414 |
| 415 int start() => _span.begin; |
| 416 int end() => _span.end; |
| 417 Source source() => new Dart2jsSource(_script); |
| 418 |
| 419 String text() => _script.text.substring(start(), end()); |
| 420 } |
| 421 |
| 422 class Dart2jsSource implements Source { |
| 423 Script _script; |
| 424 |
| 425 Dart2jsSource(this._script); |
| 426 |
| 427 Uri uri() => _script.uri; |
| 428 String text() => _script.text; |
| 429 } |
| 430 |
| 431 class Dart2jsParameterMirror extends Dart2jsElementMirror |
| 432 implements ParameterMirror { |
| 433 final MethodMirror _method; |
| 434 final bool _isOptional; |
| 435 |
| 436 Dart2jsParameterMirror(Dart2jsMirrorSystem system, |
| 437 this._method, |
| 438 VariableElement element, |
| 439 this._isOptional) |
| 440 : super(system, element); |
| 441 |
| 442 VariableElement get _variableElement() => _element; |
| 443 |
| 444 String get canonicalName() => simpleName(); |
| 445 |
| 446 String qualifiedName() => '${_method.qualifiedName()}#${simpleName()}'; |
| 447 |
| 448 // TODO(johnniwinther): Provide |
| 449 // [:_variableElement.variables.functionSignature:] instead of [:null:]. |
| 450 TypeMirror type() => _convertTypeToTypeMirror(system, |
| 451 _variableElement.computeType(system.compiler), |
| 452 system.compiler.dynamicClass.computeType(system.compiler), |
| 453 null); |
| 454 |
| 455 String defaultValue() => null; // TODO(johnniwinther): How to compute this? |
| 456 |
| 457 bool hasDefaultValue() => false; // TODO(johnniwinther): How to compute this? |
| 458 |
| 459 bool isOptional() => _isOptional; |
| 460 } |
| 461 |
| 462 //------------------------------------------------------------------------------ |
| 463 // Declarations |
| 464 //------------------------------------------------------------------------------ |
| 465 class Dart2jsInterfaceMirror extends Dart2jsObjectMirror |
| 466 implements Dart2jsTypeMirror, InterfaceMirror { |
| 467 final Dart2jsLibraryMirror _library; |
| 468 Map<String, Dart2jsMemberMirror> _members; |
| 469 List<TypeVariableMirror> _typeVariables; |
| 470 |
| 471 Dart2jsInterfaceMirror(Dart2jsMirrorSystem system, ClassElement _class) |
| 472 : this._library = system.getLibrary(_class.getLibrary()), |
| 473 super(system, _class); |
| 474 |
| 475 ClassElement get _class() => _element; |
| 476 |
| 477 |
| 478 Dart2jsInterfaceMirror.fromLibrary(Dart2jsLibraryMirror library, |
| 479 ClassElement _class) |
| 480 : this._library = library, |
| 481 super(library.system, _class); |
| 482 |
| 483 String get canonicalName() => simpleName(); |
| 484 |
| 485 String qualifiedName() => '${library().qualifiedName()}.${simpleName()}'; |
| 486 |
| 487 Location location() { |
| 488 if (_class is PartialClassElement) { |
| 489 var node = _class.parseNode(_diagnosticListener); |
| 490 if (node !== null) { |
| 491 var script = _class.getCompilationUnit().script; |
| 492 var span = system.compiler.spanFromNode(node, script.uri); |
| 493 return new Dart2jsLocation(script, span); |
| 494 } |
| 495 } |
| 496 return super.location(); |
| 497 } |
| 498 |
| 499 void _ensureMembers() { |
| 500 if (_members == null) { |
| 501 _members = <Dart2jsMemberMirror>{}; |
| 502 _class.constructors.forEach((_, e) { |
| 503 for (var member in _convertElementMemberToMemberMirrors(this, e)) { |
| 504 _members[member.canonicalName] = member; |
| 505 } |
| 506 }); |
| 507 _class.localMembers.forEach((_, e) { |
| 508 for (var member in _convertElementMemberToMemberMirrors(this, e)) { |
| 509 _members[member.canonicalName] = member; |
| 510 } |
| 511 }); |
| 512 } |
| 513 } |
| 514 |
| 515 Map<Object, MemberMirror> declaredMembers() { |
| 516 _ensureMembers(); |
| 517 return new ImmutableMapWrapper<Object, MemberMirror>(_members); |
| 518 } |
| 519 |
| 520 LibraryMirror library() { |
| 521 return _library; |
| 522 } |
| 523 |
| 524 bool get isObject() => _class == system.compiler.objectClass; |
| 525 |
| 526 bool get isDynamic() => _class == system.compiler.dynamicClass; |
| 527 |
| 528 bool get isVoid() => false; |
| 529 |
| 530 bool get isTypeVariable() => false; |
| 531 |
| 532 bool get isTypedef() => false; |
| 533 |
| 534 bool get isFunction() => false; |
| 535 |
| 536 InterfaceMirror get declaration() => this; |
| 537 |
| 538 InterfaceMirror superclass() { |
| 539 if (_class.supertype != null) { |
| 540 return new Dart2jsInterfaceTypeMirror(system, _class.supertype); |
| 541 } |
| 542 return null; |
| 543 } |
| 544 |
| 545 Map<Object, InterfaceMirror> interfaces() { |
| 546 var map = new Map<String, InterfaceMirror>(); |
| 547 Link<Type> link = _class.interfaces; |
| 548 while (!link.isEmpty()) { |
| 549 var type = _convertTypeToTypeMirror(system, link.head, |
| 550 system.compiler.dynamicClass.computeType(system.compiler)); |
| 551 map[type.canonicalName] = type; |
| 552 link = link.tail; |
| 553 } |
| 554 return new ImmutableMapWrapper<Object, InterfaceMirror>(map); |
| 555 } |
| 556 |
| 557 bool get isClass() => !_class.isInterface(); |
| 558 |
| 559 bool get isInterface() => _class.isInterface(); |
| 560 |
| 561 bool get isPrivate() => _isPrivate(simpleName()); |
| 562 |
| 563 bool get isDeclaration() => true; |
| 564 |
| 565 List<TypeMirror> typeArguments() { |
| 566 throw new UnsupportedOperationException( |
| 567 'Declarations do not have type arguments'); |
| 568 } |
| 569 |
| 570 List<TypeVariableMirror> typeVariables() { |
| 571 if (_typeVariables == null) { |
| 572 _typeVariables = <TypeVariableMirror>[]; |
| 573 _class.typeParameters.forEach((_,parameter) { |
| 574 _typeVariables.add( |
| 575 new Dart2jsTypeVariableMirror(system, |
| 576 parameter.computeType(system.compiler))); |
| 577 }); |
| 578 } |
| 579 return _typeVariables; |
| 580 } |
| 581 |
| 582 Map<Object, MethodMirror> constructors() { |
| 583 _ensureMembers(); |
| 584 return new AsFilteredImmutableMap<Object, MemberMirror, MethodMirror>( |
| 585 _members, (m) => m.isConstructor ? m : null); |
| 586 } |
| 587 |
| 588 /** |
| 589 * Returns the default type for this interface. |
| 590 */ |
| 591 InterfaceMirror defaultType() { |
| 592 if (_class.defaultClass != null) { |
| 593 return new Dart2jsInterfaceTypeMirror(system, _class.defaultClass); |
| 594 } |
| 595 return null; |
| 596 } |
| 597 |
| 598 bool operator ==(Object other) { |
| 599 if (this === other) { |
| 600 return true; |
| 601 } |
| 602 if (other is! InterfaceMirror) { |
| 603 return false; |
| 604 } |
| 605 if (library() != other.library()) { |
| 606 return false; |
| 607 } |
| 608 if (isDeclaration !== other.isDeclaration) { |
| 609 return false; |
| 610 } |
| 611 return qualifiedName() == other.qualifiedName(); |
| 612 } |
| 613 } |
| 614 |
| 615 class Dart2jsTypedefMirror extends Dart2jsElementMirror |
| 616 implements Dart2jsTypeMirror, TypedefMirror { |
| 617 final Dart2jsLibraryMirror _library; |
| 618 List<TypeVariableMirror> _typeVariables; |
| 619 TypeMirror _definition; |
| 620 |
| 621 Dart2jsTypedefMirror(Dart2jsMirrorSystem system, TypedefElement _typedef) |
| 622 : this._library = system.getLibrary(_typedef.getLibrary()), |
| 623 super(system, _typedef); |
| 624 |
| 625 Dart2jsTypedefMirror.fromLibrary(Dart2jsLibraryMirror library, |
| 626 TypedefElement _typedef) |
| 627 : this._library = library, |
| 628 super(library.system, _typedef); |
| 629 |
| 630 TypedefElement get _typedef() => _element; |
| 631 |
| 632 String get canonicalName() => simpleName(); |
| 633 |
| 634 String qualifiedName() => '${library().qualifiedName()}.${simpleName()}'; |
| 635 |
| 636 Location location() { |
| 637 var node = _typedef.parseNode(_diagnosticListener); |
| 638 if (node !== null) { |
| 639 var script = _typedef.getCompilationUnit().script; |
| 640 var span = system.compiler.spanFromNode(node, script.uri); |
| 641 return new Dart2jsLocation(script, span); |
| 642 } |
| 643 return super.location(); |
| 644 } |
| 645 |
| 646 LibraryMirror library() => _library; |
| 647 |
| 648 bool get isObject() => false; |
| 649 |
| 650 bool get isDynamic() => false; |
| 651 |
| 652 bool get isVoid() => false; |
| 653 |
| 654 bool get isTypeVariable() => false; |
| 655 |
| 656 bool get isTypedef() => true; |
| 657 |
| 658 bool get isFunction() => false; |
| 659 |
| 660 List<TypeMirror> typeArguments() { |
| 661 throw new UnsupportedOperationException( |
| 662 'Declarations do not have type arguments'); |
| 663 } |
| 664 |
| 665 List<TypeVariableMirror> typeVariables() { |
| 666 if (_typeVariables == null) { |
| 667 _typeVariables = <TypeVariableMirror>[]; |
| 668 // TODO(johnniwinther): Equip [Typedef] with a [typeParameters] map, just |
| 669 // like [ClassElement]. |
| 670 } |
| 671 return _typeVariables; |
| 672 } |
| 673 |
| 674 TypeMirror definition() { |
| 675 if (_definition === null) { |
| 676 // TODO(johnniwinther): Provide access to the functionSignature of the |
| 677 // aliased function definition. |
| 678 } |
| 679 return _definition; |
| 680 } |
| 681 |
| 682 Map<Object, MemberMirror> declaredMembers() => const <MemberMirror>{}; |
| 683 |
| 684 InterfaceMirror get declaration() => this; |
| 685 |
| 686 // TODO(johnniwinther): How should a typedef respond to these? |
| 687 InterfaceMirror superclass() => null; |
| 688 |
| 689 Map<Object, InterfaceMirror> interfaces() => const <InterfaceMirror>{}; |
| 690 |
| 691 bool get isClass() => false; |
| 692 |
| 693 bool get isInterface() => false; |
| 694 |
| 695 bool get isPrivate() => _isPrivate(simpleName()); |
| 696 |
| 697 bool get isDeclaration() => true; |
| 698 |
| 699 Map<Object, MethodMirror> constructors() => const <MethodMirror>{}; |
| 700 |
| 701 InterfaceMirror defaultType() => null; |
| 702 } |
| 703 |
| 704 class Dart2jsTypeVariableMirror extends Dart2jsTypeElementMirror |
| 705 implements TypeVariableMirror { |
| 706 final TypeVariableType _typeVariableType; |
| 707 InterfaceMirror _declarer; |
| 708 |
| 709 Dart2jsTypeVariableMirror(Dart2jsMirrorSystem system, |
| 710 TypeVariableType typeVariableType) |
| 711 : this._typeVariableType = typeVariableType, |
| 712 super(system, typeVariableType) { |
| 713 assert(_typeVariableType !== null); |
| 714 } |
| 715 |
| 716 |
| 717 String qualifiedName() => '${declarer().qualifiedName()}.${simpleName()}'; |
| 718 |
| 719 InterfaceMirror declarer() { |
| 720 if (_declarer === null) { |
| 721 if (_typeVariableType.element.enclosingElement.isClass()) { |
| 722 _declarer = new Dart2jsInterfaceMirror(system, |
| 723 _typeVariableType.element.enclosingElement); |
| 724 } else if (_typeVariableType.element.enclosingElement.isTypedef()) { |
| 725 _declarer = new Dart2jsTypedefMirror(system, |
| 726 _typeVariableType.element.enclosingElement); |
| 727 } |
| 728 } |
| 729 return _declarer; |
| 730 } |
| 731 |
| 732 LibraryMirror library() => declarer().library(); |
| 733 |
| 734 bool get isObject() => false; |
| 735 |
| 736 bool get isDynamic() => false; |
| 737 |
| 738 bool get isVoid() => false; |
| 739 |
| 740 bool get isTypeVariable() => true; |
| 741 |
| 742 bool get isTypedef() => false; |
| 743 |
| 744 bool get isFunction() => false; |
| 745 |
| 746 TypeMirror bound() => _convertTypeToTypeMirror( |
| 747 system, |
| 748 _typeVariableType.element.bound, |
| 749 system.compiler.objectClass.computeType(system.compiler)); |
| 750 |
| 751 bool operator ==(Object other) { |
| 752 if (this === other) { |
| 753 return true; |
| 754 } |
| 755 if (other is! TypeVariableMirror) { |
| 756 return false; |
| 757 } |
| 758 if (declarer() != other.declarer()) { |
| 759 return false; |
| 760 } |
| 761 return qualifiedName() == other.qualifiedName(); |
| 762 } |
| 763 } |
| 764 |
| 765 |
| 766 //------------------------------------------------------------------------------ |
| 767 // Types |
| 768 //------------------------------------------------------------------------------ |
| 769 |
| 770 abstract class Dart2jsTypeElementMirror extends Dart2jsProxyMirror |
| 771 implements Dart2jsTypeMirror { |
| 772 final Type _type; |
| 773 |
| 774 Dart2jsTypeElementMirror(Dart2jsMirrorSystem system, this._type) |
| 775 : super(system); |
| 776 |
| 777 String simpleName() => _type.name.slowToString(); |
| 778 |
| 779 String get canonicalName() => simpleName(); |
| 780 |
| 781 Location location() { |
| 782 var script = _type.element.getCompilationUnit().script; |
| 783 return new Dart2jsLocation(script, |
| 784 system.compiler.spanFromElement(_type.element)); |
| 785 } |
| 786 |
| 787 LibraryMirror library() { |
| 788 return system.getLibrary(_type.element.getLibrary()); |
| 789 } |
| 790 |
| 791 String toString() => _type.element.toString(); |
| 792 } |
| 793 |
| 794 class Dart2jsInterfaceTypeMirror extends Dart2jsTypeElementMirror |
| 795 implements InterfaceMirror { |
| 796 List<TypeMirror> _typeArguments; |
| 797 |
| 798 Dart2jsInterfaceTypeMirror(Dart2jsMirrorSystem system, |
| 799 InterfaceType interfaceType) |
| 800 : super(system, interfaceType); |
| 801 |
| 802 InterfaceType get _interfaceType() => _type; |
| 803 |
| 804 String qualifiedName() => declaration.qualifiedName(); |
| 805 |
| 806 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 807 Map<Object, MemberMirror> declaredMembers() => declaration.declaredMembers(); |
| 808 |
| 809 bool get isObject() => system.compiler.objectClass == _type.element; |
| 810 |
| 811 bool get isDynamic() => system.compiler.dynamicClass == _type.element; |
| 812 |
| 813 bool get isTypeVariable() => false; |
| 814 |
| 815 bool get isVoid() => false; |
| 816 |
| 817 bool get isTypedef() => false; |
| 818 |
| 819 bool get isFunction() => false; |
| 820 |
| 821 InterfaceMirror get declaration() |
| 822 => new Dart2jsInterfaceMirror(system, _type.element); |
| 823 |
| 824 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 825 InterfaceMirror superclass() => declaration.superclass(); |
| 826 |
| 827 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 828 Map<Object, InterfaceMirror> interfaces() => declaration.interfaces(); |
| 829 |
| 830 bool get isClass() => declaration.isClass; |
| 831 |
| 832 bool get isInterface() => declaration.isInterface; |
| 833 |
| 834 bool get isPrivate() => declaration.isPrivate; |
| 835 |
| 836 bool get isDeclaration() => false; |
| 837 |
| 838 List<TypeMirror> typeArguments() { |
| 839 if (_typeArguments == null) { |
| 840 _typeArguments = <TypeMirror>[]; |
| 841 Link<Type> type = _interfaceType.arguments; |
| 842 while (type != null && type.head != null) { |
| 843 _typeArguments.add(_convertTypeToTypeMirror(system, type.head, |
| 844 system.compiler.dynamicClass.computeType(system.compiler))); |
| 845 type = type.tail; |
| 846 } |
| 847 } |
| 848 return _typeArguments; |
| 849 } |
| 850 |
| 851 List<TypeVariableMirror> typeVariables() => declaration.typeVariables(); |
| 852 |
| 853 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 854 Map<Object, MethodMirror> constructors() => declaration.constructors(); |
| 855 |
| 856 // TODO(johnniwinther): Substitute type arguments for type variables? |
| 857 InterfaceMirror defaultType() => declaration.defaultType(); |
| 858 |
| 859 bool operator ==(Object other) { |
| 860 if (this === other) { |
| 861 return true; |
| 862 } |
| 863 if (other is! InterfaceMirror) { |
| 864 return false; |
| 865 } |
| 866 if (other.isDeclaration) { |
| 867 return false; |
| 868 } |
| 869 if (declaration != other.declaration) { |
| 870 return false; |
| 871 } |
| 872 var thisTypeArguments = typeArguments().iterator(); |
| 873 var otherTypeArguments = other.typeArguments().iterator(); |
| 874 while (thisTypeArguments.hasNext() && otherTypeArguments.hasNext()) { |
| 875 if (thisTypeArguments.next() != otherTypeArguments.next()) { |
| 876 return false; |
| 877 } |
| 878 } |
| 879 return !thisTypeArguments.hasNext() && !otherTypeArguments.hasNext(); |
| 880 } |
| 881 } |
| 882 |
| 883 |
| 884 class Dart2jsFunctionTypeMirror extends Dart2jsTypeElementMirror |
| 885 implements FunctionTypeMirror { |
| 886 final FunctionSignature _functionSignature; |
| 887 List<ParameterMirror> _parameters; |
| 888 |
| 889 Dart2jsFunctionTypeMirror(Dart2jsMirrorSystem system, |
| 890 FunctionType functionType, this._functionSignature) |
| 891 : super(system, functionType) { |
| 892 assert (_functionSignature !== null); |
| 893 } |
| 894 |
| 895 FunctionType get _functionType() => _type; |
| 896 |
| 897 // TODO(johnniwinther): Is this the qualified name of a function type? |
| 898 String qualifiedName() => declaration.qualifiedName(); |
| 899 |
| 900 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 901 Map<Object, MemberMirror> declaredMembers() { |
| 902 var method = callMethod(); |
| 903 if (method !== null) { |
| 904 var map = new Map<String, MemberMirror>.from( |
| 905 declaration.declaredMembers()); |
| 906 var name = method.qualifiedName(); |
| 907 map[name] = method; |
| 908 Function func = null; |
| 909 return new ImmutableMapWrapper<Object, MemberMirror>(map); |
| 910 } |
| 911 return declaration.declaredMembers(); |
| 912 } |
| 913 |
| 914 bool get isObject() => system.compiler.objectClass == _type.element; |
| 915 |
| 916 bool get isDynamic() => system.compiler.dynamicClass == _type.element; |
| 917 |
| 918 bool get isVoid() => false; |
| 919 |
| 920 bool get isTypeVariable() => false; |
| 921 |
| 922 bool get isTypedef() => false; |
| 923 |
| 924 bool get isFunction() => true; |
| 925 |
| 926 MethodMirror callMethod() => _convertElementMethodToMethodMirror( |
| 927 system.getLibrary(_functionType.element.getLibrary()), |
| 928 _functionType.element); |
| 929 |
| 930 InterfaceMirror get declaration() |
| 931 => new Dart2jsInterfaceMirror(system, system.compiler.functionClass); |
| 932 |
| 933 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 934 InterfaceMirror superclass() => declaration.superclass(); |
| 935 |
| 936 // TODO(johnniwinther): Substitute type arguments for type variables. |
| 937 Map<Object, InterfaceMirror> interfaces() => declaration.interfaces(); |
| 938 |
| 939 bool get isClass() => declaration.isClass; |
| 940 |
| 941 bool get isInterface() => declaration.isInterface; |
| 942 |
| 943 bool get isPrivate() => declaration.isPrivate; |
| 944 |
| 945 bool get isDeclaration() => false; |
| 946 |
| 947 List<TypeMirror> typeArguments() => const <TypeMirror>[]; |
| 948 |
| 949 List<TypeVariableMirror> typeVariables() => declaration.typeVariables(); |
| 950 |
| 951 Map<Object, MethodMirror> constructors() => <MethodMirror>{}; |
| 952 |
| 953 InterfaceMirror defaultType() => null; |
| 954 |
| 955 TypeMirror returnType() { |
| 956 return _convertTypeToTypeMirror(system, _functionType.returnType, |
| 957 system.compiler.dynamicClass.computeType(system.compiler)); |
| 958 } |
| 959 |
| 960 List<ParameterMirror> parameters() { |
| 961 if (_parameters === null) { |
| 962 _parameters = _parametersFromFunctionSignature(system, callMethod(), |
| 963 _functionSignature); |
| 964 } |
| 965 return _parameters; |
| 966 } |
| 967 } |
| 968 |
| 969 class Dart2jsVoidMirror extends Dart2jsTypeElementMirror { |
| 970 |
| 971 Dart2jsVoidMirror(Dart2jsMirrorSystem system, VoidType voidType) |
| 972 : super(system, voidType); |
| 973 |
| 974 VoidType get _voidType() => _type; |
| 975 |
| 976 String qualifiedName() => simpleName(); |
| 977 |
| 978 /** |
| 979 * The void type has no location. |
| 980 */ |
| 981 Location location() => null; |
| 982 |
| 983 /** |
| 984 * The void type has no library. |
| 985 */ |
| 986 LibraryMirror getLibrary() => null; |
| 987 |
| 988 bool get isObject() => false; |
| 989 |
| 990 bool get isVoid() => true; |
| 991 |
| 992 bool get isDynamic() => false; |
| 993 |
| 994 bool get isTypeVariable() => false; |
| 995 |
| 996 bool get isTypedef() => false; |
| 997 |
| 998 bool get isFunction() => false; |
| 999 |
| 1000 bool operator ==(Object other) { |
| 1001 if (this === other) { |
| 1002 return true; |
| 1003 } |
| 1004 if (other is! TypeMirror) { |
| 1005 return false; |
| 1006 } |
| 1007 return other.isVoid; |
| 1008 } |
| 1009 } |
| 1010 |
| 1011 /////////////////////////////////////////////////////// |
| 1012 // members |
| 1013 /////////////////////////////////////////////////////// |
| 1014 |
| 1015 class Dart2jsMethodMirror extends Dart2jsElementMirror |
| 1016 implements Dart2jsMemberMirror, MethodMirror { |
| 1017 final Dart2jsObjectMirror _objectMirror; |
| 1018 String _name; |
| 1019 String _constructorName; |
| 1020 String _operatorName; |
| 1021 Dart2jsMethodKind _kind; |
| 1022 String _canonicalName; |
| 1023 |
| 1024 Dart2jsMethodMirror(Dart2jsObjectMirror objectMirror, |
| 1025 FunctionElement function, |
| 1026 [Dart2jsMethodKind kind = null]) |
| 1027 : this._objectMirror = objectMirror, |
| 1028 this._kind = kind, |
| 1029 super(objectMirror.system, function) { |
| 1030 _name = _element.name.slowToString(); |
| 1031 if (kind == null) { |
| 1032 if (_function.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 1033 _constructorName = ''; |
| 1034 int dollarPos = _name.indexOf('\$'); |
| 1035 if (dollarPos != -1) { |
| 1036 _constructorName = _name.substring(dollarPos+1); |
| 1037 _name = _name.substring(0, dollarPos); |
| 1038 // canonical name is TypeName.constructorName |
| 1039 _canonicalName = '$_name.$_constructorName'; |
| 1040 } else { |
| 1041 // canonical name is TypeName |
| 1042 _canonicalName = _name; |
| 1043 } |
| 1044 if (_function.modifiers !== null && _function.modifiers.isConst()) { |
| 1045 _kind = Dart2jsMethodKind.CONST; |
| 1046 } else { |
| 1047 _kind = Dart2jsMethodKind.CONSTRUCTOR; |
| 1048 } |
| 1049 } else if (_function.modifiers !== null |
| 1050 && _function.modifiers.isFactory()) { |
| 1051 _constructorName = ''; |
| 1052 int dollarPos = _name.indexOf('\$'); |
| 1053 if (dollarPos != -1) { |
| 1054 _constructorName = _name.substring(dollarPos+1); |
| 1055 _name = _name.substring(0, dollarPos); |
| 1056 } |
| 1057 _kind = Dart2jsMethodKind.FACTORY; |
| 1058 // canonical name is TypeName.constructorName |
| 1059 _canonicalName = '$_name.$_constructorName'; |
| 1060 } else if (_name.startsWith('operator\$')) { |
| 1061 String str = _name.substring(9); |
| 1062 _name = 'operator'; |
| 1063 _kind = Dart2jsMethodKind.OPERATOR; |
| 1064 _operatorName = _getOperatorFromOperatorName(str); |
| 1065 // canonical name is 'operator operatorName' |
| 1066 _canonicalName = 'operator $_operatorName'; |
| 1067 } else { |
| 1068 _kind = Dart2jsMethodKind.NORMAL; |
| 1069 _canonicalName = _name; |
| 1070 } |
| 1071 } else if (kind == Dart2jsMethodKind.GETTER) { |
| 1072 _canonicalName = _name; |
| 1073 } else if (kind == Dart2jsMethodKind.SETTER) { |
| 1074 _canonicalName = '$_name='; |
| 1075 } else { |
| 1076 assert(false); |
| 1077 } |
| 1078 } |
| 1079 |
| 1080 FunctionElement get _function() => _element; |
| 1081 |
| 1082 String simpleName() => _name; |
| 1083 |
| 1084 String qualifiedName() |
| 1085 => '${surroundingDeclaration().qualifiedName()}.$canonicalName'; |
| 1086 |
| 1087 String get canonicalName() => _canonicalName; |
| 1088 |
| 1089 ObjectMirror surroundingDeclaration() => _objectMirror; |
| 1090 |
| 1091 bool get isTopLevel() => _objectMirror is LibraryMirror; |
| 1092 |
| 1093 bool get isConstructor() |
| 1094 => _kind == Dart2jsMethodKind.CONSTRUCTOR || isConst || isFactory; |
| 1095 |
| 1096 bool get isField() => false; |
| 1097 |
| 1098 bool get isMethod() => !isConstructor; |
| 1099 |
| 1100 bool get isPrivate() => _isPrivate(simpleName()); |
| 1101 |
| 1102 bool get isStatic() => |
| 1103 _function.modifiers !== null && _function.modifiers.isStatic(); |
| 1104 |
| 1105 List<ParameterMirror> parameters() { |
| 1106 return _parametersFromFunctionSignature(system, this, |
| 1107 _function.computeSignature(system.compiler)); |
| 1108 } |
| 1109 |
| 1110 TypeMirror returnType() => _convertTypeToTypeMirror( |
| 1111 system, _function.computeSignature(system.compiler).returnType, |
| 1112 system.compiler.dynamicClass.computeType(system.compiler)); |
| 1113 |
| 1114 bool get isConst() => _kind == Dart2jsMethodKind.CONST; |
| 1115 |
| 1116 bool get isFactory() => _kind == Dart2jsMethodKind.FACTORY; |
| 1117 |
| 1118 String get constructorName() => _constructorName; |
| 1119 |
| 1120 bool get isGetter() => _kind == Dart2jsMethodKind.GETTER; |
| 1121 |
| 1122 bool get isSetter() => _kind == Dart2jsMethodKind.SETTER; |
| 1123 |
| 1124 bool get isOperator() => _kind == Dart2jsMethodKind.OPERATOR; |
| 1125 |
| 1126 String get operatorName() => _operatorName; |
| 1127 |
| 1128 Location location() { |
| 1129 var node = _function.parseNode(_diagnosticListener); |
| 1130 if (node !== null) { |
| 1131 var script = _function.getCompilationUnit().script; |
| 1132 var span = system.compiler.spanFromNode(node, script.uri); |
| 1133 return new Dart2jsLocation(script, span); |
| 1134 } |
| 1135 return super.location(); |
| 1136 } |
| 1137 |
| 1138 } |
| 1139 |
| 1140 class Dart2jsFieldMirror extends Dart2jsElementMirror |
| 1141 implements Dart2jsMemberMirror, FieldMirror { |
| 1142 Dart2jsObjectMirror _objectMirror; |
| 1143 VariableElement _variable; |
| 1144 |
| 1145 Dart2jsFieldMirror(Dart2jsObjectMirror objectMirror, |
| 1146 VariableElement variable) |
| 1147 : this._objectMirror = objectMirror, |
| 1148 this._variable = variable, |
| 1149 super(objectMirror.system, variable); |
| 1150 |
| 1151 String qualifiedName() |
| 1152 => '${surroundingDeclaration().qualifiedName()}.$canonicalName'; |
| 1153 |
| 1154 String get canonicalName() => simpleName(); |
| 1155 |
| 1156 ObjectMirror surroundingDeclaration() => _objectMirror; |
| 1157 |
| 1158 bool get isTopLevel() => _objectMirror is LibraryMirror; |
| 1159 |
| 1160 bool get isConstructor() => false; |
| 1161 |
| 1162 bool get isField() => true; |
| 1163 |
| 1164 bool get isMethod() => false; |
| 1165 |
| 1166 bool get isPrivate() => _isPrivate(simpleName()); |
| 1167 |
| 1168 bool get isStatic() => _variable.modifiers.isStatic(); |
| 1169 |
| 1170 bool get isFinal() => _variable.modifiers.isFinal(); |
| 1171 |
| 1172 TypeMirror type() => _convertTypeToTypeMirror(system, |
| 1173 _variable.computeType(system.compiler), |
| 1174 system.compiler.dynamicClass.computeType(system.compiler)); |
| 1175 |
| 1176 Location location() { |
| 1177 var script = _variable.getCompilationUnit().script; |
| 1178 var node = _variable.variables.parseNode(_diagnosticListener); |
| 1179 if (node !== null) { |
| 1180 var span = system.compiler.spanFromNode(node, script.uri); |
| 1181 return new Dart2jsLocation(script, span); |
| 1182 } else { |
| 1183 var span = system.compiler.spanFromElement(_variable); |
| 1184 return new Dart2jsLocation(script, span); |
| 1185 } |
| 1186 } |
| 1187 } |
| 1188 |
| OLD | NEW |