| 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 AnalyzableElement get analyzedElement; | 8 AnalyzableElement get analyzedElement; |
| 9 Iterable<Node> get superUses; | 9 Iterable<Node> get superUses; |
| 10 | 10 |
| (...skipping 2891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 // Potentially a 'dynamic' type literal. | 2902 // Potentially a 'dynamic' type literal. |
| 2903 type = registry.getType(node.selector); | 2903 type = registry.getType(node.selector); |
| 2904 } | 2904 } |
| 2905 if (type == null) { | 2905 if (type == null) { |
| 2906 type = target.computeType(compiler); | 2906 type = target.computeType(compiler); |
| 2907 } | 2907 } |
| 2908 registry.registerTypeLiteral(node, type); | 2908 registry.registerTypeLiteral(node, type); |
| 2909 | 2909 |
| 2910 // Don't try to make constants of calls to type literals. | 2910 // Don't try to make constants of calls to type literals. |
| 2911 if (!node.isCall) { | 2911 if (!node.isCall) { |
| 2912 analyzeConstant(node); | 2912 analyzeConstantDeferred(node); |
| 2913 } else { | 2913 } else { |
| 2914 // The node itself is not a constant but we register the selector (the | 2914 // The node itself is not a constant but we register the selector (the |
| 2915 // identifier that refers to the class/typedef) as a constant. | 2915 // identifier that refers to the class/typedef) as a constant. |
| 2916 analyzeConstant(node.selector); | 2916 analyzeConstantDeferred(node.selector); |
| 2917 } | 2917 } |
| 2918 } | 2918 } |
| 2919 if (isPotentiallyMutableTarget(target)) { | 2919 if (isPotentiallyMutableTarget(target)) { |
| 2920 if (enclosingElement != target.enclosingElement) { | 2920 if (enclosingElement != target.enclosingElement) { |
| 2921 for (Node scope in promotionScope) { | 2921 for (Node scope in promotionScope) { |
| 2922 registry.setAccessedByClosureIn(scope, target, node); | 2922 registry.setAccessedByClosureIn(scope, target, node); |
| 2923 } | 2923 } |
| 2924 } | 2924 } |
| 2925 } | 2925 } |
| 2926 } | 2926 } |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3170 | 3170 |
| 3171 visitLiteralSymbol(LiteralSymbol node) { | 3171 visitLiteralSymbol(LiteralSymbol node) { |
| 3172 registry.registerInstantiatedClass(compiler.symbolClass); | 3172 registry.registerInstantiatedClass(compiler.symbolClass); |
| 3173 registry.registerStaticUse(compiler.symbolConstructor.declaration); | 3173 registry.registerStaticUse(compiler.symbolConstructor.declaration); |
| 3174 registry.registerConstSymbol(node.slowNameString); | 3174 registry.registerConstSymbol(node.slowNameString); |
| 3175 if (!validateSymbol(node, node.slowNameString, reportError: false)) { | 3175 if (!validateSymbol(node, node.slowNameString, reportError: false)) { |
| 3176 compiler.reportError(node, | 3176 compiler.reportError(node, |
| 3177 MessageKind.UNSUPPORTED_LITERAL_SYMBOL, | 3177 MessageKind.UNSUPPORTED_LITERAL_SYMBOL, |
| 3178 {'value': node.slowNameString}); | 3178 {'value': node.slowNameString}); |
| 3179 } | 3179 } |
| 3180 analyzeConstant(node); | 3180 analyzeConstantDeferred(node); |
| 3181 } | 3181 } |
| 3182 | 3182 |
| 3183 visitStringJuxtaposition(StringJuxtaposition node) { | 3183 visitStringJuxtaposition(StringJuxtaposition node) { |
| 3184 registry.registerInstantiatedClass(compiler.stringClass); | 3184 registry.registerInstantiatedClass(compiler.stringClass); |
| 3185 node.visitChildren(this); | 3185 node.visitChildren(this); |
| 3186 } | 3186 } |
| 3187 | 3187 |
| 3188 visitNodeList(NodeList node) { | 3188 visitNodeList(NodeList node) { |
| 3189 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 3189 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 3190 visit(link.head); | 3190 visit(link.head); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3421 compiler.reportHint( | 3421 compiler.reportHint( |
| 3422 node.newToken, MessageKind.NON_CONST_BLOAT, | 3422 node.newToken, MessageKind.NON_CONST_BLOAT, |
| 3423 {'name': compiler.symbolClass.name}); | 3423 {'name': compiler.symbolClass.name}); |
| 3424 } | 3424 } |
| 3425 registry.registerNewSymbol(); | 3425 registry.registerNewSymbol(); |
| 3426 } | 3426 } |
| 3427 } else if (isMirrorsUsedConstant) { | 3427 } else if (isMirrorsUsedConstant) { |
| 3428 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping); | 3428 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping); |
| 3429 } | 3429 } |
| 3430 if (node.isConst) { | 3430 if (node.isConst) { |
| 3431 analyzeConstant(node); | 3431 analyzeConstantDeferred(node); |
| 3432 } | 3432 } |
| 3433 | 3433 |
| 3434 return null; | 3434 return null; |
| 3435 } | 3435 } |
| 3436 | 3436 |
| 3437 void checkConstMapKeysDontOverrideEquals(Spannable spannable, | 3437 void checkConstMapKeysDontOverrideEquals(Spannable spannable, |
| 3438 MapConstantValue map) { | 3438 MapConstantValue map) { |
| 3439 for (ConstantValue key in map.keys) { | 3439 for (ConstantValue key in map.keys) { |
| 3440 if (!key.isObject) continue; | 3440 if (!key.isObject) continue; |
| 3441 ObjectConstantValue objectConstant = key; | 3441 ObjectConstantValue objectConstant = key; |
| 3442 DartType keyType = objectConstant.type; | 3442 DartType keyType = objectConstant.type; |
| 3443 ClassElement cls = keyType.element; | 3443 ClassElement cls = keyType.element; |
| 3444 if (cls == compiler.stringClass) continue; | 3444 if (cls == compiler.stringClass) continue; |
| 3445 Element equals = cls.lookupMember('=='); | 3445 Element equals = cls.lookupMember('=='); |
| 3446 if (equals.enclosingClass != compiler.objectClass) { | 3446 if (equals.enclosingClass != compiler.objectClass) { |
| 3447 compiler.reportError(spannable, | 3447 compiler.reportError(spannable, |
| 3448 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, | 3448 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, |
| 3449 {'type': keyType}); | 3449 {'type': keyType}); |
| 3450 } | 3450 } |
| 3451 } | 3451 } |
| 3452 } | 3452 } |
| 3453 | 3453 |
| 3454 void analyzeConstant(Node node) { | 3454 void analyzeConstant(Node node) { |
| 3455 addDeferredAction(enclosingElement, () { | 3455 ConstantExpression constant = |
| 3456 ConstantExpression constant = | 3456 compiler.resolver.constantCompiler.compileNode( |
| 3457 compiler.resolver.constantCompiler.compileNode( | 3457 node, registry.mapping); |
| 3458 node, registry.mapping); | |
| 3459 | 3458 |
| 3460 ConstantValue value = constant.value; | 3459 ConstantValue value = constant.value; |
| 3461 if (value.isMap) { | 3460 if (value.isMap) { |
| 3462 checkConstMapKeysDontOverrideEquals(node, value); | 3461 checkConstMapKeysDontOverrideEquals(node, value); |
| 3463 } | 3462 } |
| 3464 | 3463 |
| 3465 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names | 3464 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names |
| 3466 // a class that will be instantiated outside the program by attaching a | 3465 // a class that will be instantiated outside the program by attaching a |
| 3467 // native class dispatch record referencing the interceptor. | 3466 // native class dispatch record referencing the interceptor. |
| 3468 if (argumentsToJsInterceptorConstant != null && | 3467 if (argumentsToJsInterceptorConstant != null && |
| 3469 argumentsToJsInterceptorConstant.contains(node)) { | 3468 argumentsToJsInterceptorConstant.contains(node)) { |
| 3470 if (value.isType) { | 3469 if (value.isType) { |
| 3471 TypeConstantValue typeConstant = value; | 3470 TypeConstantValue typeConstant = value; |
| 3472 if (typeConstant.representedType is InterfaceType) { | 3471 if (typeConstant.representedType is InterfaceType) { |
| 3473 registry.registerInstantiatedType(typeConstant.representedType); | 3472 registry.registerInstantiatedType(typeConstant.representedType); |
| 3474 } else { | |
| 3475 compiler.reportError(node, | |
| 3476 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | |
| 3477 } | |
| 3478 } else { | 3473 } else { |
| 3479 compiler.reportError(node, | 3474 compiler.reportError(node, |
| 3480 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 3475 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 3481 } | 3476 } |
| 3477 } else { |
| 3478 compiler.reportError(node, |
| 3479 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 3482 } | 3480 } |
| 3481 } |
| 3482 } |
| 3483 |
| 3484 void analyzeConstantDeferred(Node node) { |
| 3485 addDeferredAction(enclosingElement, () { |
| 3486 analyzeConstant(node); |
| 3483 }); | 3487 }); |
| 3484 } | 3488 } |
| 3485 | 3489 |
| 3486 bool validateSymbol(Node node, String name, {bool reportError: true}) { | 3490 bool validateSymbol(Node node, String name, {bool reportError: true}) { |
| 3487 if (name.isEmpty) return true; | 3491 if (name.isEmpty) return true; |
| 3488 if (name.startsWith('_')) { | 3492 if (name.startsWith('_')) { |
| 3489 if (reportError) { | 3493 if (reportError) { |
| 3490 compiler.reportError(node, MessageKind.PRIVATE_IDENTIFIER, | 3494 compiler.reportError(node, MessageKind.PRIVATE_IDENTIFIER, |
| 3491 {'value': name}); | 3495 {'value': name}); |
| 3492 } | 3496 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3562 listType = new InterfaceType(compiler.listClass, [typeArgument]); | 3566 listType = new InterfaceType(compiler.listClass, [typeArgument]); |
| 3563 } else { | 3567 } else { |
| 3564 compiler.listClass.computeType(compiler); | 3568 compiler.listClass.computeType(compiler); |
| 3565 listType = compiler.listClass.rawType; | 3569 listType = compiler.listClass.rawType; |
| 3566 } | 3570 } |
| 3567 registry.setType(node, listType); | 3571 registry.setType(node, listType); |
| 3568 registry.registerInstantiatedType(listType); | 3572 registry.registerInstantiatedType(listType); |
| 3569 registry.registerRequiredType(listType, enclosingElement); | 3573 registry.registerRequiredType(listType, enclosingElement); |
| 3570 visit(node.elements); | 3574 visit(node.elements); |
| 3571 if (node.isConst) { | 3575 if (node.isConst) { |
| 3572 analyzeConstant(node); | 3576 analyzeConstantDeferred(node); |
| 3573 } | 3577 } |
| 3574 | 3578 |
| 3575 sendIsMemberAccess = false; | 3579 sendIsMemberAccess = false; |
| 3576 } | 3580 } |
| 3577 | 3581 |
| 3578 visitConditional(Conditional node) { | 3582 visitConditional(Conditional node) { |
| 3579 doInPromotionScope(node.condition, () => visit(node.condition)); | 3583 doInPromotionScope(node.condition, () => visit(node.condition)); |
| 3580 doInPromotionScope(node.thenExpression, () => visit(node.thenExpression)); | 3584 doInPromotionScope(node.thenExpression, () => visit(node.thenExpression)); |
| 3581 visit(node.elseExpression); | 3585 visit(node.elseExpression); |
| 3582 } | 3586 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3783 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 3787 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
| 3784 } | 3788 } |
| 3785 registry.setType(node, mapType); | 3789 registry.setType(node, mapType); |
| 3786 registry.registerInstantiatedType(mapType); | 3790 registry.registerInstantiatedType(mapType); |
| 3787 if (node.isConst) { | 3791 if (node.isConst) { |
| 3788 registry.registerConstantMap(); | 3792 registry.registerConstantMap(); |
| 3789 } | 3793 } |
| 3790 registry.registerRequiredType(mapType, enclosingElement); | 3794 registry.registerRequiredType(mapType, enclosingElement); |
| 3791 node.visitChildren(this); | 3795 node.visitChildren(this); |
| 3792 if (node.isConst) { | 3796 if (node.isConst) { |
| 3793 analyzeConstant(node); | 3797 analyzeConstantDeferred(node); |
| 3794 } | 3798 } |
| 3795 | 3799 |
| 3796 sendIsMemberAccess = false; | 3800 sendIsMemberAccess = false; |
| 3797 } | 3801 } |
| 3798 | 3802 |
| 3799 visitLiteralMapEntry(LiteralMapEntry node) { | 3803 visitLiteralMapEntry(LiteralMapEntry node) { |
| 3800 node.visitChildren(this); | 3804 node.visitChildren(this); |
| 3801 } | 3805 } |
| 3802 | 3806 |
| 3803 visitNamedArgument(NamedArgument node) { | 3807 visitNamedArgument(NamedArgument node) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3888 } | 3892 } |
| 3889 } | 3893 } |
| 3890 } | 3894 } |
| 3891 | 3895 |
| 3892 visitSwitchStatement(SwitchStatement node) { | 3896 visitSwitchStatement(SwitchStatement node) { |
| 3893 node.expression.accept(this); | 3897 node.expression.accept(this); |
| 3894 | 3898 |
| 3895 JumpTarget breakElement = getOrDefineTarget(node); | 3899 JumpTarget breakElement = getOrDefineTarget(node); |
| 3896 Map<String, LabelDefinition> continueLabels = <String, LabelDefinition>{}; | 3900 Map<String, LabelDefinition> continueLabels = <String, LabelDefinition>{}; |
| 3897 Link<Node> cases = node.cases.nodes; | 3901 Link<Node> cases = node.cases.nodes; |
| 3902 List<Node> caseExpressions = <Node>[]; |
| 3898 while (!cases.isEmpty) { | 3903 while (!cases.isEmpty) { |
| 3899 SwitchCase switchCase = cases.head; | 3904 SwitchCase switchCase = cases.head; |
| 3900 for (Node labelOrCase in switchCase.labelsAndCases) { | 3905 for (Node labelOrCase in switchCase.labelsAndCases) { |
| 3901 CaseMatch caseMatch = labelOrCase.asCaseMatch(); | 3906 CaseMatch caseMatch = labelOrCase.asCaseMatch(); |
| 3902 if (caseMatch != null) { | 3907 if (caseMatch != null) { |
| 3903 analyzeConstant(caseMatch.expression); | 3908 caseExpressions.add(caseMatch.expression); |
| 3904 continue; | 3909 continue; |
| 3905 } | 3910 } |
| 3906 Label label = labelOrCase; | 3911 Label label = labelOrCase; |
| 3907 String labelName = label.labelName; | 3912 String labelName = label.labelName; |
| 3908 | 3913 |
| 3909 LabelDefinition existingElement = continueLabels[labelName]; | 3914 LabelDefinition existingElement = continueLabels[labelName]; |
| 3910 if (existingElement != null) { | 3915 if (existingElement != null) { |
| 3911 // It's an error if the same label occurs twice in the same switch. | 3916 // It's an error if the same label occurs twice in the same switch. |
| 3912 compiler.reportError( | 3917 compiler.reportError( |
| 3913 label, | 3918 label, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3953 if (!label.isContinueTarget) { | 3958 if (!label.isContinueTarget) { |
| 3954 JumpTarget targetElement = label.target; | 3959 JumpTarget targetElement = label.target; |
| 3955 SwitchCase switchCase = targetElement.statement; | 3960 SwitchCase switchCase = targetElement.statement; |
| 3956 registry.undefineTarget(switchCase); | 3961 registry.undefineTarget(switchCase); |
| 3957 registry.undefineLabel(label.label); | 3962 registry.undefineLabel(label.label); |
| 3958 } | 3963 } |
| 3959 }); | 3964 }); |
| 3960 // TODO(15575): We should warn if we can detect a fall through | 3965 // TODO(15575): We should warn if we can detect a fall through |
| 3961 // error. | 3966 // error. |
| 3962 registry.registerFallThroughError(); | 3967 registry.registerFallThroughError(); |
| 3968 |
| 3969 caseExpressions.forEach(analyzeConstant); |
| 3963 } | 3970 } |
| 3964 | 3971 |
| 3965 visitSwitchCase(SwitchCase node) { | 3972 visitSwitchCase(SwitchCase node) { |
| 3966 node.labelsAndCases.accept(this); | 3973 node.labelsAndCases.accept(this); |
| 3967 visitIn(node.statements, new BlockScope(scope)); | 3974 visitIn(node.statements, new BlockScope(scope)); |
| 3968 } | 3975 } |
| 3969 | 3976 |
| 3970 visitCaseMatch(CaseMatch node) { | 3977 visitCaseMatch(CaseMatch node) { |
| 3971 visit(node.expression); | 3978 visit(node.expression); |
| 3972 } | 3979 } |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4354 | 4361 |
| 4355 invariant(node, element != null); | 4362 invariant(node, element != null); |
| 4356 invariant(element, element.resolutionState == STATE_STARTED, | 4363 invariant(element, element.resolutionState == STATE_STARTED, |
| 4357 message: () => 'cyclic resolution of class $element'); | 4364 message: () => 'cyclic resolution of class $element'); |
| 4358 | 4365 |
| 4359 InterfaceType enumType = element.computeType(compiler); | 4366 InterfaceType enumType = element.computeType(compiler); |
| 4360 element.supertype = compiler.objectClass.computeType(compiler); | 4367 element.supertype = compiler.objectClass.computeType(compiler); |
| 4361 element.interfaces = const Link<DartType>(); | 4368 element.interfaces = const Link<DartType>(); |
| 4362 calculateAllSupertypes(element); | 4369 calculateAllSupertypes(element); |
| 4363 | 4370 |
| 4371 if (node.names.nodes.isEmpty) { |
| 4372 compiler.reportError(node, |
| 4373 MessageKind.EMPTY_ENUM_DECLARATION, |
| 4374 {'enumName': element.name}); |
| 4375 } |
| 4376 |
| 4364 EnumCreator creator = new EnumCreator(compiler, element); | 4377 EnumCreator creator = new EnumCreator(compiler, element); |
| 4365 creator.createMembers(); | 4378 creator.createMembers(); |
| 4366 return enumType; | 4379 return enumType; |
| 4367 } | 4380 } |
| 4368 | 4381 |
| 4369 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type | 4382 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type |
| 4370 /// is a valid, non-blacklisted interface type. The mixin type is returned. | 4383 /// is a valid, non-blacklisted interface type. The mixin type is returned. |
| 4371 DartType checkMixinType(TypeAnnotation mixinNode) { | 4384 DartType checkMixinType(TypeAnnotation mixinNode) { |
| 4372 DartType mixinType = resolveType(mixinNode); | 4385 DartType mixinType = resolveType(mixinNode); |
| 4373 if (isBlackListed(mixinType)) { | 4386 if (isBlackListed(mixinType)) { |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5091 } | 5104 } |
| 5092 | 5105 |
| 5093 /// The result for the resolution of the `assert` method. | 5106 /// The result for the resolution of the `assert` method. |
| 5094 class AssertResult implements ResolutionResult { | 5107 class AssertResult implements ResolutionResult { |
| 5095 const AssertResult(); | 5108 const AssertResult(); |
| 5096 | 5109 |
| 5097 Element get element => null; | 5110 Element get element => null; |
| 5098 | 5111 |
| 5099 String toString() => 'AssertResult()'; | 5112 String toString() => 'AssertResult()'; |
| 5100 } | 5113 } |
| OLD | NEW |