| 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 if (name !== null) { | |
| 22 String mangled = mangleJsName(); | |
| 23 assert(!mangled.contains(':')); | |
| 24 _jsname = mangled; | |
| 25 } | |
| 26 } | |
| 27 | |
| 28 // TODO - walk tree | |
| 29 Library get library() => null; | |
| 30 | |
| 31 /** A source location for messages to the user about this [Element]. */ | |
| 32 SourceSpan get span() => null; | |
| 33 | |
| 34 /** Should this element be treated as native JS? */ | |
| 35 bool get isNative() => false; | |
| 36 | |
| 37 int hashCode() => name.hashCode(); | |
| 38 | |
| 39 /** Will return a safe name to refer to this element with in JS code. */ | |
| 40 String get jsname() => _jsname; | |
| 41 | |
| 42 /** The native name of this element if it has one. */ | |
| 43 String get nativeName() => _jsname; | |
| 44 | |
| 45 /** Avoid the native name if hidden native. */ | |
| 46 bool get avoidNativeName() => false; | |
| 47 | |
| 48 /** | |
| 49 * [jsname] priority of this element, if two elements conflict. | |
| 50 * Higher one gets the name. | |
| 51 */ | |
| 52 int get jsnamePriority() => isNative ? 2 : (library.isCore ? 1 : 0); | |
| 53 | |
| 54 /** Resolve types and other references in the [Element]. */ | |
| 55 void resolve() {} | |
| 56 | |
| 57 /** | |
| 58 * By default we mangle the JS name of an element to avoid | |
| 59 * giving them names that clash with JS keywords. | |
| 60 */ | |
| 61 String mangleJsName() => world.toJsIdentifier(name); | |
| 62 | |
| 63 /** | |
| 64 * Any type parameters that this element defines to setup a generic | |
| 65 * type resolution context. This is currently used for both generic | |
| 66 * types and the semi-magical generic factory methods - but it will | |
| 67 * not be used for any other members in the current dart language. | |
| 68 */ | |
| 69 // TODO(jimhug): Confirm whether or not these are still on factories. | |
| 70 List<ParameterType> get typeParameters() => null; | |
| 71 | |
| 72 List<Type> get typeArgsInOrder() => const []; | |
| 73 | |
| 74 // TODO(jimhug): Probably kill this. | |
| 75 Element get enclosingElement() => | |
| 76 _enclosingElement == null ? library : _enclosingElement; | |
| 77 | |
| 78 // TODO(jimhug): Absolutely kill this one. | |
| 79 set enclosingElement(Element e) => _enclosingElement = e; | |
| 80 | |
| 81 Type lookupTypeParam(String name) { | |
| 82 if (typeParameters == null) return null; | |
| 83 | |
| 84 for (int i=0; i < typeParameters.length; i++) { | |
| 85 if (typeParameters[i].name == name) { | |
| 86 return typeArgsInOrder[i]; | |
| 87 } | |
| 88 } | |
| 89 return null; | |
| 90 } | |
| 91 | |
| 92 | |
| 93 /** | |
| 94 * Resolves [node] in the context of this element. Will | |
| 95 * search up the tree of [enclosingElement] to look for matches. | |
| 96 * If [typeErrors] then types that are not found will create errors, | |
| 97 * otherwise they will only signal warnings. | |
| 98 */ | |
| 99 Type resolveType(TypeReference node, bool typeErrors, bool allowTypeParams) { | |
| 100 if (node == null) return world.varType; | |
| 101 | |
| 102 // TODO(jmesserly): if we failed to resolve a type, we need a way to save | |
| 103 // that it was an error, so we don't try to resolve it again and show the | |
| 104 // same message twice. | |
| 105 | |
| 106 if (node is SimpleTypeReference) { | |
| 107 var ret = node.dynamic.type; | |
| 108 if (ret == world.voidType) { | |
| 109 world.error('"void" only allowed as return type', node.span); | |
| 110 return world.varType; | |
| 111 } | |
| 112 return ret; | |
| 113 } else if (node is NameTypeReference) { | |
| 114 NameTypeReference typeRef = node; | |
| 115 String name; | |
| 116 if (typeRef.names != null) { | |
| 117 name = typeRef.names.last().name; | |
| 118 } else { | |
| 119 name = typeRef.name.name; | |
| 120 } | |
| 121 var typeParamType = lookupTypeParam(name); | |
| 122 if (typeParamType != null) { | |
| 123 if (!allowTypeParams) { | |
| 124 world.error('using type parameter in illegal context.', node.span); | |
| 125 } | |
| 126 return typeParamType; | |
| 127 } | |
| 128 | |
| 129 return enclosingElement.resolveType(node, typeErrors, allowTypeParams); | |
| 130 } else if (node is GenericTypeReference) { | |
| 131 GenericTypeReference typeRef = node; | |
| 132 // TODO(jimhug): Expand the handling of typeErrors to generics and funcs | |
| 133 var baseType = resolveType(typeRef.baseType, typeErrors, | |
| 134 allowTypeParams); | |
| 135 //!!!print('resolving generic: ${baseType.name}'); | |
| 136 if (!baseType.isGeneric) { | |
| 137 world.error('${baseType.name} is not generic', typeRef.span); | |
| 138 return world.varType; | |
| 139 } | |
| 140 if (typeRef.typeArguments.length != baseType.typeParameters.length) { | |
| 141 world.error('wrong number of type arguments', typeRef.span); | |
| 142 return world.varType; | |
| 143 } | |
| 144 var typeArgs = []; | |
| 145 for (int i=0; i < typeRef.typeArguments.length; i++) { | |
| 146 typeArgs.add(resolveType(typeRef.typeArguments[i], typeErrors, | |
| 147 allowTypeParams)); | |
| 148 } | |
| 149 return baseType.getOrMakeConcreteType(typeArgs); | |
| 150 } else if (node is FunctionTypeReference) { | |
| 151 FunctionTypeReference typeRef = node; | |
| 152 var name = ''; | |
| 153 if (typeRef.func.name != null) { | |
| 154 name = typeRef.func.name.name; | |
| 155 } | |
| 156 return library.getOrAddFunctionType(this, name, typeRef.func, null); | |
| 157 } | |
| 158 world.internalError('unexpected TypeReference', node.span); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 /** | |
| 163 * An [Element] representing something in the top level JavaScript environment. | |
| 164 */ | |
| 165 class ExistingJsGlobal extends Element { | |
| 166 /** The element causing this alias. */ | |
| 167 final Element declaringElement; | |
| 168 | |
| 169 ExistingJsGlobal(name, this.declaringElement) : super(name, null); | |
| 170 | |
| 171 /** Should this element be treated as native JS? */ | |
| 172 bool get isNative() => true; | |
| 173 | |
| 174 /** This must be the highest possible priority. */ | |
| 175 int get jsnamePriority() => 10; | |
| 176 | |
| 177 /** A source location for messages to the user about this [Element]. */ | |
| 178 SourceSpan get span() => declaringElement.span; | |
| 179 | |
| 180 /** A library for messages. */ | |
| 181 Library get library() => declaringElement.library; | |
| 182 | |
| 183 } | |
| OLD | NEW |