OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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; | 5 library dart2js.resolution; |
6 | 6 |
7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/names.dart' show | 10 import '../common/names.dart' show Identifiers; |
11 Identifiers; | 11 import '../common/resolution.dart' |
12 import '../common/resolution.dart' show | 12 show Feature, Parsing, Resolution, ResolutionImpact; |
13 Feature, | 13 import '../common/tasks.dart' show CompilerTask, DeferredAction; |
14 Parsing, | 14 import '../compiler.dart' show Compiler; |
15 Resolution, | 15 import '../compile_time_constants.dart' show ConstantCompiler; |
16 ResolutionImpact; | 16 import '../constants/expressions.dart' |
17 import '../common/tasks.dart' show | 17 show |
18 CompilerTask, | 18 ConstantExpression, |
19 DeferredAction; | 19 ConstantExpressionKind, |
20 import '../compiler.dart' show | 20 ConstructedConstantExpression, |
21 Compiler; | 21 ErroneousConstantExpression; |
22 import '../compile_time_constants.dart' show | 22 import '../constants/values.dart' show ConstantValue; |
23 ConstantCompiler; | 23 import '../core_types.dart' show CoreClasses, CoreTypes; |
24 import '../constants/expressions.dart' show | |
25 ConstantExpression, | |
26 ConstantExpressionKind, | |
27 ConstructedConstantExpression, | |
28 ErroneousConstantExpression; | |
29 import '../constants/values.dart' show | |
30 ConstantValue; | |
31 import '../core_types.dart' show | |
32 CoreClasses, | |
33 CoreTypes; | |
34 import '../dart_types.dart'; | 24 import '../dart_types.dart'; |
35 import '../elements/elements.dart'; | 25 import '../elements/elements.dart'; |
36 import '../elements/modelx.dart' show | 26 import '../elements/modelx.dart' |
37 BaseClassElementX, | 27 show |
38 BaseFunctionElementX, | 28 BaseClassElementX, |
39 ConstructorElementX, | 29 BaseFunctionElementX, |
40 FieldElementX, | 30 ConstructorElementX, |
41 FunctionElementX, | 31 FieldElementX, |
42 GetterElementX, | 32 FunctionElementX, |
43 MetadataAnnotationX, | 33 GetterElementX, |
44 MixinApplicationElementX, | 34 MetadataAnnotationX, |
45 ParameterMetadataAnnotation, | 35 MixinApplicationElementX, |
46 SetterElementX, | 36 ParameterMetadataAnnotation, |
47 TypedefElementX; | 37 SetterElementX, |
48 import '../tokens/token.dart' show | 38 TypedefElementX; |
49 isBinaryOperator, | 39 import '../tokens/token.dart' |
50 isMinusOperator, | 40 show |
51 isTernaryOperator, | 41 isBinaryOperator, |
52 isUnaryOperator, | 42 isMinusOperator, |
53 isUserDefinableOperator; | 43 isTernaryOperator, |
| 44 isUnaryOperator, |
| 45 isUserDefinableOperator; |
54 import '../tree/tree.dart'; | 46 import '../tree/tree.dart'; |
55 import '../universe/call_structure.dart' show | 47 import '../universe/call_structure.dart' show CallStructure; |
56 CallStructure; | 48 import '../universe/use.dart' show StaticUse, TypeUse; |
57 import '../universe/use.dart' show | 49 import '../universe/world_impact.dart' show WorldImpact; |
58 StaticUse, | 50 import '../util/util.dart' show Link, LinkBuilder, Setlet; |
59 TypeUse; | |
60 import '../universe/world_impact.dart' show | |
61 WorldImpact; | |
62 import '../util/util.dart' show | |
63 Link, | |
64 LinkBuilder, | |
65 Setlet; | |
66 | 51 |
67 import 'class_hierarchy.dart'; | 52 import 'class_hierarchy.dart'; |
68 import 'class_members.dart' show MembersCreator; | 53 import 'class_members.dart' show MembersCreator; |
69 import 'constructors.dart'; | 54 import 'constructors.dart'; |
70 import 'members.dart'; | 55 import 'members.dart'; |
71 import 'registry.dart'; | 56 import 'registry.dart'; |
72 import 'signatures.dart'; | 57 import 'signatures.dart'; |
73 import 'tree_elements.dart'; | 58 import 'tree_elements.dart'; |
74 import 'typedefs.dart'; | 59 import 'typedefs.dart'; |
75 | 60 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 return processMetadata(const ResolutionImpact()); | 106 return processMetadata(const ResolutionImpact()); |
122 } else if (element.isTypedef) { | 107 } else if (element.isTypedef) { |
123 TypedefElement typdef = element; | 108 TypedefElement typdef = element; |
124 return processMetadata(resolveTypedef(typdef)); | 109 return processMetadata(resolveTypedef(typdef)); |
125 } | 110 } |
126 | 111 |
127 compiler.unimplemented(element, "resolve($element)"); | 112 compiler.unimplemented(element, "resolve($element)"); |
128 }); | 113 }); |
129 } | 114 } |
130 | 115 |
131 void resolveRedirectingConstructor(InitializerResolver resolver, | 116 void resolveRedirectingConstructor(InitializerResolver resolver, Node node, |
132 Node node, | 117 FunctionElement constructor, FunctionElement redirection) { |
133 FunctionElement constructor, | |
134 FunctionElement redirection) { | |
135 assert(invariant(node, constructor.isImplementation, | 118 assert(invariant(node, constructor.isImplementation, |
136 message: 'Redirecting constructors must be resolved on implementation ' | 119 message: 'Redirecting constructors must be resolved on implementation ' |
137 'elements.')); | 120 'elements.')); |
138 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 121 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); |
139 seen.add(constructor); | 122 seen.add(constructor); |
140 while (redirection != null) { | 123 while (redirection != null) { |
141 // Ensure that we follow redirections through implementation elements. | 124 // Ensure that we follow redirections through implementation elements. |
142 redirection = redirection.implementation; | 125 redirection = redirection.implementation; |
143 if (redirection.isError) { | 126 if (redirection.isError) { |
144 break; | 127 break; |
145 } | 128 } |
146 if (seen.contains(redirection)) { | 129 if (seen.contains(redirection)) { |
147 reporter.reportErrorMessage( | 130 reporter.reportErrorMessage( |
148 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 131 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
149 return; | 132 return; |
150 } | 133 } |
151 seen.add(redirection); | 134 seen.add(redirection); |
152 redirection = resolver.visitor.resolveConstructorRedirection(redirection); | 135 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
153 } | 136 } |
154 } | 137 } |
155 | 138 |
156 static void processAsyncMarker(Compiler compiler, | 139 static void processAsyncMarker(Compiler compiler, |
157 BaseFunctionElementX element, | 140 BaseFunctionElementX element, ResolutionRegistry registry) { |
158 ResolutionRegistry registry) { | |
159 DiagnosticReporter reporter = compiler.reporter; | 141 DiagnosticReporter reporter = compiler.reporter; |
160 Resolution resolution = compiler.resolution; | 142 Resolution resolution = compiler.resolution; |
161 CoreClasses coreClasses = compiler.coreClasses; | 143 CoreClasses coreClasses = compiler.coreClasses; |
162 FunctionExpression functionExpression = element.node; | 144 FunctionExpression functionExpression = element.node; |
163 AsyncModifier asyncModifier = functionExpression.asyncModifier; | 145 AsyncModifier asyncModifier = functionExpression.asyncModifier; |
164 if (asyncModifier != null) { | 146 if (asyncModifier != null) { |
165 | |
166 if (asyncModifier.isAsynchronous) { | 147 if (asyncModifier.isAsynchronous) { |
167 element.asyncMarker = asyncModifier.isYielding | 148 element.asyncMarker = asyncModifier.isYielding |
168 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; | 149 ? AsyncMarker.ASYNC_STAR |
| 150 : AsyncMarker.ASYNC; |
169 } else { | 151 } else { |
170 element.asyncMarker = AsyncMarker.SYNC_STAR; | 152 element.asyncMarker = AsyncMarker.SYNC_STAR; |
171 } | 153 } |
172 if (element.isAbstract) { | 154 if (element.isAbstract) { |
173 reporter.reportErrorMessage( | 155 reporter.reportErrorMessage( |
174 asyncModifier, | 156 asyncModifier, |
175 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, | 157 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, |
176 {'modifier': element.asyncMarker}); | 158 {'modifier': element.asyncMarker}); |
177 } else if (element.isConstructor) { | 159 } else if (element.isConstructor) { |
178 reporter.reportErrorMessage( | 160 reporter.reportErrorMessage( |
179 asyncModifier, | 161 asyncModifier, |
180 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, | 162 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, |
181 {'modifier': element.asyncMarker}); | 163 {'modifier': element.asyncMarker}); |
182 } else { | 164 } else { |
183 if (element.isSetter) { | 165 if (element.isSetter) { |
184 reporter.reportErrorMessage( | 166 reporter.reportErrorMessage( |
185 asyncModifier, | 167 asyncModifier, |
186 MessageKind.ASYNC_MODIFIER_ON_SETTER, | 168 MessageKind.ASYNC_MODIFIER_ON_SETTER, |
187 {'modifier': element.asyncMarker}); | 169 {'modifier': element.asyncMarker}); |
188 | |
189 } | 170 } |
190 if (functionExpression.body.asReturn() != null && | 171 if (functionExpression.body.asReturn() != null && |
191 element.asyncMarker.isYielding) { | 172 element.asyncMarker.isYielding) { |
192 reporter.reportErrorMessage( | 173 reporter.reportErrorMessage( |
193 asyncModifier, | 174 asyncModifier, |
194 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, | 175 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, |
195 {'modifier': element.asyncMarker}); | 176 {'modifier': element.asyncMarker}); |
196 } | 177 } |
197 } | 178 } |
198 switch (element.asyncMarker) { | 179 switch (element.asyncMarker) { |
199 case AsyncMarker.ASYNC: | 180 case AsyncMarker.ASYNC: |
200 registry.registerFeature(Feature.ASYNC); | 181 registry.registerFeature(Feature.ASYNC); |
201 coreClasses.futureClass.ensureResolved(resolution); | 182 coreClasses.futureClass.ensureResolved(resolution); |
202 break; | 183 break; |
203 case AsyncMarker.ASYNC_STAR: | 184 case AsyncMarker.ASYNC_STAR: |
204 registry.registerFeature(Feature.ASYNC_STAR); | 185 registry.registerFeature(Feature.ASYNC_STAR); |
205 coreClasses.streamClass.ensureResolved(resolution); | 186 coreClasses.streamClass.ensureResolved(resolution); |
206 break; | 187 break; |
207 case AsyncMarker.SYNC_STAR: | 188 case AsyncMarker.SYNC_STAR: |
208 registry.registerFeature(Feature.SYNC_STAR); | 189 registry.registerFeature(Feature.SYNC_STAR); |
209 coreClasses.iterableClass.ensureResolved(resolution); | 190 coreClasses.iterableClass.ensureResolved(resolution); |
210 break; | 191 break; |
211 } | 192 } |
212 } | 193 } |
213 } | 194 } |
214 | 195 |
215 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { | 196 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { |
216 assert(classElement != null); | 197 assert(classElement != null); |
217 while (classElement != null) { | 198 while (classElement != null) { |
218 if (compiler.backend.isNative(classElement)) return true; | 199 if (compiler.backend.isNative(classElement)) return true; |
219 classElement = classElement.superclass; | 200 classElement = classElement.superclass; |
220 } | 201 } |
221 return false; | 202 return false; |
222 } | 203 } |
223 | 204 |
224 WorldImpact resolveMethodElementImplementation( | 205 WorldImpact resolveMethodElementImplementation( |
225 FunctionElement element, FunctionExpression tree) { | 206 FunctionElement element, FunctionExpression tree) { |
226 return reporter.withCurrentElement(element, () { | 207 return reporter.withCurrentElement(element, () { |
227 if (element.isExternal && tree.hasBody) { | 208 if (element.isExternal && tree.hasBody) { |
228 reporter.reportErrorMessage( | 209 reporter.reportErrorMessage(element, MessageKind.EXTERNAL_WITH_BODY, |
229 element, | |
230 MessageKind.EXTERNAL_WITH_BODY, | |
231 {'functionName': element.name}); | 210 {'functionName': element.name}); |
232 } | 211 } |
233 if (element.isConstructor) { | 212 if (element.isConstructor) { |
234 if (tree.returnType != null) { | 213 if (tree.returnType != null) { |
235 reporter.reportErrorMessage( | 214 reporter.reportErrorMessage( |
236 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 215 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
237 } | 216 } |
238 if (tree.hasBody && element.isConst) { | 217 if (tree.hasBody && element.isConst) { |
239 if (element.isGenerativeConstructor) { | 218 if (element.isGenerativeConstructor) { |
240 reporter.reportErrorMessage( | 219 reporter.reportErrorMessage( |
241 tree, MessageKind.CONST_CONSTRUCTOR_WITH_BODY); | 220 tree, MessageKind.CONST_CONSTRUCTOR_WITH_BODY); |
242 } else if (!tree.isRedirectingFactory) { | 221 } else if (!tree.isRedirectingFactory) { |
243 reporter.reportErrorMessage( | 222 reporter.reportErrorMessage(tree, MessageKind.CONST_FACTORY); |
244 tree, MessageKind.CONST_FACTORY); | |
245 } | 223 } |
246 } | 224 } |
247 } | 225 } |
248 | 226 |
249 ResolverVisitor visitor = visitorFor(element); | 227 ResolverVisitor visitor = visitorFor(element); |
250 ResolutionRegistry registry = visitor.registry; | 228 ResolutionRegistry registry = visitor.registry; |
251 registry.defineFunction(tree, element); | 229 registry.defineFunction(tree, element); |
252 visitor.setupFunction(tree, element); | 230 visitor.setupFunction(tree, element); |
253 processAsyncMarker(compiler, element, registry); | 231 processAsyncMarker(compiler, element, registry); |
254 | 232 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 for (MixinApplicationElement mixinApplication in mixinUses) { | 266 for (MixinApplicationElement mixinApplication in mixinUses) { |
289 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); | 267 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); |
290 } | 268 } |
291 } | 269 } |
292 | 270 |
293 // TODO(9631): support noSuchMethod on native classes. | 271 // TODO(9631): support noSuchMethod on native classes. |
294 if (element.isFunction && | 272 if (element.isFunction && |
295 element.isInstanceMember && | 273 element.isInstanceMember && |
296 element.name == Identifiers.noSuchMethod_ && | 274 element.name == Identifiers.noSuchMethod_ && |
297 _isNativeClassOrExtendsNativeClass(enclosingClass)) { | 275 _isNativeClassOrExtendsNativeClass(enclosingClass)) { |
298 reporter.reportErrorMessage( | 276 reporter.reportErrorMessage(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); |
299 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); | |
300 } | 277 } |
301 | 278 |
302 return registry.worldImpact; | 279 return registry.worldImpact; |
303 }); | 280 }); |
304 | |
305 } | 281 } |
306 | 282 |
307 WorldImpact resolveMethodElement(FunctionElementX element) { | 283 WorldImpact resolveMethodElement(FunctionElementX element) { |
308 assert(invariant(element, element.isDeclaration)); | 284 assert(invariant(element, element.isDeclaration)); |
309 return reporter.withCurrentElement(element, () { | 285 return reporter.withCurrentElement(element, () { |
310 if (compiler.enqueuer.resolution.hasBeenProcessed(element)) { | 286 if (compiler.enqueuer.resolution.hasBeenProcessed(element)) { |
311 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] | 287 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] |
312 // should never be non-null, not even for constructors. | 288 // should never be non-null, not even for constructors. |
313 assert(invariant(element, element.isConstructor, | 289 assert(invariant(element, element.isConstructor, |
314 message: 'Non-constructor element $element ' | 290 message: 'Non-constructor element $element ' |
315 'has already been analyzed.')); | 291 'has already been analyzed.')); |
316 return const ResolutionImpact(); | 292 return const ResolutionImpact(); |
317 } | 293 } |
318 if (element.isSynthesized) { | 294 if (element.isSynthesized) { |
319 if (element.isGenerativeConstructor) { | 295 if (element.isGenerativeConstructor) { |
320 ResolutionRegistry registry = | 296 ResolutionRegistry registry = |
321 new ResolutionRegistry(compiler, _ensureTreeElements(element)); | 297 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
322 ConstructorElement constructor = element.asFunctionElement(); | 298 ConstructorElement constructor = element.asFunctionElement(); |
323 ConstructorElement target = constructor.definingConstructor; | 299 ConstructorElement target = constructor.definingConstructor; |
324 // Ensure the signature of the synthesized element is | 300 // Ensure the signature of the synthesized element is |
325 // resolved. This is the only place where the resolver is | 301 // resolved. This is the only place where the resolver is |
326 // seeing this element. | 302 // seeing this element. |
327 element.computeType(resolution); | 303 element.computeType(resolution); |
328 if (!target.isMalformed) { | 304 if (!target.isMalformed) { |
329 registry.registerStaticUse( | 305 registry.registerStaticUse(new StaticUse.superConstructorInvoke( |
330 new StaticUse.superConstructorInvoke( | 306 target, CallStructure.NO_ARGS)); |
331 target, CallStructure.NO_ARGS)); | |
332 } | 307 } |
333 return registry.worldImpact; | 308 return registry.worldImpact; |
334 } else { | 309 } else { |
335 assert(element.isDeferredLoaderGetter || element.isMalformed); | 310 assert(element.isDeferredLoaderGetter || element.isMalformed); |
336 _ensureTreeElements(element); | 311 _ensureTreeElements(element); |
337 return const ResolutionImpact(); | 312 return const ResolutionImpact(); |
338 } | 313 } |
339 } else { | 314 } else { |
340 element.parseNode(resolution.parsing); | 315 element.parseNode(resolution.parsing); |
341 element.computeType(resolution); | 316 element.computeType(resolution); |
(...skipping 14 matching lines...) Expand all Loading... |
356 /// This method should only be used by this library (or tests of | 331 /// This method should only be used by this library (or tests of |
357 /// this library). | 332 /// this library). |
358 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { | 333 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { |
359 return new ResolverVisitor(compiler, element, | 334 return new ResolverVisitor(compiler, element, |
360 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 335 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
361 useEnclosingScope: useEnclosingScope); | 336 useEnclosingScope: useEnclosingScope); |
362 } | 337 } |
363 | 338 |
364 WorldImpact resolveField(FieldElementX element) { | 339 WorldImpact resolveField(FieldElementX element) { |
365 VariableDefinitions tree = element.parseNode(parsing); | 340 VariableDefinitions tree = element.parseNode(parsing); |
366 if(element.modifiers.isStatic && element.isTopLevel) { | 341 if (element.modifiers.isStatic && element.isTopLevel) { |
367 reporter.reportErrorMessage( | 342 reporter.reportErrorMessage(element.modifiers.getStatic(), |
368 element.modifiers.getStatic(), | |
369 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 343 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
370 } | 344 } |
371 ResolverVisitor visitor = visitorFor(element); | 345 ResolverVisitor visitor = visitorFor(element); |
372 ResolutionRegistry registry = visitor.registry; | 346 ResolutionRegistry registry = visitor.registry; |
373 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 347 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
374 // to the backend ast. | 348 // to the backend ast. |
375 registry.defineElement(tree.definitions.nodes.head, element); | 349 registry.defineElement(tree.definitions.nodes.head, element); |
376 // TODO(johnniwinther): Share the resolved type between all variables | 350 // TODO(johnniwinther): Share the resolved type between all variables |
377 // declared in the same declaration. | 351 // declared in the same declaration. |
378 if (tree.type != null) { | 352 if (tree.type != null) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 | 391 |
418 // Perform various checks as side effect of "computing" the type. | 392 // Perform various checks as side effect of "computing" the type. |
419 element.computeType(resolution); | 393 element.computeType(resolution); |
420 | 394 |
421 return registry.worldImpact; | 395 return registry.worldImpact; |
422 } | 396 } |
423 | 397 |
424 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 398 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { |
425 DartType type = resolveReturnType(element, annotation); | 399 DartType type = resolveReturnType(element, annotation); |
426 if (type.isVoid) { | 400 if (type.isVoid) { |
427 reporter.reportErrorMessage( | 401 reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); |
428 annotation, MessageKind.VOID_NOT_ALLOWED); | |
429 } | 402 } |
430 return type; | 403 return type; |
431 } | 404 } |
432 | 405 |
433 DartType resolveReturnType(Element element, TypeAnnotation annotation) { | 406 DartType resolveReturnType(Element element, TypeAnnotation annotation) { |
434 if (annotation == null) return const DynamicType(); | 407 if (annotation == null) return const DynamicType(); |
435 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 408 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); |
436 if (result == null) { | 409 if (result == null) { |
437 // TODO(karklose): warning. | 410 // TODO(karklose): warning. |
438 return const DynamicType(); | 411 return const DynamicType(); |
439 } | 412 } |
440 return result; | 413 return result; |
441 } | 414 } |
442 | 415 |
443 void resolveRedirectionChain(ConstructorElementX constructor, | 416 void resolveRedirectionChain( |
444 Spannable node) { | 417 ConstructorElementX constructor, Spannable node) { |
445 ConstructorElementX target = constructor; | 418 ConstructorElementX target = constructor; |
446 InterfaceType targetType; | 419 InterfaceType targetType; |
447 List<Element> seen = new List<Element>(); | 420 List<Element> seen = new List<Element>(); |
448 bool isMalformed = false; | 421 bool isMalformed = false; |
449 // Follow the chain of redirections and check for cycles. | 422 // Follow the chain of redirections and check for cycles. |
450 while (target.isRedirectingFactory || target.isPatched) { | 423 while (target.isRedirectingFactory || target.isPatched) { |
451 if (target.effectiveTargetInternal != null) { | 424 if (target.effectiveTargetInternal != null) { |
452 // We found a constructor that already has been processed. | 425 // We found a constructor that already has been processed. |
453 targetType = target.effectiveTargetType; | 426 targetType = target.effectiveTargetType; |
454 assert(invariant(target, targetType != null, | 427 assert(invariant(target, targetType != null, |
455 message: 'Redirection target type has not been computed for ' | 428 message: 'Redirection target type has not been computed for ' |
456 '$target')); | 429 '$target')); |
457 target = target.effectiveTargetInternal; | 430 target = target.effectiveTargetInternal; |
458 break; | 431 break; |
459 } | 432 } |
460 | 433 |
461 Element nextTarget; | 434 Element nextTarget; |
462 if (target.isPatched) { | 435 if (target.isPatched) { |
463 nextTarget = target.patch; | 436 nextTarget = target.patch; |
464 } else { | 437 } else { |
465 nextTarget = target.immediateRedirectionTarget; | 438 nextTarget = target.immediateRedirectionTarget; |
466 } | 439 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 * Load and resolve the supertypes of [cls]. | 487 * Load and resolve the supertypes of [cls]. |
515 * | 488 * |
516 * Warning: do not call this method directly. It should only be | 489 * Warning: do not call this method directly. It should only be |
517 * called by [resolveClass] and [ClassSupertypeResolver]. | 490 * called by [resolveClass] and [ClassSupertypeResolver]. |
518 */ | 491 */ |
519 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 492 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
520 measure(() { | 493 measure(() { |
521 if (cls.supertypeLoadState == STATE_DONE) return; | 494 if (cls.supertypeLoadState == STATE_DONE) return; |
522 if (cls.supertypeLoadState == STATE_STARTED) { | 495 if (cls.supertypeLoadState == STATE_STARTED) { |
523 reporter.reportErrorMessage( | 496 reporter.reportErrorMessage( |
524 from, | 497 from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); |
525 MessageKind.CYCLIC_CLASS_HIERARCHY, | |
526 {'className': cls.name}); | |
527 cls.supertypeLoadState = STATE_DONE; | 498 cls.supertypeLoadState = STATE_DONE; |
528 cls.hasIncompleteHierarchy = true; | 499 cls.hasIncompleteHierarchy = true; |
529 cls.allSupertypesAndSelf = | 500 cls.allSupertypesAndSelf = coreClasses.objectClass.allSupertypesAndSelf |
530 coreClasses.objectClass.allSupertypesAndSelf.extendClass( | 501 .extendClass(cls.computeType(resolution)); |
531 cls.computeType(resolution)); | |
532 cls.supertype = cls.allSupertypes.head; | 502 cls.supertype = cls.allSupertypes.head; |
533 assert(invariant(from, cls.supertype != null, | 503 assert(invariant(from, cls.supertype != null, |
534 message: 'Missing supertype on cyclic class $cls.')); | 504 message: 'Missing supertype on cyclic class $cls.')); |
535 cls.interfaces = const Link<DartType>(); | 505 cls.interfaces = const Link<DartType>(); |
536 return; | 506 return; |
537 } | 507 } |
538 cls.supertypeLoadState = STATE_STARTED; | 508 cls.supertypeLoadState = STATE_STARTED; |
539 reporter.withCurrentElement(cls, () { | 509 reporter.withCurrentElement(cls, () { |
540 // TODO(ahe): Cache the node in cls. | 510 // TODO(ahe): Cache the node in cls. |
541 cls.parseNode(parsing).accept( | 511 cls |
542 new ClassSupertypeResolver(compiler, cls)); | 512 .parseNode(parsing) |
| 513 .accept(new ClassSupertypeResolver(compiler, cls)); |
543 if (cls.supertypeLoadState != STATE_DONE) { | 514 if (cls.supertypeLoadState != STATE_DONE) { |
544 cls.supertypeLoadState = STATE_DONE; | 515 cls.supertypeLoadState = STATE_DONE; |
545 } | 516 } |
546 }); | 517 }); |
547 }); | 518 }); |
548 } | 519 } |
549 | 520 |
550 // TODO(johnniwinther): Remove this queue when resolution has been split into | 521 // TODO(johnniwinther): Remove this queue when resolution has been split into |
551 // syntax and semantic resolution. | 522 // syntax and semantic resolution. |
552 TypeDeclarationElement currentlyResolvedTypeDeclaration; | 523 TypeDeclarationElement currentlyResolvedTypeDeclaration; |
553 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); | 524 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); |
554 Queue<ClassElement> pendingClassesToBePostProcessed = | 525 Queue<ClassElement> pendingClassesToBePostProcessed = |
555 new Queue<ClassElement>(); | 526 new Queue<ClassElement>(); |
556 | 527 |
557 /// Resolve [element] using [resolveTypeDeclaration]. | 528 /// Resolve [element] using [resolveTypeDeclaration]. |
558 /// | 529 /// |
559 /// This methods ensure that class declarations encountered through type | 530 /// This methods ensure that class declarations encountered through type |
560 /// annotations during the resolution of [element] are resolved after | 531 /// annotations during the resolution of [element] are resolved after |
561 /// [element] has been resolved. | 532 /// [element] has been resolved. |
562 // TODO(johnniwinther): Encapsulate this functionality in a | 533 // TODO(johnniwinther): Encapsulate this functionality in a |
563 // 'TypeDeclarationResolver'. | 534 // 'TypeDeclarationResolver'. |
564 _resolveTypeDeclaration(TypeDeclarationElement element, | 535 _resolveTypeDeclaration( |
565 resolveTypeDeclaration()) { | 536 TypeDeclarationElement element, resolveTypeDeclaration()) { |
566 return reporter.withCurrentElement(element, () { | 537 return reporter.withCurrentElement(element, () { |
567 return measure(() { | 538 return measure(() { |
568 TypeDeclarationElement previousResolvedTypeDeclaration = | 539 TypeDeclarationElement previousResolvedTypeDeclaration = |
569 currentlyResolvedTypeDeclaration; | 540 currentlyResolvedTypeDeclaration; |
570 currentlyResolvedTypeDeclaration = element; | 541 currentlyResolvedTypeDeclaration = element; |
571 var result = resolveTypeDeclaration(); | 542 var result = resolveTypeDeclaration(); |
572 if (previousResolvedTypeDeclaration == null) { | 543 if (previousResolvedTypeDeclaration == null) { |
573 do { | 544 do { |
574 while (!pendingClassesToBeResolved.isEmpty) { | 545 while (!pendingClassesToBeResolved.isEmpty) { |
575 pendingClassesToBeResolved.removeFirst() | 546 pendingClassesToBeResolved |
| 547 .removeFirst() |
576 .ensureResolved(resolution); | 548 .ensureResolved(resolution); |
577 } | 549 } |
578 while (!pendingClassesToBePostProcessed.isEmpty) { | 550 while (!pendingClassesToBePostProcessed.isEmpty) { |
579 _postProcessClassElement( | 551 _postProcessClassElement( |
580 pendingClassesToBePostProcessed.removeFirst()); | 552 pendingClassesToBePostProcessed.removeFirst()); |
581 } | 553 } |
582 } while (!pendingClassesToBeResolved.isEmpty); | 554 } while (!pendingClassesToBeResolved.isEmpty); |
583 assert(pendingClassesToBeResolved.isEmpty); | 555 assert(pendingClassesToBeResolved.isEmpty); |
584 assert(pendingClassesToBePostProcessed.isEmpty); | 556 assert(pendingClassesToBePostProcessed.isEmpty); |
585 } | 557 } |
(...skipping 25 matching lines...) Expand all Loading... |
611 } | 583 } |
612 | 584 |
613 void ensureClassWillBeResolvedInternal(ClassElement element) { | 585 void ensureClassWillBeResolvedInternal(ClassElement element) { |
614 if (currentlyResolvedTypeDeclaration == null) { | 586 if (currentlyResolvedTypeDeclaration == null) { |
615 element.ensureResolved(resolution); | 587 element.ensureResolved(resolution); |
616 } else { | 588 } else { |
617 pendingClassesToBeResolved.add(element); | 589 pendingClassesToBeResolved.add(element); |
618 } | 590 } |
619 } | 591 } |
620 | 592 |
621 void resolveClassInternal(BaseClassElementX element, | 593 void resolveClassInternal( |
622 ResolutionRegistry registry) { | 594 BaseClassElementX element, ResolutionRegistry registry) { |
623 if (!element.isPatch) { | 595 if (!element.isPatch) { |
624 reporter.withCurrentElement(element, () => measure(() { | 596 reporter.withCurrentElement( |
625 assert(element.resolutionState == STATE_NOT_STARTED); | 597 element, |
626 element.resolutionState = STATE_STARTED; | 598 () => measure(() { |
627 Node tree = element.parseNode(parsing); | 599 assert(element.resolutionState == STATE_NOT_STARTED); |
628 loadSupertypes(element, tree); | 600 element.resolutionState = STATE_STARTED; |
| 601 Node tree = element.parseNode(parsing); |
| 602 loadSupertypes(element, tree); |
629 | 603 |
630 ClassResolverVisitor visitor = | 604 ClassResolverVisitor visitor = |
631 new ClassResolverVisitor(compiler, element, registry); | 605 new ClassResolverVisitor(compiler, element, registry); |
632 visitor.visit(tree); | 606 visitor.visit(tree); |
633 element.resolutionState = STATE_DONE; | 607 element.resolutionState = STATE_DONE; |
634 compiler.onClassResolved(element); | 608 compiler.onClassResolved(element); |
635 pendingClassesToBePostProcessed.add(element); | 609 pendingClassesToBePostProcessed.add(element); |
636 })); | 610 })); |
637 if (element.isPatched) { | 611 if (element.isPatched) { |
638 // Ensure handling patch after origin. | 612 // Ensure handling patch after origin. |
639 element.patch.ensureResolved(resolution); | 613 element.patch.ensureResolved(resolution); |
640 } | 614 } |
641 } else { // Handle patch classes: | 615 } else { |
| 616 // Handle patch classes: |
642 element.resolutionState = STATE_STARTED; | 617 element.resolutionState = STATE_STARTED; |
643 // Ensure handling origin before patch. | 618 // Ensure handling origin before patch. |
644 element.origin.ensureResolved(resolution); | 619 element.origin.ensureResolved(resolution); |
645 // Ensure that the type is computed. | 620 // Ensure that the type is computed. |
646 element.computeType(resolution); | 621 element.computeType(resolution); |
647 // Copy class hierarchy from origin. | 622 // Copy class hierarchy from origin. |
648 element.supertype = element.origin.supertype; | 623 element.supertype = element.origin.supertype; |
649 element.interfaces = element.origin.interfaces; | 624 element.interfaces = element.origin.interfaces; |
650 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; | 625 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; |
651 // Stepwise assignment to ensure invariant. | 626 // Stepwise assignment to ensure invariant. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 | 690 |
716 // In case of cyclic mixin applications, the mixin chain will have | 691 // In case of cyclic mixin applications, the mixin chain will have |
717 // been cut. If so, we have already reported the error to the | 692 // been cut. If so, we have already reported the error to the |
718 // user so we just return from here. | 693 // user so we just return from here. |
719 ClassElement mixin = mixinApplication.mixin; | 694 ClassElement mixin = mixinApplication.mixin; |
720 if (mixin == null) return; | 695 if (mixin == null) return; |
721 | 696 |
722 // Check that we're not trying to use Object as a mixin. | 697 // Check that we're not trying to use Object as a mixin. |
723 if (mixin.superclass == null) { | 698 if (mixin.superclass == null) { |
724 reporter.reportErrorMessage( | 699 reporter.reportErrorMessage( |
725 mixinApplication, | 700 mixinApplication, MessageKind.ILLEGAL_MIXIN_OBJECT); |
726 MessageKind.ILLEGAL_MIXIN_OBJECT); | |
727 // Avoid reporting additional errors for the Object class. | 701 // Avoid reporting additional errors for the Object class. |
728 return; | 702 return; |
729 } | 703 } |
730 | 704 |
731 if (mixin.isEnumClass) { | 705 if (mixin.isEnumClass) { |
732 // Mixing in an enum has already caused a compile-time error. | 706 // Mixing in an enum has already caused a compile-time error. |
733 return; | 707 return; |
734 } | 708 } |
735 | 709 |
736 // Check that the mixed in class has Object as its superclass. | 710 // Check that the mixed in class has Object as its superclass. |
737 if (!mixin.superclass.isObject) { | 711 if (!mixin.superclass.isObject) { |
738 reporter.reportErrorMessage( | 712 reporter.reportErrorMessage(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); |
739 mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); | |
740 } | 713 } |
741 | 714 |
742 // Check that the mixed in class doesn't have any constructors and | 715 // Check that the mixed in class doesn't have any constructors and |
743 // make sure we aren't mixing in methods that use 'super'. | 716 // make sure we aren't mixing in methods that use 'super'. |
744 mixin.forEachLocalMember((AstElement member) { | 717 mixin.forEachLocalMember((AstElement member) { |
745 if (member.isGenerativeConstructor && !member.isSynthesized) { | 718 if (member.isGenerativeConstructor && !member.isSynthesized) { |
746 reporter.reportErrorMessage( | 719 reporter.reportErrorMessage( |
747 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); | 720 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); |
748 } else { | 721 } else { |
749 // Get the resolution tree and check that the resolved member | 722 // Get the resolution tree and check that the resolved member |
750 // doesn't use 'super'. This is the part of the 'super' mixin | 723 // doesn't use 'super'. This is the part of the 'super' mixin |
751 // check that happens when a function is resolved before the | 724 // check that happens when a function is resolved before the |
752 // mixin application has been performed. | 725 // mixin application has been performed. |
753 // TODO(johnniwinther): Obtain the [TreeElements] for [member] | 726 // TODO(johnniwinther): Obtain the [TreeElements] for [member] |
754 // differently. | 727 // differently. |
755 if (compiler.enqueuer.resolution.hasBeenProcessed(member)) { | 728 if (compiler.enqueuer.resolution.hasBeenProcessed(member)) { |
756 checkMixinSuperUses( | 729 checkMixinSuperUses( |
757 member.resolvedAst.elements, | 730 member.resolvedAst.elements, mixinApplication, mixin); |
758 mixinApplication, | |
759 mixin); | |
760 } | 731 } |
761 } | 732 } |
762 }); | 733 }); |
763 } | 734 } |
764 | 735 |
765 void checkMixinSuperUses(TreeElements resolutionTree, | 736 void checkMixinSuperUses(TreeElements resolutionTree, |
766 MixinApplicationElement mixinApplication, | 737 MixinApplicationElement mixinApplication, ClassElement mixin) { |
767 ClassElement mixin) { | |
768 // TODO(johnniwinther): Avoid the use of [TreeElements] here. | 738 // TODO(johnniwinther): Avoid the use of [TreeElements] here. |
769 if (resolutionTree == null) return; | 739 if (resolutionTree == null) return; |
770 Iterable<SourceSpan> superUses = resolutionTree.superUses; | 740 Iterable<SourceSpan> superUses = resolutionTree.superUses; |
771 if (superUses.isEmpty) return; | 741 if (superUses.isEmpty) return; |
772 DiagnosticMessage error = reporter.createMessage( | 742 DiagnosticMessage error = reporter.createMessage(mixinApplication, |
773 mixinApplication, | 743 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, {'className': mixin.name}); |
774 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, | |
775 {'className': mixin.name}); | |
776 // Show the user the problematic uses of 'super' in the mixin. | 744 // Show the user the problematic uses of 'super' in the mixin. |
777 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 745 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
778 for (SourceSpan use in superUses) { | 746 for (SourceSpan use in superUses) { |
779 infos.add(reporter.createMessage( | 747 infos.add( |
780 use, | 748 reporter.createMessage(use, MessageKind.ILLEGAL_MIXIN_SUPER_USE)); |
781 MessageKind.ILLEGAL_MIXIN_SUPER_USE)); | |
782 } | 749 } |
783 reporter.reportError(error, infos); | 750 reporter.reportError(error, infos); |
784 } | 751 } |
785 | 752 |
786 void checkClassMembers(ClassElement cls) { | 753 void checkClassMembers(ClassElement cls) { |
787 assert(invariant(cls, cls.isDeclaration)); | 754 assert(invariant(cls, cls.isDeclaration)); |
788 if (cls.isObject) return; | 755 if (cls.isObject) return; |
789 // TODO(johnniwinther): Should this be done on the implementation element as | 756 // TODO(johnniwinther): Should this be done on the implementation element as |
790 // well? | 757 // well? |
791 List<Element> constConstructors = <Element>[]; | 758 List<Element> constConstructors = <Element>[]; |
792 List<Element> nonFinalInstanceFields = <Element>[]; | 759 List<Element> nonFinalInstanceFields = <Element>[]; |
793 cls.forEachMember((holder, member) { | 760 cls.forEachMember((holder, member) { |
794 reporter.withCurrentElement(member, () { | 761 reporter.withCurrentElement(member, () { |
795 // Perform various checks as side effect of "computing" the type. | 762 // Perform various checks as side effect of "computing" the type. |
796 member.computeType(resolution); | 763 member.computeType(resolution); |
797 | 764 |
798 // Check modifiers. | 765 // Check modifiers. |
799 if (member.isFunction && member.modifiers.isFinal) { | 766 if (member.isFunction && member.modifiers.isFinal) { |
800 reporter.reportErrorMessage( | 767 reporter.reportErrorMessage( |
801 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 768 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
802 } | 769 } |
803 if (member.isConstructor) { | 770 if (member.isConstructor) { |
804 final mismatchedFlagsBits = | 771 final mismatchedFlagsBits = member.modifiers.flags & |
805 member.modifiers.flags & | |
806 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 772 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
807 if (mismatchedFlagsBits != 0) { | 773 if (mismatchedFlagsBits != 0) { |
808 final mismatchedFlags = | 774 final mismatchedFlags = |
809 new Modifiers.withFlags(null, mismatchedFlagsBits); | 775 new Modifiers.withFlags(null, mismatchedFlagsBits); |
810 reporter.reportErrorMessage( | 776 reporter.reportErrorMessage( |
811 member, | 777 member, |
812 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 778 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
813 {'modifiers': mismatchedFlags}); | 779 {'modifiers': mismatchedFlags}); |
814 } | 780 } |
815 if (member.modifiers.isConst) { | 781 if (member.modifiers.isConst) { |
816 constConstructors.add(member); | 782 constConstructors.add(member); |
817 } | 783 } |
818 } | 784 } |
819 if (member.isField) { | 785 if (member.isField) { |
820 if (member.modifiers.isConst && !member.modifiers.isStatic) { | 786 if (member.modifiers.isConst && !member.modifiers.isStatic) { |
821 reporter.reportErrorMessage( | 787 reporter.reportErrorMessage( |
822 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); | 788 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); |
823 } | 789 } |
824 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { | 790 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { |
825 nonFinalInstanceFields.add(member); | 791 nonFinalInstanceFields.add(member); |
826 } | 792 } |
827 } | 793 } |
828 checkAbstractField(member); | 794 checkAbstractField(member); |
829 checkUserDefinableOperator(member); | 795 checkUserDefinableOperator(member); |
830 }); | 796 }); |
831 }); | 797 }); |
832 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { | 798 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { |
833 Spannable span = constConstructors.length > 1 | 799 Spannable span = |
834 ? cls : constConstructors[0]; | 800 constConstructors.length > 1 ? cls : constConstructors[0]; |
835 DiagnosticMessage error = reporter.createMessage( | 801 DiagnosticMessage error = reporter.createMessage( |
836 span, | 802 span, |
837 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, | 803 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, |
838 {'className': cls.name}); | 804 {'className': cls.name}); |
839 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 805 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
840 if (constConstructors.length > 1) { | 806 if (constConstructors.length > 1) { |
841 for (Element constructor in constConstructors) { | 807 for (Element constructor in constConstructors) { |
842 infos.add(reporter.createMessage( | 808 infos.add(reporter.createMessage(constructor, |
843 constructor, | |
844 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); | 809 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); |
845 } | 810 } |
846 } | 811 } |
847 for (Element field in nonFinalInstanceFields) { | 812 for (Element field in nonFinalInstanceFields) { |
848 infos.add(reporter.createMessage( | 813 infos.add(reporter.createMessage( |
849 field, | 814 field, MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); |
850 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); | |
851 } | 815 } |
852 reporter.reportError(error, infos); | 816 reporter.reportError(error, infos); |
853 } | 817 } |
854 } | 818 } |
855 | 819 |
856 void checkAbstractField(Element member) { | 820 void checkAbstractField(Element member) { |
857 // Only check for getters. The test can only fail if there is both a setter | 821 // Only check for getters. The test can only fail if there is both a setter |
858 // and a getter with the same name, and we only need to check each abstract | 822 // and a getter with the same name, and we only need to check each abstract |
859 // field once, so we just ignore setters. | 823 // field once, so we just ignore setters. |
860 if (!member.isGetter) return; | 824 if (!member.isGetter) return; |
861 | 825 |
862 // Find the associated abstract field. | 826 // Find the associated abstract field. |
863 ClassElement classElement = member.enclosingClass; | 827 ClassElement classElement = member.enclosingClass; |
864 Element lookupElement = classElement.lookupLocalMember(member.name); | 828 Element lookupElement = classElement.lookupLocalMember(member.name); |
865 if (lookupElement == null) { | 829 if (lookupElement == null) { |
866 reporter.internalError(member, | 830 reporter.internalError(member, "No abstract field for accessor"); |
867 "No abstract field for accessor"); | |
868 } else if (!lookupElement.isAbstractField) { | 831 } else if (!lookupElement.isAbstractField) { |
869 if (lookupElement.isMalformed || lookupElement.isAmbiguous) return; | 832 if (lookupElement.isMalformed || lookupElement.isAmbiguous) return; |
870 reporter.internalError(member, | 833 reporter.internalError( |
871 "Inaccessible abstract field for accessor"); | 834 member, "Inaccessible abstract field for accessor"); |
872 } | 835 } |
873 AbstractFieldElement field = lookupElement; | 836 AbstractFieldElement field = lookupElement; |
874 | 837 |
875 GetterElementX getter = field.getter; | 838 GetterElementX getter = field.getter; |
876 if (getter == null) return; | 839 if (getter == null) return; |
877 SetterElementX setter = field.setter; | 840 SetterElementX setter = field.setter; |
878 if (setter == null) return; | 841 if (setter == null) return; |
879 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 842 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
880 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 843 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
881 if (getterFlags != setterFlags) { | 844 if (getterFlags != setterFlags) { |
882 final mismatchedFlags = | 845 final mismatchedFlags = |
883 new Modifiers.withFlags(null, getterFlags ^ setterFlags); | 846 new Modifiers.withFlags(null, getterFlags ^ setterFlags); |
884 reporter.reportWarningMessage( | 847 reporter.reportWarningMessage(field.getter, MessageKind.GETTER_MISMATCH, |
885 field.getter, | |
886 MessageKind.GETTER_MISMATCH, | |
887 {'modifiers': mismatchedFlags}); | 848 {'modifiers': mismatchedFlags}); |
888 reporter.reportWarningMessage( | 849 reporter.reportWarningMessage(field.setter, MessageKind.SETTER_MISMATCH, |
889 field.setter, | |
890 MessageKind.SETTER_MISMATCH, | |
891 {'modifiers': mismatchedFlags}); | 850 {'modifiers': mismatchedFlags}); |
892 } | 851 } |
893 } | 852 } |
894 | 853 |
895 void checkUserDefinableOperator(Element member) { | 854 void checkUserDefinableOperator(Element member) { |
896 FunctionElement function = member.asFunctionElement(); | 855 FunctionElement function = member.asFunctionElement(); |
897 if (function == null) return; | 856 if (function == null) return; |
898 String value = member.name; | 857 String value = member.name; |
899 if (value == null) return; | 858 if (value == null) return; |
900 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return; | 859 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return; |
(...skipping 13 matching lines...) Expand all Loading... |
914 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; | 873 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; |
915 requiredParameterCount = 0; | 874 requiredParameterCount = 0; |
916 } else if (isBinaryOperator(value)) { | 875 } else if (isBinaryOperator(value)) { |
917 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; | 876 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; |
918 requiredParameterCount = 1; | 877 requiredParameterCount = 1; |
919 if (identical(value, '==')) checkOverrideHashCode(member); | 878 if (identical(value, '==')) checkOverrideHashCode(member); |
920 } else if (isTernaryOperator(value)) { | 879 } else if (isTernaryOperator(value)) { |
921 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; | 880 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; |
922 requiredParameterCount = 2; | 881 requiredParameterCount = 2; |
923 } else { | 882 } else { |
924 reporter.internalError(function, | 883 reporter.internalError( |
925 'Unexpected user defined operator $value'); | 884 function, 'Unexpected user defined operator $value'); |
926 } | 885 } |
927 checkArity(function, requiredParameterCount, messageKind, isMinus); | 886 checkArity(function, requiredParameterCount, messageKind, isMinus); |
928 } | 887 } |
929 | 888 |
930 void checkOverrideHashCode(FunctionElement operatorEquals) { | 889 void checkOverrideHashCode(FunctionElement operatorEquals) { |
931 if (operatorEquals.isAbstract) return; | 890 if (operatorEquals.isAbstract) return; |
932 ClassElement cls = operatorEquals.enclosingClass; | 891 ClassElement cls = operatorEquals.enclosingClass; |
933 Element hashCodeImplementation = | 892 Element hashCodeImplementation = cls.lookupLocalMember('hashCode'); |
934 cls.lookupLocalMember('hashCode'); | |
935 if (hashCodeImplementation != null) return; | 893 if (hashCodeImplementation != null) return; |
936 reporter.reportHintMessage( | 894 reporter.reportHintMessage(operatorEquals, |
937 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, | 895 MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, {'class': cls.name}); |
938 {'class': cls.name}); | |
939 } | 896 } |
940 | 897 |
941 void checkArity(FunctionElement function, | 898 void checkArity(FunctionElement function, int requiredParameterCount, |
942 int requiredParameterCount, MessageKind messageKind, | 899 MessageKind messageKind, bool isMinus) { |
943 bool isMinus) { | |
944 FunctionExpression node = function.node; | 900 FunctionExpression node = function.node; |
945 FunctionSignature signature = function.functionSignature; | 901 FunctionSignature signature = function.functionSignature; |
946 if (signature.requiredParameterCount != requiredParameterCount) { | 902 if (signature.requiredParameterCount != requiredParameterCount) { |
947 Node errorNode = node; | 903 Node errorNode = node; |
948 if (node.parameters != null) { | 904 if (node.parameters != null) { |
949 if (isMinus || | 905 if (isMinus || |
950 signature.requiredParameterCount < requiredParameterCount) { | 906 signature.requiredParameterCount < requiredParameterCount) { |
951 // If there are too few parameters, point to the whole parameter list. | 907 // If there are too few parameters, point to the whole parameter list. |
952 // For instance | 908 // For instance |
953 // | 909 // |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 {'operatorName': function.name}); | 943 {'operatorName': function.name}); |
988 } else { | 944 } else { |
989 reporter.reportErrorMessage( | 945 reporter.reportErrorMessage( |
990 errorNode, | 946 errorNode, |
991 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, | 947 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, |
992 {'operatorName': function.name}); | 948 {'operatorName': function.name}); |
993 } | 949 } |
994 } | 950 } |
995 } | 951 } |
996 | 952 |
997 reportErrorWithContext(Element errorneousElement, | 953 reportErrorWithContext(Element errorneousElement, MessageKind errorMessage, |
998 MessageKind errorMessage, | 954 Element contextElement, MessageKind contextMessage) { |
999 Element contextElement, | |
1000 MessageKind contextMessage) { | |
1001 reporter.reportError( | 955 reporter.reportError( |
1002 reporter.createMessage( | 956 reporter.createMessage(errorneousElement, errorMessage, { |
1003 errorneousElement, | 957 'memberName': contextElement.name, |
1004 errorMessage, | 958 'className': contextElement.enclosingClass.name |
1005 {'memberName': contextElement.name, | 959 }), |
1006 'className': contextElement.enclosingClass.name}), | |
1007 <DiagnosticMessage>[ | 960 <DiagnosticMessage>[ |
1008 reporter.createMessage(contextElement, contextMessage), | 961 reporter.createMessage(contextElement, contextMessage), |
1009 ]); | 962 ]); |
1010 } | 963 } |
1011 | 964 |
1012 | |
1013 FunctionSignature resolveSignature(FunctionElementX element) { | 965 FunctionSignature resolveSignature(FunctionElementX element) { |
1014 MessageKind defaultValuesError = null; | 966 MessageKind defaultValuesError = null; |
1015 if (element.isFactoryConstructor) { | 967 if (element.isFactoryConstructor) { |
1016 FunctionExpression body = element.parseNode(parsing); | 968 FunctionExpression body = element.parseNode(parsing); |
1017 if (body.isRedirectingFactory) { | 969 if (body.isRedirectingFactory) { |
1018 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; | 970 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; |
1019 } | 971 } |
1020 } | 972 } |
1021 return reporter.withCurrentElement(element, () { | 973 return reporter.withCurrentElement(element, () { |
1022 FunctionExpression node = element.parseNode(parsing); | 974 FunctionExpression node = element.parseNode(parsing); |
1023 return measure(() => SignatureResolver.analyze( | 975 return measure(() => SignatureResolver.analyze( |
1024 compiler, node.parameters, node.returnType, element, | 976 compiler, |
| 977 node.parameters, |
| 978 node.returnType, |
| 979 element, |
1025 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 980 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
1026 defaultValuesError: defaultValuesError, | 981 defaultValuesError: defaultValuesError, |
1027 createRealParameters: true)); | 982 createRealParameters: true)); |
1028 }); | 983 }); |
1029 } | 984 } |
1030 | 985 |
1031 WorldImpact resolveTypedef(TypedefElementX element) { | 986 WorldImpact resolveTypedef(TypedefElementX element) { |
1032 if (element.isResolved) return const ResolutionImpact(); | 987 if (element.isResolved) return const ResolutionImpact(); |
1033 compiler.world.allTypedefs.add(element); | 988 compiler.world.allTypedefs.add(element); |
1034 return _resolveTypeDeclaration(element, () { | 989 return _resolveTypeDeclaration(element, () { |
1035 ResolutionRegistry registry = new ResolutionRegistry( | 990 ResolutionRegistry registry = |
1036 compiler, _ensureTreeElements(element)); | 991 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
1037 return reporter.withCurrentElement(element, () { | 992 return reporter.withCurrentElement(element, () { |
1038 return measure(() { | 993 return measure(() { |
1039 assert(element.resolutionState == STATE_NOT_STARTED); | 994 assert(element.resolutionState == STATE_NOT_STARTED); |
1040 element.resolutionState = STATE_STARTED; | 995 element.resolutionState = STATE_STARTED; |
1041 Typedef node = element.parseNode(parsing); | 996 Typedef node = element.parseNode(parsing); |
1042 TypedefResolverVisitor visitor = | 997 TypedefResolverVisitor visitor = |
1043 new TypedefResolverVisitor(compiler, element, registry); | 998 new TypedefResolverVisitor(compiler, element, registry); |
1044 visitor.visit(node); | 999 visitor.visit(node); |
1045 element.resolutionState = STATE_DONE; | 1000 element.resolutionState = STATE_DONE; |
1046 return registry.worldImpact; | 1001 return registry.worldImpact; |
1047 }); | 1002 }); |
1048 }); | 1003 }); |
1049 }); | 1004 }); |
1050 } | 1005 } |
1051 | 1006 |
1052 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { | 1007 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { |
1053 reporter.withCurrentElement(annotation.annotatedElement, () => measure(() { | 1008 reporter.withCurrentElement( |
1054 assert(annotation.resolutionState == STATE_NOT_STARTED); | 1009 annotation.annotatedElement, |
1055 annotation.resolutionState = STATE_STARTED; | 1010 () => measure(() { |
| 1011 assert(annotation.resolutionState == STATE_NOT_STARTED); |
| 1012 annotation.resolutionState = STATE_STARTED; |
1056 | 1013 |
1057 Node node = annotation.parseNode(parsing); | 1014 Node node = annotation.parseNode(parsing); |
1058 Element annotatedElement = annotation.annotatedElement; | 1015 Element annotatedElement = annotation.annotatedElement; |
1059 AnalyzableElement context = annotatedElement.analyzableElement; | 1016 AnalyzableElement context = annotatedElement.analyzableElement; |
1060 ClassElement classElement = annotatedElement.enclosingClass; | 1017 ClassElement classElement = annotatedElement.enclosingClass; |
1061 if (classElement != null) { | 1018 if (classElement != null) { |
1062 // The annotation is resolved in the scope of [classElement]. | 1019 // The annotation is resolved in the scope of [classElement]. |
1063 classElement.ensureResolved(resolution); | 1020 classElement.ensureResolved(resolution); |
1064 } | 1021 } |
1065 assert(invariant(node, context != null, | 1022 assert(invariant(node, context != null, |
1066 message: "No context found for metadata annotation " | 1023 message: "No context found for metadata annotation " |
1067 "on $annotatedElement.")); | 1024 "on $annotatedElement.")); |
1068 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); | 1025 ResolverVisitor visitor = |
1069 ResolutionRegistry registry = visitor.registry; | 1026 visitorFor(context, useEnclosingScope: true); |
1070 node.accept(visitor); | 1027 ResolutionRegistry registry = visitor.registry; |
1071 // TODO(johnniwinther): Avoid passing the [TreeElements] to | 1028 node.accept(visitor); |
1072 // [compileMetadata]. | 1029 // TODO(johnniwinther): Avoid passing the [TreeElements] to |
1073 ConstantExpression constant = constantCompiler.compileMetadata( | 1030 // [compileMetadata]. |
1074 annotation, node, registry.mapping); | 1031 ConstantExpression constant = constantCompiler.compileMetadata( |
1075 switch (constant.kind) { | 1032 annotation, node, registry.mapping); |
1076 case ConstantExpressionKind.CONSTRUCTED: | 1033 switch (constant.kind) { |
1077 ConstructedConstantExpression constructedConstant = constant; | 1034 case ConstantExpressionKind.CONSTRUCTED: |
1078 if (constructedConstant.type.isGeneric) { | 1035 ConstructedConstantExpression constructedConstant = constant; |
1079 // Const constructor calls cannot have type arguments. | 1036 if (constructedConstant.type.isGeneric) { |
1080 // TODO(24312): Remove this. | 1037 // Const constructor calls cannot have type arguments. |
1081 reporter.reportErrorMessage( | 1038 // TODO(24312): Remove this. |
1082 node, MessageKind.INVALID_METADATA_GENERIC); | 1039 reporter.reportErrorMessage( |
1083 constant = new ErroneousConstantExpression(); | 1040 node, MessageKind.INVALID_METADATA_GENERIC); |
1084 } | 1041 constant = new ErroneousConstantExpression(); |
1085 break; | 1042 } |
1086 case ConstantExpressionKind.VARIABLE: | 1043 break; |
1087 case ConstantExpressionKind.ERRONEOUS: | 1044 case ConstantExpressionKind.VARIABLE: |
1088 break; | 1045 case ConstantExpressionKind.ERRONEOUS: |
1089 default: | 1046 break; |
1090 reporter.reportErrorMessage(node, MessageKind.INVALID_METADATA); | 1047 default: |
1091 constant = new ErroneousConstantExpression(); | 1048 reporter.reportErrorMessage( |
1092 break; | 1049 node, MessageKind.INVALID_METADATA); |
1093 } | 1050 constant = new ErroneousConstantExpression(); |
1094 annotation.constant = constant; | 1051 break; |
| 1052 } |
| 1053 annotation.constant = constant; |
1095 | 1054 |
1096 constantCompiler.evaluate(annotation.constant); | 1055 constantCompiler.evaluate(annotation.constant); |
1097 // TODO(johnniwinther): Register the relation between the annotation | 1056 // TODO(johnniwinther): Register the relation between the annotati
on |
1098 // and the annotated element instead. This will allow the backend to | 1057 // and the annotated element instead. This will allow the backend
to |
1099 // retrieve the backend constant and only register metadata on the | 1058 // retrieve the backend constant and only register metadata on the |
1100 // elements for which it is needed. (Issue 17732). | 1059 // elements for which it is needed. (Issue 17732). |
1101 registry.registerMetadataConstant(annotation); | 1060 registry.registerMetadataConstant(annotation); |
1102 annotation.resolutionState = STATE_DONE; | 1061 annotation.resolutionState = STATE_DONE; |
1103 })); | 1062 })); |
1104 } | 1063 } |
1105 | 1064 |
1106 List<MetadataAnnotation> resolveMetadata(Element element, | 1065 List<MetadataAnnotation> resolveMetadata( |
1107 VariableDefinitions node) { | 1066 Element element, VariableDefinitions node) { |
1108 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; | 1067 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; |
1109 for (Metadata annotation in node.metadata.nodes) { | 1068 for (Metadata annotation in node.metadata.nodes) { |
1110 ParameterMetadataAnnotation metadataAnnotation = | 1069 ParameterMetadataAnnotation metadataAnnotation = |
1111 new ParameterMetadataAnnotation(annotation); | 1070 new ParameterMetadataAnnotation(annotation); |
1112 metadataAnnotation.annotatedElement = element; | 1071 metadataAnnotation.annotatedElement = element; |
1113 metadata.add(metadataAnnotation.ensureResolved(resolution)); | 1072 metadata.add(metadataAnnotation.ensureResolved(resolution)); |
1114 } | 1073 } |
1115 return metadata; | 1074 return metadata; |
1116 } | 1075 } |
1117 } | 1076 } |
1118 | 1077 |
1119 TreeElements _ensureTreeElements(AnalyzableElementX element) { | 1078 TreeElements _ensureTreeElements(AnalyzableElementX element) { |
1120 if (element._treeElements == null) { | 1079 if (element._treeElements == null) { |
1121 element._treeElements = new TreeElementMapping(element); | 1080 element._treeElements = new TreeElementMapping(element); |
1122 } | 1081 } |
1123 return element._treeElements; | 1082 return element._treeElements; |
1124 } | 1083 } |
1125 | 1084 |
1126 abstract class AnalyzableElementX implements AnalyzableElement { | 1085 abstract class AnalyzableElementX implements AnalyzableElement { |
1127 TreeElements _treeElements; | 1086 TreeElements _treeElements; |
1128 | 1087 |
1129 bool get hasTreeElements => _treeElements != null; | 1088 bool get hasTreeElements => _treeElements != null; |
1130 | 1089 |
1131 TreeElements get treeElements { | 1090 TreeElements get treeElements { |
1132 assert(invariant(this, _treeElements !=null, | 1091 assert(invariant(this, _treeElements != null, |
1133 message: "TreeElements have not been computed for $this.")); | 1092 message: "TreeElements have not been computed for $this.")); |
1134 return _treeElements; | 1093 return _treeElements; |
1135 } | 1094 } |
1136 | 1095 |
1137 void reuseElement() { | 1096 void reuseElement() { |
1138 _treeElements = null; | 1097 _treeElements = null; |
1139 } | 1098 } |
1140 } | 1099 } |
OLD | NEW |