| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 library dart2js.resolution; | 5 library dart2js.resolution; | 
| 6 | 6 | 
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; | 
| 8 | 8 | 
| 9 import '../common.dart'; | 9 import '../common.dart'; | 
| 10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 75   CommonElements get commonElements => resolution.commonElements; | 75   CommonElements get commonElements => resolution.commonElements; | 
| 76   ParsingContext get parsingContext => resolution.parsingContext; | 76   ParsingContext get parsingContext => resolution.parsingContext; | 
| 77   CompilerOptions get options => resolution.options; | 77   CompilerOptions get options => resolution.options; | 
| 78   ResolutionEnqueuer get enqueuer => resolution.enqueuer; | 78   ResolutionEnqueuer get enqueuer => resolution.enqueuer; | 
| 79   OpenWorld get world => enqueuer.worldBuilder; | 79   OpenWorld get world => enqueuer.worldBuilder; | 
| 80 | 80 | 
| 81   ResolutionImpact resolve(Element element) { | 81   ResolutionImpact resolve(Element element) { | 
| 82     return measure(() { | 82     return measure(() { | 
| 83       if (Elements.isMalformed(element)) { | 83       if (Elements.isMalformed(element)) { | 
| 84         // TODO(johnniwinther): Add a predicate for this. | 84         // TODO(johnniwinther): Add a predicate for this. | 
| 85         assert(invariant(element, element is! ErroneousElement, | 85         assert( | 
| 86             message: "Element $element expected to have parse errors.")); | 86             element is! ErroneousElement, | 
|  | 87             failedAt( | 
|  | 88                 element, "Element $element expected to have parse errors.")); | 
| 87         _ensureTreeElements(element); | 89         _ensureTreeElements(element); | 
| 88         return const ResolutionImpact(); | 90         return const ResolutionImpact(); | 
| 89       } | 91       } | 
| 90 | 92 | 
| 91       WorldImpact processMetadata([WorldImpact result]) { | 93       WorldImpact processMetadata([WorldImpact result]) { | 
| 92         for (MetadataAnnotation metadata in element.implementation.metadata) { | 94         for (MetadataAnnotation metadata in element.implementation.metadata) { | 
| 93           metadata.ensureResolved(resolution); | 95           metadata.ensureResolved(resolution); | 
| 94         } | 96         } | 
| 95         return result; | 97         return result; | 
| 96       } | 98       } | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 113         TypedefElement typdef = element; | 115         TypedefElement typdef = element; | 
| 114         return processMetadata(resolveTypedef(typdef)); | 116         return processMetadata(resolveTypedef(typdef)); | 
| 115       } | 117       } | 
| 116 | 118 | 
| 117       reporter.internalError(element, "resolve($element) not implemented."); | 119       reporter.internalError(element, "resolve($element) not implemented."); | 
| 118     }); | 120     }); | 
| 119   } | 121   } | 
| 120 | 122 | 
| 121   void resolveRedirectingConstructor(InitializerResolver resolver, Node node, | 123   void resolveRedirectingConstructor(InitializerResolver resolver, Node node, | 
| 122       FunctionElement constructor, FunctionElement redirection) { | 124       FunctionElement constructor, FunctionElement redirection) { | 
| 123     assert(invariant(node, constructor.isImplementation, | 125     assert( | 
| 124         message: 'Redirecting constructors must be resolved on implementation ' | 126         constructor.isImplementation, | 
|  | 127         failedAt( | 
|  | 128             node, | 
|  | 129             'Redirecting constructors must be resolved on implementation ' | 
| 125             'elements.')); | 130             'elements.')); | 
| 126     Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 131     Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 
| 127     seen.add(constructor); | 132     seen.add(constructor); | 
| 128     while (redirection != null) { | 133     while (redirection != null) { | 
| 129       // Ensure that we follow redirections through implementation elements. | 134       // Ensure that we follow redirections through implementation elements. | 
| 130       redirection = redirection.implementation; | 135       redirection = redirection.implementation; | 
| 131       if (redirection.isError) { | 136       if (redirection.isError) { | 
| 132         break; | 137         break; | 
| 133       } | 138       } | 
| 134       if (seen.contains(redirection)) { | 139       if (seen.contains(redirection)) { | 
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 286       } | 291       } | 
| 287 | 292 | 
| 288       resolution.target.resolveNativeMember(element, registry.impactBuilder); | 293       resolution.target.resolveNativeMember(element, registry.impactBuilder); | 
| 289 | 294 | 
| 290       return registry.impactBuilder; | 295       return registry.impactBuilder; | 
| 291     }); | 296     }); | 
| 292   } | 297   } | 
| 293 | 298 | 
| 294   /// Returns `true` if [element] has been processed by the resolution enqueuer. | 299   /// Returns `true` if [element] has been processed by the resolution enqueuer. | 
| 295   bool _hasBeenProcessed(MemberElement element) { | 300   bool _hasBeenProcessed(MemberElement element) { | 
| 296     assert(invariant(element, element == element.analyzableElement.declaration, | 301     assert(element == element.analyzableElement.declaration, | 
| 297         message: "Unexpected element $element")); | 302         failedAt(element, "Unexpected element $element")); | 
| 298     return enqueuer.processedEntities.contains(element); | 303     return enqueuer.processedEntities.contains(element); | 
| 299   } | 304   } | 
| 300 | 305 | 
| 301   WorldImpact resolveMethodElement(FunctionElementX element) { | 306   WorldImpact resolveMethodElement(FunctionElementX element) { | 
| 302     assert(invariant(element, element.isDeclaration)); | 307     assert(element.isDeclaration, failedAt(element)); | 
| 303     return reporter.withCurrentElement(element, () { | 308     return reporter.withCurrentElement(element, () { | 
| 304       if (_hasBeenProcessed(element)) { | 309       if (_hasBeenProcessed(element)) { | 
| 305         // TODO(karlklose): Remove the check for [isConstructor]. [elememts] | 310         // TODO(karlklose): Remove the check for [isConstructor]. [elememts] | 
| 306         // should never be non-null, not even for constructors. | 311         // should never be non-null, not even for constructors. | 
| 307         assert(invariant(element, element.isConstructor, | 312         assert( | 
| 308             message: 'Non-constructor element $element ' | 313             element.isConstructor, | 
| 309                 'has already been analyzed.')); | 314             failedAt(element, | 
|  | 315                 'Non-constructor element $element has already been analyzed.')); | 
| 310         return const ResolutionImpact(); | 316         return const ResolutionImpact(); | 
| 311       } | 317       } | 
| 312       if (element.isSynthesized) { | 318       if (element.isSynthesized) { | 
| 313         if (element.isGenerativeConstructor) { | 319         if (element.isGenerativeConstructor) { | 
| 314           ResolutionRegistry registry = | 320           ResolutionRegistry registry = | 
| 315               new ResolutionRegistry(this.target, _ensureTreeElements(element)); | 321               new ResolutionRegistry(this.target, _ensureTreeElements(element)); | 
| 316           ConstructorElement constructor = element.asFunctionElement(); | 322           ConstructorElement constructor = element.asFunctionElement(); | 
| 317           ConstructorElement target = constructor.definingConstructor; | 323           ConstructorElement target = constructor.definingConstructor; | 
| 318           // Ensure the signature of the synthesized element is | 324           // Ensure the signature of the synthesized element is | 
| 319           // resolved. This is the only place where the resolver is | 325           // resolved. This is the only place where the resolver is | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 374       } | 380       } | 
| 375       ResolverVisitor visitor = visitorFor(element); | 381       ResolverVisitor visitor = visitorFor(element); | 
| 376       ResolutionRegistry registry = visitor.registry; | 382       ResolutionRegistry registry = visitor.registry; | 
| 377       // TODO(johnniwinther): Maybe remove this when placeholderCollector | 383       // TODO(johnniwinther): Maybe remove this when placeholderCollector | 
| 378       // migrates to the backend ast. | 384       // migrates to the backend ast. | 
| 379       registry.defineElement(element.definition, element); | 385       registry.defineElement(element.definition, element); | 
| 380       // TODO(johnniwinther): Share the resolved type between all variables | 386       // TODO(johnniwinther): Share the resolved type between all variables | 
| 381       // declared in the same declaration. | 387       // declared in the same declaration. | 
| 382       if (tree.type != null) { | 388       if (tree.type != null) { | 
| 383         ResolutionDartType type = visitor.resolveTypeAnnotation(tree.type); | 389         ResolutionDartType type = visitor.resolveTypeAnnotation(tree.type); | 
| 384         assert(invariant( | 390         assert( | 
| 385             element, |  | 
| 386             element.variables.type == null || | 391             element.variables.type == null || | 
| 387                 // Crude check but we have no equivalence relation that | 392                 // Crude check but we have no equivalence relation that | 
| 388                 // equates malformed types, like matching creations of type | 393                 // equates malformed types, like matching creations of type | 
| 389                 // `Foo<Unresolved>`. | 394                 // `Foo<Unresolved>`. | 
| 390                 element.variables.type.toString() == type.toString(), | 395                 element.variables.type.toString() == type.toString(), | 
| 391             message: "Unexpected type computed for $element. " | 396             failedAt( | 
|  | 397                 element, | 
|  | 398                 "Unexpected type computed for $element. " | 
| 392                 "Was ${element.variables.type}, computed $type.")); | 399                 "Was ${element.variables.type}, computed $type.")); | 
| 393         element.variables.type = type; | 400         element.variables.type = type; | 
| 394       } else if (element.variables.type == null) { | 401       } else if (element.variables.type == null) { | 
| 395         // Only assign the dynamic type if the element has no known type. This | 402         // Only assign the dynamic type if the element has no known type. This | 
| 396         // happens for enum fields where the type is known but is not in the | 403         // happens for enum fields where the type is known but is not in the | 
| 397         // synthesized AST. | 404         // synthesized AST. | 
| 398         element.variables.type = const ResolutionDynamicType(); | 405         element.variables.type = const ResolutionDynamicType(); | 
| 399       } else { | 406       } else { | 
| 400         registry.registerCheckedModeCheck(element.variables.type); | 407         registry.registerCheckedModeCheck(element.variables.type); | 
| 401       } | 408       } | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 453       reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); | 460       reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); | 
| 454     } | 461     } | 
| 455     return type; | 462     return type; | 
| 456   } | 463   } | 
| 457 | 464 | 
| 458   ResolutionDartType _resolveReturnType( | 465   ResolutionDartType _resolveReturnType( | 
| 459       Element element, TypeAnnotation annotation) { | 466       Element element, TypeAnnotation annotation) { | 
| 460     if (annotation == null) return const ResolutionDynamicType(); | 467     if (annotation == null) return const ResolutionDynamicType(); | 
| 461     ResolutionDartType result = | 468     ResolutionDartType result = | 
| 462         visitorFor(element).resolveTypeAnnotation(annotation); | 469         visitorFor(element).resolveTypeAnnotation(annotation); | 
| 463     assert(invariant(annotation, result != null, | 470     assert(result != null, | 
| 464         message: "No type computed for $annotation.")); | 471         failedAt(annotation, "No type computed for $annotation.")); | 
| 465     if (result == null) { | 472     if (result == null) { | 
| 466       // TODO(karklose): warning. | 473       // TODO(karklose): warning. | 
| 467       return const ResolutionDynamicType(); | 474       return const ResolutionDynamicType(); | 
| 468     } | 475     } | 
| 469     return result; | 476     return result; | 
| 470   } | 477   } | 
| 471 | 478 | 
| 472   void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { | 479   void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { | 
| 473     ConstructorElement target = constructor; | 480     ConstructorElement target = constructor; | 
| 474     ResolutionDartType targetType; | 481     ResolutionDartType targetType; | 
| 475     List<ConstructorElement> seen = new List<ConstructorElement>(); | 482     List<ConstructorElement> seen = new List<ConstructorElement>(); | 
| 476     bool isMalformed = false; | 483     bool isMalformed = false; | 
| 477     // Follow the chain of redirections and check for cycles. | 484     // Follow the chain of redirections and check for cycles. | 
| 478     while (target.isRedirectingFactory) { | 485     while (target.isRedirectingFactory) { | 
| 479       if (target.hasEffectiveTarget) { | 486       if (target.hasEffectiveTarget) { | 
| 480         // We found a constructor that already has been processed. | 487         // We found a constructor that already has been processed. | 
| 481         // TODO(johnniwinther): Should `effectiveTargetType` be part of the | 488         // TODO(johnniwinther): Should `effectiveTargetType` be part of the | 
| 482         // interface? | 489         // interface? | 
| 483         targetType = | 490         targetType = | 
| 484             target.computeEffectiveTargetType(target.enclosingClass.thisType); | 491             target.computeEffectiveTargetType(target.enclosingClass.thisType); | 
| 485         assert(invariant(target, targetType != null, | 492         assert( | 
| 486             message: 'Redirection target type has not been computed for ' | 493             targetType != null, | 
| 487                 '$target')); | 494             failedAt(target, | 
|  | 495                 'Redirection target type has not been computed for $target')); | 
| 488         target = target.effectiveTarget; | 496         target = target.effectiveTarget; | 
| 489         break; | 497         break; | 
| 490       } | 498       } | 
| 491 | 499 | 
| 492       Element nextTarget = target.immediateRedirectionTarget; | 500       Element nextTarget = target.immediateRedirectionTarget; | 
| 493 | 501 | 
| 494       if (seen.contains(nextTarget)) { | 502       if (seen.contains(nextTarget)) { | 
| 495         reporter.reportErrorMessage( | 503         reporter.reportErrorMessage( | 
| 496             node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 504             node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 
| 497         targetType = target.enclosingClass.thisType; | 505         targetType = target.enclosingClass.thisType; | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 515     } | 523     } | 
| 516 | 524 | 
| 517     // [target] is now the actual target of the redirections.  Run through | 525     // [target] is now the actual target of the redirections.  Run through | 
| 518     // the constructors again and set their [redirectionTarget], so that we | 526     // the constructors again and set their [redirectionTarget], so that we | 
| 519     // do not have to run the loop for these constructors again. Furthermore, | 527     // do not have to run the loop for these constructors again. Furthermore, | 
| 520     // compute [redirectionTargetType] for each factory by computing the | 528     // compute [redirectionTargetType] for each factory by computing the | 
| 521     // substitution of the target type with respect to the factory type. | 529     // substitution of the target type with respect to the factory type. | 
| 522     while (!seen.isEmpty) { | 530     while (!seen.isEmpty) { | 
| 523       ConstructorElementX factory = seen.removeLast(); | 531       ConstructorElementX factory = seen.removeLast(); | 
| 524       ResolvedAst resolvedAst = factory.resolvedAst; | 532       ResolvedAst resolvedAst = factory.resolvedAst; | 
| 525       assert(invariant(node, resolvedAst != null, | 533       assert( | 
| 526           message: 'No ResolvedAst for $factory.')); | 534           resolvedAst != null, failedAt(node, 'No ResolvedAst for $factory.')); | 
| 527       RedirectingFactoryBody redirectionNode = resolvedAst.body; | 535       RedirectingFactoryBody redirectionNode = resolvedAst.body; | 
| 528       ResolutionDartType factoryType = | 536       ResolutionDartType factoryType = | 
| 529           resolvedAst.elements.getType(redirectionNode); | 537           resolvedAst.elements.getType(redirectionNode); | 
| 530       if (!factoryType.isDynamic) { | 538       if (!factoryType.isDynamic) { | 
| 531         targetType = targetType.substByContext(factoryType); | 539         targetType = targetType.substByContext(factoryType); | 
| 532       } | 540       } | 
| 533       factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); | 541       factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); | 
| 534     } | 542     } | 
| 535   } | 543   } | 
| 536 | 544 | 
| 537   /** | 545   /** | 
| 538    * Load and resolve the supertypes of [cls]. | 546    * Load and resolve the supertypes of [cls]. | 
| 539    * | 547    * | 
| 540    * Warning: do not call this method directly. It should only be | 548    * Warning: do not call this method directly. It should only be | 
| 541    * called by [resolveClass] and [ClassSupertypeResolver]. | 549    * called by [resolveClass] and [ClassSupertypeResolver]. | 
| 542    */ | 550    */ | 
| 543   void loadSupertypes(BaseClassElementX cls, Spannable from) { | 551   void loadSupertypes(BaseClassElementX cls, Spannable from) { | 
| 544     measure(() { | 552     measure(() { | 
| 545       if (cls.supertypeLoadState == STATE_DONE) return; | 553       if (cls.supertypeLoadState == STATE_DONE) return; | 
| 546       if (cls.supertypeLoadState == STATE_STARTED) { | 554       if (cls.supertypeLoadState == STATE_STARTED) { | 
| 547         reporter.reportErrorMessage( | 555         reporter.reportErrorMessage( | 
| 548             from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); | 556             from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); | 
| 549         cls.supertypeLoadState = STATE_DONE; | 557         cls.supertypeLoadState = STATE_DONE; | 
| 550         cls.hasIncompleteHierarchy = true; | 558         cls.hasIncompleteHierarchy = true; | 
| 551         ClassElement objectClass = commonElements.objectClass; | 559         ClassElement objectClass = commonElements.objectClass; | 
| 552         cls.allSupertypesAndSelf = objectClass.allSupertypesAndSelf | 560         cls.allSupertypesAndSelf = objectClass.allSupertypesAndSelf | 
| 553             .extendClass(cls.computeType(resolution)); | 561             .extendClass(cls.computeType(resolution)); | 
| 554         cls.supertype = cls.allSupertypes.head; | 562         cls.supertype = cls.allSupertypes.head; | 
| 555         assert(invariant(from, cls.supertype != null, | 563         assert(cls.supertype != null, | 
| 556             message: 'Missing supertype on cyclic class $cls.')); | 564             failedAt(from, 'Missing supertype on cyclic class $cls.')); | 
| 557         cls.interfaces = const Link<ResolutionDartType>(); | 565         cls.interfaces = const Link<ResolutionDartType>(); | 
| 558         return; | 566         return; | 
| 559       } | 567       } | 
| 560       cls.supertypeLoadState = STATE_STARTED; | 568       cls.supertypeLoadState = STATE_STARTED; | 
| 561       reporter.withCurrentElement(cls, () { | 569       reporter.withCurrentElement(cls, () { | 
| 562         // TODO(ahe): Cache the node in cls. | 570         // TODO(ahe): Cache the node in cls. | 
| 563         cls | 571         cls | 
| 564             .parseNode(parsingContext) | 572             .parseNode(parsingContext) | 
| 565             .accept(new ClassSupertypeResolver(resolution, cls)); | 573             .accept(new ClassSupertypeResolver(resolution, cls)); | 
| 566         if (cls.supertypeLoadState != STATE_DONE) { | 574         if (cls.supertypeLoadState != STATE_DONE) { | 
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 796     // Show the user the problematic uses of 'super' in the mixin. | 804     // Show the user the problematic uses of 'super' in the mixin. | 
| 797     List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 805     List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 
| 798     for (SourceSpan use in superUses) { | 806     for (SourceSpan use in superUses) { | 
| 799       infos.add( | 807       infos.add( | 
| 800           reporter.createMessage(use, MessageKind.ILLEGAL_MIXIN_SUPER_USE)); | 808           reporter.createMessage(use, MessageKind.ILLEGAL_MIXIN_SUPER_USE)); | 
| 801     } | 809     } | 
| 802     reporter.reportError(error, infos); | 810     reporter.reportError(error, infos); | 
| 803   } | 811   } | 
| 804 | 812 | 
| 805   void checkClassMembers(ClassElement cls) { | 813   void checkClassMembers(ClassElement cls) { | 
| 806     assert(invariant(cls, cls.isDeclaration)); | 814     assert(cls.isDeclaration, failedAt(cls)); | 
| 807     if (cls.isObject) return; | 815     if (cls.isObject) return; | 
| 808     // TODO(johnniwinther): Should this be done on the implementation element as | 816     // TODO(johnniwinther): Should this be done on the implementation element as | 
| 809     // well? | 817     // well? | 
| 810     List<Element> constConstructors = <Element>[]; | 818     List<Element> constConstructors = <Element>[]; | 
| 811     List<Element> nonFinalInstanceFields = <Element>[]; | 819     List<Element> nonFinalInstanceFields = <Element>[]; | 
| 812     cls.forEachMember((holder, dynamic member) { | 820     cls.forEachMember((holder, dynamic member) { | 
| 813       reporter.withCurrentElement(member, () { | 821       reporter.withCurrentElement(member, () { | 
| 814         // Perform various checks as side effect of "computing" the type. | 822         // Perform various checks as side effect of "computing" the type. | 
| 815         member.computeType(resolution); | 823         member.computeType(resolution); | 
| 816 | 824 | 
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1072               annotation.resolutionState = STATE_STARTED; | 1080               annotation.resolutionState = STATE_STARTED; | 
| 1073 | 1081 | 
| 1074               Node node = annotation.parseNode(parsingContext); | 1082               Node node = annotation.parseNode(parsingContext); | 
| 1075               Element annotatedElement = annotation.annotatedElement; | 1083               Element annotatedElement = annotation.annotatedElement; | 
| 1076               AnalyzableElement context = annotatedElement.analyzableElement; | 1084               AnalyzableElement context = annotatedElement.analyzableElement; | 
| 1077               ClassElement classElement = annotatedElement.enclosingClass; | 1085               ClassElement classElement = annotatedElement.enclosingClass; | 
| 1078               if (classElement != null) { | 1086               if (classElement != null) { | 
| 1079                 // The annotation is resolved in the scope of [classElement]. | 1087                 // The annotation is resolved in the scope of [classElement]. | 
| 1080                 classElement.ensureResolved(resolution); | 1088                 classElement.ensureResolved(resolution); | 
| 1081               } | 1089               } | 
| 1082               assert(invariant(node, context != null, | 1090               assert( | 
| 1083                   message: "No context found for metadata annotation " | 1091                   context != null, | 
|  | 1092                   failedAt( | 
|  | 1093                       node, | 
|  | 1094                       "No context found for metadata annotation " | 
| 1084                       "on $annotatedElement.")); | 1095                       "on $annotatedElement.")); | 
| 1085               ResolverVisitor visitor = | 1096               ResolverVisitor visitor = | 
| 1086                   visitorFor(context, useEnclosingScope: true); | 1097                   visitorFor(context, useEnclosingScope: true); | 
| 1087               ResolutionRegistry registry = visitor.registry; | 1098               ResolutionRegistry registry = visitor.registry; | 
| 1088               node.accept(visitor); | 1099               node.accept(visitor); | 
| 1089               // TODO(johnniwinther): Avoid passing the [TreeElements] to | 1100               // TODO(johnniwinther): Avoid passing the [TreeElements] to | 
| 1090               // [compileMetadata]. | 1101               // [compileMetadata]. | 
| 1091               ConstantExpression constant = constantCompiler.compileMetadata( | 1102               ConstantExpression constant = constantCompiler.compileMetadata( | 
| 1092                   annotation, node, registry.mapping); | 1103                   annotation, node, registry.mapping); | 
| 1093               switch (constant.kind) { | 1104               switch (constant.kind) { | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1141   } | 1152   } | 
| 1142   return element._treeElements; | 1153   return element._treeElements; | 
| 1143 } | 1154 } | 
| 1144 | 1155 | 
| 1145 abstract class AnalyzableElementX implements AnalyzableElement { | 1156 abstract class AnalyzableElementX implements AnalyzableElement { | 
| 1146   TreeElements _treeElements; | 1157   TreeElements _treeElements; | 
| 1147 | 1158 | 
| 1148   bool get hasTreeElements => _treeElements != null; | 1159   bool get hasTreeElements => _treeElements != null; | 
| 1149 | 1160 | 
| 1150   TreeElements get treeElements { | 1161   TreeElements get treeElements { | 
| 1151     assert(invariant(this, _treeElements != null, | 1162     assert(_treeElements != null, | 
| 1152         message: "TreeElements have not been computed for $this.")); | 1163         failedAt(this, "TreeElements have not been computed for $this.")); | 
| 1153     return _treeElements; | 1164     return _treeElements; | 
| 1154   } | 1165   } | 
| 1155 | 1166 | 
| 1156   void reuseElement() { | 1167   void reuseElement() { | 
| 1157     _treeElements = null; | 1168     _treeElements = null; | 
| 1158   } | 1169   } | 
| 1159 } | 1170 } | 
| OLD | NEW | 
|---|