| 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 |