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

Unified Diff: lib/dartdoc/mirrors/dart2js_mirror.dart

Issue 10692040: Mirrors prototype added to dartdoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Utility libraries added Created 8 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: lib/dartdoc/mirrors/dart2js_mirror.dart
diff --git a/lib/dartdoc/mirrors/dart2js_mirror.dart b/lib/dartdoc/mirrors/dart2js_mirror.dart
new file mode 100644
index 0000000000000000000000000000000000000000..098d978e13f6da8b84bd8949a6ec4670bdf6e00c
--- /dev/null
+++ b/lib/dartdoc/mirrors/dart2js_mirror.dart
@@ -0,0 +1,1190 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#library('mirrors.dart2js');
+
+#import('../../compiler/compiler.dart', prefix: 'diagnostics');
+#import('../../compiler/implementation/elements/elements.dart');
+#import('../../compiler/implementation/apiimpl.dart', prefix: 'api');
+#import('../../compiler/implementation/scanner/scannerlib.dart');
+#import('../../compiler/implementation/leg.dart');
+#import('../../compiler/implementation/filenames.dart');
+#import('../../compiler/implementation/source_file.dart');
+#import('../../compiler/implementation/tree/tree.dart');
+#import('../../compiler/implementation/util/util.dart');
+#import('../../compiler/implementation/util/uri_extras.dart');
+#import('../../compiler/implementation/dart2js.dart');
+#import('mirrors.dart');
+#import('util.dart');
+#import('dart:io');
+#import('dart:uri');
+
+
+//------------------------------------------------------------------------------
+// Utility types and functions for the dart2js mirror system
+//------------------------------------------------------------------------------
+
+bool _isPrivate(String name) {
+ return name.startsWith('_');
+}
+
+List<ParameterMirror> _parametersFromFunctionSignature(
+ Dart2jsMirrorSystem system,
+ Dart2jsMethodMirror method,
+ FunctionSignature signature) {
+ var parameters = <ParameterMirror>[];
+ Link<Element> link = signature.requiredParameters;
+ while (!link.isEmpty()) {
+ parameters.add(new Dart2jsParameterMirror(system, method,
+ link.head, false));
+ link = link.tail;
+ }
+ link = signature.optionalParameters;
+ while (!link.isEmpty()) {
+ parameters.add(new Dart2jsParameterMirror(system, method,
+ link.head, true));
+ link = link.tail;
+ }
+ return parameters;
+}
+
+Dart2jsTypeMirror _convertTypeToTypeMirror(
+ Dart2jsMirrorSystem system,
+ Type type,
+ InterfaceType defaultType,
+ [FunctionSignature functionSignature]) {
+ if (type === null) {
+ return new Dart2jsInterfaceTypeMirror(system, defaultType);
+ } else if (type is InterfaceType) {
+ return new Dart2jsInterfaceTypeMirror(system, type);
+ } else if (type is TypeVariableType) {
+ return new Dart2jsTypeVariableMirror(system, type);
+ } else if (type is FunctionType) {
+ if (type.element is TypedefElement) {
+ return new Dart2jsTypedefMirror(system, type.element);
+ } else {
+ return new Dart2jsFunctionTypeMirror(system, type, functionSignature);
+ }
+ } else if (type is VoidType) {
+ return new Dart2jsVoidMirror(system, type);
+ }
+ throw new IllegalArgumentException("Unexpected interface type $type");
+}
+
+Collection<Dart2jsMemberMirror> _convertElementMemberToMemberMirrors(
+ Dart2jsObjectMirror library, Element element) {
+ if (element is SynthesizedConstructorElement) {
+ return const <Dart2jsMemberMirror>[];
+ } else if (element is VariableElement) {
+ return [new Dart2jsFieldMirror(library, element)];
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Type the literal with <Dart2jsMemberMirror>. Or pe
Johnni Winther 2012/07/04 13:19:17 Done.
+ } else if (element is FunctionElement) {
+ return [new Dart2jsMethodMirror(library, element)];
Lasse Reichstein Nielsen 2012/07/04 10:58:59 ditto
Johnni Winther 2012/07/04 13:19:17 Done.
+ } else if (element is AbstractFieldElement) {
+ var members = <Dart2jsMemberMirror>[];
+ if (element.getter !== null) {
+ members.add(new Dart2jsMethodMirror(library, element.getter,
+ Dart2jsMethodKind.GETTER));
+ }
+ if (element.setter !== null) {
+ members.add(new Dart2jsMethodMirror(library, element.setter,
+ Dart2jsMethodKind.SETTER));
+ }
+ return members;
+ }
+ throw new IllegalArgumentException(
+ "Unexpected member type $element ${element.kind}");
+}
+
+MethodMirror _convertElementMethodToMethodMirror(Dart2jsObjectMirror library,
+ Element element) {
Lasse Reichstein Nielsen 2012/07/04 10:58:59 indent.
Johnni Winther 2012/07/04 13:19:17 Done.
+ if (element is FunctionElement) {
+ return new Dart2jsMethodMirror(library, element);
+ } else {
+ return null;
+ }
+}
+
+class Dart2jsMethodKind {
+ static final Dart2jsMethodKind NORMAL = const Dart2jsMethodKind("normal");
+ static final Dart2jsMethodKind CONSTRUCTOR
+ = const Dart2jsMethodKind("constructor");
+ static final Dart2jsMethodKind CONST = const Dart2jsMethodKind("const");
+ static final Dart2jsMethodKind FACTORY = const Dart2jsMethodKind("factory");
+ static final Dart2jsMethodKind GETTER = const Dart2jsMethodKind("getter");
+ static final Dart2jsMethodKind SETTER = const Dart2jsMethodKind("setter");
+ static final Dart2jsMethodKind OPERATOR = const Dart2jsMethodKind("operator");
+
+ final String text;
+
+ const Dart2jsMethodKind(this.text);
+
+ String toString() => text;
+}
+
+String _getOperatorFromOperatorName(String str) {
Lasse Reichstein Nielsen 2012/07/04 10:58:59 "str"->"name" It's not just a string, it's an oper
Johnni Winther 2012/07/04 13:19:17 Done.
+ if (str == 'eq') return '==';
+ else if (str == 'not') return '~';
+ else if (str == 'negate') return 'negate';
+ else if (str == 'index') return '[]';
+ else if (str == 'indexSet') return '[]=';
+ else if (str == 'mul') return '*';
+ else if (str == 'div') return '/';
+ else if (str == 'mod') return '%';
+ else if (str == 'tdiv') return '~/';
+ else if (str == 'add') return '+';
+ else if (str == 'sub') return '-';
+ else if (str == 'shl') return '<<';
+ else if (str == 'shr') return '>>';
+ else if (str == 'ge') return '>=';
+ else if (str == 'gt') return '>';
+ else if (str == 'le') return '<=';
+ else if (str == 'lt') return '<';
+ else if (str == 'and') return '&';
+ else if (str == 'xor') return '^';
+ else if (str == 'or') return '|';
Lasse Reichstein Nielsen 2012/07/04 10:58:59 You could have a constant Map<String, String> to c
Johnni Winther 2012/07/04 13:19:17 Done. (Using : instead of => in the constant map!)
+ else {
+ throw new Exception('Unhandled operator name: $str');
+ }
+}
+
+final DiagnosticListener _diagnosticListener
+ = const Dart2jsDiagnosticListener();
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Consider making it a getter instead of a field. No
Johnni Winther 2012/07/04 13:19:17 Done.
+
+class Dart2jsDiagnosticListener implements DiagnosticListener {
+ const Dart2jsDiagnosticListener();
+
+ void cancel([String reason, node, token, instruction, element]) {
+ print(reason);
+ }
+
+ void log(message) {
+ print(message);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Compilation implementation
+//------------------------------------------------------------------------------
+
+class Dart2jsCompilation implements Compilation {
+ api.Compiler _compiler;
+ Uri cwd;
+ bool isAborting = false;
+ Map<String, SourceFile> sourceFiles;
+
+ Future<String> provider(Uri uri) {
+ if (uri.scheme != 'file') {
+ throw new IllegalArgumentException(uri);
+ }
+ String source;
+ try {
+ source = readAll(uriPathToNative(uri.path));
+ } catch (FileIOException ex) {
+ throw 'Error: Cannot read "${relativize(cwd, uri)}" (${ex.osError}).';
+ }
+ sourceFiles[uri.toString()] =
+ new SourceFile(relativize(cwd, uri), source);
+ return new Future.immediate(source);
+ }
+
+ void handler(Uri uri, int begin, int end,
+ String message, diagnostics.Diagnostic kind) {
+ if (isAborting) return;
+ bool fatal =
+ kind === diagnostics.Diagnostic.CRASH ||
+ kind === diagnostics.Diagnostic.ERROR;
+ if (uri === null) {
+ if (!fatal) {
+ return;
+ }
+ assert(fatal);
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Drop this assert. It's only checking that the 'if'
Johnni Winther 2012/07/04 13:19:17 Done.
+ print(message);
+ throw message;
+ } else if (fatal) {
+ SourceFile file = sourceFiles[uri.toString()];
+ print(file.getLocationMessage(message, begin, end, true, (s) => s));
+ throw message;
+ }
+ }
+
+ Dart2jsCompilation(String script, String libraryRoot,
+ [String packageRoot, List<String> opts = const []])
+ : cwd = getCurrentDirectory(),
Lasse Reichstein Nielsen 2012/07/04 10:58:59 indentation.
Johnni Winther 2012/07/04 13:19:17 Ignored!
+ sourceFiles = <SourceFile>{} {
+ var libraryUri = cwd.resolve(nativeToUriPath(libraryRoot));
+ var packageUri;
+ if (packageRoot !== null) {
+ packageUri = cwd.resolve(nativeToUriPath(packageRoot));
+ } else {
+ packageUri = libraryUri;
+ }
+ _compiler = new api.Compiler(provider, handler,
+ libraryUri, packageUri, <String>[]);
+ var scriptUri = cwd.resolve(nativeToUriPath(script));
+ // TODO(johnniwinther): Detect file not found
+ _compiler.run(scriptUri);
+ }
+
+ void addLibrary(String path) {
+ var uri = cwd.resolve(nativeToUriPath(path));
+ _compiler.scanner.loadLibrary(uri, null);
+ }
+
+ MirrorSystem mirrors() => new Dart2jsMirrorSystem(_compiler);
+}
+
+
+//------------------------------------------------------------------------------
+// Dart2js specific extensions of mirror interfaces
+//------------------------------------------------------------------------------
+
+interface Dart2jsMirror extends Mirror {
+ /**
+ * A unique name used as the key in maps.
+ */
+ final String canonicalName;
+ final Dart2jsMirrorSystem system;
+}
+
+interface Dart2jsMemberMirror extends Dart2jsMirror, MemberMirror {
+
+}
+
+interface Dart2jsTypeMirror extends Dart2jsMirror, TypeMirror {
+
+}
+
+abstract class Dart2jsElementMirror implements Dart2jsMirror {
+ final Dart2jsMirrorSystem system;
+ final Element _element;
+
+ Dart2jsElementMirror(this.system, this._element) {
+ assert (system !== null);
+ assert (_element !== null);
+ }
+
+ String simpleName() => _element.name.slowToString();
+
+ Location location() => new Dart2jsLocation(
+ _element.getCompilationUnit().script,
+ system.compiler.spanFromElement(_element));
+
+ String toString() => _element.toString();
+}
+
+abstract class Dart2jsProxyMirror implements Dart2jsMirror {
+ final Dart2jsMirrorSystem system;
+
+ Dart2jsProxyMirror(this.system);
+}
+
+///////////////////////////////////////////////////////
+// implementation
+///////////////////////////////////////////////////////
+
+class Dart2jsMirrorSystem implements MirrorSystem, Dart2jsMirror {
+ final api.Compiler compiler;
+ Map<String, Dart2jsLibraryMirror> _libraries;
+ Map<LibraryElement, Dart2jsLibraryMirror> _libraryMap;
+
+ Dart2jsMirrorSystem(this.compiler)
+ : _libraryMap = new Map<LibraryElement, Dart2jsLibraryMirror>();
+
+ void _ensureLibraries() {
+ if (_libraries == null) {
+ _libraries = <Dart2jsLibraryMirror>{};
+ compiler.libraries.forEach((_, LibraryElement v) {
+ var mirror = new Dart2jsLibraryMirror(system, v);
+ _libraries[mirror.canonicalName] = mirror;
+ _libraryMap[v] = mirror;
+ });
+ }
+ }
+
+ Map<Object, LibraryMirror> libraries() {
+ _ensureLibraries();
+ return new ImmutableMapWrapper<Object, LibraryMirror>(_libraries);
+ }
+
+ Dart2jsLibraryMirror getLibrary(LibraryElement element) {
+ return _libraryMap[element];
+ }
+
+ Dart2jsMirrorSystem get system() => this;
+
+ String simpleName() => "mirror";
+ String qualifiedName() => simpleName();
+
+ String get canonicalName() => simpleName();
+}
+
+abstract class Dart2jsObjectMirror extends Dart2jsElementMirror
+ implements ObjectMirror {
+ Dart2jsObjectMirror(Dart2jsMirrorSystem system, Element element)
+ : super(system, element);
Lasse Reichstein Nielsen 2012/07/04 10:58:59 indentation.
Johnni Winther 2012/07/04 13:19:17 Done.
+}
+
+class Dart2jsLibraryMirror extends Dart2jsObjectMirror
+ implements LibraryMirror {
+ Map<String, InterfaceMirror> _types;
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Do we really need to make these fields private? We
Johnni Winther 2012/07/04 13:19:17 I like that they are private when the need initial
+ Map<String, MemberMirror> _members;
+
+ Dart2jsLibraryMirror(Dart2jsMirrorSystem system, LibraryElement library)
+ : super(system, library);
+
+ LibraryElement get _library() => _element;
+
+ String get canonicalName() => simpleName();
+
+ /**
+ * Returns the library name (for libraries with a #library tag) or the script
+ * file name (for scripts without a #library tag). The latter case is used to
+ * provide a 'library name' for scripts, to use for instance in dartdoc.
+ */
+ String simpleName() {
+ if (_library.libraryTag !== null) {
+ return _library.libraryTag.argument.dartString.slowToString();
+ } else {
+ // Use the file name as script name.
+ String path = _library.script.uri.path;
+ return path.substring(path.lastIndexOf('/') + 1);
+ }
+ }
+
+ String qualifiedName() => simpleName();
+
+ void _ensureTypes() {
+ if (_types == null) {
+ _types = <InterfaceMirror>{};
+ _library.forEachExport((Element e) {
+ if (e.getLibrary() == _library) {
+ if (e.isClass()) {
+ var type = new Dart2jsInterfaceMirror.fromLibrary(this, e);
+ _types[type.canonicalName] = type;
+ } else if (e.isTypedef()) {
+ var type = new Dart2jsTypedefMirror.fromLibrary(this, e);
+ _types[type.canonicalName] = type;
+ }
+ }
+ });
+ }
+ }
+
+ void _ensureMembers() {
+ if (_members == null) {
+ _members = <MemberMirror>{};
+ _library.forEachExport((Element e) {
+ if (!e.isClass() && !e.isTypedef()) {
+ for (var member in _convertElementMemberToMemberMirrors(this, e)) {
+ _members[member.canonicalName] = member;
+ }
+ }
+ });
+ }
+ }
+
+ Map<Object, MemberMirror> declaredMembers() {
+ _ensureMembers();
+ return new ImmutableMapWrapper<Object,MemberMirror>(_members);
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Space after comma. More cases below.
Johnni Winther 2012/07/04 13:19:17 Done.
+ }
+
+ Map<Object, InterfaceMirror> types() {
+ _ensureTypes();
+ return new ImmutableMapWrapper<Object,InterfaceMirror>(_types);
+ }
+
+ Location location() {
+ var script = _library.getCompilationUnit().script;
+ return new Dart2jsLocation(
+ script,
+ new SourceSpan(script.uri, 0, script.text.length));
+ }
+}
+
+class Dart2jsLocation implements Location {
+ Script _script;
+ SourceSpan _span;
+
+ Dart2jsLocation(this._script, this._span);
+
+ int start() => _span.begin;
+ int end() => _span.end;
+ Source source() => new Dart2jsSource(_script);
+
+ String text() => _script.text.substring(start(), end());
+}
+
+class Dart2jsSource implements Source {
+ Script _script;
+
+ Dart2jsSource(this._script);
+
+ Uri uri() => _script.uri;
+ String text() => _script.text;
+}
+
+class Dart2jsParameterMirror extends Dart2jsElementMirror
+ implements ParameterMirror {
+ final MethodMirror _method;
+ final bool _isOptional;
+
+ Dart2jsParameterMirror(Dart2jsMirrorSystem system,
+ this._method,
+ VariableElement element,
+ this._isOptional)
+ : super(system, element);
+
+ VariableElement get _variableElement() => _element;
+
+ String get canonicalName() => simpleName();
+
+ String qualifiedName() => '${_method.qualifiedName()}#${simpleName()}';
+
+ // TODO(johnniwinther): Provide
+ // [:_variableElement.variables.functionSignature:] instead of [:null:].
+ TypeMirror type() => _convertTypeToTypeMirror(system,
+ _variableElement.computeType(system.compiler),
+ system.compiler.dynamicClass.computeType(system.compiler),
+ null);
+
+ String defaultValue() => null; // TODO(johnniwinther): How to compute this?
+
+ bool hasDefaultValue() => false; // TODO(johnniwinther): How to compute this?
+
+ bool isOptional() => _isOptional;
+}
+
+///////////////////////////////////////////////////////
+// declarations
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Capitalize comment.
Johnni Winther 2012/07/04 13:19:17 Done.
+///////////////////////////////////////////////////////
+
+class Dart2jsInterfaceMirror extends Dart2jsObjectMirror
+ implements Dart2jsTypeMirror, InterfaceMirror {
+ final Dart2jsLibraryMirror _library;
+ Map<String, Dart2jsMemberMirror> _members;
+ List<TypeVariableMirror> _typeVariables;
+
+ Dart2jsInterfaceMirror(Dart2jsMirrorSystem system, ClassElement _class)
+ : this._library = system.getLibrary(_class.getLibrary()),
+ super(system, _class);
+
+ ClassElement get _class() => _element;
+
+
+ Dart2jsInterfaceMirror.fromLibrary(Dart2jsLibraryMirror library,
+ ClassElement _class)
+ : this._library = library,
+ super(library.system, _class);
+
+ String get canonicalName() => simpleName();
+
+ String qualifiedName() => '${library().qualifiedName()}.${simpleName()}';
+
+ Location location() {
+ if (_class is PartialClassElement) {
+ var node = _class.parseNode(_diagnosticListener);
+ if (node !== null) {
+ var script = _class.getCompilationUnit().script;
+ var span = system.compiler.spanFromNode(node, script.uri);
+ return new Dart2jsLocation(script, span);
+ }
+ }
+ return super.location();
+ }
+
+ void _ensureMembers() {
+ if (_members == null) {
+ _members = <Dart2jsMemberMirror>{};
+ _class.constructors.forEach((_, e) {
+ for (var member in _convertElementMemberToMemberMirrors(this, e)) {
+ _members[member.canonicalName] = member;
+ }
+ });
+ _class.localMembers.forEach((_, e) {
+ for (var member in _convertElementMemberToMemberMirrors(this, e)) {
+ _members[member.canonicalName] = member;
+ }
+ });
+ }
+ }
+
+ Map<Object, MemberMirror> declaredMembers() {
+ _ensureMembers();
+ return new ImmutableMapWrapper<Object,MemberMirror>(_members);
+ }
+
+ LibraryMirror library() {
+ return _library;
+ }
+
+ bool get isObject() => _class == system.compiler.objectClass;
+
+ bool get isDynamic() => _class == system.compiler.dynamicClass;
+
+ bool get isVoid() => false;
+
+ bool get isTypeVariable() => false;
+
+ bool get isTypedef() => false;
+
+ bool get isFunction() => false;
+
+ InterfaceMirror get declaration() => this;
+
+ InterfaceMirror superclass() {
+ if (_class.supertype != null) {
+ return new Dart2jsInterfaceTypeMirror(system, _class.supertype);
+ }
+ return null;
+ }
+
+ Map<Object, InterfaceMirror> interfaces() {
+ var map = new Map<String, InterfaceMirror>();
+ var link = _class.interfaces;
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Type on "link". I assume it's Link<Something>, but
Johnni Winther 2012/07/04 13:19:17 Done.
+ while (!link.isEmpty()) {
+ var type = _convertTypeToTypeMirror(system, link.head,
+ system.compiler.dynamicClass.computeType(system.compiler));
+ map[type.canonicalName] = type;
+ link = link.tail;
+ }
+ return new ImmutableMapWrapper<Object,InterfaceMirror>(map);
+ }
+
+ bool get isClass() => !_class.isInterface();
+
+ bool get isInterface() => _class.isInterface();
+
+ bool get isPrivate() => _isPrivate(simpleName());
+
+ bool get isDeclaration() => true;
+
+ List<TypeMirror> typeArguments() {
+ throw new UnsupportedOperationException(
+ 'Declarations do not have type arguments');
+ }
+
+ List<TypeVariableMirror> typeVariables() {
+ if (_typeVariables == null) {
+ _typeVariables = <TypeVariableMirror>[];
+ _class.typeParameters.forEach((_,parameter) {
+ _typeVariables.add(
+ new Dart2jsTypeVariableMirror(system,
+ parameter.computeType(system.compiler)));
+ });
+ }
+ return _typeVariables;
+ }
+
+ Map<Object, MethodMirror> constructors() {
+ _ensureMembers();
+ return new AsFilteredImmutableMapWrapper<Object, MemberMirror, MethodMirror>(
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Line length > 80. No, there is no way to make this
Johnni Winther 2012/07/04 13:19:17 Done.
+ _members, (m) => m.isConstructor ? m : null);
+ }
+
+ /**
+ * Returns the default type for this interface.
+ */
+ InterfaceMirror defaultType() {
+ if (_class.defaultClass != null) {
+ return new Dart2jsInterfaceTypeMirror(system, _class.defaultClass);
+ }
+ return null;
+ }
+
+ bool operator ==(Object other) {
+ if (this === other) {
+ return true;
+ }
+ if (other is! InterfaceMirror) {
+ return false;
+ }
+ if (library() != other.library()) {
+ return false;
+ }
+ if (isDeclaration !== other.isDeclaration) {
+ return false;
+ }
+ return qualifiedName() == other.qualifiedName();
+ }
+}
+
+class Dart2jsTypedefMirror extends Dart2jsElementMirror
+ implements Dart2jsTypeMirror, TypedefMirror {
+ final Dart2jsLibraryMirror _library;
+ List<TypeVariableMirror> _typeVariables;
+ TypeMirror _definition;
+
+ Dart2jsTypedefMirror(Dart2jsMirrorSystem system, TypedefElement _typedef)
+ : this._library = system.getLibrary(_typedef.getLibrary()),
+ super(system, _typedef);
+
+ Dart2jsTypedefMirror.fromLibrary(Dart2jsLibraryMirror library,
+ TypedefElement _typedef)
+ : this._library = library,
+ super(library.system, _typedef);
+
+ TypedefElement get _typedef() => _element;
+
+ String get canonicalName() => simpleName();
+
+ String qualifiedName() => '${library().qualifiedName()}.${simpleName()}';
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Make this, "location", "library", "typeArguments",
Johnni Winther 2012/07/04 13:19:17 This issue will be considered for the whole mirror
+
+ Location location() {
+ var node = _typedef.parseNode(_diagnosticListener);
+ if (node !== null) {
+ var script = _typedef.getCompilationUnit().script;
+ var span = system.compiler.spanFromNode(node, script.uri);
+ return new Dart2jsLocation(script, span);
+ }
+ return super.location();
+ }
+
+ LibraryMirror library() => _library;
+
+ bool get isObject() => false;
+
+ bool get isDynamic() => false;
+
+ bool get isVoid() => false;
+
+ bool get isTypeVariable() => false;
+
+ bool get isTypedef() => true;
+
+ bool get isFunction() => false;
+
+ List<TypeMirror> typeArguments() {
+ throw new UnsupportedOperationException(
+ 'Declarations do not have type arguments');
+ }
+
+ List<TypeVariableMirror> typeVariables() {
+ if (_typeVariables == null) {
+ _typeVariables = <TypeVariableMirror>[];
+ // TODO(johnniwinther): Equip [Typedef] with a [typeParameters] map, just
+ // like [ClassElement].
+ }
+ return _typeVariables;
+ }
+
+ TypeMirror definition() {
+ if (_definition === null) {
+ // TODO(johnniwinther): Provide access to the functionSignature of the
+ // aliased function definition.
+ }
+ return _definition;
+ }
+
+ Map<Object, MemberMirror> declaredMembers() => const <MemberMirror>{};
+
+ InterfaceMirror get declaration() => this;
+
+ // TODO(johnniwinther): How should a typedef respond to these?
+ InterfaceMirror superclass() => null;
+
+ Map<Object, InterfaceMirror> interfaces() => const <InterfaceMirror>{};
+
+ bool get isClass() => false;
+
+ bool get isInterface() => false;
+
+ bool get isPrivate() => _isPrivate(simpleName());
+
+ bool get isDeclaration() => true;
+
+ Map<Object, MethodMirror> constructors() => const <MethodMirror>{};
+
+ InterfaceMirror defaultType() => null;
+}
+
+class Dart2jsTypeVariableMirror extends Dart2jsTypeElementMirror
+ implements TypeVariableMirror {
+ final TypeVariableType _typeVariableType;
+ InterfaceMirror _declarer;
+
+ Dart2jsTypeVariableMirror(Dart2jsMirrorSystem system,
+ TypeVariableType typeVariableType)
+ : this._typeVariableType = typeVariableType,
+ super(system, typeVariableType)
+ {
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Brace on previous line (and indentation of initial
Johnni Winther 2012/07/04 13:19:17 Done.
+ assert (_typeVariableType !== null);
Lasse Reichstein Nielsen 2012/07/04 10:58:59 No space after assert. It's written as a function
Johnni Winther 2012/07/04 13:19:17 Done.
+ }
+
+
+ String qualifiedName() => '${declarer().qualifiedName()}.${simpleName()}';
+
+ InterfaceMirror declarer() {
+ if (_declarer === null) {
+ if (_typeVariableType.element.enclosingElement.isClass()) {
+ _declarer = new Dart2jsInterfaceMirror(system,
+ _typeVariableType.element.enclosingElement);
+ } else if (_typeVariableType.element.enclosingElement.isTypedef()) {
+ _declarer = new Dart2jsTypedefMirror(system,
+ _typeVariableType.element.enclosingElement);
+ }
+ }
+ return _declarer;
+ }
+
+ LibraryMirror library() => declarer().library();
+
+ bool get isObject() => false;
+
+ bool get isDynamic() => false;
+
+ bool get isVoid() => false;
+
+ bool get isTypeVariable() => true;
+
+ bool get isTypedef() => false;
+
+ bool get isFunction() => false;
+
+ TypeMirror bound() => _convertTypeToTypeMirror(
+ system,
+ _typeVariableType.element.bound,
+ system.compiler.objectClass.computeType(system.compiler));
+
+ bool operator ==(Object other) {
+ if (this === other) {
+ return true;
+ }
+ if (other is! TypeVariableMirror) {
+ return false;
+ }
+ if (declarer() != other.declarer()) {
+ print('${declarer()} != ${other.declarer()}');
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Debug-print?
Johnni Winther 2012/07/04 13:19:17 Yes, the one that got away!
+ return false;
+ }
+ return qualifiedName() == other.qualifiedName();
+ }
+}
+
+
+///////////////////////////////////////////////////////
+// types
+///////////////////////////////////////////////////////
+
+abstract class Dart2jsTypeElementMirror extends Dart2jsProxyMirror
+ implements Dart2jsTypeMirror {
+ final Type _type;
+
+ Dart2jsTypeElementMirror(Dart2jsMirrorSystem system, this._type)
+ : super(system);
+
+ String simpleName() => _type.name.slowToString();
+
+ String get canonicalName() => simpleName();
+
+ Location location() {
+ var script = _type.element.getCompilationUnit().script;
+ return new Dart2jsLocation(script,
+ system.compiler.spanFromElement(_type.element));
+ }
+
+ LibraryMirror library() {
+ return system.getLibrary(_type.element.getLibrary());
+ }
+
+ String toString() => _type.element.toString();
+}
+
+class Dart2jsInterfaceTypeMirror extends Dart2jsTypeElementMirror
+ implements InterfaceMirror {
+ List<TypeMirror> _typeArguments;
+
+ Dart2jsInterfaceTypeMirror(Dart2jsMirrorSystem system,
+ InterfaceType interfaceType)
+ : super(system, interfaceType);
+
+ InterfaceType get _interfaceType() => _type;
+
+ String qualifiedName() => declaration.qualifiedName();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ Map<Object, MemberMirror> declaredMembers() => declaration.declaredMembers();
+
+ bool get isObject() => system.compiler.objectClass == _type.element;
+
+ bool get isDynamic() => system.compiler.dynamicClass == _type.element;
+
+ bool get isTypeVariable() => false;
+
+ bool get isVoid() => false;
+
+ bool get isTypedef() => false;
+
+ bool get isFunction() => false;
+
+ InterfaceMirror get declaration()
+ => new Dart2jsInterfaceMirror(system, _type.element);
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ InterfaceMirror superclass() => declaration.superclass();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ Map<Object, InterfaceMirror> interfaces() => declaration.interfaces();
+
+ bool get isClass() => declaration.isClass;
+
+ bool get isInterface() => declaration.isInterface;
+
+ bool get isPrivate() => declaration.isPrivate;
+
+ bool get isDeclaration() => false;
+
+ List<TypeMirror> typeArguments() {
+ if (_typeArguments == null) {
+ _typeArguments = <TypeMirror>[];
+ Link<Type> type = _interfaceType.arguments;
+ while (type != null && type.head != null) {
+ _typeArguments.add(_convertTypeToTypeMirror(system, type.head,
+ system.compiler.dynamicClass.computeType(system.compiler)));
+ type = type.tail;
+ }
+ }
+ return _typeArguments;
+ }
+
+ List<TypeVariableMirror> typeVariables() => declaration.typeVariables();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ Map<Object, MethodMirror> constructors() => declaration.constructors();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables?
+ InterfaceMirror defaultType() => declaration.defaultType();
+
+ bool operator ==(Object other) {
+ if (this === other) {
+ return true;
+ }
+ if (other is! InterfaceMirror) {
+ return false;
+ }
+ if (other.isDeclaration) {
+ return false;
+ }
+ if (declaration != other.declaration) {
+ return false;
+ }
+ var thisTypeArguments = typeArguments().iterator();
+ var otherTypeArguments = other.typeArguments().iterator();
+ while (thisTypeArguments.hasNext() && otherTypeArguments.hasNext()) {
+ if (thisTypeArguments.next() != otherTypeArguments.next()) {
+ return false;
+ }
+ }
+ return !thisTypeArguments.hasNext() && !otherTypeArguments.hasNext();
+ }
+}
+
+
+class Dart2jsFunctionTypeMirror extends Dart2jsTypeElementMirror
+ implements FunctionTypeMirror {
+ final FunctionSignature _functionSignature;
+ List<ParameterMirror> _parameters;
+
+ Dart2jsFunctionTypeMirror(Dart2jsMirrorSystem system,
+ FunctionType functionType, this._functionSignature)
+ : super(system, functionType) {
+ assert (_functionSignature !== null);
+ }
+
+ FunctionType get _functionType() => _type;
+
+ // TODO(johnniwinther): Is this the qualified name of a function type?
+ String qualifiedName() => declaration.qualifiedName();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ Map<Object, MemberMirror> declaredMembers() {
+ var method = callMethod();
+ if (method !== null) {
+ var map = new Map<String, MemberMirror>.from(
+ declaration.declaredMembers());
+ var name = method.qualifiedName();
+ map[name] = method;
+ Function func = null;
+ return new ImmutableMapWrapper<Object,MemberMirror>(map);
+ }
+ return declaration.declaredMembers();
+ }
+
+ bool get isObject() => system.compiler.objectClass == _type.element;
+
+ bool get isDynamic() => system.compiler.dynamicClass == _type.element;
+
+ bool get isVoid() => false;
+
+ bool get isTypeVariable() => false;
+
+ bool get isTypedef() => false;
+
+ bool get isFunction() => true;
+
+ MethodMirror callMethod() => _convertElementMethodToMethodMirror(
+ system.getLibrary(_functionType.element.getLibrary()),
+ _functionType.element);
+
+ InterfaceMirror get declaration()
+ => new Dart2jsInterfaceMirror(system, system.compiler.functionClass);
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ InterfaceMirror superclass() => declaration.superclass();
+
+ // TODO(johnniwinther): Substitute type arguments for type variables.
+ Map<Object, InterfaceMirror> interfaces() => declaration.interfaces();
+
+ bool get isClass() => declaration.isClass;
+
+ bool get isInterface() => declaration.isInterface;
+
+ bool get isPrivate() => declaration.isPrivate;
+
+ bool get isDeclaration() => false;
+
+ List<TypeMirror> typeArguments() => const <TypeMirror>[];
+
+ List<TypeVariableMirror> typeVariables() => declaration.typeVariables();
+
+ Map<Object, MethodMirror> constructors() => <MethodMirror>{};
+
+ InterfaceMirror defaultType() => null;
+
+ TypeMirror returnType() {
+ return _convertTypeToTypeMirror(system, _functionType.returnType,
+ system.compiler.dynamicClass.computeType(system.compiler));
+ }
+
+ List<ParameterMirror> parameters() {
+ if (_parameters === null) {
+ _parameters = _parametersFromFunctionSignature(system, callMethod(),
+ _functionSignature);
+ }
+ return _parameters;
+ }
+}
+
+class Dart2jsVoidMirror extends Dart2jsTypeElementMirror {
+
+ Dart2jsVoidMirror(Dart2jsMirrorSystem system, VoidType voidType)
+ : super(system, voidType);
+
+ VoidType get _voidType() => _type;
+
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Extra empty line.
Johnni Winther 2012/07/04 13:19:17 Done.
+
+ String qualifiedName() => simpleName();
+
+ /**
+ * The void type has no location.
+ */
+ Location location() => null;
+
+ /**
+ * The void type has no library.
+ */
+ LibraryMirror getLibrary() => null;
+
+ bool get isObject() => false;
+
+ bool get isVoid() => true;
+
+ bool get isDynamic() => false;
+
+ bool get isTypeVariable() => false;
+
+ bool get isTypedef() => false;
+
+ bool get isFunction() => false;
+
+ bool operator ==(Object other) {
+ if (this === other) {
+ return true;
+ }
+ if (other is! TypeMirror) {
+ return false;
+ }
+ return other.isVoid;
+ }
+}
+
+///////////////////////////////////////////////////////
+// members
+///////////////////////////////////////////////////////
+
+class Dart2jsMethodMirror extends Dart2jsElementMirror
+ implements Dart2jsMemberMirror, MethodMirror {
+ final Dart2jsObjectMirror _objectMirror;
+ String _name;
+ String _constructorName;
+ String _operatorName;
+ Dart2jsMethodKind _kind;
+ String _canonicalName;
+
+ Dart2jsMethodMirror(Dart2jsObjectMirror objectMirror,
+ FunctionElement function,
+ [Dart2jsMethodKind kind = null])
+ : this._objectMirror = objectMirror,
+ this._kind = kind,
+ super(objectMirror.system, function) {
+ _name = _element.name.slowToString();
+ if (kind == null) {
+ if (_function.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
+ _constructorName = '';
+ var dollarPos = _name.indexOf('\$');
Lasse Reichstein Nielsen 2012/07/04 10:58:59 "var" => "int". No need not to. Really, don't use
Johnni Winther 2012/07/04 13:19:17 Done.
+ if (dollarPos != -1) {
+ _constructorName = _name.substring(dollarPos+1);
+ _name = _name.substring(0, dollarPos);
+ // canonical name is TypeName.constructorName
+ _canonicalName = '$_name.$_constructorName';
+ } else {
+ // canonical name is TypeName
+ _canonicalName = _name;
+ }
+ if (_function.modifiers !== null && _function.modifiers.isConst()) {
+ _kind = Dart2jsMethodKind.CONST;
+ } else {
+ _kind = Dart2jsMethodKind.CONSTRUCTOR;
+ }
+ } else if (_function.modifiers !== null
+ && _function.modifiers.isFactory())
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Indent to paren.
Johnni Winther 2012/07/04 13:19:17 Done.
+ {
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Brace on previous line.
Johnni Winther 2012/07/04 13:19:17 Done.
+ _constructorName = '';
+ var dollarPos = _name.indexOf('\$');
+ if (dollarPos != -1) {
+ _constructorName = _name.substring(dollarPos+1);
+ _name = _name.substring(0, dollarPos);
+ }
+ _kind = Dart2jsMethodKind.FACTORY;
+ // canonical name is TypeName.constructorName
+ _canonicalName = '$_name.$_constructorName';
+ } else if (_name.startsWith('operator\$')) {
+ var str = _name.substring(9);
+ _name = 'operator';
+ _kind = Dart2jsMethodKind.OPERATOR;
+ _operatorName = _getOperatorFromOperatorName(str);
+ // canonical name is 'operator operatorName'
+ _canonicalName = 'operator $_operatorName';
+ } else {
+ _kind = Dart2jsMethodKind.NORMAL;
+ _canonicalName = _name;
+ }
+ } else if (kind == Dart2jsMethodKind.GETTER) {
+ _canonicalName = _name;
+ } else if (kind == Dart2jsMethodKind.SETTER) {
+ _canonicalName = '$_name=';
+ } else {
+ assert(false);
+ }
+ }
+
+ FunctionElement get _function() => _element;
+
+ String simpleName() => _name;
+
+ String qualifiedName()
+ => '${surroundingDeclaration().qualifiedName()}.$canonicalName';
+
+ String get canonicalName() => _canonicalName;
+
+ ObjectMirror surroundingDeclaration() => _objectMirror;
+
+ bool get isTopLevel() => _objectMirror is LibraryMirror;
+
+ bool get isConstructor()
+ => _kind == Dart2jsMethodKind.CONSTRUCTOR || isConst || isFactory;
+
+ bool get isField() => false;
+
+ bool get isMethod() => !isConstructor;
+
+ bool get isPrivate() => _isPrivate(simpleName());
+
+ bool get isStatic() =>
+ _function.modifiers !== null && _function.modifiers.isStatic();
+
+ List<ParameterMirror> parameters() {
+ return _parametersFromFunctionSignature(system, this,
+ _function.computeSignature(system.compiler));
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Indentation.
Johnni Winther 2012/07/04 13:19:17 Done.
+ }
+
+ TypeMirror returnType() => _convertTypeToTypeMirror(
+ system, _function.computeSignature(system.compiler).returnType,
+ system.compiler.dynamicClass.computeType(system.compiler));
+
+ bool get isConst() => _kind == Dart2jsMethodKind.CONST;
+
+ bool get isFactory() => _kind == Dart2jsMethodKind.FACTORY;
+
+ String get constructorName() => _constructorName;
+
+ bool get isGetter() => _kind == Dart2jsMethodKind.GETTER;
+
+ bool get isSetter() => _kind == Dart2jsMethodKind.SETTER;
+
+ bool get isOperator() => _kind == Dart2jsMethodKind.OPERATOR;
+
+ String get operatorName() => _operatorName;
+
+ Location location() {
+ var node = _function.parseNode(_diagnosticListener);
+ if (node !== null) {
+ var script = _function.getCompilationUnit().script;
+ var span = system.compiler.spanFromNode(node, script.uri);
+ return new Dart2jsLocation(script, span);
+ }
+ return super.location();
+ }
+
+}
+
+class Dart2jsFieldMirror extends Dart2jsElementMirror
+ implements Dart2jsMemberMirror, FieldMirror
+{
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Brace on previous line.
Johnni Winther 2012/07/04 13:19:17 Done.
+ Dart2jsObjectMirror _objectMirror;
+ VariableElement _variable;
+
+ Dart2jsFieldMirror(Dart2jsObjectMirror objectMirror,
+ VariableElement variable)
+ : this._objectMirror = objectMirror,
Lasse Reichstein Nielsen 2012/07/04 10:58:59 Indentation, both parameter and ':'.
Johnni Winther 2012/07/04 13:19:17 Done.
+ this._variable = variable,
+ super(objectMirror.system, variable);
+
+ String qualifiedName()
+ => '${surroundingDeclaration().qualifiedName()}.$canonicalName';
+
+ String get canonicalName() => simpleName();
+
+ ObjectMirror surroundingDeclaration() => _objectMirror;
+
+ bool get isTopLevel() => _objectMirror is LibraryMirror;
+
+ bool get isConstructor() => false;
+
+ bool get isField() => true;
+
+ bool get isMethod() => false;
+
+ bool get isPrivate() => _isPrivate(simpleName());
+
+ bool get isStatic() => _variable.modifiers.isStatic();
+
+ bool get isFinal() => _variable.modifiers.isFinal();
+
+ TypeMirror type() => _convertTypeToTypeMirror(system,
+ _variable.computeType(system.compiler),
+ system.compiler.dynamicClass.computeType(system.compiler));
+
+ Location location() {
+ var script = _variable.getCompilationUnit().script;
+ var node = _variable.variables.parseNode(_diagnosticListener);
+ if (node !== null) {
+ var span = system.compiler.spanFromNode(node, script.uri);
+ return new Dart2jsLocation(script, span);
+ } else {
+ var span = system.compiler.spanFromElement(_variable);
+ return new Dart2jsLocation(script, span);
+ }
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698