blob: 7440372180068355b8a5618668a175803defb938 [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;
//------------------------------------------------------------------------------
// Member mirrors implementation.
//------------------------------------------------------------------------------
abstract class Dart2JsMemberMirror extends Dart2JsElementMirror {
Dart2JsMemberMirror(Dart2JsMirrorSystem system, Element element)
: super(system, element);
bool get isStatic => false;
}
class Dart2JsMethodKind {
static const Dart2JsMethodKind REGULAR = const Dart2JsMethodKind("regular");
static const Dart2JsMethodKind GENERATIVE =
const Dart2JsMethodKind("generative");
static const Dart2JsMethodKind REDIRECTING =
const Dart2JsMethodKind("redirecting");
static const Dart2JsMethodKind CONST = const Dart2JsMethodKind("const");
static const Dart2JsMethodKind FACTORY = const Dart2JsMethodKind("factory");
static const Dart2JsMethodKind GETTER = const Dart2JsMethodKind("getter");
static const Dart2JsMethodKind SETTER = const Dart2JsMethodKind("setter");
static const Dart2JsMethodKind OPERATOR = const Dart2JsMethodKind("operator");
final String text;
const Dart2JsMethodKind(this.text);
String toString() => text;
}
String _getOperatorFromOperatorName(String name) {
Map<String, String> mapping = const {
'eq': '==',
'not': '~',
'index': '[]',
'indexSet': '[]=',
'mul': '*',
'div': '/',
'mod': '%',
'tdiv': '~/',
'add': '+',
'sub': '-',
'shl': '<<',
'shr': '>>',
'ge': '>=',
'gt': '>',
'le': '<=',
'lt': '<',
'and': '&',
'xor': '^',
'or': '|',
};
String newName = mapping[name];
if (newName == null) {
throw new Exception('Unhandled operator name: $name');
}
return newName;
}
class Dart2JsMethodMirror extends Dart2JsMemberMirror
implements MethodMirror {
final Dart2JsDeclarationMirror owner;
final String _simpleNameString;
final Dart2JsMethodKind _kind;
Dart2JsMethodMirror._internal(Dart2JsDeclarationMirror owner,
FunctionElement function,
String this._simpleNameString,
Dart2JsMethodKind this._kind)
: this.owner = owner,
super(owner.mirrorSystem, function);
factory Dart2JsMethodMirror(Dart2JsDeclarationMirror owner,
FunctionElement function) {
String realName = function.name;
// TODO(ahe): This method should not be calling
// Elements.operatorNameToIdentifier.
String simpleName =
Elements.operatorNameToIdentifier(function.name);
Dart2JsMethodKind kind;
if (function.kind == ElementKind.GETTER) {
kind = Dart2JsMethodKind.GETTER;
} else if (function.kind == ElementKind.SETTER) {
kind = Dart2JsMethodKind.SETTER;
simpleName = '$simpleName=';
} else if (function.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
// TODO(johnniwinther): Support detection of redirecting constructors.
if (function.modifiers.isConst()) {
kind = Dart2JsMethodKind.CONST;
} else {
kind = Dart2JsMethodKind.GENERATIVE;
}
} else if (function.modifiers.isFactory()) {
// TODO(johnniwinther): Support detection of redirecting constructors.
kind = Dart2JsMethodKind.FACTORY;
} else if (realName == 'unary-') {
// TODO(johnniwinther): Use a constant for 'unary-'.
kind = Dart2JsMethodKind.OPERATOR;
// Simple name is 'unary-'.
simpleName = 'unary-';
} else if (simpleName.startsWith('operator\$')) {
String str = simpleName.substring(9);
simpleName = 'operator';
kind = Dart2JsMethodKind.OPERATOR;
simpleName = _getOperatorFromOperatorName(str);
} else {
kind = Dart2JsMethodKind.REGULAR;
}
return new Dart2JsMethodMirror._internal(owner, function,
simpleName, kind);
}
FunctionElement get _function => _element;
bool get isTopLevel => owner is LibraryMirror;
// TODO(johnniwinther): This seems stale and broken.
Symbol get constructorName => isConstructor ? simpleName : const Symbol('');
bool get isConstructor
=> isGenerativeConstructor || isConstConstructor ||
isFactoryConstructor || isRedirectingConstructor;
bool get isSynthetic => false;
bool get isStatic => _function.modifiers.isStatic();
List<ParameterMirror> get parameters {
return _parametersFromFunctionSignature(this,
_function.functionSignature);
}
TypeMirror get returnType => owner._getTypeMirror(
_function.functionSignature.type.returnType);
bool get isAbstract => _function.isAbstract;
bool get isRegularMethod => !(isGetter || isSetter || isConstructor);
bool get isConstConstructor => _kind == Dart2JsMethodKind.CONST;
bool get isGenerativeConstructor => _kind == Dart2JsMethodKind.GENERATIVE;
bool get isRedirectingConstructor => _kind == Dart2JsMethodKind.REDIRECTING;
bool get isFactoryConstructor => _kind == Dart2JsMethodKind.FACTORY;
bool get isGetter => _kind == Dart2JsMethodKind.GETTER;
bool get isSetter => _kind == Dart2JsMethodKind.SETTER;
bool get isOperator => _kind == Dart2JsMethodKind.OPERATOR;
DeclarationMirror lookupInScope(String name) {
for (Dart2JsParameterMirror parameter in parameters) {
if (parameter._element.name == name) {
return parameter;
}
}
return super.lookupInScope(name);
}
// TODO(johnniwinther): Should this really be in the interface of
// [MethodMirror]?
String get source => location.sourceText;
String toString() => 'Mirror on method ${_element.name}';
}
class Dart2JsFieldMirror extends Dart2JsMemberMirror implements VariableMirror {
final Dart2JsDeclarationMirror owner;
VariableElement _variable;
Dart2JsFieldMirror(Dart2JsDeclarationMirror owner,
VariableElement variable)
: this.owner = owner,
this._variable = variable,
super(owner.mirrorSystem, variable);
bool get isTopLevel => owner is LibraryMirror;
bool get isStatic => _variable.modifiers.isStatic();
bool get isFinal => _variable.modifiers.isFinal();
bool get isConst => _variable.modifiers.isConst();
TypeMirror get type => owner._getTypeMirror(_variable.type);
}
class Dart2JsParameterMirror extends Dart2JsMemberMirror
implements ParameterMirror {
final Dart2JsDeclarationMirror owner;
final bool isOptional;
final bool isNamed;
factory Dart2JsParameterMirror(Dart2JsDeclarationMirror owner,
ParameterElement element,
{bool isOptional: false,
bool isNamed: false}) {
if (element is FieldParameterElement) {
return new Dart2JsFieldParameterMirror(
owner, element, isOptional, isNamed);
}
return new Dart2JsParameterMirror._normal(
owner, element, isOptional, isNamed);
}
Dart2JsParameterMirror._normal(Dart2JsDeclarationMirror owner,
ParameterElement element,
this.isOptional,
this.isNamed)
: this.owner = owner,
super(owner.mirrorSystem, element);
ParameterElement get _element => super._element;
TypeMirror get type => owner._getTypeMirror(_element.type,
_element.functionSignature);
bool get isFinal => false;
bool get isConst => false;
InstanceMirror get defaultValue {
if (hasDefaultValue) {
// TODO(johnniwinther): Get the constant from the [TreeElements]
// associated with the enclosing method.
Constant constant = mirrorSystem.compiler.constants
.getConstantForVariable(_element);
assert(invariant(_element, constant != null,
message: "Missing constant for parameter "
"$_element with default value."));
return _convertConstantToInstanceMirror(mirrorSystem, constant);
}
return null;
}
bool get hasDefaultValue {
return _element.initializer != null;
}
bool get isInitializingFormal => false;
VariableMirror get initializedField => null;
}
class Dart2JsFieldParameterMirror extends Dart2JsParameterMirror {
Dart2JsFieldParameterMirror(Dart2JsDeclarationMirror method,
FieldParameterElement element,
bool isOptional,
bool isNamed)
: super._normal(method, element, isOptional, isNamed);
FieldParameterElement get _fieldParameterElement => _element;
bool get isInitializingFormal => true;
VariableMirror get initializedField => new Dart2JsFieldMirror(
owner.owner, _fieldParameterElement.fieldElement);
}