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/resolution.dart' show | 11 import '../common/resolution.dart' show |
12 Parsing, | 12 Parsing, |
13 Resolution; | 13 Resolution; |
14 import '../common/tasks.dart' show | 14 import '../common/tasks.dart' show |
15 CompilerTask, | 15 CompilerTask, |
16 DeferredAction; | 16 DeferredAction; |
17 import '../compiler.dart' show | 17 import '../compiler.dart' show |
18 Compiler; | 18 Compiler; |
19 import '../compile_time_constants.dart' show | 19 import '../compile_time_constants.dart' show |
20 ConstantCompiler; | 20 ConstantCompiler; |
21 import '../constants/values.dart' show | 21 import '../constants/values.dart' show |
22 ConstantValue; | 22 ConstantValue; |
23 import '../dart_types.dart'; | 23 import '../dart_types.dart'; |
24 import '../diagnostics/diagnostic_listener.dart' show | 24 import '../diagnostics/diagnostic_listener.dart' show |
25 DiagnosticMessage; | 25 DiagnosticMessage, |
| 26 DiagnosticReporter; |
26 import '../diagnostics/invariant.dart' show | 27 import '../diagnostics/invariant.dart' show |
27 invariant; | 28 invariant; |
28 import '../diagnostics/messages.dart' show | 29 import '../diagnostics/messages.dart' show |
29 MessageKind; | 30 MessageKind; |
30 import '../diagnostics/spannable.dart' show | 31 import '../diagnostics/spannable.dart' show |
31 Spannable; | 32 Spannable; |
32 import '../elements/elements.dart'; | 33 import '../elements/elements.dart'; |
33 import '../elements/modelx.dart' show | 34 import '../elements/modelx.dart' show |
34 BaseClassElementX, | 35 BaseClassElementX, |
35 BaseFunctionElementX, | 36 BaseFunctionElementX, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 FunctionElement redirection) { | 124 FunctionElement redirection) { |
124 assert(invariant(node, constructor.isImplementation, | 125 assert(invariant(node, constructor.isImplementation, |
125 message: 'Redirecting constructors must be resolved on implementation ' | 126 message: 'Redirecting constructors must be resolved on implementation ' |
126 'elements.')); | 127 'elements.')); |
127 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 128 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); |
128 seen.add(constructor); | 129 seen.add(constructor); |
129 while (redirection != null) { | 130 while (redirection != null) { |
130 // Ensure that we follow redirections through implementation elements. | 131 // Ensure that we follow redirections through implementation elements. |
131 redirection = redirection.implementation; | 132 redirection = redirection.implementation; |
132 if (seen.contains(redirection)) { | 133 if (seen.contains(redirection)) { |
133 compiler.reportErrorMessage( | 134 reporter.reportErrorMessage( |
134 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 135 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
135 return; | 136 return; |
136 } | 137 } |
137 seen.add(redirection); | 138 seen.add(redirection); |
138 redirection = resolver.visitor.resolveConstructorRedirection(redirection); | 139 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
139 } | 140 } |
140 } | 141 } |
141 | 142 |
142 static void processAsyncMarker(Compiler compiler, | 143 static void processAsyncMarker(Compiler compiler, |
143 BaseFunctionElementX element, | 144 BaseFunctionElementX element, |
144 ResolutionRegistry registry) { | 145 ResolutionRegistry registry) { |
| 146 DiagnosticReporter reporter = compiler.reporter; |
145 Resolution resolution = compiler.resolution; | 147 Resolution resolution = compiler.resolution; |
146 FunctionExpression functionExpression = element.node; | 148 FunctionExpression functionExpression = element.node; |
147 AsyncModifier asyncModifier = functionExpression.asyncModifier; | 149 AsyncModifier asyncModifier = functionExpression.asyncModifier; |
148 if (asyncModifier != null) { | 150 if (asyncModifier != null) { |
149 | 151 |
150 if (asyncModifier.isAsynchronous) { | 152 if (asyncModifier.isAsynchronous) { |
151 element.asyncMarker = asyncModifier.isYielding | 153 element.asyncMarker = asyncModifier.isYielding |
152 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; | 154 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; |
153 } else { | 155 } else { |
154 element.asyncMarker = AsyncMarker.SYNC_STAR; | 156 element.asyncMarker = AsyncMarker.SYNC_STAR; |
155 } | 157 } |
156 if (element.isAbstract) { | 158 if (element.isAbstract) { |
157 compiler.reportErrorMessage( | 159 reporter.reportErrorMessage( |
158 asyncModifier, | 160 asyncModifier, |
159 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, | 161 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, |
160 {'modifier': element.asyncMarker}); | 162 {'modifier': element.asyncMarker}); |
161 } else if (element.isConstructor) { | 163 } else if (element.isConstructor) { |
162 compiler.reportErrorMessage( | 164 reporter.reportErrorMessage( |
163 asyncModifier, | 165 asyncModifier, |
164 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, | 166 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, |
165 {'modifier': element.asyncMarker}); | 167 {'modifier': element.asyncMarker}); |
166 } else { | 168 } else { |
167 if (element.isSetter) { | 169 if (element.isSetter) { |
168 compiler.reportErrorMessage( | 170 reporter.reportErrorMessage( |
169 asyncModifier, | 171 asyncModifier, |
170 MessageKind.ASYNC_MODIFIER_ON_SETTER, | 172 MessageKind.ASYNC_MODIFIER_ON_SETTER, |
171 {'modifier': element.asyncMarker}); | 173 {'modifier': element.asyncMarker}); |
172 | 174 |
173 } | 175 } |
174 if (functionExpression.body.asReturn() != null && | 176 if (functionExpression.body.asReturn() != null && |
175 element.asyncMarker.isYielding) { | 177 element.asyncMarker.isYielding) { |
176 compiler.reportErrorMessage( | 178 reporter.reportErrorMessage( |
177 asyncModifier, | 179 asyncModifier, |
178 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, | 180 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, |
179 {'modifier': element.asyncMarker}); | 181 {'modifier': element.asyncMarker}); |
180 } | 182 } |
181 } | 183 } |
182 registry.registerAsyncMarker(element); | 184 registry.registerAsyncMarker(element); |
183 switch (element.asyncMarker) { | 185 switch (element.asyncMarker) { |
184 case AsyncMarker.ASYNC: | 186 case AsyncMarker.ASYNC: |
185 compiler.futureClass.ensureResolved(resolution); | 187 compiler.futureClass.ensureResolved(resolution); |
186 break; | 188 break; |
(...skipping 11 matching lines...) Expand all Loading... |
198 assert(classElement != null); | 200 assert(classElement != null); |
199 while (classElement != null) { | 201 while (classElement != null) { |
200 if (classElement.isNative) return true; | 202 if (classElement.isNative) return true; |
201 classElement = classElement.superclass; | 203 classElement = classElement.superclass; |
202 } | 204 } |
203 return false; | 205 return false; |
204 } | 206 } |
205 | 207 |
206 WorldImpact resolveMethodElementImplementation( | 208 WorldImpact resolveMethodElementImplementation( |
207 FunctionElement element, FunctionExpression tree) { | 209 FunctionElement element, FunctionExpression tree) { |
208 return compiler.withCurrentElement(element, () { | 210 return reporter.withCurrentElement(element, () { |
209 if (element.isExternal && tree.hasBody()) { | 211 if (element.isExternal && tree.hasBody()) { |
210 compiler.reportErrorMessage( | 212 reporter.reportErrorMessage( |
211 element, | 213 element, |
212 MessageKind.EXTERNAL_WITH_BODY, | 214 MessageKind.EXTERNAL_WITH_BODY, |
213 {'functionName': element.name}); | 215 {'functionName': element.name}); |
214 } | 216 } |
215 if (element.isConstructor) { | 217 if (element.isConstructor) { |
216 if (tree.returnType != null) { | 218 if (tree.returnType != null) { |
217 compiler.reportErrorMessage( | 219 reporter.reportErrorMessage( |
218 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 220 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
219 } | 221 } |
220 if (element.isConst && | 222 if (element.isConst && |
221 tree.hasBody() && | 223 tree.hasBody() && |
222 !tree.isRedirectingFactory) { | 224 !tree.isRedirectingFactory) { |
223 compiler.reportErrorMessage( | 225 reporter.reportErrorMessage( |
224 tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY); | 226 tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY); |
225 } | 227 } |
226 } | 228 } |
227 | 229 |
228 ResolverVisitor visitor = visitorFor(element); | 230 ResolverVisitor visitor = visitorFor(element); |
229 ResolutionRegistry registry = visitor.registry; | 231 ResolutionRegistry registry = visitor.registry; |
230 registry.defineFunction(tree, element); | 232 registry.defineFunction(tree, element); |
231 visitor.setupFunction(tree, element); | 233 visitor.setupFunction(tree, element); |
232 processAsyncMarker(compiler, element, registry); | 234 processAsyncMarker(compiler, element, registry); |
233 | 235 |
234 if (element.isGenerativeConstructor) { | 236 if (element.isGenerativeConstructor) { |
235 // Even if there is no initializer list we still have to do the | 237 // Even if there is no initializer list we still have to do the |
236 // resolution in case there is an implicit super constructor call. | 238 // resolution in case there is an implicit super constructor call. |
237 InitializerResolver resolver = | 239 InitializerResolver resolver = |
238 new InitializerResolver(visitor, element, tree); | 240 new InitializerResolver(visitor, element, tree); |
239 FunctionElement redirection = resolver.resolveInitializers(); | 241 FunctionElement redirection = resolver.resolveInitializers(); |
240 if (redirection != null) { | 242 if (redirection != null) { |
241 resolveRedirectingConstructor(resolver, tree, element, redirection); | 243 resolveRedirectingConstructor(resolver, tree, element, redirection); |
242 } | 244 } |
243 } else if (tree.initializers != null) { | 245 } else if (tree.initializers != null) { |
244 compiler.reportErrorMessage( | 246 reporter.reportErrorMessage( |
245 tree, MessageKind.FUNCTION_WITH_INITIALIZER); | 247 tree, MessageKind.FUNCTION_WITH_INITIALIZER); |
246 } | 248 } |
247 | 249 |
248 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { | 250 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { |
249 // We need to analyze the redirecting factory bodies to ensure that | 251 // We need to analyze the redirecting factory bodies to ensure that |
250 // we can analyze compile-time constants. | 252 // we can analyze compile-time constants. |
251 visitor.visit(tree.body); | 253 visitor.visit(tree.body); |
252 } | 254 } |
253 | 255 |
254 // Get the resolution tree and check that the resolved | 256 // Get the resolution tree and check that the resolved |
(...skipping 10 matching lines...) Expand all Loading... |
265 ClassElement mixin = enclosingClass; | 267 ClassElement mixin = enclosingClass; |
266 for (MixinApplicationElement mixinApplication in mixinUses) { | 268 for (MixinApplicationElement mixinApplication in mixinUses) { |
267 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); | 269 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); |
268 } | 270 } |
269 } | 271 } |
270 | 272 |
271 // TODO(9631): support noSuchMethod on native classes. | 273 // TODO(9631): support noSuchMethod on native classes. |
272 if (Elements.isInstanceMethod(element) && | 274 if (Elements.isInstanceMethod(element) && |
273 element.name == Identifiers.noSuchMethod_ && | 275 element.name == Identifiers.noSuchMethod_ && |
274 _isNativeClassOrExtendsNativeClass(enclosingClass)) { | 276 _isNativeClassOrExtendsNativeClass(enclosingClass)) { |
275 compiler.reportErrorMessage( | 277 reporter.reportErrorMessage( |
276 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); | 278 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); |
277 } | 279 } |
278 | 280 |
279 return registry.worldImpact; | 281 return registry.worldImpact; |
280 }); | 282 }); |
281 | 283 |
282 } | 284 } |
283 | 285 |
284 WorldImpact resolveMethodElement(FunctionElementX element) { | 286 WorldImpact resolveMethodElement(FunctionElementX element) { |
285 assert(invariant(element, element.isDeclaration)); | 287 assert(invariant(element, element.isDeclaration)); |
286 return compiler.withCurrentElement(element, () { | 288 return reporter.withCurrentElement(element, () { |
287 if (compiler.enqueuer.resolution.hasBeenResolved(element)) { | 289 if (compiler.enqueuer.resolution.hasBeenResolved(element)) { |
288 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] | 290 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] |
289 // should never be non-null, not even for constructors. | 291 // should never be non-null, not even for constructors. |
290 assert(invariant(element, element.isConstructor, | 292 assert(invariant(element, element.isConstructor, |
291 message: 'Non-constructor element $element ' | 293 message: 'Non-constructor element $element ' |
292 'has already been analyzed.')); | 294 'has already been analyzed.')); |
293 return const WorldImpact(); | 295 return const WorldImpact(); |
294 } | 296 } |
295 if (element.isSynthesized) { | 297 if (element.isSynthesized) { |
296 if (element.isGenerativeConstructor) { | 298 if (element.isGenerativeConstructor) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 /// this library). | 335 /// this library). |
334 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { | 336 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { |
335 return new ResolverVisitor(compiler, element, | 337 return new ResolverVisitor(compiler, element, |
336 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 338 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
337 useEnclosingScope: useEnclosingScope); | 339 useEnclosingScope: useEnclosingScope); |
338 } | 340 } |
339 | 341 |
340 WorldImpact resolveField(FieldElementX element) { | 342 WorldImpact resolveField(FieldElementX element) { |
341 VariableDefinitions tree = element.parseNode(parsing); | 343 VariableDefinitions tree = element.parseNode(parsing); |
342 if(element.modifiers.isStatic && element.isTopLevel) { | 344 if(element.modifiers.isStatic && element.isTopLevel) { |
343 compiler.reportErrorMessage( | 345 reporter.reportErrorMessage( |
344 element.modifiers.getStatic(), | 346 element.modifiers.getStatic(), |
345 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 347 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
346 } | 348 } |
347 ResolverVisitor visitor = visitorFor(element); | 349 ResolverVisitor visitor = visitorFor(element); |
348 ResolutionRegistry registry = visitor.registry; | 350 ResolutionRegistry registry = visitor.registry; |
349 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 351 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
350 // to the backend ast. | 352 // to the backend ast. |
351 registry.defineElement(tree.definitions.nodes.head, element); | 353 registry.defineElement(tree.definitions.nodes.head, element); |
352 // TODO(johnniwinther): Share the resolved type between all variables | 354 // TODO(johnniwinther): Share the resolved type between all variables |
353 // declared in the same declaration. | 355 // declared in the same declaration. |
354 if (tree.type != null) { | 356 if (tree.type != null) { |
355 element.variables.type = visitor.resolveTypeAnnotation(tree.type); | 357 element.variables.type = visitor.resolveTypeAnnotation(tree.type); |
356 } else { | 358 } else { |
357 element.variables.type = const DynamicType(); | 359 element.variables.type = const DynamicType(); |
358 } | 360 } |
359 | 361 |
360 Expression initializer = element.initializer; | 362 Expression initializer = element.initializer; |
361 Modifiers modifiers = element.modifiers; | 363 Modifiers modifiers = element.modifiers; |
362 if (initializer != null) { | 364 if (initializer != null) { |
363 // TODO(johnniwinther): Avoid analyzing initializers if | 365 // TODO(johnniwinther): Avoid analyzing initializers if |
364 // [Compiler.analyzeSignaturesOnly] is set. | 366 // [Compiler.analyzeSignaturesOnly] is set. |
365 visitor.visit(initializer); | 367 visitor.visit(initializer); |
366 } else if (modifiers.isConst) { | 368 } else if (modifiers.isConst) { |
367 compiler.reportErrorMessage( | 369 reporter.reportErrorMessage( |
368 element, MessageKind.CONST_WITHOUT_INITIALIZER); | 370 element, MessageKind.CONST_WITHOUT_INITIALIZER); |
369 } else if (modifiers.isFinal && !element.isInstanceMember) { | 371 } else if (modifiers.isFinal && !element.isInstanceMember) { |
370 compiler.reportErrorMessage( | 372 reporter.reportErrorMessage( |
371 element, MessageKind.FINAL_WITHOUT_INITIALIZER); | 373 element, MessageKind.FINAL_WITHOUT_INITIALIZER); |
372 } else { | 374 } else { |
373 registry.registerInstantiatedClass(compiler.nullClass); | 375 registry.registerInstantiatedClass(compiler.nullClass); |
374 } | 376 } |
375 | 377 |
376 if (Elements.isStaticOrTopLevelField(element)) { | 378 if (Elements.isStaticOrTopLevelField(element)) { |
377 visitor.addDeferredAction(element, () { | 379 visitor.addDeferredAction(element, () { |
378 if (element.modifiers.isConst) { | 380 if (element.modifiers.isConst) { |
379 element.constant = constantCompiler.compileConstant(element); | 381 element.constant = constantCompiler.compileConstant(element); |
380 } else { | 382 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
392 | 394 |
393 // Perform various checks as side effect of "computing" the type. | 395 // Perform various checks as side effect of "computing" the type. |
394 element.computeType(resolution); | 396 element.computeType(resolution); |
395 | 397 |
396 return registry.worldImpact; | 398 return registry.worldImpact; |
397 } | 399 } |
398 | 400 |
399 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 401 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { |
400 DartType type = resolveReturnType(element, annotation); | 402 DartType type = resolveReturnType(element, annotation); |
401 if (type.isVoid) { | 403 if (type.isVoid) { |
402 compiler.reportErrorMessage( | 404 reporter.reportErrorMessage( |
403 annotation, MessageKind.VOID_NOT_ALLOWED); | 405 annotation, MessageKind.VOID_NOT_ALLOWED); |
404 } | 406 } |
405 return type; | 407 return type; |
406 } | 408 } |
407 | 409 |
408 DartType resolveReturnType(Element element, TypeAnnotation annotation) { | 410 DartType resolveReturnType(Element element, TypeAnnotation annotation) { |
409 if (annotation == null) return const DynamicType(); | 411 if (annotation == null) return const DynamicType(); |
410 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 412 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); |
411 if (result == null) { | 413 if (result == null) { |
412 // TODO(karklose): warning. | 414 // TODO(karklose): warning. |
(...skipping 14 matching lines...) Expand all Loading... |
427 targetType = target.effectiveTargetType; | 429 targetType = target.effectiveTargetType; |
428 assert(invariant(target, targetType != null, | 430 assert(invariant(target, targetType != null, |
429 message: 'Redirection target type has not been computed for ' | 431 message: 'Redirection target type has not been computed for ' |
430 '$target')); | 432 '$target')); |
431 target = target.internalEffectiveTarget; | 433 target = target.internalEffectiveTarget; |
432 break; | 434 break; |
433 } | 435 } |
434 | 436 |
435 Element nextTarget = target.immediateRedirectionTarget; | 437 Element nextTarget = target.immediateRedirectionTarget; |
436 if (seen.contains(nextTarget)) { | 438 if (seen.contains(nextTarget)) { |
437 compiler.reportErrorMessage( | 439 reporter.reportErrorMessage( |
438 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 440 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); |
439 targetType = target.enclosingClass.thisType; | 441 targetType = target.enclosingClass.thisType; |
440 break; | 442 break; |
441 } | 443 } |
442 seen.add(target); | 444 seen.add(target); |
443 target = nextTarget; | 445 target = nextTarget; |
444 } | 446 } |
445 | 447 |
446 if (targetType == null) { | 448 if (targetType == null) { |
447 assert(!target.isRedirectingFactory); | 449 assert(!target.isRedirectingFactory); |
(...skipping 26 matching lines...) Expand all Loading... |
474 } | 476 } |
475 } | 477 } |
476 | 478 |
477 /** | 479 /** |
478 * Load and resolve the supertypes of [cls]. | 480 * Load and resolve the supertypes of [cls]. |
479 * | 481 * |
480 * Warning: do not call this method directly. It should only be | 482 * Warning: do not call this method directly. It should only be |
481 * called by [resolveClass] and [ClassSupertypeResolver]. | 483 * called by [resolveClass] and [ClassSupertypeResolver]. |
482 */ | 484 */ |
483 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 485 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
484 compiler.withCurrentElement(cls, () => measure(() { | 486 reporter.withCurrentElement(cls, () => measure(() { |
485 if (cls.supertypeLoadState == STATE_DONE) return; | 487 if (cls.supertypeLoadState == STATE_DONE) return; |
486 if (cls.supertypeLoadState == STATE_STARTED) { | 488 if (cls.supertypeLoadState == STATE_STARTED) { |
487 compiler.reportErrorMessage( | 489 reporter.reportErrorMessage( |
488 from, | 490 from, |
489 MessageKind.CYCLIC_CLASS_HIERARCHY, | 491 MessageKind.CYCLIC_CLASS_HIERARCHY, |
490 {'className': cls.name}); | 492 {'className': cls.name}); |
491 cls.supertypeLoadState = STATE_DONE; | 493 cls.supertypeLoadState = STATE_DONE; |
492 cls.hasIncompleteHierarchy = true; | 494 cls.hasIncompleteHierarchy = true; |
493 cls.allSupertypesAndSelf = | 495 cls.allSupertypesAndSelf = |
494 compiler.objectClass.allSupertypesAndSelf.extendClass( | 496 compiler.objectClass.allSupertypesAndSelf.extendClass( |
495 cls.computeType(resolution)); | 497 cls.computeType(resolution)); |
496 cls.supertype = cls.allSupertypes.head; | 498 cls.supertype = cls.allSupertypes.head; |
497 assert(invariant(from, cls.supertype != null, | 499 assert(invariant(from, cls.supertype != null, |
498 message: 'Missing supertype on cyclic class $cls.')); | 500 message: 'Missing supertype on cyclic class $cls.')); |
499 cls.interfaces = const Link<DartType>(); | 501 cls.interfaces = const Link<DartType>(); |
500 return; | 502 return; |
501 } | 503 } |
502 cls.supertypeLoadState = STATE_STARTED; | 504 cls.supertypeLoadState = STATE_STARTED; |
503 compiler.withCurrentElement(cls, () { | 505 reporter.withCurrentElement(cls, () { |
504 // TODO(ahe): Cache the node in cls. | 506 // TODO(ahe): Cache the node in cls. |
505 cls.parseNode(parsing).accept( | 507 cls.parseNode(parsing).accept( |
506 new ClassSupertypeResolver(compiler, cls)); | 508 new ClassSupertypeResolver(compiler, cls)); |
507 if (cls.supertypeLoadState != STATE_DONE) { | 509 if (cls.supertypeLoadState != STATE_DONE) { |
508 cls.supertypeLoadState = STATE_DONE; | 510 cls.supertypeLoadState = STATE_DONE; |
509 } | 511 } |
510 }); | 512 }); |
511 })); | 513 })); |
512 } | 514 } |
513 | 515 |
514 // TODO(johnniwinther): Remove this queue when resolution has been split into | 516 // TODO(johnniwinther): Remove this queue when resolution has been split into |
515 // syntax and semantic resolution. | 517 // syntax and semantic resolution. |
516 TypeDeclarationElement currentlyResolvedTypeDeclaration; | 518 TypeDeclarationElement currentlyResolvedTypeDeclaration; |
517 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); | 519 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); |
518 Queue<ClassElement> pendingClassesToBePostProcessed = | 520 Queue<ClassElement> pendingClassesToBePostProcessed = |
519 new Queue<ClassElement>(); | 521 new Queue<ClassElement>(); |
520 | 522 |
521 /// Resolve [element] using [resolveTypeDeclaration]. | 523 /// Resolve [element] using [resolveTypeDeclaration]. |
522 /// | 524 /// |
523 /// This methods ensure that class declarations encountered through type | 525 /// This methods ensure that class declarations encountered through type |
524 /// annotations during the resolution of [element] are resolved after | 526 /// annotations during the resolution of [element] are resolved after |
525 /// [element] has been resolved. | 527 /// [element] has been resolved. |
526 // TODO(johnniwinther): Encapsulate this functionality in a | 528 // TODO(johnniwinther): Encapsulate this functionality in a |
527 // 'TypeDeclarationResolver'. | 529 // 'TypeDeclarationResolver'. |
528 _resolveTypeDeclaration(TypeDeclarationElement element, | 530 _resolveTypeDeclaration(TypeDeclarationElement element, |
529 resolveTypeDeclaration()) { | 531 resolveTypeDeclaration()) { |
530 return compiler.withCurrentElement(element, () { | 532 return reporter.withCurrentElement(element, () { |
531 return measure(() { | 533 return measure(() { |
532 TypeDeclarationElement previousResolvedTypeDeclaration = | 534 TypeDeclarationElement previousResolvedTypeDeclaration = |
533 currentlyResolvedTypeDeclaration; | 535 currentlyResolvedTypeDeclaration; |
534 currentlyResolvedTypeDeclaration = element; | 536 currentlyResolvedTypeDeclaration = element; |
535 var result = resolveTypeDeclaration(); | 537 var result = resolveTypeDeclaration(); |
536 if (previousResolvedTypeDeclaration == null) { | 538 if (previousResolvedTypeDeclaration == null) { |
537 do { | 539 do { |
538 while (!pendingClassesToBeResolved.isEmpty) { | 540 while (!pendingClassesToBeResolved.isEmpty) { |
539 pendingClassesToBeResolved.removeFirst().ensureResolved(resolution
); | 541 pendingClassesToBeResolved.removeFirst().ensureResolved(resolution
); |
540 } | 542 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 if (currentlyResolvedTypeDeclaration == null) { | 579 if (currentlyResolvedTypeDeclaration == null) { |
578 element.ensureResolved(resolution); | 580 element.ensureResolved(resolution); |
579 } else { | 581 } else { |
580 pendingClassesToBeResolved.add(element); | 582 pendingClassesToBeResolved.add(element); |
581 } | 583 } |
582 } | 584 } |
583 | 585 |
584 void resolveClassInternal(BaseClassElementX element, | 586 void resolveClassInternal(BaseClassElementX element, |
585 ResolutionRegistry registry) { | 587 ResolutionRegistry registry) { |
586 if (!element.isPatch) { | 588 if (!element.isPatch) { |
587 compiler.withCurrentElement(element, () => measure(() { | 589 reporter.withCurrentElement(element, () => measure(() { |
588 assert(element.resolutionState == STATE_NOT_STARTED); | 590 assert(element.resolutionState == STATE_NOT_STARTED); |
589 element.resolutionState = STATE_STARTED; | 591 element.resolutionState = STATE_STARTED; |
590 Node tree = element.parseNode(parsing); | 592 Node tree = element.parseNode(parsing); |
591 loadSupertypes(element, tree); | 593 loadSupertypes(element, tree); |
592 | 594 |
593 ClassResolverVisitor visitor = | 595 ClassResolverVisitor visitor = |
594 new ClassResolverVisitor(compiler, element, registry); | 596 new ClassResolverVisitor(compiler, element, registry); |
595 visitor.visit(tree); | 597 visitor.visit(tree); |
596 element.resolutionState = STATE_DONE; | 598 element.resolutionState = STATE_DONE; |
597 compiler.onClassResolved(element); | 599 compiler.onClassResolved(element); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 } | 632 } |
631 } | 633 } |
632 | 634 |
633 // Force resolution of metadata on non-instance members since they may be | 635 // Force resolution of metadata on non-instance members since they may be |
634 // inspected by the backend while emitting. Metadata on instance members is | 636 // inspected by the backend while emitting. Metadata on instance members is |
635 // handled as a result of processing instantiated class members in the | 637 // handled as a result of processing instantiated class members in the |
636 // enqueuer. | 638 // enqueuer. |
637 // TODO(ahe): Avoid this eager resolution. | 639 // TODO(ahe): Avoid this eager resolution. |
638 element.forEachMember((_, Element member) { | 640 element.forEachMember((_, Element member) { |
639 if (!member.isInstanceMember) { | 641 if (!member.isInstanceMember) { |
640 compiler.withCurrentElement(member, () { | 642 reporter.withCurrentElement(member, () { |
641 for (MetadataAnnotation metadata in member.implementation.metadata) { | 643 for (MetadataAnnotation metadata in member.implementation.metadata) { |
642 metadata.ensureResolved(resolution); | 644 metadata.ensureResolved(resolution); |
643 } | 645 } |
644 }); | 646 }); |
645 } | 647 } |
646 }); | 648 }); |
647 | 649 |
648 computeClassMember(element, Identifiers.call); | 650 computeClassMember(element, Identifiers.call); |
649 } | 651 } |
650 | 652 |
(...skipping 12 matching lines...) Expand all Loading... |
663 } else { | 665 } else { |
664 checkClassMembers(element); | 666 checkClassMembers(element); |
665 } | 667 } |
666 } | 668 } |
667 | 669 |
668 void checkMixinApplication(MixinApplicationElementX mixinApplication) { | 670 void checkMixinApplication(MixinApplicationElementX mixinApplication) { |
669 Modifiers modifiers = mixinApplication.modifiers; | 671 Modifiers modifiers = mixinApplication.modifiers; |
670 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; | 672 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; |
671 if (illegalFlags != 0) { | 673 if (illegalFlags != 0) { |
672 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); | 674 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); |
673 compiler.reportErrorMessage( | 675 reporter.reportErrorMessage( |
674 modifiers, | 676 modifiers, |
675 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, | 677 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, |
676 {'modifiers': illegalModifiers}); | 678 {'modifiers': illegalModifiers}); |
677 } | 679 } |
678 | 680 |
679 // In case of cyclic mixin applications, the mixin chain will have | 681 // In case of cyclic mixin applications, the mixin chain will have |
680 // been cut. If so, we have already reported the error to the | 682 // been cut. If so, we have already reported the error to the |
681 // user so we just return from here. | 683 // user so we just return from here. |
682 ClassElement mixin = mixinApplication.mixin; | 684 ClassElement mixin = mixinApplication.mixin; |
683 if (mixin == null) return; | 685 if (mixin == null) return; |
684 | 686 |
685 // Check that we're not trying to use Object as a mixin. | 687 // Check that we're not trying to use Object as a mixin. |
686 if (mixin.superclass == null) { | 688 if (mixin.superclass == null) { |
687 compiler.reportErrorMessage( | 689 reporter.reportErrorMessage( |
688 mixinApplication, | 690 mixinApplication, |
689 MessageKind.ILLEGAL_MIXIN_OBJECT); | 691 MessageKind.ILLEGAL_MIXIN_OBJECT); |
690 // Avoid reporting additional errors for the Object class. | 692 // Avoid reporting additional errors for the Object class. |
691 return; | 693 return; |
692 } | 694 } |
693 | 695 |
694 if (mixin.isEnumClass) { | 696 if (mixin.isEnumClass) { |
695 // Mixing in an enum has already caused a compile-time error. | 697 // Mixing in an enum has already caused a compile-time error. |
696 return; | 698 return; |
697 } | 699 } |
698 | 700 |
699 // Check that the mixed in class has Object as its superclass. | 701 // Check that the mixed in class has Object as its superclass. |
700 if (!mixin.superclass.isObject) { | 702 if (!mixin.superclass.isObject) { |
701 compiler.reportErrorMessage( | 703 reporter.reportErrorMessage( |
702 mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); | 704 mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); |
703 } | 705 } |
704 | 706 |
705 // Check that the mixed in class doesn't have any constructors and | 707 // Check that the mixed in class doesn't have any constructors and |
706 // make sure we aren't mixing in methods that use 'super'. | 708 // make sure we aren't mixing in methods that use 'super'. |
707 mixin.forEachLocalMember((AstElement member) { | 709 mixin.forEachLocalMember((AstElement member) { |
708 if (member.isGenerativeConstructor && !member.isSynthesized) { | 710 if (member.isGenerativeConstructor && !member.isSynthesized) { |
709 compiler.reportErrorMessage( | 711 reporter.reportErrorMessage( |
710 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); | 712 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); |
711 } else { | 713 } else { |
712 // Get the resolution tree and check that the resolved member | 714 // Get the resolution tree and check that the resolved member |
713 // doesn't use 'super'. This is the part of the 'super' mixin | 715 // doesn't use 'super'. This is the part of the 'super' mixin |
714 // check that happens when a function is resolved before the | 716 // check that happens when a function is resolved before the |
715 // mixin application has been performed. | 717 // mixin application has been performed. |
716 // TODO(johnniwinther): Obtain the [TreeElements] for [member] | 718 // TODO(johnniwinther): Obtain the [TreeElements] for [member] |
717 // differently. | 719 // differently. |
718 if (compiler.enqueuer.resolution.hasBeenResolved(member)) { | 720 if (compiler.enqueuer.resolution.hasBeenResolved(member)) { |
719 checkMixinSuperUses( | 721 checkMixinSuperUses( |
720 member.resolvedAst.elements, | 722 member.resolvedAst.elements, |
721 mixinApplication, | 723 mixinApplication, |
722 mixin); | 724 mixin); |
723 } | 725 } |
724 } | 726 } |
725 }); | 727 }); |
726 } | 728 } |
727 | 729 |
728 void checkMixinSuperUses(TreeElements resolutionTree, | 730 void checkMixinSuperUses(TreeElements resolutionTree, |
729 MixinApplicationElement mixinApplication, | 731 MixinApplicationElement mixinApplication, |
730 ClassElement mixin) { | 732 ClassElement mixin) { |
731 // TODO(johnniwinther): Avoid the use of [TreeElements] here. | 733 // TODO(johnniwinther): Avoid the use of [TreeElements] here. |
732 if (resolutionTree == null) return; | 734 if (resolutionTree == null) return; |
733 Iterable<Node> superUses = resolutionTree.superUses; | 735 Iterable<Node> superUses = resolutionTree.superUses; |
734 if (superUses.isEmpty) return; | 736 if (superUses.isEmpty) return; |
735 DiagnosticMessage error = compiler.createMessage( | 737 DiagnosticMessage error = reporter.createMessage( |
736 mixinApplication, | 738 mixinApplication, |
737 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, | 739 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, |
738 {'className': mixin.name}); | 740 {'className': mixin.name}); |
739 // Show the user the problematic uses of 'super' in the mixin. | 741 // Show the user the problematic uses of 'super' in the mixin. |
740 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 742 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
741 for (Node use in superUses) { | 743 for (Node use in superUses) { |
742 infos.add(compiler.createMessage( | 744 infos.add(reporter.createMessage( |
743 use, | 745 use, |
744 MessageKind.ILLEGAL_MIXIN_SUPER_USE)); | 746 MessageKind.ILLEGAL_MIXIN_SUPER_USE)); |
745 } | 747 } |
746 compiler.reportError(error, infos); | 748 reporter.reportError(error, infos); |
747 } | 749 } |
748 | 750 |
749 void checkClassMembers(ClassElement cls) { | 751 void checkClassMembers(ClassElement cls) { |
750 assert(invariant(cls, cls.isDeclaration)); | 752 assert(invariant(cls, cls.isDeclaration)); |
751 if (cls.isObject) return; | 753 if (cls.isObject) return; |
752 // TODO(johnniwinther): Should this be done on the implementation element as | 754 // TODO(johnniwinther): Should this be done on the implementation element as |
753 // well? | 755 // well? |
754 List<Element> constConstructors = <Element>[]; | 756 List<Element> constConstructors = <Element>[]; |
755 List<Element> nonFinalInstanceFields = <Element>[]; | 757 List<Element> nonFinalInstanceFields = <Element>[]; |
756 cls.forEachMember((holder, member) { | 758 cls.forEachMember((holder, member) { |
757 compiler.withCurrentElement(member, () { | 759 reporter.withCurrentElement(member, () { |
758 // Perform various checks as side effect of "computing" the type. | 760 // Perform various checks as side effect of "computing" the type. |
759 member.computeType(resolution); | 761 member.computeType(resolution); |
760 | 762 |
761 // Check modifiers. | 763 // Check modifiers. |
762 if (member.isFunction && member.modifiers.isFinal) { | 764 if (member.isFunction && member.modifiers.isFinal) { |
763 compiler.reportErrorMessage( | 765 reporter.reportErrorMessage( |
764 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 766 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
765 } | 767 } |
766 if (member.isConstructor) { | 768 if (member.isConstructor) { |
767 final mismatchedFlagsBits = | 769 final mismatchedFlagsBits = |
768 member.modifiers.flags & | 770 member.modifiers.flags & |
769 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 771 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
770 if (mismatchedFlagsBits != 0) { | 772 if (mismatchedFlagsBits != 0) { |
771 final mismatchedFlags = | 773 final mismatchedFlags = |
772 new Modifiers.withFlags(null, mismatchedFlagsBits); | 774 new Modifiers.withFlags(null, mismatchedFlagsBits); |
773 compiler.reportErrorMessage( | 775 reporter.reportErrorMessage( |
774 member, | 776 member, |
775 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 777 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
776 {'modifiers': mismatchedFlags}); | 778 {'modifiers': mismatchedFlags}); |
777 } | 779 } |
778 if (member.modifiers.isConst) { | 780 if (member.modifiers.isConst) { |
779 constConstructors.add(member); | 781 constConstructors.add(member); |
780 } | 782 } |
781 } | 783 } |
782 if (member.isField) { | 784 if (member.isField) { |
783 if (member.modifiers.isConst && !member.modifiers.isStatic) { | 785 if (member.modifiers.isConst && !member.modifiers.isStatic) { |
784 compiler.reportErrorMessage( | 786 reporter.reportErrorMessage( |
785 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); | 787 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); |
786 } | 788 } |
787 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { | 789 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { |
788 nonFinalInstanceFields.add(member); | 790 nonFinalInstanceFields.add(member); |
789 } | 791 } |
790 } | 792 } |
791 checkAbstractField(member); | 793 checkAbstractField(member); |
792 checkUserDefinableOperator(member); | 794 checkUserDefinableOperator(member); |
793 }); | 795 }); |
794 }); | 796 }); |
795 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { | 797 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { |
796 Spannable span = constConstructors.length > 1 | 798 Spannable span = constConstructors.length > 1 |
797 ? cls : constConstructors[0]; | 799 ? cls : constConstructors[0]; |
798 DiagnosticMessage error = compiler.createMessage( | 800 DiagnosticMessage error = reporter.createMessage( |
799 span, | 801 span, |
800 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, | 802 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, |
801 {'className': cls.name}); | 803 {'className': cls.name}); |
802 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 804 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
803 if (constConstructors.length > 1) { | 805 if (constConstructors.length > 1) { |
804 for (Element constructor in constConstructors) { | 806 for (Element constructor in constConstructors) { |
805 infos.add(compiler.createMessage( | 807 infos.add(reporter.createMessage( |
806 constructor, | 808 constructor, |
807 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); | 809 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); |
808 } | 810 } |
809 } | 811 } |
810 for (Element field in nonFinalInstanceFields) { | 812 for (Element field in nonFinalInstanceFields) { |
811 infos.add(compiler.createMessage( | 813 infos.add(reporter.createMessage( |
812 field, | 814 field, |
813 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); | 815 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); |
814 } | 816 } |
815 compiler.reportError(error, infos); | 817 reporter.reportError(error, infos); |
816 } | 818 } |
817 } | 819 } |
818 | 820 |
819 void checkAbstractField(Element member) { | 821 void checkAbstractField(Element member) { |
820 // Only check for getters. The test can only fail if there is both a setter | 822 // Only check for getters. The test can only fail if there is both a setter |
821 // and a getter with the same name, and we only need to check each abstract | 823 // and a getter with the same name, and we only need to check each abstract |
822 // field once, so we just ignore setters. | 824 // field once, so we just ignore setters. |
823 if (!member.isGetter) return; | 825 if (!member.isGetter) return; |
824 | 826 |
825 // Find the associated abstract field. | 827 // Find the associated abstract field. |
826 ClassElement classElement = member.enclosingClass; | 828 ClassElement classElement = member.enclosingClass; |
827 Element lookupElement = classElement.lookupLocalMember(member.name); | 829 Element lookupElement = classElement.lookupLocalMember(member.name); |
828 if (lookupElement == null) { | 830 if (lookupElement == null) { |
829 compiler.internalError(member, | 831 reporter.internalError(member, |
830 "No abstract field for accessor"); | 832 "No abstract field for accessor"); |
831 } else if (!identical(lookupElement.kind, ElementKind.ABSTRACT_FIELD)) { | 833 } else if (!identical(lookupElement.kind, ElementKind.ABSTRACT_FIELD)) { |
832 if (lookupElement.isErroneous || lookupElement.isAmbiguous) return; | 834 if (lookupElement.isErroneous || lookupElement.isAmbiguous) return; |
833 compiler.internalError(member, | 835 reporter.internalError(member, |
834 "Inaccessible abstract field for accessor"); | 836 "Inaccessible abstract field for accessor"); |
835 } | 837 } |
836 AbstractFieldElement field = lookupElement; | 838 AbstractFieldElement field = lookupElement; |
837 | 839 |
838 GetterElementX getter = field.getter; | 840 GetterElementX getter = field.getter; |
839 if (getter == null) return; | 841 if (getter == null) return; |
840 SetterElementX setter = field.setter; | 842 SetterElementX setter = field.setter; |
841 if (setter == null) return; | 843 if (setter == null) return; |
842 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 844 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
843 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 845 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
844 if (!identical(getterFlags, setterFlags)) { | 846 if (!identical(getterFlags, setterFlags)) { |
845 final mismatchedFlags = | 847 final mismatchedFlags = |
846 new Modifiers.withFlags(null, getterFlags ^ setterFlags); | 848 new Modifiers.withFlags(null, getterFlags ^ setterFlags); |
847 compiler.reportErrorMessage( | 849 reporter.reportErrorMessage( |
848 field.getter, | 850 field.getter, |
849 MessageKind.GETTER_MISMATCH, | 851 MessageKind.GETTER_MISMATCH, |
850 {'modifiers': mismatchedFlags}); | 852 {'modifiers': mismatchedFlags}); |
851 compiler.reportErrorMessage( | 853 reporter.reportErrorMessage( |
852 field.setter, | 854 field.setter, |
853 MessageKind.SETTER_MISMATCH, | 855 MessageKind.SETTER_MISMATCH, |
854 {'modifiers': mismatchedFlags}); | 856 {'modifiers': mismatchedFlags}); |
855 } | 857 } |
856 } | 858 } |
857 | 859 |
858 void checkUserDefinableOperator(Element member) { | 860 void checkUserDefinableOperator(Element member) { |
859 FunctionElement function = member.asFunctionElement(); | 861 FunctionElement function = member.asFunctionElement(); |
860 if (function == null) return; | 862 if (function == null) return; |
861 String value = member.name; | 863 String value = member.name; |
(...skipping 15 matching lines...) Expand all Loading... |
877 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; | 879 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; |
878 requiredParameterCount = 0; | 880 requiredParameterCount = 0; |
879 } else if (isBinaryOperator(value)) { | 881 } else if (isBinaryOperator(value)) { |
880 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; | 882 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; |
881 requiredParameterCount = 1; | 883 requiredParameterCount = 1; |
882 if (identical(value, '==')) checkOverrideHashCode(member); | 884 if (identical(value, '==')) checkOverrideHashCode(member); |
883 } else if (isTernaryOperator(value)) { | 885 } else if (isTernaryOperator(value)) { |
884 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; | 886 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; |
885 requiredParameterCount = 2; | 887 requiredParameterCount = 2; |
886 } else { | 888 } else { |
887 compiler.internalError(function, | 889 reporter.internalError(function, |
888 'Unexpected user defined operator $value'); | 890 'Unexpected user defined operator $value'); |
889 } | 891 } |
890 checkArity(function, requiredParameterCount, messageKind, isMinus); | 892 checkArity(function, requiredParameterCount, messageKind, isMinus); |
891 } | 893 } |
892 | 894 |
893 void checkOverrideHashCode(FunctionElement operatorEquals) { | 895 void checkOverrideHashCode(FunctionElement operatorEquals) { |
894 if (operatorEquals.isAbstract) return; | 896 if (operatorEquals.isAbstract) return; |
895 ClassElement cls = operatorEquals.enclosingClass; | 897 ClassElement cls = operatorEquals.enclosingClass; |
896 Element hashCodeImplementation = | 898 Element hashCodeImplementation = |
897 cls.lookupLocalMember('hashCode'); | 899 cls.lookupLocalMember('hashCode'); |
898 if (hashCodeImplementation != null) return; | 900 if (hashCodeImplementation != null) return; |
899 compiler.reportHintMessage( | 901 reporter.reportHintMessage( |
900 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, | 902 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, |
901 {'class': cls.name}); | 903 {'class': cls.name}); |
902 } | 904 } |
903 | 905 |
904 void checkArity(FunctionElement function, | 906 void checkArity(FunctionElement function, |
905 int requiredParameterCount, MessageKind messageKind, | 907 int requiredParameterCount, MessageKind messageKind, |
906 bool isMinus) { | 908 bool isMinus) { |
907 FunctionExpression node = function.node; | 909 FunctionExpression node = function.node; |
908 FunctionSignature signature = function.functionSignature; | 910 FunctionSignature signature = function.functionSignature; |
909 if (signature.requiredParameterCount != requiredParameterCount) { | 911 if (signature.requiredParameterCount != requiredParameterCount) { |
(...skipping 20 matching lines...) Expand all Loading... |
930 // int operator -(a, b) {} | 932 // int operator -(a, b) {} |
931 // ^ | 933 // ^ |
932 // | 934 // |
933 // since the correction might not be to remove 'b' but instead to | 935 // since the correction might not be to remove 'b' but instead to |
934 // remove 'a, b'. | 936 // remove 'a, b'. |
935 errorNode = node.parameters; | 937 errorNode = node.parameters; |
936 } else { | 938 } else { |
937 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; | 939 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; |
938 } | 940 } |
939 } | 941 } |
940 compiler.reportErrorMessage( | 942 reporter.reportErrorMessage( |
941 errorNode, messageKind, {'operatorName': function.name}); | 943 errorNode, messageKind, {'operatorName': function.name}); |
942 } | 944 } |
943 if (signature.optionalParameterCount != 0) { | 945 if (signature.optionalParameterCount != 0) { |
944 Node errorNode = | 946 Node errorNode = |
945 node.parameters.nodes.skip(signature.requiredParameterCount).head; | 947 node.parameters.nodes.skip(signature.requiredParameterCount).head; |
946 if (signature.optionalParametersAreNamed) { | 948 if (signature.optionalParametersAreNamed) { |
947 compiler.reportErrorMessage( | 949 reporter.reportErrorMessage( |
948 errorNode, | 950 errorNode, |
949 MessageKind.OPERATOR_NAMED_PARAMETERS, | 951 MessageKind.OPERATOR_NAMED_PARAMETERS, |
950 {'operatorName': function.name}); | 952 {'operatorName': function.name}); |
951 } else { | 953 } else { |
952 compiler.reportErrorMessage( | 954 reporter.reportErrorMessage( |
953 errorNode, | 955 errorNode, |
954 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, | 956 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, |
955 {'operatorName': function.name}); | 957 {'operatorName': function.name}); |
956 } | 958 } |
957 } | 959 } |
958 } | 960 } |
959 | 961 |
960 reportErrorWithContext(Element errorneousElement, | 962 reportErrorWithContext(Element errorneousElement, |
961 MessageKind errorMessage, | 963 MessageKind errorMessage, |
962 Element contextElement, | 964 Element contextElement, |
963 MessageKind contextMessage) { | 965 MessageKind contextMessage) { |
964 compiler.reportError( | 966 reporter.reportError( |
965 compiler.createMessage( | 967 reporter.createMessage( |
966 errorneousElement, | 968 errorneousElement, |
967 errorMessage, | 969 errorMessage, |
968 {'memberName': contextElement.name, | 970 {'memberName': contextElement.name, |
969 'className': contextElement.enclosingClass.name}), | 971 'className': contextElement.enclosingClass.name}), |
970 <DiagnosticMessage>[ | 972 <DiagnosticMessage>[ |
971 compiler.createMessage(contextElement, contextMessage), | 973 reporter.createMessage(contextElement, contextMessage), |
972 ]); | 974 ]); |
973 } | 975 } |
974 | 976 |
975 | 977 |
976 FunctionSignature resolveSignature(FunctionElementX element) { | 978 FunctionSignature resolveSignature(FunctionElementX element) { |
977 MessageKind defaultValuesError = null; | 979 MessageKind defaultValuesError = null; |
978 if (element.isFactoryConstructor) { | 980 if (element.isFactoryConstructor) { |
979 FunctionExpression body = element.parseNode(parsing); | 981 FunctionExpression body = element.parseNode(parsing); |
980 if (body.isRedirectingFactory) { | 982 if (body.isRedirectingFactory) { |
981 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; | 983 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; |
982 } | 984 } |
983 } | 985 } |
984 return compiler.withCurrentElement(element, () { | 986 return reporter.withCurrentElement(element, () { |
985 FunctionExpression node = element.parseNode(parsing); | 987 FunctionExpression node = element.parseNode(parsing); |
986 return measure(() => SignatureResolver.analyze( | 988 return measure(() => SignatureResolver.analyze( |
987 compiler, node.parameters, node.returnType, element, | 989 compiler, node.parameters, node.returnType, element, |
988 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 990 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
989 defaultValuesError: defaultValuesError, | 991 defaultValuesError: defaultValuesError, |
990 createRealParameters: true)); | 992 createRealParameters: true)); |
991 }); | 993 }); |
992 } | 994 } |
993 | 995 |
994 WorldImpact resolveTypedef(TypedefElementX element) { | 996 WorldImpact resolveTypedef(TypedefElementX element) { |
995 if (element.isResolved) return const WorldImpact(); | 997 if (element.isResolved) return const WorldImpact(); |
996 compiler.world.allTypedefs.add(element); | 998 compiler.world.allTypedefs.add(element); |
997 return _resolveTypeDeclaration(element, () { | 999 return _resolveTypeDeclaration(element, () { |
998 ResolutionRegistry registry = new ResolutionRegistry( | 1000 ResolutionRegistry registry = new ResolutionRegistry( |
999 compiler, _ensureTreeElements(element)); | 1001 compiler, _ensureTreeElements(element)); |
1000 return compiler.withCurrentElement(element, () { | 1002 return reporter.withCurrentElement(element, () { |
1001 return measure(() { | 1003 return measure(() { |
1002 assert(element.resolutionState == STATE_NOT_STARTED); | 1004 assert(element.resolutionState == STATE_NOT_STARTED); |
1003 element.resolutionState = STATE_STARTED; | 1005 element.resolutionState = STATE_STARTED; |
1004 Typedef node = element.parseNode(parsing); | 1006 Typedef node = element.parseNode(parsing); |
1005 TypedefResolverVisitor visitor = | 1007 TypedefResolverVisitor visitor = |
1006 new TypedefResolverVisitor(compiler, element, registry); | 1008 new TypedefResolverVisitor(compiler, element, registry); |
1007 visitor.visit(node); | 1009 visitor.visit(node); |
1008 element.resolutionState = STATE_DONE; | 1010 element.resolutionState = STATE_DONE; |
1009 return registry.worldImpact; | 1011 return registry.worldImpact; |
1010 }); | 1012 }); |
1011 }); | 1013 }); |
1012 }); | 1014 }); |
1013 } | 1015 } |
1014 | 1016 |
1015 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { | 1017 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { |
1016 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() { | 1018 reporter.withCurrentElement(annotation.annotatedElement, () => measure(() { |
1017 assert(annotation.resolutionState == STATE_NOT_STARTED); | 1019 assert(annotation.resolutionState == STATE_NOT_STARTED); |
1018 annotation.resolutionState = STATE_STARTED; | 1020 annotation.resolutionState = STATE_STARTED; |
1019 | 1021 |
1020 Node node = annotation.parseNode(parsing); | 1022 Node node = annotation.parseNode(parsing); |
1021 Element annotatedElement = annotation.annotatedElement; | 1023 Element annotatedElement = annotation.annotatedElement; |
1022 AnalyzableElement context = annotatedElement.analyzableElement; | 1024 AnalyzableElement context = annotatedElement.analyzableElement; |
1023 ClassElement classElement = annotatedElement.enclosingClass; | 1025 ClassElement classElement = annotatedElement.enclosingClass; |
1024 if (classElement != null) { | 1026 if (classElement != null) { |
1025 // The annotation is resolved in the scope of [classElement]. | 1027 // The annotation is resolved in the scope of [classElement]. |
1026 classElement.ensureResolved(resolution); | 1028 classElement.ensureResolved(resolution); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 TreeElements get treeElements { | 1075 TreeElements get treeElements { |
1074 assert(invariant(this, _treeElements !=null, | 1076 assert(invariant(this, _treeElements !=null, |
1075 message: "TreeElements have not been computed for $this.")); | 1077 message: "TreeElements have not been computed for $this.")); |
1076 return _treeElements; | 1078 return _treeElements; |
1077 } | 1079 } |
1078 | 1080 |
1079 void reuseElement() { | 1081 void reuseElement() { |
1080 _treeElements = null; | 1082 _treeElements = null; |
1081 } | 1083 } |
1082 } | 1084 } |
OLD | NEW |