| Index: frog/member.dart
|
| diff --git a/frog/member.dart b/frog/member.dart
|
| index 22214b10cdeed3f01b83099815478d533adb1342..3c5b04317a7bcc1a37045d84467587b6135dd582 100644
|
| --- a/frog/member.dart
|
| +++ b/frog/member.dart
|
| @@ -5,6 +5,7 @@
|
| /** A formal parameter to a [Method]. */
|
| class Parameter {
|
| FormalNode definition;
|
| + Member method;
|
|
|
| String name;
|
| Type type;
|
| @@ -12,18 +13,18 @@ class Parameter {
|
|
|
| Value value;
|
|
|
| - Parameter(this.definition);
|
| + Parameter(this.definition, this.method);
|
|
|
| - resolve(Member method, Type inType) {
|
| + resolve() {
|
| name = definition.name.name;
|
| if (name.startsWith('this.')) {
|
| name = name.substring(5);
|
| isInitializer = true;
|
| }
|
|
|
| - type = inType.resolveType(definition.type, false);
|
| + type = method.resolveType(definition.type, false);
|
|
|
| - if (method.isStatic && type.hasTypeParams) {
|
| + if (method.isStatic && method.typeParameters === null && type.hasTypeParams) {
|
| world.error('using type parameter in static context', definition.span);
|
| }
|
|
|
| @@ -62,8 +63,8 @@ class Parameter {
|
| value = value.convertTo(context, type, definition.value);
|
| }
|
|
|
| - Parameter copyWithNewType(Type newType) {
|
| - var ret = new Parameter(definition);
|
| + Parameter copyWithNewType(Member newMethod, Type newType) {
|
| + var ret = new Parameter(definition, newMethod);
|
| ret.type = newType;
|
| ret.name = name;
|
| ret.isInitializer = isInitializer;
|
| @@ -74,28 +75,15 @@ class Parameter {
|
| }
|
|
|
|
|
| -interface Named {
|
| - String get name();
|
| - Library get library();
|
| - bool get isNative();
|
| - String get jsname();
|
| - set jsname(String name);
|
| -
|
| - SourceSpan get span();
|
| -}
|
| -
|
| -class Member implements Named {
|
| - final String name;
|
| +class Member extends Element {
|
| final Type declaringType;
|
|
|
| - String _jsname;
|
| -
|
| bool isGenerated;
|
| MethodGenerator generator;
|
|
|
| - Member(this.name, this.declaringType): isGenerated = false;
|
| -
|
| - abstract SourceSpan get span();
|
| + Member(String name, Type declaringType)
|
| + : isGenerated = false, this.declaringType = declaringType,
|
| + super(name, declaringType);
|
|
|
| abstract bool get isStatic();
|
| abstract Type get returnType();
|
| @@ -103,12 +91,6 @@ class Member implements Named {
|
| abstract bool get canGet();
|
| abstract bool get canSet();
|
|
|
| - abstract void resolve(Type inType);
|
| -
|
| - String get jsname() => _jsname == null ? name : _jsname;
|
| -
|
| - set jsname(String name) => _jsname = name;
|
| -
|
| Library get library() => declaringType.library;
|
|
|
| bool get isPrivate() => name.startsWith('_');
|
| @@ -211,16 +193,6 @@ class Member implements Named {
|
| }
|
| }
|
|
|
| - Type resolveType(TypeReference node, bool isRequired) {
|
| - var type = declaringType.resolveType(node, isRequired);
|
| - if (isStatic && type.hasTypeParams) {
|
| - // TODO(jimhug): Is this really so hard?
|
| - world.error('using type parameter in static context',
|
| - node.span);
|
| - }
|
| - return type;
|
| - }
|
| -
|
| int hashCode() => (declaringType.hashCode() << 4) ^ name.hashCode();
|
| }
|
|
|
| @@ -248,8 +220,6 @@ class TypeMember extends Member {
|
| bool get canGet() => true;
|
| bool get canSet() => false;
|
|
|
| - void resolve(Type inType) {}
|
| -
|
| Value _get(MethodGenerator context, Node node, Value target,
|
| [bool isDynamic=false]) {
|
| return new Value.type(type, node.span);
|
| @@ -327,7 +297,7 @@ class FieldMember extends Member {
|
|
|
| bool get isField() => true;
|
|
|
| - resolve(Type inType) {
|
| + resolve() {
|
| isStatic = declaringType.isTop;
|
| isFinal = false;
|
| if (definition.modifiers != null) {
|
| @@ -347,7 +317,7 @@ class FieldMember extends Member {
|
| }
|
| }
|
| }
|
| - type = inType.resolveType(definition.type, false);
|
| + type = resolveType(definition.type, false);
|
| if (isStatic && type.hasTypeParams) {
|
| world.error('using type parameter in static context',
|
| definition.type.span);
|
| @@ -534,9 +504,9 @@ class PropertyMember extends Member {
|
| if (setter == null) setter = parent.setter;
|
| }
|
|
|
| - resolve(Type inType) {
|
| - if (getter != null) getter.resolve(inType);
|
| - if (setter != null) setter.resolve(inType);
|
| + resolve() {
|
| + if (getter != null) getter.resolve();
|
| + if (setter != null) setter.resolve();
|
|
|
| library._addMember(this);
|
| }
|
| @@ -552,11 +522,11 @@ class ConcreteMember extends Member {
|
| : super(name, declaringType) {
|
| parameters = [];
|
| returnType = baseMember.returnType.resolveTypeParams(declaringType);
|
| - // TODO(jimhug): Optimize not creating new array if new param types.
|
| + // TODO(jimhug): Optimize not creating new array if no new param types.
|
| for (var p in baseMember.parameters) {
|
| var newType = p.type.resolveTypeParams(declaringType);
|
| if (newType != p.type) {
|
| - parameters.add(p.copyWithNewType(newType));
|
| + parameters.add(p.copyWithNewType(this, newType));
|
| } else {
|
| parameters.add(p);
|
| }
|
| @@ -648,6 +618,10 @@ class MethodMember extends Member {
|
| Type returnType;
|
| List<Parameter> parameters;
|
|
|
| + // Could support generic methods in general. Right now only used for
|
| + // strange corner case of factory methods for generic types.
|
| + List<ParameterType> typeParameters;
|
| +
|
|
|
| Type _functionType;
|
| bool isStatic = false;
|
| @@ -689,8 +663,11 @@ class MethodMember extends Member {
|
| SourceSpan get span() => definition == null ? null : definition.span;
|
|
|
| String get constructorName() {
|
| - NameTypeReference returnType = definition.returnType;
|
| + var returnType = definition.returnType;
|
| if (returnType == null) return '';
|
| + if (returnType is GenericTypeReference) {
|
| + return '';
|
| + }
|
|
|
| // TODO(jmesserly): make this easier?
|
| if (returnType.names != null) {
|
| @@ -703,11 +680,10 @@ class MethodMember extends Member {
|
|
|
| Type get functionType() {
|
| if (_functionType == null) {
|
| - _functionType = library.getOrAddFunctionType(name,
|
| - definition, declaringType);
|
| + _functionType = library.getOrAddFunctionType(declaringType, name, definition);
|
| // TODO(jimhug): Better resolution checks.
|
| if (parameters == null) {
|
| - resolve(declaringType);
|
| + resolve();
|
| }
|
| }
|
| return _functionType;
|
| @@ -860,7 +836,7 @@ class MethodMember extends Member {
|
| // TODO(jimhug): Fix this hack for ensuring a method is resolved.
|
| if (parameters == null) {
|
| world.info('surprised to need to resolve: ${declaringType.name}.$name');
|
| - this.resolve(declaringType);
|
| + resolve();
|
| }
|
|
|
| declaringType.genMethod(this);
|
| @@ -1215,7 +1191,7 @@ class MethodMember extends Member {
|
| return new Value(declaringType, '${target.code} + ${argsCode[0]}',
|
| node.span);
|
| }
|
| - } else if (declaringType.isNativeType) {
|
| + } else if (declaringType.isNative) {
|
| if (name == '\$index') {
|
| // Note: this could technically propagate constness, but that's not
|
| // specified explicitly and the VM doesn't do that.
|
| @@ -1274,9 +1250,9 @@ class MethodMember extends Member {
|
| }
|
|
|
|
|
| - resolve(Type inType) {
|
| + resolve() {
|
| // TODO(jimhug): cut-and-paste-and-edit from Field.resolve
|
| - isStatic = inType.isTop;
|
| + isStatic = declaringType.isTop;
|
| isConst = false;
|
| isFactory = false;
|
| isAbstract = !declaringType.isClass;
|
| @@ -1317,6 +1293,20 @@ class MethodMember extends Member {
|
| isStatic = true;
|
| }
|
|
|
| + if (definition.typeParameters != null) {
|
| + if (!isFactory) {
|
| + world.error(
|
| + 'Only factories are allowed to have explicit type parameters',
|
| + definition.typeParameters[0].span);
|
| + } else {
|
| + typeParameters = definition.typeParameters;
|
| + for (var tp in definition.typeParameters) {
|
| + tp.enclosingElement = this;
|
| + tp.resolve();
|
| + }
|
| + }
|
| + }
|
| +
|
| // TODO(jimhug): need a better annotation for being an operator method
|
| if (isOperator && isStatic && !isCallMethod) {
|
| world.error('operator method may not be static "${name}"', span);
|
| @@ -1339,22 +1329,16 @@ class MethodMember extends Member {
|
| }
|
| }
|
|
|
| - if (isConstructor) {
|
| + if (isConstructor && !isFactory) {
|
| returnType = declaringType;
|
| } else {
|
| - // TODO(jimhug): Unify this check and the below with method's
|
| - // resolveType method - requires cleaning up inType stuff.
|
| - returnType = inType.resolveType(definition.returnType, false);
|
| -
|
| - if (isStatic && returnType.hasTypeParams) {
|
| - world.error('using type parameter in static context',
|
| - definition.returnType.span);
|
| - }
|
| + returnType = resolveType(definition.returnType, false);
|
| }
|
| parameters = [];
|
| for (var formal in definition.formals) {
|
| - var param = new Parameter(formal);
|
| - param.resolve(this, inType);
|
| + // TODO(jimhug): Clean up construction of Parameters.
|
| + var param = new Parameter(formal, this);
|
| + param.resolve();
|
| parameters.add(param);
|
| }
|
|
|
| @@ -1362,38 +1346,6 @@ class MethodMember extends Member {
|
| library._addMember(this);
|
| }
|
| }
|
| -
|
| - Type findTypeVariable(TypeReference node, bool isRequired) {
|
| - if (!this.isFactory || node is! NameTypeReference) {
|
| - return super.resolveType(node, isRequired);
|
| - } else {
|
| - // TODO(ahe): We cannot find any type variables as they aren't
|
| - // recorded. So we turn this in to a warning instead.
|
| - return super.resolveType(node, false);
|
| - }
|
| - }
|
| -
|
| - Type resolveType(TypeReference node, bool isRequired) {
|
| - if (node !== null && this.isFactory && isRequired) {
|
| - if (node is GenericTypeReference) {
|
| - // TODO(ahe): This is bascially a copy of code in
|
| - // DefinedType.resolveType. More checks should be performed,
|
| - // such as bounds check, but the code is structured in a way
|
| - // that makes this hard.
|
| - GenericTypeReference genericReference = node;
|
| - var baseType = super.resolveType(genericReference.baseType, isRequired);
|
| - var typeArguments = [];
|
| - for (TypeReference ref in genericReference.typeArguments) {
|
| - // TODO(ahe): This let us ignore T in new Foo<T>, but not in
|
| - // new Foo<Foo<T>>.
|
| - typeArguments.add(findTypeVariable(ref, isRequired));
|
| - }
|
| - node.type = baseType.getOrMakeConcreteType(typeArguments);
|
| - return node.type;
|
| - }
|
| - }
|
| - return super.resolveType(node, isRequired);
|
| - }
|
| }
|
|
|
|
|
|
|