| 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 Element get currentElement; | 8 Element get currentElement; |
| 9 Setlet<Node> get superUses; | 9 Setlet<Node> get superUses; |
| 10 | 10 |
| 11 /// Iterables of the dependencies that this [TreeElement] records of | 11 /// Iterables of the dependencies that this [TreeElement] records of |
| 12 /// [currentElement]. | 12 /// [currentElement]. |
| 13 Iterable<Element> get allElements; | 13 Iterable<Element> get allElements; |
| 14 void forEachConstantNode(f(Node n, Constant c)); | 14 Iterable<Constant> get allConstants; |
| 15 | 15 |
| 16 /// A set of additional dependencies. See [registerDependency] below. | 16 /// A set of additional dependencies. See [registerDependency] below. |
| 17 Setlet<Element> get otherDependencies; | 17 Setlet<Element> get otherDependencies; |
| 18 | 18 |
| 19 Element operator[](Node node); | 19 Element operator[](Node node); |
| 20 Selector getSelector(Send send); | 20 Selector getSelector(Send send); |
| 21 Selector getGetterSelectorInComplexSendSet(SendSet node); | 21 Selector getGetterSelectorInComplexSendSet(SendSet node); |
| 22 Selector getOperatorSelectorInComplexSendSet(SendSet node); | 22 Selector getOperatorSelectorInComplexSendSet(SendSet node); |
| 23 DartType getType(Node node); | 23 DartType getType(Node node); |
| 24 void setSelector(Node node, Selector selector); | 24 void setSelector(Node node, Selector selector); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 Map<VariableElement, List<Node>> accessMap = | 238 Map<VariableElement, List<Node>> accessMap = |
| 239 accessedByClosureIn.putIfAbsent(contextNode, | 239 accessedByClosureIn.putIfAbsent(contextNode, |
| 240 () => new Map<VariableElement, List<Node>>()); | 240 () => new Map<VariableElement, List<Node>>()); |
| 241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode); | 241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode); |
| 242 } | 242 } |
| 243 | 243 |
| 244 String toString() => 'TreeElementMapping($currentElement)'; | 244 String toString() => 'TreeElementMapping($currentElement)'; |
| 245 | 245 |
| 246 Iterable<Element> get allElements => elements; | 246 Iterable<Element> get allElements => elements; |
| 247 | 247 |
| 248 void forEachConstantNode(f(Node n, Constant c)) => constants.forEach(f); | 248 Iterable<Constant> get allConstants => constants.values; |
| 249 } | 249 } |
| 250 | 250 |
| 251 class ResolverTask extends CompilerTask { | 251 class ResolverTask extends CompilerTask { |
| 252 final ConstantCompiler constantCompiler; | 252 ResolverTask(Compiler compiler) : super(compiler); |
| 253 | |
| 254 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); | |
| 255 | 253 |
| 256 String get name => 'Resolver'; | 254 String get name => 'Resolver'; |
| 257 | 255 |
| 258 TreeElements resolve(Element element) { | 256 TreeElements resolve(Element element) { |
| 259 return measure(() { | 257 return measure(() { |
| 260 if (Elements.isErroneousElement(element)) return null; | 258 if (Elements.isErroneousElement(element)) return null; |
| 261 | 259 |
| 262 for (MetadataAnnotation metadata in element.metadata) { | 260 for (MetadataAnnotation metadata in element.metadata) { |
| 263 metadata.ensureResolved(compiler); | 261 metadata.ensureResolved(compiler); |
| 264 } | 262 } |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); | 576 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); |
| 579 } else if (modifiers.isFinal() && !element.isInstanceMember()) { | 577 } else if (modifiers.isFinal() && !element.isInstanceMember()) { |
| 580 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); | 578 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); |
| 581 } else { | 579 } else { |
| 582 compiler.enqueuer.resolution.registerInstantiatedClass( | 580 compiler.enqueuer.resolution.registerInstantiatedClass( |
| 583 compiler.nullClass, visitor.mapping); | 581 compiler.nullClass, visitor.mapping); |
| 584 } | 582 } |
| 585 | 583 |
| 586 if (Elements.isStaticOrTopLevelField(element)) { | 584 if (Elements.isStaticOrTopLevelField(element)) { |
| 587 visitor.addDeferredAction(element, () { | 585 visitor.addDeferredAction(element, () { |
| 588 if (element.modifiers.isConst()) { | 586 compiler.constantHandler.compileVariable( |
| 589 constantCompiler.compileConstant(element); | 587 element, isConst: element.modifiers.isConst()); |
| 590 } else { | |
| 591 constantCompiler.compileVariable(element); | |
| 592 } | |
| 593 }); | 588 }); |
| 594 if (initializer != null) { | 589 if (initializer != null) { |
| 595 if (!element.modifiers.isConst()) { | 590 if (!element.modifiers.isConst()) { |
| 596 // TODO(johnniwinther): Determine the const-ness eagerly to avoid | 591 // TODO(johnniwinther): Determine the const-ness eagerly to avoid |
| 597 // unnecessary registrations. | 592 // unnecessary registrations. |
| 598 compiler.backend.registerLazyField(visitor.mapping); | 593 compiler.backend.registerLazyField(visitor.mapping); |
| 599 } | 594 } |
| 600 } | 595 } |
| 601 } | 596 } |
| 602 | 597 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 Node node = annotation.parseNode(compiler); | 1172 Node node = annotation.parseNode(compiler); |
| 1178 // TODO(johnniwinther): Find the right analyzable element to hold the | 1173 // TODO(johnniwinther): Find the right analyzable element to hold the |
| 1179 // [TreeElements] for the annotation. | 1174 // [TreeElements] for the annotation. |
| 1180 Element annotatedElement = annotation.annotatedElement; | 1175 Element annotatedElement = annotation.annotatedElement; |
| 1181 Element context = annotatedElement.enclosingElement; | 1176 Element context = annotatedElement.enclosingElement; |
| 1182 if (context == null) { | 1177 if (context == null) { |
| 1183 context = annotatedElement; | 1178 context = annotatedElement; |
| 1184 } | 1179 } |
| 1185 ResolverVisitor visitor = visitorFor(context); | 1180 ResolverVisitor visitor = visitorFor(context); |
| 1186 node.accept(visitor); | 1181 node.accept(visitor); |
| 1187 annotation.value = | 1182 annotation.value = compiler.constantHandler.compileNodeWithDefinitions( |
| 1188 constantCompiler.compileMetadata(annotation, node, visitor.mapping); | 1183 node, visitor.mapping, isConst: true); |
| 1189 // TODO(johnniwinther): Register the relation between the annotation | 1184 compiler.backend.registerMetadataConstant(annotation.value, |
| 1190 // and the annotated element instead. This will allow the backed to | 1185 visitor.mapping); |
| 1191 // retrieve the backend constant and only registered metadata on the | 1186 |
| 1192 // elements for which it is needed. (Issue 17732). | |
| 1193 compiler.backend.registerMetadataConstant( | |
| 1194 annotation.value, visitor.mapping); | |
| 1195 annotation.resolutionState = STATE_DONE; | 1187 annotation.resolutionState = STATE_DONE; |
| 1196 })); | 1188 })); |
| 1197 } | 1189 } |
| 1198 | 1190 |
| 1199 error(Spannable node, MessageKind kind, [arguments = const {}]) { | 1191 error(Spannable node, MessageKind kind, [arguments = const {}]) { |
| 1200 // TODO(ahe): Make non-fatal. | 1192 // TODO(ahe): Make non-fatal. |
| 1201 compiler.reportFatalError(node, kind, arguments); | 1193 compiler.reportFatalError(node, kind, arguments); |
| 1202 } | 1194 } |
| 1203 | 1195 |
| 1204 Link<MetadataAnnotation> resolveMetadata(Element element, | 1196 Link<MetadataAnnotation> resolveMetadata(Element element, |
| 1205 VariableDefinitions node) { | 1197 VariableDefinitions node) { |
| 1206 LinkBuilder<MetadataAnnotation> metadata = | 1198 LinkBuilder<MetadataAnnotation> metadata = |
| 1207 new LinkBuilder<MetadataAnnotation>(); | 1199 new LinkBuilder<MetadataAnnotation>(); |
| 1208 for (Metadata annotation in node.metadata.nodes) { | 1200 for (Metadata annotation in node.metadata.nodes) { |
| 1209 ParameterMetadataAnnotation metadataAnnotation = | 1201 ParameterMetadataAnnotation metadataAnnotation = |
| 1210 new ParameterMetadataAnnotation(annotation); | 1202 new ParameterMetadataAnnotation(annotation); |
| 1211 metadataAnnotation.annotatedElement = element; | 1203 metadataAnnotation.annotatedElement = element; |
| 1212 metadata.addLast(metadataAnnotation.ensureResolved(compiler)); | 1204 metadata.addLast(metadataAnnotation.ensureResolved(compiler)); |
| 1213 } | 1205 } |
| 1214 return metadata.toLink(); | 1206 return metadata.toLink(); |
| 1215 } | 1207 } |
| 1216 } | 1208 } |
| 1217 | 1209 |
| 1210 class ConstantMapper extends Visitor { |
| 1211 final Map<Constant, Node> constantToNodeMap = new Map<Constant, Node>(); |
| 1212 final CompileTimeConstantEvaluator evaluator; |
| 1213 |
| 1214 ConstantMapper(ConstantHandler handler, |
| 1215 TreeElements elements, |
| 1216 Compiler compiler) |
| 1217 : evaluator = new CompileTimeConstantEvaluator( |
| 1218 handler, elements, compiler, isConst: false); |
| 1219 |
| 1220 visitNode(Node node) { |
| 1221 Constant constant = evaluator.evaluate(node); |
| 1222 if (constant != null) constantToNodeMap[constant] = node; |
| 1223 node.visitChildren(this); |
| 1224 } |
| 1225 } |
| 1226 |
| 1218 class InitializerResolver { | 1227 class InitializerResolver { |
| 1219 final ResolverVisitor visitor; | 1228 final ResolverVisitor visitor; |
| 1220 final Map<Element, Node> initialized; | 1229 final Map<Element, Node> initialized; |
| 1221 Link<Node> initializers; | 1230 Link<Node> initializers; |
| 1222 bool hasSuper; | 1231 bool hasSuper; |
| 1223 | 1232 |
| 1224 InitializerResolver(this.visitor) | 1233 InitializerResolver(this.visitor) |
| 1225 : initialized = new Map<Element, Node>(), hasSuper = false; | 1234 : initialized = new Map<Element, Node>(), hasSuper = false; |
| 1226 | 1235 |
| 1227 error(Node node, MessageKind kind, [arguments = const {}]) { | 1236 error(Node node, MessageKind kind, [arguments = const {}]) { |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2192 // fields they reference are visible, but must be resolved independently. | 2201 // fields they reference are visible, but must be resolved independently. |
| 2193 if (element.kind == ElementKind.FIELD_PARAMETER) { | 2202 if (element.kind == ElementKind.FIELD_PARAMETER) { |
| 2194 useElement(parameterNode, element); | 2203 useElement(parameterNode, element); |
| 2195 } else { | 2204 } else { |
| 2196 defineElement(parameterNode, element); | 2205 defineElement(parameterNode, element); |
| 2197 } | 2206 } |
| 2198 parameterNodes = parameterNodes.tail; | 2207 parameterNodes = parameterNodes.tail; |
| 2199 }); | 2208 }); |
| 2200 addDeferredAction(enclosingElement, () { | 2209 addDeferredAction(enclosingElement, () { |
| 2201 functionParameters.forEachOptionalParameter((Element parameter) { | 2210 functionParameters.forEachOptionalParameter((Element parameter) { |
| 2202 compiler.resolver.constantCompiler.compileConstant(parameter); | 2211 compiler.constantHandler.compileConstant(parameter); |
| 2203 }); | 2212 }); |
| 2204 }); | 2213 }); |
| 2205 if (inCheckContext) { | 2214 if (inCheckContext) { |
| 2206 functionParameters.forEachParameter((Element element) { | 2215 functionParameters.forEachParameter((Element element) { |
| 2207 compiler.enqueuer.resolution.registerIsCheck( | 2216 compiler.enqueuer.resolution.registerIsCheck( |
| 2208 element.computeType(compiler), mapping); | 2217 element.computeType(compiler), mapping); |
| 2209 }); | 2218 }); |
| 2210 } | 2219 } |
| 2211 } | 2220 } |
| 2212 | 2221 |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2572 // type variable expression. | 2581 // type variable expression. |
| 2573 mapping.setType(node, compiler.typeClass.computeType(compiler)); | 2582 mapping.setType(node, compiler.typeClass.computeType(compiler)); |
| 2574 world.registerTypeLiteral(target, mapping); | 2583 world.registerTypeLiteral(target, mapping); |
| 2575 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) { | 2584 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) { |
| 2576 // Set the type of the node to [Type] to mark this send as a | 2585 // Set the type of the node to [Type] to mark this send as a |
| 2577 // type literal. | 2586 // type literal. |
| 2578 mapping.setType(node, compiler.typeClass.computeType(compiler)); | 2587 mapping.setType(node, compiler.typeClass.computeType(compiler)); |
| 2579 world.registerTypeLiteral(target, mapping); | 2588 world.registerTypeLiteral(target, mapping); |
| 2580 | 2589 |
| 2581 // Don't try to make constants of calls to type literals. | 2590 // Don't try to make constants of calls to type literals. |
| 2582 if (!node.isCall) { | 2591 analyzeConstant(node, isConst: !node.isCall); |
| 2583 analyzeConstant(node); | |
| 2584 } else { | |
| 2585 // The node itself is not a constant but we register the selector (the | |
| 2586 // identifier that refers to the class/typedef) as a constant. | |
| 2587 analyzeConstant(node.selector); | |
| 2588 } | |
| 2589 } | 2592 } |
| 2590 if (isPotentiallyMutableTarget(target)) { | 2593 if (isPotentiallyMutableTarget(target)) { |
| 2591 if (enclosingElement != target.enclosingElement) { | 2594 if (enclosingElement != target.enclosingElement) { |
| 2592 for (Node scope in promotionScope) { | 2595 for (Node scope in promotionScope) { |
| 2593 mapping.setAccessedByClosureIn(scope, target, node); | 2596 mapping.setAccessedByClosureIn(scope, target, node); |
| 2594 } | 2597 } |
| 2595 } | 2598 } |
| 2596 } | 2599 } |
| 2597 } | 2600 } |
| 2598 | 2601 |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3048 world.registerFactoryWithTypeArguments(mapping); | 3051 world.registerFactoryWithTypeArguments(mapping); |
| 3049 } | 3052 } |
| 3050 if (constructor.isGenerativeConstructor() && cls.isAbstract) { | 3053 if (constructor.isGenerativeConstructor() && cls.isAbstract) { |
| 3051 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION); | 3054 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION); |
| 3052 compiler.backend.registerAbstractClassInstantiation(mapping); | 3055 compiler.backend.registerAbstractClassInstantiation(mapping); |
| 3053 } | 3056 } |
| 3054 | 3057 |
| 3055 if (isSymbolConstructor) { | 3058 if (isSymbolConstructor) { |
| 3056 if (node.isConst()) { | 3059 if (node.isConst()) { |
| 3057 Node argumentNode = node.send.arguments.head; | 3060 Node argumentNode = node.send.arguments.head; |
| 3058 Constant name = compiler.resolver.constantCompiler.compileNode( | 3061 Constant name = compiler.constantHandler.compileNodeWithDefinitions( |
| 3059 argumentNode, mapping); | 3062 argumentNode, mapping, isConst: true); |
| 3060 if (!name.isString) { | 3063 if (!name.isString) { |
| 3061 DartType type = name.computeType(compiler); | 3064 DartType type = name.computeType(compiler); |
| 3062 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, | 3065 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, |
| 3063 {'type': type}); | 3066 {'type': type}); |
| 3064 } else { | 3067 } else { |
| 3065 StringConstant stringConstant = name; | 3068 StringConstant stringConstant = name; |
| 3066 String nameString = stringConstant.toDartString().slowToString(); | 3069 String nameString = stringConstant.toDartString().slowToString(); |
| 3067 if (validateSymbol(argumentNode, nameString)) { | 3070 if (validateSymbol(argumentNode, nameString)) { |
| 3068 world.registerConstSymbol(nameString, mapping); | 3071 world.registerConstSymbol(nameString, mapping); |
| 3069 } | 3072 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3097 if (cls == compiler.stringClass) continue; | 3100 if (cls == compiler.stringClass) continue; |
| 3098 Element equals = cls.lookupMember('=='); | 3101 Element equals = cls.lookupMember('=='); |
| 3099 if (equals.getEnclosingClass() != compiler.objectClass) { | 3102 if (equals.getEnclosingClass() != compiler.objectClass) { |
| 3100 compiler.reportError(spannable, | 3103 compiler.reportError(spannable, |
| 3101 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, | 3104 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, |
| 3102 {'type': keyType}); | 3105 {'type': keyType}); |
| 3103 } | 3106 } |
| 3104 } | 3107 } |
| 3105 } | 3108 } |
| 3106 | 3109 |
| 3107 void analyzeConstant(Node node) { | 3110 void analyzeConstant(Node node, {bool isConst: true}) { |
| 3108 addDeferredAction(enclosingElement, () { | 3111 addDeferredAction(enclosingElement, () { |
| 3109 Constant constant = | 3112 Constant constant = compiler.constantHandler.compileNodeWithDefinitions( |
| 3110 compiler.resolver.constantCompiler.compileNode(node, mapping); | 3113 node, mapping, isConst: isConst); |
| 3111 | 3114 |
| 3112 if (constant.isMap) { | 3115 if (isConst && constant != null && constant.isMap) { |
| 3113 checkConstMapKeysDontOverrideEquals(node, constant); | 3116 checkConstMapKeysDontOverrideEquals(node, constant); |
| 3114 } | 3117 } |
| 3115 | 3118 |
| 3116 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | 3119 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names |
| 3117 // a class that will be instantiated outside the program by attaching a | 3120 // a class that will be instantiated outside the program by attaching a |
| 3118 // native class dispatch record referencing the interceptor. | 3121 // native class dispatch record referencing the interceptor. |
| 3119 if (argumentsToJsInterceptorConstant != null && | 3122 if (argumentsToJsInterceptorConstant != null && |
| 3120 argumentsToJsInterceptorConstant.contains(node)) { | 3123 argumentsToJsInterceptorConstant.contains(node)) { |
| 3121 if (constant.isType) { | 3124 if (constant.isType) { |
| 3122 TypeConstant typeConstant = constant; | 3125 TypeConstant typeConstant = constant; |
| (...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4452 | 4455 |
| 4453 visitNodeList(NodeList node) { | 4456 visitNodeList(NodeList node) { |
| 4454 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 4457 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 4455 Identifier name = visit(link.head); | 4458 Identifier name = visit(link.head); |
| 4456 VariableElement element = new VariableElementX( | 4459 VariableElement element = new VariableElementX( |
| 4457 name.source, kind, resolver.enclosingElement, | 4460 name.source, kind, resolver.enclosingElement, |
| 4458 variables, name.token); | 4461 variables, name.token); |
| 4459 resolver.defineElement(link.head, element); | 4462 resolver.defineElement(link.head, element); |
| 4460 if (definitions.modifiers.isConst()) { | 4463 if (definitions.modifiers.isConst()) { |
| 4461 compiler.enqueuer.resolution.addDeferredAction(element, () { | 4464 compiler.enqueuer.resolution.addDeferredAction(element, () { |
| 4462 compiler.resolver.constantCompiler.compileConstant(element); | 4465 compiler.constantHandler.compileVariable(element, isConst: true); |
| 4463 }); | 4466 }); |
| 4464 } | 4467 } |
| 4465 } | 4468 } |
| 4466 } | 4469 } |
| 4467 } | 4470 } |
| 4468 | 4471 |
| 4469 class ConstructorResolver extends CommonResolverVisitor<Element> { | 4472 class ConstructorResolver extends CommonResolverVisitor<Element> { |
| 4470 final ResolverVisitor resolver; | 4473 final ResolverVisitor resolver; |
| 4471 bool inConstContext; | 4474 bool inConstContext; |
| 4472 DartType type; | 4475 DartType type; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4659 TreeElements _treeElements; | 4662 TreeElements _treeElements; |
| 4660 | 4663 |
| 4661 bool get hasTreeElements => _treeElements != null; | 4664 bool get hasTreeElements => _treeElements != null; |
| 4662 | 4665 |
| 4663 TreeElements get treeElements { | 4666 TreeElements get treeElements { |
| 4664 assert(invariant(this, _treeElements !=null, | 4667 assert(invariant(this, _treeElements !=null, |
| 4665 message: "TreeElements have not been computed for $this.")); | 4668 message: "TreeElements have not been computed for $this.")); |
| 4666 return _treeElements; | 4669 return _treeElements; |
| 4667 } | 4670 } |
| 4668 } | 4671 } |
| OLD | NEW |