blob: 6520b36f80ec40339eb810248cf086677e3dd62b [file] [log] [blame]
// Copyright (c) 2013, 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.
part of dart2js.mirrors;
abstract class ObjectMirrorMixin implements ObjectMirror {
InstanceMirror getField(Symbol fieldName) {
throw new UnsupportedError('ObjectMirror.getField unsupported.');
}
InstanceMirror setField(Symbol fieldName, Object value) {
throw new UnsupportedError('ObjectMirror.setField unsupported.');
}
InstanceMirror invoke(Symbol memberName,
List positionalArguments,
[Map<Symbol, dynamic> namedArguments]) {
throw new UnsupportedError('ObjectMirror.invoke unsupported.');
}
}
abstract class InstanceMirrorMixin implements InstanceMirror {
bool get hasReflectee => false;
get reflectee {
throw new UnsupportedError('InstanceMirror.reflectee unsupported.');
}
delegate(Invocation invocation) {
throw new UnsupportedError('InstanceMirror.delegate unsupported');
}
}
InstanceMirror _convertConstantToInstanceMirror(
Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
ConstantValue value) {
if (value.isBool) {
return new Dart2JsBoolConstantMirror(mirrorSystem, constant, value);
} else if (value.isNum) {
return new Dart2JsNumConstantMirror(mirrorSystem, constant, value);
} else if (value.isString) {
return new Dart2JsStringConstantMirror(mirrorSystem, constant, value);
} else if (value.isList) {
return new Dart2JsListConstantMirror(mirrorSystem, constant, value);
} else if (value.isMap) {
return new Dart2JsMapConstantMirror(mirrorSystem, constant, value);
} else if (value.isType) {
return new Dart2JsTypeConstantMirror(mirrorSystem, constant, value);
} else if (value.isFunction) {
return new Dart2JsConstantMirror(mirrorSystem, constant, value);
} else if (value.isNull) {
return new Dart2JsNullConstantMirror(mirrorSystem, constant, value);
} else if (value.isConstructedObject) {
return new Dart2JsConstructedConstantMirror(mirrorSystem, constant, value);
}
mirrorSystem.compiler.internalError(NO_LOCATION_SPANNABLE,
"Unexpected constant value $value");
return null;
}
////////////////////////////////////////////////////////////////////////////////
// Mirrors on constant values used for metadata.
////////////////////////////////////////////////////////////////////////////////
class Dart2JsConstantMirror extends Object
with ObjectMirrorMixin, InstanceMirrorMixin {
final Dart2JsMirrorSystem mirrorSystem;
final ConstantExpression _constant;
final ConstantValue _value;
Dart2JsConstantMirror(this.mirrorSystem, this._constant, this._value);
String toString() {
if (_constant != null) {
return _constant.getText();
} else {
return _value.unparse();
}
}
ClassMirror get type {
return mirrorSystem._getTypeDeclarationMirror(
_value.computeType(mirrorSystem.compiler).element);
}
int get hashCode => 13 * _constant.hashCode;
bool operator ==(var other) {
if (other is! Dart2JsConstantMirror) return false;
return _value == other._value;
}
}
class Dart2JsNullConstantMirror extends Dart2JsConstantMirror {
Dart2JsNullConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
NullConstantValue value)
: super(mirrorSystem, constant, value);
NullConstantValue get _value => super._value;
bool get hasReflectee => true;
get reflectee => null;
}
class Dart2JsBoolConstantMirror extends Dart2JsConstantMirror {
Dart2JsBoolConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
BoolConstantValue value)
: super(mirrorSystem, constant, value);
Dart2JsBoolConstantMirror.fromBool(Dart2JsMirrorSystem mirrorSystem,
bool value)
: super(mirrorSystem, null,
value ? new TrueConstantValue() : new FalseConstantValue());
BoolConstantValue get _value => super._value;
bool get hasReflectee => true;
get reflectee => _value is TrueConstantValue;
}
class Dart2JsStringConstantMirror extends Dart2JsConstantMirror {
Dart2JsStringConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
StringConstantValue value)
: super(mirrorSystem, constant, value);
Dart2JsStringConstantMirror.fromString(Dart2JsMirrorSystem mirrorSystem,
String text)
: super(mirrorSystem, null,
new StringConstantValue(new DartString.literal(text)));
StringConstantValue get _value => super._value;
bool get hasReflectee => true;
get reflectee => _value.primitiveValue.slowToString();
}
class Dart2JsNumConstantMirror extends Dart2JsConstantMirror {
Dart2JsNumConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
NumConstantValue value)
: super(mirrorSystem, constant, value);
NumConstantValue get _value => super._value;
bool get hasReflectee => true;
get reflectee => _value.primitiveValue;
}
class Dart2JsListConstantMirror extends Dart2JsConstantMirror
implements ListInstanceMirror {
Dart2JsListConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
ListConstantValue value)
: super(mirrorSystem, constant, value);
ListConstantValue get _value => super._value;
int get length => _value.length;
InstanceMirror getElement(int index) {
if (index < 0) throw new RangeError('Negative index');
if (index >= _value.length) throw new RangeError('Index out of bounds');
return _convertConstantToInstanceMirror(
mirrorSystem, null, _value.entries[index]);
}
}
class Dart2JsMapConstantMirror extends Dart2JsConstantMirror
implements MapInstanceMirror {
List<String> _listCache;
Dart2JsMapConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
MapConstantValue value)
: super(mirrorSystem, constant, value);
MapConstantValue get _value => super._value;
List<String> get _list {
if (_listCache == null) {
_listCache = new List<String>(_value.length);
int index = 0;
for (StringConstantValue keyConstant in _value.keys) {
_listCache[index] = keyConstant.primitiveValue.slowToString();
index++;
}
_listCache = new UnmodifiableListView<String>(_listCache);
}
return _listCache;
}
int get length => _value.length;
Iterable<String> get keys {
return _list;
}
InstanceMirror getValue(String key) {
int index = _list.indexOf(key);
if (index == -1) return null;
return _convertConstantToInstanceMirror(
mirrorSystem, null, _value.values[index]);
}
}
class Dart2JsTypeConstantMirror extends Dart2JsConstantMirror
implements TypeInstanceMirror {
Dart2JsTypeConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
TypeConstantValue value)
: super(mirrorSystem, constant, value);
TypeConstantValue get _value => super._value;
TypeMirror get representedType =>
mirrorSystem._convertTypeToTypeMirror(_value.representedType);
}
class Dart2JsConstructedConstantMirror extends Dart2JsConstantMirror {
Map<String,ConstantValue> _fieldMapCache;
Dart2JsConstructedConstantMirror(Dart2JsMirrorSystem mirrorSystem,
ConstantExpression constant,
ConstructedConstantValue value)
: super(mirrorSystem, constant, value);
ConstructedConstantValue get _value => super._value;
Map<String,ConstantValue> get _fieldMap {
if (_fieldMapCache == null) {
_fieldMapCache = new Map<String,ConstantValue>();
if (identical(_value.type.element.kind, ElementKind.CLASS)) {
var index = 0;
ClassElement element = _value.type.element;
element.forEachInstanceField((_, Element field) {
String fieldName = field.name;
_fieldMapCache.putIfAbsent(fieldName, () => _value.fields[index]);
index++;
}, includeSuperAndInjectedMembers: true);
}
}
return _fieldMapCache;
}
InstanceMirror getField(Symbol fieldName) {
String name = MirrorSystem.getName(fieldName);
ConstantValue fieldConstant = _fieldMap[name];
if (fieldConstant != null) {
return _convertConstantToInstanceMirror(
mirrorSystem, null, fieldConstant);
}
return super.getField(fieldName);
}
}
class Dart2JsCommentInstanceMirror extends Object
with ObjectMirrorMixin, InstanceMirrorMixin
implements CommentInstanceMirror {
final Dart2JsMirrorSystem mirrorSystem;
final String text;
String _trimmedText;
Dart2JsCommentInstanceMirror(this.mirrorSystem, this.text);
ClassMirror get type {
return mirrorSystem._getTypeDeclarationMirror(
mirrorSystem.compiler.documentClass);
}
bool get isDocComment => text.startsWith('/**') || text.startsWith('///');
String get trimmedText {
if (_trimmedText == null) {
_trimmedText = stripComment(text);
}
return _trimmedText;
}
InstanceMirror getField(Symbol fieldName) {
if (fieldName == #isDocComment) {
return new Dart2JsBoolConstantMirror.fromBool(mirrorSystem, isDocComment);
} else if (fieldName == #text) {
return new Dart2JsStringConstantMirror.fromString(mirrorSystem, text);
} else if (fieldName == #trimmedText) {
return new Dart2JsStringConstantMirror.fromString(mirrorSystem,
trimmedText);
}
return super.getField(fieldName);
}
}