// 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.computeSignature(mirrorSystem.compiler)); | |
} | |
TypeMirror get returnType => owner._getTypeMirror( | |
_function.computeSignature(mirrorSystem.compiler).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); | |
Element get _beginElement => _variable.variables; | |
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.computeType(mirrorSystem.compiler)); | |
} | |
class Dart2JsParameterMirror extends Dart2JsMemberMirror | |
implements ParameterMirror { | |
final Dart2JsDeclarationMirror owner; | |
final bool isOptional; | |
final bool isNamed; | |
factory Dart2JsParameterMirror(Dart2JsDeclarationMirror owner, | |
VariableElement 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, | |
VariableElement element, | |
this.isOptional, | |
this.isNamed) | |
: this.owner = owner, | |
super(owner.mirrorSystem, element); | |
Element get _beginElement => _variableElement.variables; | |
VariableElement get _variableElement => _element; | |
TypeMirror get type => owner._getTypeMirror( | |
_variableElement.computeType(mirrorSystem.compiler), | |
_variableElement.variables.functionSignature); | |
bool get isFinal => false; | |
bool get isConst => false; | |
InstanceMirror get defaultValue { | |
if (hasDefaultValue) { | |
Constant constant = mirrorSystem.compiler.constantHandler | |
.getConstantForVariable(_variableElement); | |
assert(invariant(_variableElement, constant != null, | |
message: "Missing constant for parameter " | |
"$_variableElement with default value.")); | |
return _convertConstantToInstanceMirror(mirrorSystem, constant); | |
} | |
return null; | |
} | |
bool get hasDefaultValue { | |
return _variableElement.cachedNode.asSendSet() != 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; | |
TypeMirror get type { | |
VariableListElement variables = _fieldParameterElement.variables; | |
VariableDefinitions node = variables.parseNode(mirrorSystem.compiler); | |
if (node.type != null) { | |
return super.type; | |
} | |
// Use the field type for initializing formals with no type annotation. | |
return owner._getTypeMirror( | |
_fieldParameterElement.fieldElement.computeType(mirrorSystem.compiler), | |
_fieldParameterElement.fieldElement.variables.functionSignature); | |
} | |
bool get isInitializingFormal => true; | |
VariableMirror get initializedField => new Dart2JsFieldMirror( | |
owner.owner, _fieldParameterElement.fieldElement); | |
} |