OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.resolution.class_hierarchy; | 5 library dart2js.resolution.class_hierarchy; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart' show | 8 import '../common/resolution.dart' show Feature; |
9 Feature; | 9 import '../compiler.dart' show Compiler; |
10 import '../compiler.dart' show | 10 import '../core_types.dart' show CoreClasses, CoreTypes; |
11 Compiler; | |
12 import '../core_types.dart' show | |
13 CoreClasses, | |
14 CoreTypes; | |
15 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
16 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
17 import '../elements/modelx.dart' show | 13 import '../elements/modelx.dart' |
18 BaseClassElementX, | 14 show |
19 ErroneousElementX, | 15 BaseClassElementX, |
20 MixinApplicationElementX, | 16 ErroneousElementX, |
21 SynthesizedConstructorElementX, | 17 MixinApplicationElementX, |
22 TypeVariableElementX, | 18 SynthesizedConstructorElementX, |
23 UnnamedMixinApplicationElementX; | 19 TypeVariableElementX, |
24 import '../ordered_typeset.dart' show | 20 UnnamedMixinApplicationElementX; |
25 OrderedTypeSet, | 21 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder; |
26 OrderedTypeSetBuilder; | |
27 import '../tree/tree.dart'; | 22 import '../tree/tree.dart'; |
28 import '../util/util.dart' show | 23 import '../util/util.dart' show Link, Setlet; |
29 Link, | 24 import '../universe/call_structure.dart' show CallStructure; |
30 Setlet; | |
31 import '../universe/call_structure.dart' show | |
32 CallStructure; | |
33 | 25 |
34 import 'enum_creator.dart'; | 26 import 'enum_creator.dart'; |
35 import 'members.dart' show | 27 import 'members.dart' show lookupInScope; |
36 lookupInScope; | 28 import 'registry.dart' show ResolutionRegistry; |
37 import 'registry.dart' show | 29 import 'resolution_common.dart' show CommonResolverVisitor, MappingVisitor; |
38 ResolutionRegistry; | 30 import 'scope.dart' show Scope, TypeDeclarationScope; |
39 import 'resolution_common.dart' show | |
40 CommonResolverVisitor, | |
41 MappingVisitor; | |
42 import 'scope.dart' show | |
43 Scope, | |
44 TypeDeclarationScope; | |
45 | 31 |
46 class TypeDefinitionVisitor extends MappingVisitor<DartType> { | 32 class TypeDefinitionVisitor extends MappingVisitor<DartType> { |
47 Scope scope; | 33 Scope scope; |
48 final TypeDeclarationElement enclosingElement; | 34 final TypeDeclarationElement enclosingElement; |
49 TypeDeclarationElement get element => enclosingElement; | 35 TypeDeclarationElement get element => enclosingElement; |
50 | 36 |
51 TypeDefinitionVisitor(Compiler compiler, | 37 TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element, |
52 TypeDeclarationElement element, | 38 ResolutionRegistry registry) |
53 ResolutionRegistry registry) | |
54 : this.enclosingElement = element, | 39 : this.enclosingElement = element, |
55 scope = Scope.buildEnclosingScope(element), | 40 scope = Scope.buildEnclosingScope(element), |
56 super(compiler, registry); | 41 super(compiler, registry); |
57 | 42 |
58 CoreTypes get coreTypes => compiler.coreTypes; | 43 CoreTypes get coreTypes => compiler.coreTypes; |
59 | 44 |
60 DartType get objectType => coreTypes.objectType; | 45 DartType get objectType => coreTypes.objectType; |
61 | 46 |
62 | |
63 void resolveTypeVariableBounds(NodeList node) { | 47 void resolveTypeVariableBounds(NodeList node) { |
64 if (node == null) return; | 48 if (node == null) return; |
65 | 49 |
66 Setlet<String> nameSet = new Setlet<String>(); | 50 Setlet<String> nameSet = new Setlet<String>(); |
67 // Resolve the bounds of type variables. | 51 // Resolve the bounds of type variables. |
68 Iterator<DartType> types = element.typeVariables.iterator; | 52 Iterator<DartType> types = element.typeVariables.iterator; |
69 Link<Node> nodeLink = node.nodes; | 53 Link<Node> nodeLink = node.nodes; |
70 while (!nodeLink.isEmpty) { | 54 while (!nodeLink.isEmpty) { |
71 types.moveNext(); | 55 types.moveNext(); |
72 TypeVariableType typeVariable = types.current; | 56 TypeVariableType typeVariable = types.current; |
73 String typeName = typeVariable.name; | 57 String typeName = typeVariable.name; |
74 TypeVariable typeNode = nodeLink.head; | 58 TypeVariable typeNode = nodeLink.head; |
75 registry.useType(typeNode, typeVariable); | 59 registry.useType(typeNode, typeVariable); |
76 if (nameSet.contains(typeName)) { | 60 if (nameSet.contains(typeName)) { |
77 reporter.reportErrorMessage( | 61 reporter.reportErrorMessage( |
78 typeNode, | 62 typeNode, |
79 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, | 63 MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, |
80 {'typeVariableName': typeName}); | 64 {'typeVariableName': typeName}); |
81 } | 65 } |
82 nameSet.add(typeName); | 66 nameSet.add(typeName); |
83 | 67 |
84 TypeVariableElementX variableElement = typeVariable.element; | 68 TypeVariableElementX variableElement = typeVariable.element; |
85 if (typeNode.bound != null) { | 69 if (typeNode.bound != null) { |
86 DartType boundType = typeResolver.resolveTypeAnnotation( | 70 DartType boundType = |
87 this, typeNode.bound); | 71 typeResolver.resolveTypeAnnotation(this, typeNode.bound); |
88 variableElement.boundCache = boundType; | 72 variableElement.boundCache = boundType; |
89 | 73 |
90 void checkTypeVariableBound() { | 74 void checkTypeVariableBound() { |
91 Link<TypeVariableElement> seenTypeVariables = | 75 Link<TypeVariableElement> seenTypeVariables = |
92 const Link<TypeVariableElement>(); | 76 const Link<TypeVariableElement>(); |
93 seenTypeVariables = seenTypeVariables.prepend(variableElement); | 77 seenTypeVariables = seenTypeVariables.prepend(variableElement); |
94 DartType bound = boundType; | 78 DartType bound = boundType; |
95 while (bound.isTypeVariable) { | 79 while (bound.isTypeVariable) { |
96 TypeVariableElement element = bound.element; | 80 TypeVariableElement element = bound.element; |
97 if (seenTypeVariables.contains(element)) { | 81 if (seenTypeVariables.contains(element)) { |
(...skipping 29 matching lines...) Expand all Loading... |
127 * this may lead to cycles. | 111 * this may lead to cycles. |
128 * | 112 * |
129 * This visitor can assume that the supertypes have already been | 113 * This visitor can assume that the supertypes have already been |
130 * resolved, but it cannot call [ResolverTask.resolveClass] directly | 114 * resolved, but it cannot call [ResolverTask.resolveClass] directly |
131 * or indirectly (through [ClassElement.ensureResolved]) for any other | 115 * or indirectly (through [ClassElement.ensureResolved]) for any other |
132 * types. | 116 * types. |
133 */ | 117 */ |
134 class ClassResolverVisitor extends TypeDefinitionVisitor { | 118 class ClassResolverVisitor extends TypeDefinitionVisitor { |
135 BaseClassElementX get element => enclosingElement; | 119 BaseClassElementX get element => enclosingElement; |
136 | 120 |
137 ClassResolverVisitor(Compiler compiler, | 121 ClassResolverVisitor( |
138 ClassElement classElement, | 122 Compiler compiler, ClassElement classElement, ResolutionRegistry registry) |
139 ResolutionRegistry registry) | 123 : super(compiler, classElement, registry); |
140 : super(compiler, classElement, registry); | |
141 | 124 |
142 DartType visitClassNode(ClassNode node) { | 125 DartType visitClassNode(ClassNode node) { |
143 if (element == null) { | 126 if (element == null) { |
144 throw reporter.internalError(node, 'element is null'); | 127 throw reporter.internalError(node, 'element is null'); |
145 } | 128 } |
146 if (element.resolutionState != STATE_STARTED) { | 129 if (element.resolutionState != STATE_STARTED) { |
147 throw reporter.internalError(element, | 130 throw reporter.internalError( |
148 'cyclic resolution of class $element'); | 131 element, 'cyclic resolution of class $element'); |
149 } | 132 } |
150 | 133 |
151 element.computeType(resolution); | 134 element.computeType(resolution); |
152 scope = new TypeDeclarationScope(scope, element); | 135 scope = new TypeDeclarationScope(scope, element); |
153 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. | 136 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. |
154 // As a side-effect, this may get us back here trying to | 137 // As a side-effect, this may get us back here trying to |
155 // resolve this class again. | 138 // resolve this class again. |
156 resolveTypeVariableBounds(node.typeParameters); | 139 resolveTypeVariableBounds(node.typeParameters); |
157 | 140 |
158 // Setup the supertype for the element (if there is a cycle in the | 141 // Setup the supertype for the element (if there is a cycle in the |
159 // class hierarchy, it has already been set to Object). | 142 // class hierarchy, it has already been set to Object). |
160 if (element.supertype == null && node.superclass != null) { | 143 if (element.supertype == null && node.superclass != null) { |
161 MixinApplication superMixin = node.superclass.asMixinApplication(); | 144 MixinApplication superMixin = node.superclass.asMixinApplication(); |
162 if (superMixin != null) { | 145 if (superMixin != null) { |
163 DartType supertype = resolveSupertype(element, superMixin.superclass); | 146 DartType supertype = resolveSupertype(element, superMixin.superclass); |
164 Link<Node> link = superMixin.mixins.nodes; | 147 Link<Node> link = superMixin.mixins.nodes; |
165 while (!link.isEmpty) { | 148 while (!link.isEmpty) { |
166 supertype = applyMixin(supertype, | 149 supertype = |
167 checkMixinType(link.head), link.head); | 150 applyMixin(supertype, checkMixinType(link.head), link.head); |
168 link = link.tail; | 151 link = link.tail; |
169 } | 152 } |
170 element.supertype = supertype; | 153 element.supertype = supertype; |
171 } else { | 154 } else { |
172 element.supertype = resolveSupertype(element, node.superclass); | 155 element.supertype = resolveSupertype(element, node.superclass); |
173 } | 156 } |
174 } | 157 } |
175 // If the super type isn't specified, we provide a default. The language | 158 // If the super type isn't specified, we provide a default. The language |
176 // specifies [Object] but the backend can pick a specific 'implementation' | 159 // specifies [Object] but the backend can pick a specific 'implementation' |
177 // of Object - the JavaScript backend chooses between Object and | 160 // of Object - the JavaScript backend chooses between Object and |
178 // Interceptor. | 161 // Interceptor. |
179 if (element.supertype == null) { | 162 if (element.supertype == null) { |
180 ClassElement superElement = registry.defaultSuperclass(element); | 163 ClassElement superElement = registry.defaultSuperclass(element); |
181 // Avoid making the superclass (usually Object) extend itself. | 164 // Avoid making the superclass (usually Object) extend itself. |
182 if (element != superElement) { | 165 if (element != superElement) { |
183 if (superElement == null) { | 166 if (superElement == null) { |
184 reporter.internalError(node, | 167 reporter.internalError( |
185 "Cannot resolve default superclass for $element."); | 168 node, "Cannot resolve default superclass for $element."); |
186 } else { | 169 } else { |
187 superElement.ensureResolved(resolution); | 170 superElement.ensureResolved(resolution); |
188 } | 171 } |
189 element.supertype = superElement.computeType(resolution); | 172 element.supertype = superElement.computeType(resolution); |
190 } | 173 } |
191 } | 174 } |
192 | 175 |
193 if (element.interfaces == null) { | 176 if (element.interfaces == null) { |
194 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 177 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); |
195 } else { | 178 } else { |
196 assert(invariant(element, element.hasIncompleteHierarchy)); | 179 assert(invariant(element, element.hasIncompleteHierarchy)); |
197 } | 180 } |
198 calculateAllSupertypes(element); | 181 calculateAllSupertypes(element); |
199 | 182 |
200 if (!element.hasConstructor) { | 183 if (!element.hasConstructor) { |
201 Element superMember = element.superclass.localLookup(''); | 184 Element superMember = element.superclass.localLookup(''); |
202 if (superMember == null) { | 185 if (superMember == null) { |
203 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; | 186 MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR; |
204 Map arguments = {'className': element.superclass.name}; | 187 Map arguments = {'className': element.superclass.name}; |
205 // TODO(ahe): Why is this a compile-time error? Or if it is an error, | 188 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
206 // why do we bother to registerThrowNoSuchMethod below? | 189 // why do we bother to registerThrowNoSuchMethod below? |
207 reporter.reportErrorMessage(node, kind, arguments); | 190 reporter.reportErrorMessage(node, kind, arguments); |
208 superMember = new ErroneousElementX( | 191 superMember = new ErroneousElementX(kind, arguments, '', element); |
209 kind, arguments, '', element); | |
210 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | 192 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
211 } else if (!superMember.isGenerativeConstructor) { | 193 } else if (!superMember.isGenerativeConstructor) { |
212 MessageKind kind = MessageKind.SUPER_CALL_TO_FACTORY; | 194 MessageKind kind = MessageKind.SUPER_CALL_TO_FACTORY; |
213 Map arguments = {'className': element.superclass.name}; | 195 Map arguments = {'className': element.superclass.name}; |
214 // TODO(ahe): Why is this a compile-time error? Or if it is an error, | 196 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
215 // why do we bother to registerThrowNoSuchMethod below? | 197 // why do we bother to registerThrowNoSuchMethod below? |
216 reporter.reportErrorMessage(node, kind, arguments); | 198 reporter.reportErrorMessage(node, kind, arguments); |
217 superMember = new ErroneousElementX( | 199 superMember = new ErroneousElementX(kind, arguments, '', element); |
218 kind, arguments, '', element); | 200 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
219 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | |
220 } else { | 201 } else { |
221 ConstructorElement superConstructor = superMember; | 202 ConstructorElement superConstructor = superMember; |
222 superConstructor.computeType(resolution); | 203 superConstructor.computeType(resolution); |
223 if (!CallStructure.NO_ARGS.signatureApplies( | 204 if (!CallStructure.NO_ARGS |
224 superConstructor.functionSignature)) { | 205 .signatureApplies(superConstructor.functionSignature)) { |
225 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; | 206 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; |
226 reporter.reportErrorMessage(node, kind); | 207 reporter.reportErrorMessage(node, kind); |
227 superMember = new ErroneousElementX(kind, {}, '', element); | 208 superMember = new ErroneousElementX(kind, {}, '', element); |
228 } | 209 } |
229 } | 210 } |
230 FunctionElement constructor = | 211 FunctionElement constructor = |
231 new SynthesizedConstructorElementX.forDefault(superMember, element); | 212 new SynthesizedConstructorElementX.forDefault(superMember, element); |
232 if (superMember.isMalformed) { | 213 if (superMember.isMalformed) { |
233 compiler.elementsWithCompileTimeErrors.add(constructor); | 214 compiler.elementsWithCompileTimeErrors.add(constructor); |
234 } | 215 } |
235 element.setDefaultConstructor(constructor, reporter); | 216 element.setDefaultConstructor(constructor, reporter); |
236 } | 217 } |
237 return element.computeType(resolution); | 218 return element.computeType(resolution); |
238 } | 219 } |
239 | 220 |
240 @override | 221 @override |
241 DartType visitEnum(Enum node) { | 222 DartType visitEnum(Enum node) { |
242 if (element == null) { | 223 if (element == null) { |
243 throw reporter.internalError(node, 'element is null'); | 224 throw reporter.internalError(node, 'element is null'); |
244 } | 225 } |
245 if (element.resolutionState != STATE_STARTED) { | 226 if (element.resolutionState != STATE_STARTED) { |
246 throw reporter.internalError(element, | 227 throw reporter.internalError( |
247 'cyclic resolution of class $element'); | 228 element, 'cyclic resolution of class $element'); |
248 } | 229 } |
249 | 230 |
250 InterfaceType enumType = element.computeType(resolution); | 231 InterfaceType enumType = element.computeType(resolution); |
251 element.supertype = objectType; | 232 element.supertype = objectType; |
252 element.interfaces = const Link<DartType>(); | 233 element.interfaces = const Link<DartType>(); |
253 calculateAllSupertypes(element); | 234 calculateAllSupertypes(element); |
254 | 235 |
255 if (node.names.nodes.isEmpty) { | 236 if (node.names.nodes.isEmpty) { |
256 reporter.reportErrorMessage( | 237 reporter.reportErrorMessage( |
257 node, | 238 node, MessageKind.EMPTY_ENUM_DECLARATION, {'enumName': element.name}); |
258 MessageKind.EMPTY_ENUM_DECLARATION, | |
259 {'enumName': element.name}); | |
260 } | 239 } |
261 | 240 |
262 EnumCreator creator = | 241 EnumCreator creator = |
263 new EnumCreator(reporter, compiler.coreTypes, element); | 242 new EnumCreator(reporter, compiler.coreTypes, element); |
264 creator.createMembers(); | 243 creator.createMembers(); |
265 return enumType; | 244 return enumType; |
266 } | 245 } |
267 | 246 |
268 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type | 247 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type |
269 /// is a valid, non-blacklisted interface type. The mixin type is returned. | 248 /// is a valid, non-blacklisted interface type. The mixin type is returned. |
270 DartType checkMixinType(TypeAnnotation mixinNode) { | 249 DartType checkMixinType(TypeAnnotation mixinNode) { |
271 DartType mixinType = resolveType(mixinNode); | 250 DartType mixinType = resolveType(mixinNode); |
272 if (isBlackListed(mixinType)) { | 251 if (isBlackListed(mixinType)) { |
273 reporter.reportErrorMessage( | 252 reporter.reportErrorMessage( |
274 mixinNode, | 253 mixinNode, MessageKind.CANNOT_MIXIN, {'type': mixinType}); |
275 MessageKind.CANNOT_MIXIN, | |
276 {'type': mixinType}); | |
277 } else if (mixinType.isTypeVariable) { | 254 } else if (mixinType.isTypeVariable) { |
278 reporter.reportErrorMessage( | 255 reporter.reportErrorMessage(mixinNode, MessageKind.CLASS_NAME_EXPECTED); |
279 mixinNode, | |
280 MessageKind.CLASS_NAME_EXPECTED); | |
281 } else if (mixinType.isMalformed) { | 256 } else if (mixinType.isMalformed) { |
282 reporter.reportErrorMessage( | 257 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED, |
283 mixinNode, | |
284 MessageKind.CANNOT_MIXIN_MALFORMED, | |
285 {'className': element.name, 'malformedType': mixinType}); | 258 {'className': element.name, 'malformedType': mixinType}); |
286 } else if (mixinType.isEnumType) { | 259 } else if (mixinType.isEnumType) { |
287 reporter.reportErrorMessage( | 260 reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_ENUM, |
288 mixinNode, | |
289 MessageKind.CANNOT_MIXIN_ENUM, | |
290 {'className': element.name, 'enumType': mixinType}); | 261 {'className': element.name, 'enumType': mixinType}); |
291 } | 262 } |
292 return mixinType; | 263 return mixinType; |
293 } | 264 } |
294 | 265 |
295 DartType visitNamedMixinApplication(NamedMixinApplication node) { | 266 DartType visitNamedMixinApplication(NamedMixinApplication node) { |
296 if (element == null) { | 267 if (element == null) { |
297 throw reporter.internalError(node, 'element is null'); | 268 throw reporter.internalError(node, 'element is null'); |
298 } | 269 } |
299 if (element.resolutionState != STATE_STARTED) { | 270 if (element.resolutionState != STATE_STARTED) { |
300 throw reporter.internalError(element, | 271 throw reporter.internalError( |
301 'cyclic resolution of class $element'); | 272 element, 'cyclic resolution of class $element'); |
302 } | 273 } |
303 | 274 |
304 if (identical(node.classKeyword.stringValue, 'typedef')) { | 275 if (identical(node.classKeyword.stringValue, 'typedef')) { |
305 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic | 276 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic |
306 // together with corresponding TODO in parser.dart. | 277 // together with corresponding TODO in parser.dart. |
307 reporter.reportWarningMessage( | 278 reporter.reportWarningMessage( |
308 node.classKeyword, | 279 node.classKeyword, MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); |
309 MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); | |
310 } | 280 } |
311 | 281 |
312 element.computeType(resolution); | 282 element.computeType(resolution); |
313 scope = new TypeDeclarationScope(scope, element); | 283 scope = new TypeDeclarationScope(scope, element); |
314 resolveTypeVariableBounds(node.typeParameters); | 284 resolveTypeVariableBounds(node.typeParameters); |
315 | 285 |
316 // Generate anonymous mixin application elements for the | 286 // Generate anonymous mixin application elements for the |
317 // intermediate mixin applications (excluding the last). | 287 // intermediate mixin applications (excluding the last). |
318 DartType supertype = resolveSupertype(element, node.superclass); | 288 DartType supertype = resolveSupertype(element, node.superclass); |
319 Link<Node> link = node.mixins.nodes; | 289 Link<Node> link = node.mixins.nodes; |
320 while (!link.tail.isEmpty) { | 290 while (!link.tail.isEmpty) { |
321 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); | 291 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); |
322 link = link.tail; | 292 link = link.tail; |
323 } | 293 } |
324 doApplyMixinTo(element, supertype, checkMixinType(link.head)); | 294 doApplyMixinTo(element, supertype, checkMixinType(link.head)); |
325 return element.computeType(resolution); | 295 return element.computeType(resolution); |
326 } | 296 } |
327 | 297 |
328 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { | 298 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { |
329 String superName = supertype.name; | 299 String superName = supertype.name; |
330 String mixinName = mixinType.name; | 300 String mixinName = mixinType.name; |
331 MixinApplicationElementX mixinApplication = | 301 MixinApplicationElementX mixinApplication = |
332 new UnnamedMixinApplicationElementX( | 302 new UnnamedMixinApplicationElementX("${superName}+${mixinName}", |
333 "${superName}+${mixinName}", | 303 element.compilationUnit, compiler.getNextFreeClassId(), node); |
334 element.compilationUnit, | |
335 compiler.getNextFreeClassId(), | |
336 node); | |
337 // Create synthetic type variables for the mixin application. | 304 // Create synthetic type variables for the mixin application. |
338 List<DartType> typeVariables = <DartType>[]; | 305 List<DartType> typeVariables = <DartType>[]; |
339 int index = 0; | 306 int index = 0; |
340 for (TypeVariableType type in element.typeVariables) { | 307 for (TypeVariableType type in element.typeVariables) { |
341 TypeVariableElementX typeVariableElement = new TypeVariableElementX( | 308 TypeVariableElementX typeVariableElement = new TypeVariableElementX( |
342 type.name, mixinApplication, index, type.element.node); | 309 type.name, mixinApplication, index, type.element.node); |
343 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement); | 310 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement); |
344 typeVariables.add(typeVariable); | 311 typeVariables.add(typeVariable); |
345 index++; | 312 index++; |
346 } | 313 } |
(...skipping 10 matching lines...) Expand all Loading... |
357 // Substitute in synthetic type variables in super and mixin types. | 324 // Substitute in synthetic type variables in super and mixin types. |
358 supertype = supertype.subst(typeVariables, element.typeVariables); | 325 supertype = supertype.subst(typeVariables, element.typeVariables); |
359 mixinType = mixinType.subst(typeVariables, element.typeVariables); | 326 mixinType = mixinType.subst(typeVariables, element.typeVariables); |
360 | 327 |
361 doApplyMixinTo(mixinApplication, supertype, mixinType); | 328 doApplyMixinTo(mixinApplication, supertype, mixinType); |
362 mixinApplication.resolutionState = STATE_DONE; | 329 mixinApplication.resolutionState = STATE_DONE; |
363 mixinApplication.supertypeLoadState = STATE_DONE; | 330 mixinApplication.supertypeLoadState = STATE_DONE; |
364 // Replace the synthetic type variables by the original type variables in | 331 // Replace the synthetic type variables by the original type variables in |
365 // the returned type (which should be the type actually extended). | 332 // the returned type (which should be the type actually extended). |
366 InterfaceType mixinThisType = mixinApplication.thisType; | 333 InterfaceType mixinThisType = mixinApplication.thisType; |
367 return mixinThisType.subst(element.typeVariables, | 334 return mixinThisType.subst( |
368 mixinThisType.typeArguments); | 335 element.typeVariables, mixinThisType.typeArguments); |
369 } | 336 } |
370 | 337 |
371 bool isDefaultConstructor(FunctionElement constructor) { | 338 bool isDefaultConstructor(FunctionElement constructor) { |
372 if (constructor.name != '') return false; | 339 if (constructor.name != '') return false; |
373 constructor.computeType(resolution); | 340 constructor.computeType(resolution); |
374 return constructor.functionSignature.parameterCount == 0; | 341 return constructor.functionSignature.parameterCount == 0; |
375 } | 342 } |
376 | 343 |
377 FunctionElement createForwardingConstructor(ConstructorElement target, | 344 FunctionElement createForwardingConstructor( |
378 ClassElement enclosing) { | 345 ConstructorElement target, ClassElement enclosing) { |
379 FunctionElement constructor = | 346 FunctionElement constructor = |
380 new SynthesizedConstructorElementX.notForDefault( | 347 new SynthesizedConstructorElementX.notForDefault( |
381 target.name, target, enclosing); | 348 target.name, target, enclosing); |
382 constructor.computeType(resolution); | 349 constructor.computeType(resolution); |
383 return constructor; | 350 return constructor; |
384 } | 351 } |
385 | 352 |
386 void doApplyMixinTo( | 353 void doApplyMixinTo(MixinApplicationElementX mixinApplication, |
387 MixinApplicationElementX mixinApplication, | 354 DartType supertype, DartType mixinType) { |
388 DartType supertype, | |
389 DartType mixinType) { | |
390 Node node = mixinApplication.parseNode(resolution.parsing); | 355 Node node = mixinApplication.parseNode(resolution.parsing); |
391 | 356 |
392 if (mixinApplication.supertype != null) { | 357 if (mixinApplication.supertype != null) { |
393 // [supertype] is not null if there was a cycle. | 358 // [supertype] is not null if there was a cycle. |
394 assert(invariant(node, compiler.compilationFailed)); | 359 assert(invariant(node, compiler.compilationFailed)); |
395 supertype = mixinApplication.supertype; | 360 supertype = mixinApplication.supertype; |
396 assert(invariant(node, supertype.isObject)); | 361 assert(invariant(node, supertype.isObject)); |
397 } else { | 362 } else { |
398 mixinApplication.supertype = supertype; | 363 mixinApplication.supertype = supertype; |
399 } | 364 } |
400 | 365 |
401 // Named mixin application may have an 'implements' clause. | 366 // Named mixin application may have an 'implements' clause. |
402 NamedMixinApplication namedMixinApplication = | 367 NamedMixinApplication namedMixinApplication = |
403 node.asNamedMixinApplication(); | 368 node.asNamedMixinApplication(); |
404 Link<DartType> interfaces = (namedMixinApplication != null) | 369 Link<DartType> interfaces = (namedMixinApplication != null) |
405 ? resolveInterfaces(namedMixinApplication.interfaces, | 370 ? resolveInterfaces( |
406 namedMixinApplication.superclass) | 371 namedMixinApplication.interfaces, namedMixinApplication.superclass) |
407 : const Link<DartType>(); | 372 : const Link<DartType>(); |
408 | 373 |
409 // The class that is the result of a mixin application implements | 374 // The class that is the result of a mixin application implements |
410 // the interface of the class that was mixed in so always prepend | 375 // the interface of the class that was mixed in so always prepend |
411 // that to the interface list. | 376 // that to the interface list. |
412 if (mixinApplication.interfaces == null) { | 377 if (mixinApplication.interfaces == null) { |
413 if (mixinType.isInterfaceType) { | 378 if (mixinType.isInterfaceType) { |
414 // Avoid malformed types in the interfaces. | 379 // Avoid malformed types in the interfaces. |
415 interfaces = interfaces.prepend(mixinType); | 380 interfaces = interfaces.prepend(mixinType); |
416 } | 381 } |
417 mixinApplication.interfaces = interfaces; | 382 mixinApplication.interfaces = interfaces; |
418 } else { | 383 } else { |
419 assert(invariant(mixinApplication, | 384 assert( |
420 mixinApplication.hasIncompleteHierarchy)); | 385 invariant(mixinApplication, mixinApplication.hasIncompleteHierarchy)); |
421 } | 386 } |
422 | 387 |
423 ClassElement superclass = supertype.element; | 388 ClassElement superclass = supertype.element; |
424 if (mixinType.kind != TypeKind.INTERFACE) { | 389 if (mixinType.kind != TypeKind.INTERFACE) { |
425 mixinApplication.hasIncompleteHierarchy = true; | 390 mixinApplication.hasIncompleteHierarchy = true; |
426 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; | 391 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf; |
427 return; | 392 return; |
428 } | 393 } |
429 | 394 |
430 assert(mixinApplication.mixinType == null); | 395 assert(mixinApplication.mixinType == null); |
(...skipping 11 matching lines...) Expand all Loading... |
442 // application is in a different library than the constructor in the | 407 // application is in a different library than the constructor in the |
443 // super class and it is not possible to call that constructor from the | 408 // super class and it is not possible to call that constructor from the |
444 // library using the mixin application. | 409 // library using the mixin application. |
445 return; | 410 return; |
446 } | 411 } |
447 mixinApplication.addConstructor(forwarder); | 412 mixinApplication.addConstructor(forwarder); |
448 }); | 413 }); |
449 calculateAllSupertypes(mixinApplication); | 414 calculateAllSupertypes(mixinApplication); |
450 } | 415 } |
451 | 416 |
452 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, | 417 InterfaceType resolveMixinFor( |
453 DartType mixinType) { | 418 MixinApplicationElement mixinApplication, DartType mixinType) { |
454 ClassElement mixin = mixinType.element; | 419 ClassElement mixin = mixinType.element; |
455 mixin.ensureResolved(resolution); | 420 mixin.ensureResolved(resolution); |
456 | 421 |
457 // Check for cycles in the mixin chain. | 422 // Check for cycles in the mixin chain. |
458 ClassElement previous = mixinApplication; // For better error messages. | 423 ClassElement previous = mixinApplication; // For better error messages. |
459 ClassElement current = mixin; | 424 ClassElement current = mixin; |
460 while (current != null && current.isMixinApplication) { | 425 while (current != null && current.isMixinApplication) { |
461 MixinApplicationElement currentMixinApplication = current; | 426 MixinApplicationElement currentMixinApplication = current; |
462 if (currentMixinApplication == mixinApplication) { | 427 if (currentMixinApplication == mixinApplication) { |
463 reporter.reportErrorMessage( | 428 reporter.reportErrorMessage( |
464 mixinApplication, | 429 mixinApplication, |
465 MessageKind.ILLEGAL_MIXIN_CYCLE, | 430 MessageKind.ILLEGAL_MIXIN_CYCLE, |
466 {'mixinName1': current.name, 'mixinName2': previous.name}); | 431 {'mixinName1': current.name, 'mixinName2': previous.name}); |
467 // We have found a cycle in the mixin chain. Return null as | 432 // We have found a cycle in the mixin chain. Return null as |
468 // the mixin for this application to avoid getting into | 433 // the mixin for this application to avoid getting into |
(...skipping 14 matching lines...) Expand all Loading... |
483 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 448 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
484 DartType supertype = resolveType(superclass); | 449 DartType supertype = resolveType(superclass); |
485 if (supertype != null) { | 450 if (supertype != null) { |
486 if (supertype.isMalformed) { | 451 if (supertype.isMalformed) { |
487 reporter.reportErrorMessage( | 452 reporter.reportErrorMessage( |
488 superclass, | 453 superclass, |
489 MessageKind.CANNOT_EXTEND_MALFORMED, | 454 MessageKind.CANNOT_EXTEND_MALFORMED, |
490 {'className': element.name, 'malformedType': supertype}); | 455 {'className': element.name, 'malformedType': supertype}); |
491 return objectType; | 456 return objectType; |
492 } else if (supertype.isEnumType) { | 457 } else if (supertype.isEnumType) { |
493 reporter.reportErrorMessage( | 458 reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM, |
494 superclass, | |
495 MessageKind.CANNOT_EXTEND_ENUM, | |
496 {'className': element.name, 'enumType': supertype}); | 459 {'className': element.name, 'enumType': supertype}); |
497 return objectType; | 460 return objectType; |
498 } else if (!supertype.isInterfaceType) { | 461 } else if (!supertype.isInterfaceType) { |
499 reporter.reportErrorMessage( | 462 reporter.reportErrorMessage( |
500 superclass.typeName, | 463 superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
501 MessageKind.CLASS_NAME_EXPECTED); | |
502 return objectType; | 464 return objectType; |
503 } else if (isBlackListed(supertype)) { | 465 } else if (isBlackListed(supertype)) { |
504 reporter.reportErrorMessage( | 466 reporter.reportErrorMessage( |
505 superclass, | 467 superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
506 MessageKind.CANNOT_EXTEND, | |
507 {'type': supertype}); | |
508 return objectType; | 468 return objectType; |
509 } | 469 } |
510 } | 470 } |
511 return supertype; | 471 return supertype; |
512 } | 472 } |
513 | 473 |
514 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 474 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { |
515 Link<DartType> result = const Link<DartType>(); | 475 Link<DartType> result = const Link<DartType>(); |
516 if (interfaces == null) return result; | 476 if (interfaces == null) return result; |
517 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 477 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
(...skipping 19 matching lines...) Expand all Loading... |
537 reporter.reportErrorMessage( | 497 reporter.reportErrorMessage( |
538 superclass, | 498 superclass, |
539 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 499 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
540 {'type': interfaceType}); | 500 {'type': interfaceType}); |
541 reporter.reportErrorMessage( | 501 reporter.reportErrorMessage( |
542 link.head, | 502 link.head, |
543 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 503 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
544 {'type': interfaceType}); | 504 {'type': interfaceType}); |
545 } | 505 } |
546 if (result.contains(interfaceType)) { | 506 if (result.contains(interfaceType)) { |
547 reporter.reportErrorMessage( | 507 reporter.reportErrorMessage(link.head, |
548 link.head, | 508 MessageKind.DUPLICATE_IMPLEMENTS, {'type': interfaceType}); |
549 MessageKind.DUPLICATE_IMPLEMENTS, | |
550 {'type': interfaceType}); | |
551 } | 509 } |
552 result = result.prepend(interfaceType); | 510 result = result.prepend(interfaceType); |
553 if (isBlackListed(interfaceType)) { | 511 if (isBlackListed(interfaceType)) { |
554 reporter.reportErrorMessage( | 512 reporter.reportErrorMessage(link.head, MessageKind.CANNOT_IMPLEMENT, |
555 link.head, | |
556 MessageKind.CANNOT_IMPLEMENT, | |
557 {'type': interfaceType}); | 513 {'type': interfaceType}); |
558 } | 514 } |
559 } | 515 } |
560 } | 516 } |
561 } | 517 } |
562 return result; | 518 return result; |
563 } | 519 } |
564 | 520 |
565 /** | 521 /** |
566 * Compute the list of all supertypes. | 522 * Compute the list of all supertypes. |
567 * | 523 * |
568 * The elements of this list are ordered as follows: first the supertype that | 524 * The elements of this list are ordered as follows: first the supertype that |
569 * the class extends, then the implemented interfaces, and then the supertypes | 525 * the class extends, then the implemented interfaces, and then the supertypes |
570 * of these. The class [Object] appears only once, at the end of the list. | 526 * of these. The class [Object] appears only once, at the end of the list. |
571 * | 527 * |
572 * For example, for a class `class C extends S implements I1, I2`, we compute | 528 * For example, for a class `class C extends S implements I1, I2`, we compute |
573 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) | 529 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1) |
574 * ++ supertypes(I2), | 530 * ++ supertypes(I2), |
575 * where ++ stands for list concatenation. | 531 * where ++ stands for list concatenation. |
576 * | 532 * |
577 * This order makes sure that if a class implements an interface twice with | 533 * This order makes sure that if a class implements an interface twice with |
578 * different type arguments, the type used in the most specific class comes | 534 * different type arguments, the type used in the most specific class comes |
579 * first. | 535 * first. |
580 */ | 536 */ |
581 void calculateAllSupertypes(BaseClassElementX cls) { | 537 void calculateAllSupertypes(BaseClassElementX cls) { |
582 if (cls.allSupertypesAndSelf != null) return; | 538 if (cls.allSupertypesAndSelf != null) return; |
583 final DartType supertype = cls.supertype; | 539 final DartType supertype = cls.supertype; |
584 if (supertype != null) { | 540 if (supertype != null) { |
585 cls.allSupertypesAndSelf = | 541 cls.allSupertypesAndSelf = new OrderedTypeSetBuilder(cls, |
586 new OrderedTypeSetBuilder( | 542 reporter: reporter, objectType: coreTypes.objectType) |
587 cls, reporter: reporter, objectType: coreTypes.objectType) | 543 .createOrderedTypeSet(supertype, cls.interfaces); |
588 .createOrderedTypeSet(supertype, cls.interfaces); | |
589 } else { | 544 } else { |
590 assert(cls == compiler.coreClasses.objectClass); | 545 assert(cls == compiler.coreClasses.objectClass); |
591 cls.allSupertypesAndSelf = | 546 cls.allSupertypesAndSelf = |
592 new OrderedTypeSet.singleton(cls.computeType(resolution)); | 547 new OrderedTypeSet.singleton(cls.computeType(resolution)); |
593 } | 548 } |
594 } | 549 } |
595 | 550 |
596 isBlackListed(DartType type) { | 551 isBlackListed(DartType type) { |
597 LibraryElement lib = element.library; | 552 LibraryElement lib = element.library; |
598 return | 553 return !identical(lib, compiler.coreLibrary) && |
599 !identical(lib, compiler.coreLibrary) && | 554 !compiler.backend.isBackendLibrary(lib) && |
600 !compiler.backend.isBackendLibrary(lib) && | 555 (type.isDynamic || |
601 (type.isDynamic || | 556 type == coreTypes.boolType || |
602 type == coreTypes.boolType || | 557 type == coreTypes.numType || |
603 type == coreTypes.numType || | 558 type == coreTypes.intType || |
604 type == coreTypes.intType || | 559 type == coreTypes.doubleType || |
605 type == coreTypes.doubleType || | 560 type == coreTypes.stringType || |
606 type == coreTypes.stringType || | 561 type == coreTypes.nullType); |
607 type == coreTypes.nullType); | |
608 } | 562 } |
609 } | 563 } |
610 | 564 |
611 class ClassSupertypeResolver extends CommonResolverVisitor { | 565 class ClassSupertypeResolver extends CommonResolverVisitor { |
612 Scope context; | 566 Scope context; |
613 ClassElement classElement; | 567 ClassElement classElement; |
614 | 568 |
615 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 569 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
616 : context = Scope.buildEnclosingScope(cls), | 570 : context = Scope.buildEnclosingScope(cls), |
617 this.classElement = cls, | 571 this.classElement = cls, |
618 super(compiler); | 572 super(compiler); |
619 | 573 |
620 CoreClasses get coreClasses => compiler.coreClasses; | 574 CoreClasses get coreClasses => compiler.coreClasses; |
621 | 575 |
622 void loadSupertype(ClassElement element, Node from) { | 576 void loadSupertype(ClassElement element, Node from) { |
623 if (!element.isResolved) { | 577 if (!element.isResolved) { |
624 compiler.resolver.loadSupertypes(element, from); | 578 compiler.resolver.loadSupertypes(element, from); |
625 element.ensureResolved(resolution); | 579 element.ensureResolved(resolution); |
626 } | 580 } |
627 } | 581 } |
628 | 582 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 Element element = lookupInScope(reporter, prefix, context, prefix.source); | 635 Element element = lookupInScope(reporter, prefix, context, prefix.source); |
682 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { | 636 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { |
683 reporter.reportErrorMessage( | 637 reporter.reportErrorMessage( |
684 node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | 638 node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); |
685 return; | 639 return; |
686 } | 640 } |
687 PrefixElement prefixElement = element; | 641 PrefixElement prefixElement = element; |
688 Identifier selector = node.selector.asIdentifier(); | 642 Identifier selector = node.selector.asIdentifier(); |
689 var e = prefixElement.lookupLocalMember(selector.source); | 643 var e = prefixElement.lookupLocalMember(selector.source); |
690 if (e == null || !e.impliesType) { | 644 if (e == null || !e.impliesType) { |
691 reporter.reportErrorMessage( | 645 reporter.reportErrorMessage(node.selector, |
692 node.selector, | 646 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector}); |
693 MessageKind.CANNOT_RESOLVE_TYPE, | |
694 {'typeName': node.selector}); | |
695 return; | 647 return; |
696 } | 648 } |
697 loadSupertype(e, node); | 649 loadSupertype(e, node); |
698 } | 650 } |
699 } | 651 } |
OLD | NEW |