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 |