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