OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Any abstract representation of a dart element. This includes | 6 * Any abstract representation of a dart element. This includes |
7 * [Library], [Type] and [Member]. | 7 * [Library], [Type] and [Member]. |
8 */ | 8 */ |
9 class Element implements Hashable { | 9 class Element implements Hashable { |
10 // TODO(jimhug): Make name final when we can do it for Library. | 10 // TODO(jimhug): Make name final when we can do it for Library. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 | 49 |
50 /** Resolve types and other references in the [Element]. */ | 50 /** Resolve types and other references in the [Element]. */ |
51 void resolve() {} | 51 void resolve() {} |
52 | 52 |
53 /** | 53 /** |
54 * Any type parameters that this element defines to setup a generic | 54 * Any type parameters that this element defines to setup a generic |
55 * type resolution context. This is currently used for both generic | 55 * type resolution context. This is currently used for both generic |
56 * types and the semi-magical generic factory methods - but it will | 56 * types and the semi-magical generic factory methods - but it will |
57 * not be used for any other members in the current dart language. | 57 * not be used for any other members in the current dart language. |
58 */ | 58 */ |
| 59 // TODO(jimhug): Confirm whether or not these are still on factories. |
59 List<ParameterType> get typeParameters() => null; | 60 List<ParameterType> get typeParameters() => null; |
60 | 61 |
| 62 List<Type> get typeArgsInOrder() => const []; |
| 63 |
61 // TODO(jimhug): Probably kill this. | 64 // TODO(jimhug): Probably kill this. |
62 Element get enclosingElement() => | 65 Element get enclosingElement() => |
63 _enclosingElement == null ? library : _enclosingElement; | 66 _enclosingElement == null ? library : _enclosingElement; |
64 | 67 |
65 // TODO(jimhug): Absolutely kill this one. | 68 // TODO(jimhug): Absolutely kill this one. |
66 set enclosingElement(Element e) => _enclosingElement = e; | 69 set enclosingElement(Element e) => _enclosingElement = e; |
67 | 70 |
| 71 Type lookupTypeParam(String name) { |
| 72 if (typeParameters == null) return null; |
| 73 |
| 74 for (int i=0; i < typeParameters.length; i++) { |
| 75 if (typeParameters[i].name == name) { |
| 76 return typeArgsInOrder[i]; |
| 77 } |
| 78 } |
| 79 return null; |
| 80 } |
| 81 |
68 | 82 |
69 /** | 83 /** |
70 * Resolves [node] in the context of this element. Will | 84 * Resolves [node] in the context of this element. Will |
71 * search up the tree of [enclosingElement] to look for matches. | 85 * search up the tree of [enclosingElement] to look for matches. |
72 * If [typeErrors] then types that are not found will create errors, | 86 * If [typeErrors] then types that are not found will create errors, |
73 * otherwise they will only signal warnings. | 87 * otherwise they will only signal warnings. |
74 */ | 88 */ |
75 Type resolveType(TypeReference node, bool typeErrors) { | 89 Type resolveType(TypeReference node, bool typeErrors, bool allowTypeParams) { |
76 if (node == null) return world.varType; | 90 if (node == null) return world.varType; |
77 | 91 |
78 if (node.type != null) return node.type; | |
79 | |
80 // TODO(jmesserly): if we failed to resolve a type, we need a way to save | 92 // TODO(jmesserly): if we failed to resolve a type, we need a way to save |
81 // that it was an error, so we don't try to resolve it again and show the | 93 // that it was an error, so we don't try to resolve it again and show the |
82 // same message twice. | 94 // same message twice. |
83 | 95 |
84 if (node is NameTypeReference) { | 96 if (node is SimpleTypeReference) { |
| 97 var ret = node.dynamic.type; |
| 98 if (ret == world.voidType) { |
| 99 world.error('"void" only allowed as return type', node.span); |
| 100 return world.varType; |
| 101 } |
| 102 return ret; |
| 103 } else if (node is NameTypeReference) { |
85 NameTypeReference typeRef = node; | 104 NameTypeReference typeRef = node; |
86 String name; | 105 String name; |
87 if (typeRef.names != null) { | 106 if (typeRef.names != null) { |
88 name = typeRef.names.last().name; | 107 name = typeRef.names.last().name; |
89 } else { | 108 } else { |
90 name = typeRef.name.name; | 109 name = typeRef.name.name; |
91 } | 110 } |
92 if (typeParameters != null) { | 111 var typeParamType = lookupTypeParam(name); |
93 for (var tp in typeParameters) { | 112 if (typeParamType != null) { |
94 if (tp.name == name) { | 113 if (!allowTypeParams) { |
95 typeRef.type = tp; | 114 world.error('using type parameter in illegal context.', node.span); |
96 } | |
97 } | 115 } |
98 } | 116 return typeParamType; |
99 if (typeRef.type != null) { | |
100 return typeRef.type; | |
101 } | 117 } |
102 | 118 |
103 return enclosingElement.resolveType(node, typeErrors); | 119 return enclosingElement.resolveType(node, typeErrors, allowTypeParams); |
104 } else if (node is GenericTypeReference) { | 120 } else if (node is GenericTypeReference) { |
105 GenericTypeReference typeRef = node; | 121 GenericTypeReference typeRef = node; |
106 // TODO(jimhug): Expand the handling of typeErrors to generics and funcs | 122 // TODO(jimhug): Expand the handling of typeErrors to generics and funcs |
107 var baseType = resolveType(typeRef.baseType, typeErrors); | 123 var baseType = resolveType(typeRef.baseType, typeErrors, |
| 124 allowTypeParams); |
| 125 //!!!print('resolving generic: ${baseType.name}'); |
108 if (!baseType.isGeneric) { | 126 if (!baseType.isGeneric) { |
109 world.error('${baseType.name} is not generic', typeRef.span); | 127 world.error('${baseType.name} is not generic', typeRef.span); |
110 return null; | 128 return world.varType; |
111 } | 129 } |
112 if (typeRef.typeArguments.length != baseType.typeParameters.length) { | 130 if (typeRef.typeArguments.length != baseType.typeParameters.length) { |
113 world.error('wrong number of type arguments', typeRef.span); | 131 world.error('wrong number of type arguments', typeRef.span); |
114 return null; | 132 return world.varType; |
115 } | 133 } |
116 var typeArgs = []; | 134 var typeArgs = []; |
117 for (int i=0; i < typeRef.typeArguments.length; i++) { | 135 for (int i=0; i < typeRef.typeArguments.length; i++) { |
118 typeArgs.add(resolveType(typeRef.typeArguments[i], typeErrors)); | 136 typeArgs.add(resolveType(typeRef.typeArguments[i], typeErrors, |
| 137 allowTypeParams)); |
119 } | 138 } |
120 typeRef.type = baseType.getOrMakeConcreteType(typeArgs); | 139 return baseType.getOrMakeConcreteType(typeArgs); |
121 } else if (node is FunctionTypeReference) { | 140 } else if (node is FunctionTypeReference) { |
122 FunctionTypeReference typeRef = node; | 141 FunctionTypeReference typeRef = node; |
123 var name = ''; | 142 var name = ''; |
124 if (typeRef.func.name != null) { | 143 if (typeRef.func.name != null) { |
125 name = typeRef.func.name.name; | 144 name = typeRef.func.name.name; |
126 } | 145 } |
127 // Totally bogus! | 146 return library.getOrAddFunctionType(this, name, typeRef.func, null); |
128 typeRef.type = library.getOrAddFunctionType(this, name, typeRef.func); | |
129 } else { | |
130 world.internalError('unknown type reference', node.span); | |
131 } | 147 } |
132 return node.type; | 148 world.internalError('unexpected TypeReference', node.span); |
133 } | 149 } |
134 } | 150 } |
135 | 151 |
136 /** | 152 /** |
137 * An [Element] representing something in the top level JavaScript environment. | 153 * An [Element] representing something in the top level JavaScript environment. |
138 */ | 154 */ |
139 class ExistingJsGlobal extends Element { | 155 class ExistingJsGlobal extends Element { |
140 /** The element causing this alias. */ | 156 /** The element causing this alias. */ |
141 final Element declaringElement; | 157 final Element declaringElement; |
142 | 158 |
143 ExistingJsGlobal(name, this.declaringElement) : super(name, null); | 159 ExistingJsGlobal(name, this.declaringElement) : super(name, null); |
144 | 160 |
145 /** Should this element be treated as native JS? */ | 161 /** Should this element be treated as native JS? */ |
146 bool get isNative() => true; | 162 bool get isNative() => true; |
147 | 163 |
148 /** This must be the highest possible priority. */ | 164 /** This must be the highest possible priority. */ |
149 int get jsnamePriority() => 10; | 165 int get jsnamePriority() => 10; |
150 | 166 |
151 /** A source location for messages to the user about this [Element]. */ | 167 /** A source location for messages to the user about this [Element]. */ |
152 SourceSpan get span() => declaringElement.span; | 168 SourceSpan get span() => declaringElement.span; |
153 | 169 |
154 /** A library for messages. */ | 170 /** A library for messages. */ |
155 Library get library() => declaringElement.library; | 171 Library get library() => declaringElement.library; |
156 | 172 |
157 } | 173 } |
OLD | NEW |