Chromium Code Reviews| Index: dart/sdk/lib/_internal/lib/js_mirrors.dart |
| diff --git a/dart/sdk/lib/_internal/lib/js_mirrors.dart b/dart/sdk/lib/_internal/lib/js_mirrors.dart |
| index d904246e83bd5d07c6b33bbd59621603d25480eb..5598048440d5ef2fc04c5bf8c068b38ae8b37816 100644 |
| --- a/dart/sdk/lib/_internal/lib/js_mirrors.dart |
| +++ b/dart/sdk/lib/_internal/lib/js_mirrors.dart |
| @@ -16,7 +16,9 @@ import 'dart:_js_helper' show |
| Null, |
| Primitives, |
| RuntimeError, |
| - createUnmangledInvocationMirror; |
| + createRuntimeType, |
| + createUnmangledInvocationMirror, |
| + runtimeTypeToString; |
| import 'dart:_interceptors' show Interceptor, JSExtendableArray; |
| import 'dart:_js_names'; |
| @@ -93,6 +95,8 @@ abstract class JsDeclarationMirror extends JsMirror |
| const JsDeclarationMirror(this.simpleName); |
| + Symbol get qualifiedName => computeQualifiedName(owner, simpleName); |
| + |
| bool get isPrivate => n(simpleName).startsWith('_'); |
| bool get isTopLevel => owner != null && owner is LibraryMirror; |
| @@ -105,6 +109,11 @@ class JsTypeMirror extends JsDeclarationMirror implements TypeMirror { |
| : super(simpleName); |
| String get _prettyName => 'TypeMirror'; |
| + |
| + DeclarationMirror get owner => null; |
| + |
| + // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569. |
| + bool get isTopLevel => true; |
| } |
| class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror |
| @@ -152,26 +161,20 @@ class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror |
| var result = new List<JsMethodMirror>(_functions.length); |
| for (int i = 0; i < _functions.length; i++) { |
| String name = _functions[i]; |
| + // TODO(ahe): Create accessor for accessing $. It is also |
| + // used in js_helper. |
| + var jsFunction = JS('', '#[#]', JS_CURRENT_ISOLATE(), name); |
| String unmangledName = mangledGlobalNames[name]; |
| if (unmangledName == null) unmangledName = name; |
| - int parameterCount = null; // TODO(ahe): Compute this. |
| - bool isSetter = false; // TODO(ahe): Compute this. |
| - bool isGetter = false; // TODO(ahe): Compute this. |
| bool isConstructor = unmangledName.startsWith('new '); |
| - bool isStatic = true && !isConstructor; // Top-level functions are |
| - // static, but constructors are |
| - // not. |
| + bool isStatic = !isConstructor; // Top-level functions are static, but |
| + // constructors are not. |
| if (isConstructor) { |
| unmangledName = unmangledName.substring(4).replaceAll(r'$', '.'); |
| } |
| - unmangledName = unmangledName.split(':')[0]; |
| - Symbol symbol = s(unmangledName); |
| JsMethodMirror mirror = |
| - // TODO(ahe): Create accessor for accessing $. It is also |
| - // used in js_helper. |
| - new JsMethodMirror( |
| - symbol, JS('', '#[#]', JS_CURRENT_ISOLATE(), name), |
| - parameterCount, isGetter, isSetter, isStatic, isConstructor); |
| + new JsMethodMirror.fromUnmangledName( |
|
ngeoffray
2013/07/12 09:16:55
Line 176 fits in line 175?
|
| + unmangledName, jsFunction, isStatic, isConstructor); |
| result[i] = mirror; |
| mirror._owner = this; |
| } |
| @@ -387,8 +390,6 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror |
| String get _prettyName => 'ClassMirror'; |
| - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); |
| - |
| get _jsConstructor { |
| if (_jsConstructorOrInterceptor is Interceptor) { |
| return JS('', '#.constructor', _jsConstructorOrInterceptor); |
| @@ -400,8 +401,7 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror |
| Map<Symbol, MethodMirror> get constructors { |
| Map<Symbol, MethodMirror> result = new Map<Symbol, MethodMirror>(); |
| JsLibraryMirror library = owner; |
| - String unmangledName = mangledGlobalNames[n(simpleName)]; |
| - if (unmangledName == null) unmangledName = n(simpleName); |
| + String unmangledName = n(simpleName); |
| for (JsMethodMirror mirror in library._functionMirrors) { |
| Symbol name = mirror.simpleName; |
| if (mirror.isConstructor |
| @@ -428,7 +428,9 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror |
| // reflection with metadata. |
| if (simpleName == null) continue; |
| var function = JS('', '#[#]', prototype, key); |
| - var mirror = new JsMethodMirror.fromUnmangledName(simpleName, function); |
| + var mirror = |
| + new JsMethodMirror.fromUnmangledName( |
|
ngeoffray
2013/07/12 09:16:55
ditto
|
| + simpleName, function, false, false); |
| result.add(mirror); |
| mirror._owner = this; |
| } |
| @@ -636,8 +638,6 @@ class JsVariableMirror extends JsDeclarationMirror implements VariableMirror { |
| DeclarationMirror get owner => _owner; |
| - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); |
| - |
| List<InstanceMirror> get metadata { |
| preserveMetadata(); |
| if (_metadata == null) { |
| @@ -714,6 +714,8 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror { |
| final bool isConstructor; |
| DeclarationMirror _owner; |
| List _metadata; |
| + var _returnType; |
| + var _parameters; |
| JsMethodMirror(Symbol simpleName, |
| this._jsFunction, |
| @@ -724,7 +726,10 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror { |
| this.isConstructor) |
| : super(simpleName); |
| - factory JsMethodMirror.fromUnmangledName(String name, jsFunction) { |
| + factory JsMethodMirror.fromUnmangledName(String name, |
| + jsFunction, |
| + bool isStatic, |
| + bool isConstructor) { |
| List<String> info = name.split(':'); |
| name = info[0]; |
| bool isSetter = name.endsWith('='); |
| @@ -744,31 +749,79 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror { |
| } |
| return new JsMethodMirror( |
| s(name), jsFunction, requiredParameterCount + optionalParameterCount, |
| - isGetter, isSetter, false, false); |
| + isGetter, isSetter, isStatic, isConstructor); |
| } |
| String get _prettyName => 'MethodMirror'; |
| List<ParameterMirror> get parameters { |
| - // TODO(ahe): Fill the list with parameter mirrors. |
| - return new List<ParameterMirror>(_parameterCount); |
| + metadata; // Compute _parameters as a side-effect of extracting metadata. |
|
ngeoffray
2013/07/12 09:16:55
Maybe add a computeMetadata method instead of havi
|
| + return new List<ParameterMirror>.from(_parameters); |
| } |
| DeclarationMirror get owner => _owner; |
| - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); |
| - |
| - // TODO(ahe): Improve this information and test it. |
| - TypeMirror get returnType => JsMirrorSystem._dynamicType; |
| + TypeMirror get returnType { |
| + metadata; // Compute _returnType as a side-effect of extracting metadata. |
|
ngeoffray
2013/07/12 09:16:55
ditto
|
| + return typeMirrorFromRuntimeTypeRepresentation(_returnType); |
| + } |
| List<InstanceMirror> get metadata { |
| if (_metadata == null) { |
| - _metadata = extractMetadata(_jsFunction); |
| + var raw = extractMetadata(_jsFunction); |
| + _returnType = raw[0]; |
| + int parameterLength = 1 + _parameterCount * 2; |
| + var formals = new List<ParameterMirror>(_parameterCount); |
| + int formalsCount = 0; |
| + for (int i = 1; i < parameterLength; i += 2) { |
| + var name = raw[i]; |
| + var type = raw[i + 1]; |
| + formals[formalsCount++] = new JsParameterMirror(name, this, type); |
| + } |
| + _parameters = formals; |
| + _metadata = raw.sublist(parameterLength); |
| } |
| return _metadata.map(reflect).toList(); |
| } |
| } |
| +class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror { |
| + final JsMethodMirror owner; |
| + // A JS object representing the type. |
| + final _type; |
| + |
| + JsParameterMirror(String unmangledName, this.owner, this._type) |
| + : super(s(unmangledName)); |
| + |
| + String get _prettyName => 'ParameterMirror'; |
| + |
| + TypeMirror get type => typeMirrorFromRuntimeTypeRepresentation(_type); |
| + |
| + bool get isStatic => owner.isStatic; |
| + |
| + // TODO(ahe): Implement this. |
| + bool get isFinal => false; |
| + |
| + // TODO(ahe): Implement this. |
| + bool get isOptional => false; |
| + |
| + // TODO(ahe): Implement this. |
| + bool get isNamed => false; |
| + |
| + // TODO(ahe): Implement this. |
| + bool get hasDefaultValue => false; |
| + |
| + // TODO(ahe): Implement this. |
| + get defaultValue => null; |
| +} |
| + |
| +TypeMirror typeMirrorFromRuntimeTypeRepresentation(type) { |
| + if (type == null) return JsMirrorSystem._dynamicType; |
| + String representation = runtimeTypeToString(type); |
| + if (representation == null) return reflectClass(Function); |
| + return reflectClass(createRuntimeType(representation)); |
| +} |
| + |
| Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) { |
| if (owner == null) return simpleName; |
| String ownerName = n(owner.qualifiedName); |
| @@ -779,6 +832,12 @@ Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) { |
| List extractMetadata(victim) { |
| preserveMetadata(); |
| var metadataFunction = JS('', '#["@"]', victim); |
| - return (metadataFunction == null) |
| - ? const [] : JS('', '#()', metadataFunction); |
| + if (metadataFunction != null) return JS('', '#()', metadataFunction); |
| + String source = JS('String', 'Function.prototype.toString.call(#)', victim); |
| + int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}')); |
|
ngeoffray
2013/07/12 09:16:55
Please add a comment on what you're doing here.
|
| + if (index == -1) return const []; |
| + index++; |
| + int endQuote = source.indexOf('"', index); |
| + return source.substring(index, endQuote).split(',').map(int.parse).map( |
| + (int i) => JS('', 'init.metadata[#]', i)).toList(); |
| } |