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/names.dart' show | 9 import '../common/names.dart' show |
10 Identifiers; | 10 Identifiers; |
11 import '../common/tasks.dart' show | 11 import '../common/tasks.dart' show |
12 CompilerTask, | 12 CompilerTask, |
13 DeferredAction; | 13 DeferredAction; |
14 import '../compiler.dart' show | 14 import '../compiler.dart' show |
15 Compiler; | 15 Compiler; |
16 import '../compile_time_constants.dart' show | 16 import '../compile_time_constants.dart' show |
17 ConstantCompiler; | 17 ConstantCompiler; |
18 import '../constants/values.dart' show | 18 import '../constants/values.dart' show |
19 ConstantValue; | 19 ConstantValue; |
20 import '../dart_types.dart'; | 20 import '../dart_types.dart'; |
| 21 import '../diagnostics/diagnostic_listener.dart' show |
| 22 DiagnosticMessage; |
21 import '../diagnostics/invariant.dart' show | 23 import '../diagnostics/invariant.dart' show |
22 invariant; | 24 invariant; |
23 import '../diagnostics/messages.dart' show | 25 import '../diagnostics/messages.dart' show |
24 MessageKind; | 26 MessageKind; |
25 import '../diagnostics/spannable.dart' show | 27 import '../diagnostics/spannable.dart' show |
26 Spannable; | 28 Spannable; |
27 import '../elements/elements.dart'; | 29 import '../elements/elements.dart'; |
28 import '../elements/modelx.dart' show | 30 import '../elements/modelx.dart' show |
29 BaseClassElementX, | 31 BaseClassElementX, |
30 BaseFunctionElementX, | 32 BaseFunctionElementX, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 FunctionElement redirection) { | 116 FunctionElement redirection) { |
115 assert(invariant(node, constructor.isImplementation, | 117 assert(invariant(node, constructor.isImplementation, |
116 message: 'Redirecting constructors must be resolved on implementation ' | 118 message: 'Redirecting constructors must be resolved on implementation ' |
117 'elements.')); | 119 'elements.')); |
118 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 120 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); |
119 seen.add(constructor); | 121 seen.add(constructor); |
120 while (redirection != null) { | 122 while (redirection != null) { |
121 // Ensure that we follow redirections through implementation elements. | 123 // Ensure that we follow redirections through implementation elements. |
122 redirection = redirection.implementation; | 124 redirection = redirection.implementation; |
123 if (seen.contains(redirection)) { | 125 if (seen.contains(redirection)) { |
124 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 126 compiler.reportErrorMessage( |
| 127 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
125 return; | 128 return; |
126 } | 129 } |
127 seen.add(redirection); | 130 seen.add(redirection); |
128 redirection = resolver.visitor.resolveConstructorRedirection(redirection); | 131 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
129 } | 132 } |
130 } | 133 } |
131 | 134 |
132 static void processAsyncMarker(Compiler compiler, | 135 static void processAsyncMarker(Compiler compiler, |
133 BaseFunctionElementX element, | 136 BaseFunctionElementX element, |
134 ResolutionRegistry registry) { | 137 ResolutionRegistry registry) { |
135 FunctionExpression functionExpression = element.node; | 138 FunctionExpression functionExpression = element.node; |
136 AsyncModifier asyncModifier = functionExpression.asyncModifier; | 139 AsyncModifier asyncModifier = functionExpression.asyncModifier; |
137 if (asyncModifier != null) { | 140 if (asyncModifier != null) { |
138 | 141 |
139 if (asyncModifier.isAsynchronous) { | 142 if (asyncModifier.isAsynchronous) { |
140 element.asyncMarker = asyncModifier.isYielding | 143 element.asyncMarker = asyncModifier.isYielding |
141 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; | 144 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; |
142 } else { | 145 } else { |
143 element.asyncMarker = AsyncMarker.SYNC_STAR; | 146 element.asyncMarker = AsyncMarker.SYNC_STAR; |
144 } | 147 } |
145 if (element.isAbstract) { | 148 if (element.isAbstract) { |
146 compiler.reportError(asyncModifier, | 149 compiler.reportErrorMessage( |
| 150 asyncModifier, |
147 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, | 151 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, |
148 {'modifier': element.asyncMarker}); | 152 {'modifier': element.asyncMarker}); |
149 } else if (element.isConstructor) { | 153 } else if (element.isConstructor) { |
150 compiler.reportError(asyncModifier, | 154 compiler.reportErrorMessage( |
| 155 asyncModifier, |
151 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, | 156 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, |
152 {'modifier': element.asyncMarker}); | 157 {'modifier': element.asyncMarker}); |
153 } else { | 158 } else { |
154 if (element.isSetter) { | 159 if (element.isSetter) { |
155 compiler.reportError(asyncModifier, | 160 compiler.reportErrorMessage( |
| 161 asyncModifier, |
156 MessageKind.ASYNC_MODIFIER_ON_SETTER, | 162 MessageKind.ASYNC_MODIFIER_ON_SETTER, |
157 {'modifier': element.asyncMarker}); | 163 {'modifier': element.asyncMarker}); |
158 | 164 |
159 } | 165 } |
160 if (functionExpression.body.asReturn() != null && | 166 if (functionExpression.body.asReturn() != null && |
161 element.asyncMarker.isYielding) { | 167 element.asyncMarker.isYielding) { |
162 compiler.reportError(asyncModifier, | 168 compiler.reportErrorMessage( |
| 169 asyncModifier, |
163 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, | 170 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, |
164 {'modifier': element.asyncMarker}); | 171 {'modifier': element.asyncMarker}); |
165 } | 172 } |
166 } | 173 } |
167 registry.registerAsyncMarker(element); | 174 registry.registerAsyncMarker(element); |
168 switch (element.asyncMarker) { | 175 switch (element.asyncMarker) { |
169 case AsyncMarker.ASYNC: | 176 case AsyncMarker.ASYNC: |
170 compiler.futureClass.ensureResolved(compiler); | 177 compiler.futureClass.ensureResolved(compiler); |
171 break; | 178 break; |
172 case AsyncMarker.ASYNC_STAR: | 179 case AsyncMarker.ASYNC_STAR: |
(...skipping 12 matching lines...) Expand all Loading... |
185 if (classElement.isNative) return true; | 192 if (classElement.isNative) return true; |
186 classElement = classElement.superclass; | 193 classElement = classElement.superclass; |
187 } | 194 } |
188 return false; | 195 return false; |
189 } | 196 } |
190 | 197 |
191 WorldImpact resolveMethodElementImplementation( | 198 WorldImpact resolveMethodElementImplementation( |
192 FunctionElement element, FunctionExpression tree) { | 199 FunctionElement element, FunctionExpression tree) { |
193 return compiler.withCurrentElement(element, () { | 200 return compiler.withCurrentElement(element, () { |
194 if (element.isExternal && tree.hasBody()) { | 201 if (element.isExternal && tree.hasBody()) { |
195 error(element, | 202 compiler.reportErrorMessage( |
| 203 element, |
196 MessageKind.EXTERNAL_WITH_BODY, | 204 MessageKind.EXTERNAL_WITH_BODY, |
197 {'functionName': element.name}); | 205 {'functionName': element.name}); |
198 } | 206 } |
199 if (element.isConstructor) { | 207 if (element.isConstructor) { |
200 if (tree.returnType != null) { | 208 if (tree.returnType != null) { |
201 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 209 compiler.reportErrorMessage( |
| 210 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
202 } | 211 } |
203 if (element.isConst && | 212 if (element.isConst && |
204 tree.hasBody() && | 213 tree.hasBody() && |
205 !tree.isRedirectingFactory) { | 214 !tree.isRedirectingFactory) { |
206 error(tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY); | 215 compiler.reportErrorMessage( |
| 216 tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY); |
207 } | 217 } |
208 } | 218 } |
209 | 219 |
210 ResolverVisitor visitor = visitorFor(element); | 220 ResolverVisitor visitor = visitorFor(element); |
211 ResolutionRegistry registry = visitor.registry; | 221 ResolutionRegistry registry = visitor.registry; |
212 registry.defineFunction(tree, element); | 222 registry.defineFunction(tree, element); |
213 visitor.setupFunction(tree, element); | 223 visitor.setupFunction(tree, element); |
214 processAsyncMarker(compiler, element, registry); | 224 processAsyncMarker(compiler, element, registry); |
215 | 225 |
216 if (element.isGenerativeConstructor) { | 226 if (element.isGenerativeConstructor) { |
217 // Even if there is no initializer list we still have to do the | 227 // Even if there is no initializer list we still have to do the |
218 // resolution in case there is an implicit super constructor call. | 228 // resolution in case there is an implicit super constructor call. |
219 InitializerResolver resolver = | 229 InitializerResolver resolver = |
220 new InitializerResolver(visitor, element, tree); | 230 new InitializerResolver(visitor, element, tree); |
221 FunctionElement redirection = resolver.resolveInitializers(); | 231 FunctionElement redirection = resolver.resolveInitializers(); |
222 if (redirection != null) { | 232 if (redirection != null) { |
223 resolveRedirectingConstructor(resolver, tree, element, redirection); | 233 resolveRedirectingConstructor(resolver, tree, element, redirection); |
224 } | 234 } |
225 } else if (tree.initializers != null) { | 235 } else if (tree.initializers != null) { |
226 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); | 236 compiler.reportErrorMessage( |
| 237 tree, MessageKind.FUNCTION_WITH_INITIALIZER); |
227 } | 238 } |
228 | 239 |
229 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { | 240 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { |
230 // We need to analyze the redirecting factory bodies to ensure that | 241 // We need to analyze the redirecting factory bodies to ensure that |
231 // we can analyze compile-time constants. | 242 // we can analyze compile-time constants. |
232 visitor.visit(tree.body); | 243 visitor.visit(tree.body); |
233 } | 244 } |
234 | 245 |
235 // Get the resolution tree and check that the resolved | 246 // Get the resolution tree and check that the resolved |
236 // function doesn't use 'super' if it is mixed into another | 247 // function doesn't use 'super' if it is mixed into another |
237 // class. This is the part of the 'super' mixin check that | 248 // class. This is the part of the 'super' mixin check that |
238 // happens when a function is resolved after the mixin | 249 // happens when a function is resolved after the mixin |
239 // application has been performed. | 250 // application has been performed. |
240 TreeElements resolutionTree = registry.mapping; | 251 TreeElements resolutionTree = registry.mapping; |
241 ClassElement enclosingClass = element.enclosingClass; | 252 ClassElement enclosingClass = element.enclosingClass; |
242 if (enclosingClass != null) { | 253 if (enclosingClass != null) { |
243 // TODO(johnniwinther): Find another way to obtain mixin uses. | 254 // TODO(johnniwinther): Find another way to obtain mixin uses. |
244 Iterable<MixinApplicationElement> mixinUses = | 255 Iterable<MixinApplicationElement> mixinUses = |
245 compiler.world.allMixinUsesOf(enclosingClass); | 256 compiler.world.allMixinUsesOf(enclosingClass); |
246 ClassElement mixin = enclosingClass; | 257 ClassElement mixin = enclosingClass; |
247 for (MixinApplicationElement mixinApplication in mixinUses) { | 258 for (MixinApplicationElement mixinApplication in mixinUses) { |
248 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); | 259 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); |
249 } | 260 } |
250 } | 261 } |
251 | 262 |
252 // TODO(9631): support noSuchMethod on native classes. | 263 // TODO(9631): support noSuchMethod on native classes. |
253 if (Elements.isInstanceMethod(element) && | 264 if (Elements.isInstanceMethod(element) && |
254 element.name == Identifiers.noSuchMethod_ && | 265 element.name == Identifiers.noSuchMethod_ && |
255 _isNativeClassOrExtendsNativeClass(enclosingClass)) { | 266 _isNativeClassOrExtendsNativeClass(enclosingClass)) { |
256 error(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); | 267 compiler.reportErrorMessage( |
| 268 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); |
257 } | 269 } |
258 | 270 |
259 return registry.worldImpact; | 271 return registry.worldImpact; |
260 }); | 272 }); |
261 | 273 |
262 } | 274 } |
263 | 275 |
264 WorldImpact resolveMethodElement(FunctionElementX element) { | 276 WorldImpact resolveMethodElement(FunctionElementX element) { |
265 assert(invariant(element, element.isDeclaration)); | 277 assert(invariant(element, element.isDeclaration)); |
266 return compiler.withCurrentElement(element, () { | 278 return compiler.withCurrentElement(element, () { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 /// this library). | 325 /// this library). |
314 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { | 326 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { |
315 return new ResolverVisitor(compiler, element, | 327 return new ResolverVisitor(compiler, element, |
316 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 328 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
317 useEnclosingScope: useEnclosingScope); | 329 useEnclosingScope: useEnclosingScope); |
318 } | 330 } |
319 | 331 |
320 WorldImpact resolveField(FieldElementX element) { | 332 WorldImpact resolveField(FieldElementX element) { |
321 VariableDefinitions tree = element.parseNode(compiler); | 333 VariableDefinitions tree = element.parseNode(compiler); |
322 if(element.modifiers.isStatic && element.isTopLevel) { | 334 if(element.modifiers.isStatic && element.isTopLevel) { |
323 error(element.modifiers.getStatic(), | 335 compiler.reportErrorMessage( |
324 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 336 element.modifiers.getStatic(), |
| 337 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
325 } | 338 } |
326 ResolverVisitor visitor = visitorFor(element); | 339 ResolverVisitor visitor = visitorFor(element); |
327 ResolutionRegistry registry = visitor.registry; | 340 ResolutionRegistry registry = visitor.registry; |
328 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 341 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
329 // to the backend ast. | 342 // to the backend ast. |
330 registry.defineElement(tree.definitions.nodes.head, element); | 343 registry.defineElement(tree.definitions.nodes.head, element); |
331 // TODO(johnniwinther): Share the resolved type between all variables | 344 // TODO(johnniwinther): Share the resolved type between all variables |
332 // declared in the same declaration. | 345 // declared in the same declaration. |
333 if (tree.type != null) { | 346 if (tree.type != null) { |
334 element.variables.type = visitor.resolveTypeAnnotation(tree.type); | 347 element.variables.type = visitor.resolveTypeAnnotation(tree.type); |
335 } else { | 348 } else { |
336 element.variables.type = const DynamicType(); | 349 element.variables.type = const DynamicType(); |
337 } | 350 } |
338 | 351 |
339 Expression initializer = element.initializer; | 352 Expression initializer = element.initializer; |
340 Modifiers modifiers = element.modifiers; | 353 Modifiers modifiers = element.modifiers; |
341 if (initializer != null) { | 354 if (initializer != null) { |
342 // TODO(johnniwinther): Avoid analyzing initializers if | 355 // TODO(johnniwinther): Avoid analyzing initializers if |
343 // [Compiler.analyzeSignaturesOnly] is set. | 356 // [Compiler.analyzeSignaturesOnly] is set. |
344 visitor.visit(initializer); | 357 visitor.visit(initializer); |
345 } else if (modifiers.isConst) { | 358 } else if (modifiers.isConst) { |
346 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); | 359 compiler.reportErrorMessage( |
| 360 element, MessageKind.CONST_WITHOUT_INITIALIZER); |
347 } else if (modifiers.isFinal && !element.isInstanceMember) { | 361 } else if (modifiers.isFinal && !element.isInstanceMember) { |
348 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); | 362 compiler.reportErrorMessage( |
| 363 element, MessageKind.FINAL_WITHOUT_INITIALIZER); |
349 } else { | 364 } else { |
350 registry.registerInstantiatedClass(compiler.nullClass); | 365 registry.registerInstantiatedClass(compiler.nullClass); |
351 } | 366 } |
352 | 367 |
353 if (Elements.isStaticOrTopLevelField(element)) { | 368 if (Elements.isStaticOrTopLevelField(element)) { |
354 visitor.addDeferredAction(element, () { | 369 visitor.addDeferredAction(element, () { |
355 if (element.modifiers.isConst) { | 370 if (element.modifiers.isConst) { |
356 element.constant = constantCompiler.compileConstant(element); | 371 element.constant = constantCompiler.compileConstant(element); |
357 } else { | 372 } else { |
358 constantCompiler.compileVariable(element); | 373 constantCompiler.compileVariable(element); |
(...skipping 10 matching lines...) Expand all Loading... |
369 | 384 |
370 // Perform various checks as side effect of "computing" the type. | 385 // Perform various checks as side effect of "computing" the type. |
371 element.computeType(compiler); | 386 element.computeType(compiler); |
372 | 387 |
373 return registry.worldImpact; | 388 return registry.worldImpact; |
374 } | 389 } |
375 | 390 |
376 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 391 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { |
377 DartType type = resolveReturnType(element, annotation); | 392 DartType type = resolveReturnType(element, annotation); |
378 if (type.isVoid) { | 393 if (type.isVoid) { |
379 error(annotation, MessageKind.VOID_NOT_ALLOWED); | 394 compiler.reportErrorMessage( |
| 395 annotation, MessageKind.VOID_NOT_ALLOWED); |
380 } | 396 } |
381 return type; | 397 return type; |
382 } | 398 } |
383 | 399 |
384 DartType resolveReturnType(Element element, TypeAnnotation annotation) { | 400 DartType resolveReturnType(Element element, TypeAnnotation annotation) { |
385 if (annotation == null) return const DynamicType(); | 401 if (annotation == null) return const DynamicType(); |
386 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 402 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); |
387 if (result == null) { | 403 if (result == null) { |
388 // TODO(karklose): warning. | 404 // TODO(karklose): warning. |
389 return const DynamicType(); | 405 return const DynamicType(); |
(...skipping 13 matching lines...) Expand all Loading... |
403 targetType = target.effectiveTargetType; | 419 targetType = target.effectiveTargetType; |
404 assert(invariant(target, targetType != null, | 420 assert(invariant(target, targetType != null, |
405 message: 'Redirection target type has not been computed for ' | 421 message: 'Redirection target type has not been computed for ' |
406 '$target')); | 422 '$target')); |
407 target = target.internalEffectiveTarget; | 423 target = target.internalEffectiveTarget; |
408 break; | 424 break; |
409 } | 425 } |
410 | 426 |
411 Element nextTarget = target.immediateRedirectionTarget; | 427 Element nextTarget = target.immediateRedirectionTarget; |
412 if (seen.contains(nextTarget)) { | 428 if (seen.contains(nextTarget)) { |
413 error(node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 429 compiler.reportErrorMessage( |
| 430 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); |
414 targetType = target.enclosingClass.thisType; | 431 targetType = target.enclosingClass.thisType; |
415 break; | 432 break; |
416 } | 433 } |
417 seen.add(target); | 434 seen.add(target); |
418 target = nextTarget; | 435 target = nextTarget; |
419 } | 436 } |
420 | 437 |
421 if (targetType == null) { | 438 if (targetType == null) { |
422 assert(!target.isRedirectingFactory); | 439 assert(!target.isRedirectingFactory); |
423 targetType = target.enclosingClass.thisType; | 440 targetType = target.enclosingClass.thisType; |
(...skipping 28 matching lines...) Expand all Loading... |
452 /** | 469 /** |
453 * Load and resolve the supertypes of [cls]. | 470 * Load and resolve the supertypes of [cls]. |
454 * | 471 * |
455 * Warning: do not call this method directly. It should only be | 472 * Warning: do not call this method directly. It should only be |
456 * called by [resolveClass] and [ClassSupertypeResolver]. | 473 * called by [resolveClass] and [ClassSupertypeResolver]. |
457 */ | 474 */ |
458 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 475 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
459 compiler.withCurrentElement(cls, () => measure(() { | 476 compiler.withCurrentElement(cls, () => measure(() { |
460 if (cls.supertypeLoadState == STATE_DONE) return; | 477 if (cls.supertypeLoadState == STATE_DONE) return; |
461 if (cls.supertypeLoadState == STATE_STARTED) { | 478 if (cls.supertypeLoadState == STATE_STARTED) { |
462 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY, | 479 compiler.reportErrorMessage( |
463 {'className': cls.name}); | 480 from, |
| 481 MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 482 {'className': cls.name}); |
464 cls.supertypeLoadState = STATE_DONE; | 483 cls.supertypeLoadState = STATE_DONE; |
465 cls.hasIncompleteHierarchy = true; | 484 cls.hasIncompleteHierarchy = true; |
466 cls.allSupertypesAndSelf = | 485 cls.allSupertypesAndSelf = |
467 compiler.objectClass.allSupertypesAndSelf.extendClass( | 486 compiler.objectClass.allSupertypesAndSelf.extendClass( |
468 cls.computeType(compiler)); | 487 cls.computeType(compiler)); |
469 cls.supertype = cls.allSupertypes.head; | 488 cls.supertype = cls.allSupertypes.head; |
470 assert(invariant(from, cls.supertype != null, | 489 assert(invariant(from, cls.supertype != null, |
471 message: 'Missing supertype on cyclic class $cls.')); | 490 message: 'Missing supertype on cyclic class $cls.')); |
472 cls.interfaces = const Link<DartType>(); | 491 cls.interfaces = const Link<DartType>(); |
473 return; | 492 return; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 } else { | 655 } else { |
637 checkClassMembers(element); | 656 checkClassMembers(element); |
638 } | 657 } |
639 } | 658 } |
640 | 659 |
641 void checkMixinApplication(MixinApplicationElementX mixinApplication) { | 660 void checkMixinApplication(MixinApplicationElementX mixinApplication) { |
642 Modifiers modifiers = mixinApplication.modifiers; | 661 Modifiers modifiers = mixinApplication.modifiers; |
643 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; | 662 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; |
644 if (illegalFlags != 0) { | 663 if (illegalFlags != 0) { |
645 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); | 664 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); |
646 compiler.reportError( | 665 compiler.reportErrorMessage( |
647 modifiers, | 666 modifiers, |
648 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, | 667 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, |
649 {'modifiers': illegalModifiers}); | 668 {'modifiers': illegalModifiers}); |
650 } | 669 } |
651 | 670 |
652 // In case of cyclic mixin applications, the mixin chain will have | 671 // In case of cyclic mixin applications, the mixin chain will have |
653 // been cut. If so, we have already reported the error to the | 672 // been cut. If so, we have already reported the error to the |
654 // user so we just return from here. | 673 // user so we just return from here. |
655 ClassElement mixin = mixinApplication.mixin; | 674 ClassElement mixin = mixinApplication.mixin; |
656 if (mixin == null) return; | 675 if (mixin == null) return; |
657 | 676 |
658 // Check that we're not trying to use Object as a mixin. | 677 // Check that we're not trying to use Object as a mixin. |
659 if (mixin.superclass == null) { | 678 if (mixin.superclass == null) { |
660 compiler.reportError(mixinApplication, | 679 compiler.reportErrorMessage( |
661 MessageKind.ILLEGAL_MIXIN_OBJECT); | 680 mixinApplication, |
| 681 MessageKind.ILLEGAL_MIXIN_OBJECT); |
662 // Avoid reporting additional errors for the Object class. | 682 // Avoid reporting additional errors for the Object class. |
663 return; | 683 return; |
664 } | 684 } |
665 | 685 |
666 if (mixin.isEnumClass) { | 686 if (mixin.isEnumClass) { |
667 // Mixing in an enum has already caused a compile-time error. | 687 // Mixing in an enum has already caused a compile-time error. |
668 return; | 688 return; |
669 } | 689 } |
670 | 690 |
671 // Check that the mixed in class has Object as its superclass. | 691 // Check that the mixed in class has Object as its superclass. |
672 if (!mixin.superclass.isObject) { | 692 if (!mixin.superclass.isObject) { |
673 compiler.reportError(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); | 693 compiler.reportErrorMessage( |
| 694 mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); |
674 } | 695 } |
675 | 696 |
676 // Check that the mixed in class doesn't have any constructors and | 697 // Check that the mixed in class doesn't have any constructors and |
677 // make sure we aren't mixing in methods that use 'super'. | 698 // make sure we aren't mixing in methods that use 'super'. |
678 mixin.forEachLocalMember((AstElement member) { | 699 mixin.forEachLocalMember((AstElement member) { |
679 if (member.isGenerativeConstructor && !member.isSynthesized) { | 700 if (member.isGenerativeConstructor && !member.isSynthesized) { |
680 compiler.reportError(member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); | 701 compiler.reportErrorMessage( |
| 702 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); |
681 } else { | 703 } else { |
682 // Get the resolution tree and check that the resolved member | 704 // Get the resolution tree and check that the resolved member |
683 // doesn't use 'super'. This is the part of the 'super' mixin | 705 // doesn't use 'super'. This is the part of the 'super' mixin |
684 // check that happens when a function is resolved before the | 706 // check that happens when a function is resolved before the |
685 // mixin application has been performed. | 707 // mixin application has been performed. |
686 // TODO(johnniwinther): Obtain the [TreeElements] for [member] | 708 // TODO(johnniwinther): Obtain the [TreeElements] for [member] |
687 // differently. | 709 // differently. |
688 if (compiler.enqueuer.resolution.hasBeenResolved(member)) { | 710 if (compiler.enqueuer.resolution.hasBeenResolved(member)) { |
689 checkMixinSuperUses( | 711 checkMixinSuperUses( |
690 member.resolvedAst.elements, | 712 member.resolvedAst.elements, |
691 mixinApplication, | 713 mixinApplication, |
692 mixin); | 714 mixin); |
693 } | 715 } |
694 } | 716 } |
695 }); | 717 }); |
696 } | 718 } |
697 | 719 |
698 void checkMixinSuperUses(TreeElements resolutionTree, | 720 void checkMixinSuperUses(TreeElements resolutionTree, |
699 MixinApplicationElement mixinApplication, | 721 MixinApplicationElement mixinApplication, |
700 ClassElement mixin) { | 722 ClassElement mixin) { |
701 // TODO(johnniwinther): Avoid the use of [TreeElements] here. | 723 // TODO(johnniwinther): Avoid the use of [TreeElements] here. |
702 if (resolutionTree == null) return; | 724 if (resolutionTree == null) return; |
703 Iterable<Node> superUses = resolutionTree.superUses; | 725 Iterable<Node> superUses = resolutionTree.superUses; |
704 if (superUses.isEmpty) return; | 726 if (superUses.isEmpty) return; |
705 compiler.reportError(mixinApplication, | 727 DiagnosticMessage error = compiler.createMessage( |
706 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, | 728 mixinApplication, |
707 {'className': mixin.name}); | 729 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, |
| 730 {'className': mixin.name}); |
708 // Show the user the problematic uses of 'super' in the mixin. | 731 // Show the user the problematic uses of 'super' in the mixin. |
| 732 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
709 for (Node use in superUses) { | 733 for (Node use in superUses) { |
710 compiler.reportInfo( | 734 infos.add(compiler.createMessage( |
711 use, | 735 use, |
712 MessageKind.ILLEGAL_MIXIN_SUPER_USE); | 736 MessageKind.ILLEGAL_MIXIN_SUPER_USE)); |
713 } | 737 } |
| 738 compiler.reportError(error, infos); |
714 } | 739 } |
715 | 740 |
716 void checkClassMembers(ClassElement cls) { | 741 void checkClassMembers(ClassElement cls) { |
717 assert(invariant(cls, cls.isDeclaration)); | 742 assert(invariant(cls, cls.isDeclaration)); |
718 if (cls.isObject) return; | 743 if (cls.isObject) return; |
719 // TODO(johnniwinther): Should this be done on the implementation element as | 744 // TODO(johnniwinther): Should this be done on the implementation element as |
720 // well? | 745 // well? |
721 List<Element> constConstructors = <Element>[]; | 746 List<Element> constConstructors = <Element>[]; |
722 List<Element> nonFinalInstanceFields = <Element>[]; | 747 List<Element> nonFinalInstanceFields = <Element>[]; |
723 cls.forEachMember((holder, member) { | 748 cls.forEachMember((holder, member) { |
724 compiler.withCurrentElement(member, () { | 749 compiler.withCurrentElement(member, () { |
725 // Perform various checks as side effect of "computing" the type. | 750 // Perform various checks as side effect of "computing" the type. |
726 member.computeType(compiler); | 751 member.computeType(compiler); |
727 | 752 |
728 // Check modifiers. | 753 // Check modifiers. |
729 if (member.isFunction && member.modifiers.isFinal) { | 754 if (member.isFunction && member.modifiers.isFinal) { |
730 compiler.reportError( | 755 compiler.reportErrorMessage( |
731 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 756 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
732 } | 757 } |
733 if (member.isConstructor) { | 758 if (member.isConstructor) { |
734 final mismatchedFlagsBits = | 759 final mismatchedFlagsBits = |
735 member.modifiers.flags & | 760 member.modifiers.flags & |
736 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 761 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
737 if (mismatchedFlagsBits != 0) { | 762 if (mismatchedFlagsBits != 0) { |
738 final mismatchedFlags = | 763 final mismatchedFlags = |
739 new Modifiers.withFlags(null, mismatchedFlagsBits); | 764 new Modifiers.withFlags(null, mismatchedFlagsBits); |
740 compiler.reportError( | 765 compiler.reportErrorMessage( |
741 member, | 766 member, |
742 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 767 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
743 {'modifiers': mismatchedFlags}); | 768 {'modifiers': mismatchedFlags}); |
744 } | 769 } |
745 if (member.modifiers.isConst) { | 770 if (member.modifiers.isConst) { |
746 constConstructors.add(member); | 771 constConstructors.add(member); |
747 } | 772 } |
748 } | 773 } |
749 if (member.isField) { | 774 if (member.isField) { |
750 if (member.modifiers.isConst && !member.modifiers.isStatic) { | 775 if (member.modifiers.isConst && !member.modifiers.isStatic) { |
751 compiler.reportError( | 776 compiler.reportErrorMessage( |
752 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); | 777 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); |
753 } | 778 } |
754 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { | 779 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { |
755 nonFinalInstanceFields.add(member); | 780 nonFinalInstanceFields.add(member); |
756 } | 781 } |
757 } | 782 } |
758 checkAbstractField(member); | 783 checkAbstractField(member); |
759 checkUserDefinableOperator(member); | 784 checkUserDefinableOperator(member); |
760 }); | 785 }); |
761 }); | 786 }); |
762 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { | 787 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { |
763 Spannable span = constConstructors.length > 1 | 788 Spannable span = constConstructors.length > 1 |
764 ? cls : constConstructors[0]; | 789 ? cls : constConstructors[0]; |
765 compiler.reportError(span, | 790 DiagnosticMessage error = compiler.createMessage( |
| 791 span, |
766 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, | 792 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, |
767 {'className': cls.name}); | 793 {'className': cls.name}); |
| 794 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
768 if (constConstructors.length > 1) { | 795 if (constConstructors.length > 1) { |
769 for (Element constructor in constConstructors) { | 796 for (Element constructor in constConstructors) { |
770 compiler.reportInfo(constructor, | 797 infos.add(compiler.createMessage( |
771 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR); | 798 constructor, |
| 799 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); |
772 } | 800 } |
773 } | 801 } |
774 for (Element field in nonFinalInstanceFields) { | 802 for (Element field in nonFinalInstanceFields) { |
775 compiler.reportInfo(field, | 803 infos.add(compiler.createMessage( |
776 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD); | 804 field, |
| 805 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); |
777 } | 806 } |
| 807 compiler.reportError(error, infos); |
778 } | 808 } |
779 } | 809 } |
780 | 810 |
781 void checkAbstractField(Element member) { | 811 void checkAbstractField(Element member) { |
782 // Only check for getters. The test can only fail if there is both a setter | 812 // Only check for getters. The test can only fail if there is both a setter |
783 // and a getter with the same name, and we only need to check each abstract | 813 // and a getter with the same name, and we only need to check each abstract |
784 // field once, so we just ignore setters. | 814 // field once, so we just ignore setters. |
785 if (!member.isGetter) return; | 815 if (!member.isGetter) return; |
786 | 816 |
787 // Find the associated abstract field. | 817 // Find the associated abstract field. |
(...skipping 11 matching lines...) Expand all Loading... |
799 | 829 |
800 GetterElementX getter = field.getter; | 830 GetterElementX getter = field.getter; |
801 if (getter == null) return; | 831 if (getter == null) return; |
802 SetterElementX setter = field.setter; | 832 SetterElementX setter = field.setter; |
803 if (setter == null) return; | 833 if (setter == null) return; |
804 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 834 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
805 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 835 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
806 if (!identical(getterFlags, setterFlags)) { | 836 if (!identical(getterFlags, setterFlags)) { |
807 final mismatchedFlags = | 837 final mismatchedFlags = |
808 new Modifiers.withFlags(null, getterFlags ^ setterFlags); | 838 new Modifiers.withFlags(null, getterFlags ^ setterFlags); |
809 compiler.reportError( | 839 compiler.reportErrorMessage( |
810 field.getter, | 840 field.getter, |
811 MessageKind.GETTER_MISMATCH, | 841 MessageKind.GETTER_MISMATCH, |
812 {'modifiers': mismatchedFlags}); | 842 {'modifiers': mismatchedFlags}); |
813 compiler.reportError( | 843 compiler.reportErrorMessage( |
814 field.setter, | 844 field.setter, |
815 MessageKind.SETTER_MISMATCH, | 845 MessageKind.SETTER_MISMATCH, |
816 {'modifiers': mismatchedFlags}); | 846 {'modifiers': mismatchedFlags}); |
817 } | 847 } |
818 } | 848 } |
819 | 849 |
820 void checkUserDefinableOperator(Element member) { | 850 void checkUserDefinableOperator(Element member) { |
821 FunctionElement function = member.asFunctionElement(); | 851 FunctionElement function = member.asFunctionElement(); |
822 if (function == null) return; | 852 if (function == null) return; |
823 String value = member.name; | 853 String value = member.name; |
(...skipping 27 matching lines...) Expand all Loading... |
851 } | 881 } |
852 checkArity(function, requiredParameterCount, messageKind, isMinus); | 882 checkArity(function, requiredParameterCount, messageKind, isMinus); |
853 } | 883 } |
854 | 884 |
855 void checkOverrideHashCode(FunctionElement operatorEquals) { | 885 void checkOverrideHashCode(FunctionElement operatorEquals) { |
856 if (operatorEquals.isAbstract) return; | 886 if (operatorEquals.isAbstract) return; |
857 ClassElement cls = operatorEquals.enclosingClass; | 887 ClassElement cls = operatorEquals.enclosingClass; |
858 Element hashCodeImplementation = | 888 Element hashCodeImplementation = |
859 cls.lookupLocalMember('hashCode'); | 889 cls.lookupLocalMember('hashCode'); |
860 if (hashCodeImplementation != null) return; | 890 if (hashCodeImplementation != null) return; |
861 compiler.reportHint( | 891 compiler.reportHintMessage( |
862 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, | 892 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, |
863 {'class': cls.name}); | 893 {'class': cls.name}); |
864 } | 894 } |
865 | 895 |
866 void checkArity(FunctionElement function, | 896 void checkArity(FunctionElement function, |
867 int requiredParameterCount, MessageKind messageKind, | 897 int requiredParameterCount, MessageKind messageKind, |
868 bool isMinus) { | 898 bool isMinus) { |
869 FunctionExpression node = function.node; | 899 FunctionExpression node = function.node; |
870 FunctionSignature signature = function.functionSignature; | 900 FunctionSignature signature = function.functionSignature; |
871 if (signature.requiredParameterCount != requiredParameterCount) { | 901 if (signature.requiredParameterCount != requiredParameterCount) { |
(...skipping 20 matching lines...) Expand all Loading... |
892 // int operator -(a, b) {} | 922 // int operator -(a, b) {} |
893 // ^ | 923 // ^ |
894 // | 924 // |
895 // since the correction might not be to remove 'b' but instead to | 925 // since the correction might not be to remove 'b' but instead to |
896 // remove 'a, b'. | 926 // remove 'a, b'. |
897 errorNode = node.parameters; | 927 errorNode = node.parameters; |
898 } else { | 928 } else { |
899 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; | 929 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; |
900 } | 930 } |
901 } | 931 } |
902 compiler.reportError( | 932 compiler.reportErrorMessage( |
903 errorNode, messageKind, {'operatorName': function.name}); | 933 errorNode, messageKind, {'operatorName': function.name}); |
904 } | 934 } |
905 if (signature.optionalParameterCount != 0) { | 935 if (signature.optionalParameterCount != 0) { |
906 Node errorNode = | 936 Node errorNode = |
907 node.parameters.nodes.skip(signature.requiredParameterCount).head; | 937 node.parameters.nodes.skip(signature.requiredParameterCount).head; |
908 if (signature.optionalParametersAreNamed) { | 938 if (signature.optionalParametersAreNamed) { |
909 compiler.reportError( | 939 compiler.reportErrorMessage( |
910 errorNode, | 940 errorNode, |
911 MessageKind.OPERATOR_NAMED_PARAMETERS, | 941 MessageKind.OPERATOR_NAMED_PARAMETERS, |
912 {'operatorName': function.name}); | 942 {'operatorName': function.name}); |
913 } else { | 943 } else { |
914 compiler.reportError( | 944 compiler.reportErrorMessage( |
915 errorNode, | 945 errorNode, |
916 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, | 946 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, |
917 {'operatorName': function.name}); | 947 {'operatorName': function.name}); |
918 } | 948 } |
919 } | 949 } |
920 } | 950 } |
921 | 951 |
922 reportErrorWithContext(Element errorneousElement, | 952 reportErrorWithContext(Element errorneousElement, |
923 MessageKind errorMessage, | 953 MessageKind errorMessage, |
924 Element contextElement, | 954 Element contextElement, |
925 MessageKind contextMessage) { | 955 MessageKind contextMessage) { |
926 compiler.reportError( | 956 compiler.reportError( |
927 errorneousElement, | 957 compiler.createMessage( |
928 errorMessage, | 958 errorneousElement, |
929 {'memberName': contextElement.name, | 959 errorMessage, |
930 'className': contextElement.enclosingClass.name}); | 960 {'memberName': contextElement.name, |
931 compiler.reportInfo(contextElement, contextMessage); | 961 'className': contextElement.enclosingClass.name}), |
| 962 <DiagnosticMessage>[ |
| 963 compiler.createMessage(contextElement, contextMessage), |
| 964 ]); |
932 } | 965 } |
933 | 966 |
934 | 967 |
935 FunctionSignature resolveSignature(FunctionElementX element) { | 968 FunctionSignature resolveSignature(FunctionElementX element) { |
936 MessageKind defaultValuesError = null; | 969 MessageKind defaultValuesError = null; |
937 if (element.isFactoryConstructor) { | 970 if (element.isFactoryConstructor) { |
938 FunctionExpression body = element.parseNode(compiler); | 971 FunctionExpression body = element.parseNode(compiler); |
939 if (body.isRedirectingFactory) { | 972 if (body.isRedirectingFactory) { |
940 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; | 973 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; |
941 } | 974 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 constantCompiler.evaluate(annotation.constant); | 1032 constantCompiler.evaluate(annotation.constant); |
1000 // TODO(johnniwinther): Register the relation between the annotation | 1033 // TODO(johnniwinther): Register the relation between the annotation |
1001 // and the annotated element instead. This will allow the backend to | 1034 // and the annotated element instead. This will allow the backend to |
1002 // retrieve the backend constant and only register metadata on the | 1035 // retrieve the backend constant and only register metadata on the |
1003 // elements for which it is needed. (Issue 17732). | 1036 // elements for which it is needed. (Issue 17732). |
1004 registry.registerMetadataConstant(annotation, annotatedElement); | 1037 registry.registerMetadataConstant(annotation, annotatedElement); |
1005 annotation.resolutionState = STATE_DONE; | 1038 annotation.resolutionState = STATE_DONE; |
1006 })); | 1039 })); |
1007 } | 1040 } |
1008 | 1041 |
1009 error(Spannable node, MessageKind kind, [arguments = const {}]) { | |
1010 compiler.reportError(node, kind, arguments); | |
1011 } | |
1012 | |
1013 List<MetadataAnnotation> resolveMetadata(Element element, | 1042 List<MetadataAnnotation> resolveMetadata(Element element, |
1014 VariableDefinitions node) { | 1043 VariableDefinitions node) { |
1015 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; | 1044 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; |
1016 for (Metadata annotation in node.metadata.nodes) { | 1045 for (Metadata annotation in node.metadata.nodes) { |
1017 ParameterMetadataAnnotation metadataAnnotation = | 1046 ParameterMetadataAnnotation metadataAnnotation = |
1018 new ParameterMetadataAnnotation(annotation); | 1047 new ParameterMetadataAnnotation(annotation); |
1019 metadataAnnotation.annotatedElement = element; | 1048 metadataAnnotation.annotatedElement = element; |
1020 metadata.add(metadataAnnotation.ensureResolved(compiler)); | 1049 metadata.add(metadataAnnotation.ensureResolved(compiler)); |
1021 } | 1050 } |
1022 return metadata; | 1051 return metadata; |
(...skipping 15 matching lines...) Expand all Loading... |
1038 TreeElements get treeElements { | 1067 TreeElements get treeElements { |
1039 assert(invariant(this, _treeElements !=null, | 1068 assert(invariant(this, _treeElements !=null, |
1040 message: "TreeElements have not been computed for $this.")); | 1069 message: "TreeElements have not been computed for $this.")); |
1041 return _treeElements; | 1070 return _treeElements; |
1042 } | 1071 } |
1043 | 1072 |
1044 void reuseElement() { | 1073 void reuseElement() { |
1045 _treeElements = null; | 1074 _treeElements = null; |
1046 } | 1075 } |
1047 } | 1076 } |
OLD | NEW |