OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * Any abstract representation of a dart element. This includes |
| 7 * [Library], [Type] and [Member]. |
| 8 */ |
| 9 class Element implements Hashable { |
| 10 // TODO(jimhug): Make name final when we can do it for Library. |
| 11 /** The user-visible name of this [Element]. */ |
| 12 String name; |
| 13 |
| 14 /** A safe name to use for this [Element] in generated JS code. */ |
| 15 String _jsname; |
| 16 |
| 17 /** The lexically/logically enclosing [Element] for lookups. */ |
| 18 Element _enclosingElement; |
| 19 |
| 20 Element(this.name, this._enclosingElement) { |
| 21 _jsname = name; |
| 22 } |
| 23 |
| 24 // TODO - walk tree |
| 25 Library get library() => null; |
| 26 |
| 27 /** A source location for messages to the user about this [Element]. */ |
| 28 SourceSpan get span() => null; |
| 29 |
| 30 /** Should this element be treated as native JS? */ |
| 31 bool get isNative() => false; |
| 32 |
| 33 int hashCode() => name.hashCode(); |
| 34 |
| 35 /** Will return a safe name to refer to this element with in JS code. */ |
| 36 String get jsname() => _jsname; |
| 37 |
| 38 /** Resolve types and other references in the [Element]. */ |
| 39 void resolve() {} |
| 40 |
| 41 /** |
| 42 * Any type parameters that this element defines to setup a generic |
| 43 * type resolution context. This is currently used for both generic |
| 44 * types and the semi-magical generic factory methods - but it will |
| 45 * not be used for any other members in the current dart language. |
| 46 */ |
| 47 List<ParameterType> get typeParameters() => null; |
| 48 |
| 49 // TODO(jimhug): Probably kill this. |
| 50 Element get enclosingElement() => |
| 51 _enclosingElement === null ? library : _enclosingElement; |
| 52 |
| 53 // TODO(jimhug): Absolutely kill this one. |
| 54 set enclosingElement(Element e) => _enclosingElement = e; |
| 55 |
| 56 |
| 57 /** |
| 58 * Resolves [node] in the context of this element. Will |
| 59 * search up the tree of [enclosingElement] to look for matches. |
| 60 * If [typeErrors] then types that are not found will create errors, |
| 61 * otherwise they will only signal warnings. |
| 62 */ |
| 63 Type resolveType(TypeReference node, bool typeErrors) { |
| 64 if (node == null) return world.varType; |
| 65 |
| 66 if (node.type != null) return node.type; |
| 67 |
| 68 // TODO(jmesserly): if we failed to resolve a type, we need a way to save |
| 69 // that it was an error, so we don't try to resolve it again and show the |
| 70 // same message twice. |
| 71 |
| 72 if (node is NameTypeReference) { |
| 73 NameTypeReference typeRef = node; |
| 74 String name; |
| 75 if (typeRef.names != null) { |
| 76 name = typeRef.names.last().name; |
| 77 } else { |
| 78 name = typeRef.name.name; |
| 79 } |
| 80 if (typeParameters != null) { |
| 81 for (var tp in typeParameters) { |
| 82 if (tp.name == name) { |
| 83 typeRef.type = tp; |
| 84 } |
| 85 } |
| 86 } |
| 87 if (typeRef.type != null) { |
| 88 return typeRef.type; |
| 89 } |
| 90 |
| 91 return enclosingElement.resolveType(node, typeErrors); |
| 92 } else if (node is GenericTypeReference) { |
| 93 GenericTypeReference typeRef = node; |
| 94 // TODO(jimhug): Expand the handling of typeErrors to generics and funcs |
| 95 var baseType = resolveType(typeRef.baseType, typeErrors); |
| 96 if (!baseType.isGeneric) { |
| 97 world.error('${baseType.name} is not generic', typeRef.span); |
| 98 return null; |
| 99 } |
| 100 if (typeRef.typeArguments.length != baseType.typeParameters.length) { |
| 101 world.error('wrong number of type arguments', typeRef.span); |
| 102 return null; |
| 103 } |
| 104 var typeArgs = []; |
| 105 for (int i=0; i < typeRef.typeArguments.length; i++) { |
| 106 var extendsType = baseType.typeParameters[i].extendsType; |
| 107 var typeArg = resolveType(typeRef.typeArguments[i], typeErrors); |
| 108 typeArgs.add(typeArg); |
| 109 |
| 110 if (extendsType != null && typeArg is! ParameterType) { |
| 111 typeArg.ensureSubtypeOf(extendsType, |
| 112 typeRef.typeArguments[i].span, typeErrors); |
| 113 } |
| 114 } |
| 115 typeRef.type = baseType.getOrMakeConcreteType(typeArgs); |
| 116 } else if (node is FunctionTypeReference) { |
| 117 FunctionTypeReference typeRef = node; |
| 118 var name = ''; |
| 119 if (typeRef.func.name != null) { |
| 120 name = typeRef.func.name.name; |
| 121 } |
| 122 // Totally bogus! |
| 123 typeRef.type = library.getOrAddFunctionType(this, name, typeRef.func); |
| 124 } else { |
| 125 world.internalError('unknown type reference', node.span); |
| 126 } |
| 127 return node.type; |
| 128 } |
| 129 } |
OLD | NEW |