| 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 interface TreeElements { | 5 interface TreeElements { |
| 6 Element operator[](Node node); | 6 Element operator[](Node node); |
| 7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
| 8 DartType getType(TypeAnnotation annotation); | 8 DartType getType(TypeAnnotation annotation); |
| 9 bool isParameterChecked(Element element); | 9 bool isParameterChecked(Element element); |
| 10 } | 10 } |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 } | 948 } |
| 949 | 949 |
| 950 class ResolverVisitor extends CommonResolverVisitor<Element> { | 950 class ResolverVisitor extends CommonResolverVisitor<Element> { |
| 951 final TreeElementMapping mapping; | 951 final TreeElementMapping mapping; |
| 952 final Element enclosingElement; | 952 final Element enclosingElement; |
| 953 final TypeResolver typeResolver; | 953 final TypeResolver typeResolver; |
| 954 bool inInstanceContext; | 954 bool inInstanceContext; |
| 955 bool inCheckContext; | 955 bool inCheckContext; |
| 956 Scope scope; | 956 Scope scope; |
| 957 ClassElement currentClass; | 957 ClassElement currentClass; |
| 958 ExpressionStatement currentExpressionStatement; |
| 958 bool typeRequired = false; | 959 bool typeRequired = false; |
| 959 StatementScope statementScope; | 960 StatementScope statementScope; |
| 960 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; | 961 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION; |
| 961 | 962 |
| 962 ResolverVisitor(Compiler compiler, Element element) | 963 ResolverVisitor(Compiler compiler, Element element) |
| 963 : this.mapping = new TreeElementMapping(), | 964 : this.mapping = new TreeElementMapping(), |
| 964 this.enclosingElement = element, | 965 this.enclosingElement = element, |
| 965 // When the element is a field, we are actually resolving its | 966 // When the element is a field, we are actually resolving its |
| 966 // initial value, which should not have access to instance | 967 // initial value, which should not have access to instance |
| 967 // fields. | 968 // fields. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 } | 1157 } |
| 1157 | 1158 |
| 1158 visitDoWhile(DoWhile node) { | 1159 visitDoWhile(DoWhile node) { |
| 1159 visitLoopBodyIn(node, node.body, new BlockScope(scope)); | 1160 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
| 1160 visit(node.condition); | 1161 visit(node.condition); |
| 1161 } | 1162 } |
| 1162 | 1163 |
| 1163 visitEmptyStatement(EmptyStatement node) { } | 1164 visitEmptyStatement(EmptyStatement node) { } |
| 1164 | 1165 |
| 1165 visitExpressionStatement(ExpressionStatement node) { | 1166 visitExpressionStatement(ExpressionStatement node) { |
| 1167 ExpressionStatement oldExpressionStatement = currentExpressionStatement; |
| 1168 currentExpressionStatement = node; |
| 1166 visit(node.expression); | 1169 visit(node.expression); |
| 1170 currentExpressionStatement = oldExpressionStatement; |
| 1167 } | 1171 } |
| 1168 | 1172 |
| 1169 visitFor(For node) { | 1173 visitFor(For node) { |
| 1170 Scope blockScope = new BlockScope(scope); | 1174 Scope blockScope = new BlockScope(scope); |
| 1171 visitIn(node.initializer, blockScope); | 1175 visitIn(node.initializer, blockScope); |
| 1172 visitIn(node.condition, blockScope); | 1176 visitIn(node.condition, blockScope); |
| 1173 visitIn(node.update, blockScope); | 1177 visitIn(node.update, blockScope); |
| 1174 visitLoopBodyIn(node, node.body, blockScope); | 1178 visitLoopBodyIn(node, node.body, blockScope); |
| 1175 } | 1179 } |
| 1176 | 1180 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 visit(node.condition); | 1214 visit(node.condition); |
| 1211 visit(node.thenPart); | 1215 visit(node.thenPart); |
| 1212 visit(node.elsePart); | 1216 visit(node.elsePart); |
| 1213 } | 1217 } |
| 1214 | 1218 |
| 1215 static bool isLogicalOperator(Identifier op) { | 1219 static bool isLogicalOperator(Identifier op) { |
| 1216 String str = op.source.stringValue; | 1220 String str = op.source.stringValue; |
| 1217 return (str === '&&' || str == '||' || str == '!'); | 1221 return (str === '&&' || str == '||' || str == '!'); |
| 1218 } | 1222 } |
| 1219 | 1223 |
| 1224 /** |
| 1225 * Check the lexical scope chain for a declaration with the name "assert". |
| 1226 * |
| 1227 * This is used to detect whether "assert(x)" is actually an assertion or |
| 1228 * just a call expression. |
| 1229 * It does not check fields inherited from a superclass. |
| 1230 */ |
| 1231 bool isAssertInLexicalScope() { |
| 1232 return scope.lexicalLookup(const SourceString("assert")) !== null; |
| 1233 } |
| 1234 |
| 1235 /** Check if [node] is the expression of the current expression statement. */ |
| 1236 bool isExpressionStatementExpression(Node node) { |
| 1237 return currentExpressionStatement !== null && |
| 1238 currentExpressionStatement.expression === node; |
| 1239 } |
| 1240 |
| 1220 Element resolveSend(Send node) { | 1241 Element resolveSend(Send node) { |
| 1221 Selector selector = resolveSelector(node); | 1242 Selector selector = resolveSelector(node); |
| 1222 | 1243 |
| 1223 if (node.receiver === null) { | 1244 if (node.receiver === null) { |
| 1245 // If this send is the expression of an expression statement, and is on |
| 1246 // the form "assert(expr);", and there is no declaration with name |
| 1247 // "assert" in the lexical scope, then this is actually an assertion. |
| 1248 if (isExpressionStatementExpression(node) && |
| 1249 selector.isAssertSyntax() && |
| 1250 !isAssertInLexicalScope()) { |
| 1251 return compiler.assertMethod; |
| 1252 } |
| 1224 return node.selector.accept(this); | 1253 return node.selector.accept(this); |
| 1225 } | 1254 } |
| 1226 | 1255 |
| 1227 var oldCategory = allowedCategory; | 1256 var oldCategory = allowedCategory; |
| 1228 allowedCategory |= | 1257 allowedCategory |= |
| 1229 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; | 1258 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; |
| 1230 Element resolvedReceiver = visit(node.receiver); | 1259 Element resolvedReceiver = visit(node.receiver); |
| 1231 allowedCategory = oldCategory; | 1260 allowedCategory = oldCategory; |
| 1232 | 1261 |
| 1233 Element target; | 1262 Element target; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 // we need to register that fact that we may be calling a closure | 1430 // we need to register that fact that we may be calling a closure |
| 1402 // with the same arguments. | 1431 // with the same arguments. |
| 1403 if (node.isCall && | 1432 if (node.isCall && |
| 1404 (Elements.isUnresolved(target) || | 1433 (Elements.isUnresolved(target) || |
| 1405 target.isGetter() || | 1434 target.isGetter() || |
| 1406 Elements.isClosureSend(node, target))) { | 1435 Elements.isClosureSend(node, target))) { |
| 1407 Selector call = new Selector.callClosureFrom(selector); | 1436 Selector call = new Selector.callClosureFrom(selector); |
| 1408 world.registerDynamicInvocation(call.name, call); | 1437 world.registerDynamicInvocation(call.name, call); |
| 1409 } | 1438 } |
| 1410 | 1439 |
| 1411 // TODO(ngeoffray): We should do the check in | |
| 1412 // visitExpressionStatement instead. | |
| 1413 if (target === compiler.assertMethod && !node.isCall) { | |
| 1414 // We can only use assert by calling it. | |
| 1415 if (!inInstanceContext) { | |
| 1416 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); | |
| 1417 } | |
| 1418 target = null; | |
| 1419 } | |
| 1420 | |
| 1421 // TODO(ngeoffray): Warn if target is null and the send is | 1440 // TODO(ngeoffray): Warn if target is null and the send is |
| 1422 // unqualified. | 1441 // unqualified. |
| 1423 useElement(node, target); | 1442 useElement(node, target); |
| 1424 registerSend(selector, target); | 1443 registerSend(selector, target); |
| 1425 return node.isPropertyAccess ? target : null; | 1444 return node.isPropertyAccess ? target : null; |
| 1426 } | 1445 } |
| 1427 | 1446 |
| 1428 visitSendSet(SendSet node) { | 1447 visitSendSet(SendSet node) { |
| 1429 Element target = resolveSend(node); | 1448 Element target = resolveSend(node); |
| 1430 Element setter = target; | 1449 Element setter = target; |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); | 1929 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); |
| 1911 } | 1930 } |
| 1912 TypeAnnotation type = declaration.type; | 1931 TypeAnnotation type = declaration.type; |
| 1913 if (type !== null) { | 1932 if (type !== null) { |
| 1914 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); | 1933 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); |
| 1915 } | 1934 } |
| 1916 } | 1935 } |
| 1917 } | 1936 } |
| 1918 | 1937 |
| 1919 Scope blockScope = new BlockScope(scope); | 1938 Scope blockScope = new BlockScope(scope); |
| 1920 doInCheckContext(() => visitIn(node.type, blockScope)); | 1939 doInCheckContext(() => visitIn(node.type, blockScope)); |
| 1921 visitIn(node.formals, blockScope); | 1940 visitIn(node.formals, blockScope); |
| 1922 visitIn(node.block, blockScope); | 1941 visitIn(node.block, blockScope); |
| 1923 } | 1942 } |
| 1924 | 1943 |
| 1925 visitTypedef(Typedef node) { | 1944 visitTypedef(Typedef node) { |
| 1926 unimplemented(node, 'typedef'); | 1945 unimplemented(node, 'typedef'); |
| 1927 } | 1946 } |
| 1928 } | 1947 } |
| 1929 | 1948 |
| 1930 class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> { | 1949 class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> { |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2586 return e; | 2605 return e; |
| 2587 } | 2606 } |
| 2588 } | 2607 } |
| 2589 | 2608 |
| 2590 class Scope { | 2609 class Scope { |
| 2591 final Element element; | 2610 final Element element; |
| 2592 final Scope parent; | 2611 final Scope parent; |
| 2593 | 2612 |
| 2594 Scope(this.parent, this.element); | 2613 Scope(this.parent, this.element); |
| 2595 abstract Element add(Element element); | 2614 abstract Element add(Element element); |
| 2596 abstract Element lookup(SourceString name); | 2615 |
| 2616 Element lookup(SourceString name) { |
| 2617 Element result = localLookup(name); |
| 2618 if (result != null) return result; |
| 2619 return parent.lookup(name); |
| 2620 } |
| 2621 |
| 2622 Element lexicalLookup(SourceString name) { |
| 2623 Element result = localLookup(name); |
| 2624 if (result != null) return result; |
| 2625 return parent.lexicalLookup(name); |
| 2626 } |
| 2627 |
| 2628 abstract Element localLookup(SourceString name); |
| 2597 } | 2629 } |
| 2598 | 2630 |
| 2599 class VariableScope extends Scope { | 2631 class VariableScope extends Scope { |
| 2600 VariableScope(parent, element) : super(parent, element); | 2632 VariableScope(parent, element) : super(parent, element); |
| 2601 | 2633 |
| 2602 Element add(Element newElement) { | 2634 Element add(Element newElement) { |
| 2603 throw "Cannot add element to VariableScope"; | 2635 throw "Cannot add element to VariableScope"; |
| 2604 } | 2636 } |
| 2605 | 2637 |
| 2606 Element lookup(SourceString name) => parent.lookup(name); | 2638 Element lookup(SourceString name) => parent.lookup(name); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2620 | 2652 |
| 2621 TypeDeclarationScope(parent, TypeDeclarationElement element) | 2653 TypeDeclarationScope(parent, TypeDeclarationElement element) |
| 2622 : super(parent, element) { | 2654 : super(parent, element) { |
| 2623 assert(parent !== null); | 2655 assert(parent !== null); |
| 2624 } | 2656 } |
| 2625 | 2657 |
| 2626 Element add(Element newElement) { | 2658 Element add(Element newElement) { |
| 2627 throw "Cannot add element to TypeDeclarationScope"; | 2659 throw "Cannot add element to TypeDeclarationScope"; |
| 2628 } | 2660 } |
| 2629 | 2661 |
| 2630 Element lookup(SourceString name) { | 2662 Element localLookup(SourceString name) { |
| 2631 Link<DartType> typeVariableLink = element.typeVariables; | 2663 Link<DartType> typeVariableLink = element.typeVariables; |
| 2632 while (!typeVariableLink.isEmpty()) { | 2664 while (!typeVariableLink.isEmpty()) { |
| 2633 TypeVariableType typeVariable = typeVariableLink.head; | 2665 TypeVariableType typeVariable = typeVariableLink.head; |
| 2634 if (typeVariable.name == name) { | 2666 if (typeVariable.name == name) { |
| 2635 return typeVariable.element; | 2667 return typeVariable.element; |
| 2636 } | 2668 } |
| 2637 typeVariableLink = typeVariableLink.tail; | 2669 typeVariableLink = typeVariableLink.tail; |
| 2638 } | 2670 } |
| 2639 | 2671 return null; |
| 2640 return parent.lookup(name); | |
| 2641 } | 2672 } |
| 2642 | 2673 |
| 2643 String toString() => | 2674 String toString() => |
| 2644 '$element${element.typeVariables} > $parent'; | 2675 '$element${element.typeVariables} > $parent'; |
| 2645 } | 2676 } |
| 2646 | 2677 |
| 2647 class MethodScope extends Scope { | 2678 class MethodScope extends Scope { |
| 2648 final Map<SourceString, Element> elements; | 2679 final Map<SourceString, Element> elements; |
| 2649 | 2680 |
| 2650 MethodScope(Scope parent, Element element) | 2681 MethodScope(Scope parent, Element element) |
| 2651 : super(parent, element), | 2682 : super(parent, element), |
| 2652 this.elements = new Map<SourceString, Element>() { | 2683 this.elements = new Map<SourceString, Element>() { |
| 2653 assert(parent !== null); | 2684 assert(parent !== null); |
| 2654 } | 2685 } |
| 2655 | 2686 |
| 2656 Element lookup(SourceString name) { | 2687 Element localLookup(SourceString name) => elements[name]; |
| 2657 Element found = elements[name]; | |
| 2658 if (found !== null) return found; | |
| 2659 return parent.lookup(name); | |
| 2660 } | |
| 2661 | 2688 |
| 2662 Element add(Element newElement) { | 2689 Element add(Element newElement) { |
| 2663 if (elements.containsKey(newElement.name)) { | 2690 if (elements.containsKey(newElement.name)) { |
| 2664 return elements[newElement.name]; | 2691 return elements[newElement.name]; |
| 2665 } | 2692 } |
| 2666 elements[newElement.name] = newElement; | 2693 elements[newElement.name] = newElement; |
| 2667 return newElement; | 2694 return newElement; |
| 2668 } | 2695 } |
| 2669 | 2696 |
| 2670 String toString() => '$element${elements.getKeys()} > $parent'; | 2697 String toString() => '$element${elements.getKeys()} > $parent'; |
| 2671 } | 2698 } |
| 2672 | 2699 |
| 2673 class BlockScope extends MethodScope { | 2700 class BlockScope extends MethodScope { |
| 2674 BlockScope(Scope parent) : super(parent, parent.element); | 2701 BlockScope(Scope parent) : super(parent, parent.element); |
| 2675 | 2702 |
| 2676 String toString() => 'block${elements.getKeys()} > $parent'; | 2703 String toString() => 'block${elements.getKeys()} > $parent'; |
| 2677 } | 2704 } |
| 2678 | 2705 |
| 2679 /** | 2706 /** |
| 2680 * [ClassScope] defines the inner scope of a class/interface declaration in | 2707 * [ClassScope] defines the inner scope of a class/interface declaration in |
| 2681 * which declared members, declared type variables, entities in the enclosing | 2708 * which declared members, declared type variables, entities in the enclosing |
| 2682 * scope and inherited members are available, in the given order. | 2709 * scope and inherited members are available, in the given order. |
| 2683 */ | 2710 */ |
| 2684 class ClassScope extends TypeDeclarationScope { | 2711 class ClassScope extends TypeDeclarationScope { |
| 2685 bool inStaticContext = false; | 2712 bool inStaticContext = false; |
| 2686 | 2713 |
| 2687 ClassScope(Scope parentScope, ClassElement element) | 2714 ClassScope(Scope parentScope, ClassElement element) |
| 2688 : super(parentScope, element); | 2715 : super(parentScope, element); |
| 2689 | 2716 |
| 2690 Element lookup(SourceString name) { | 2717 Element localLookup(SourceString name) { |
| 2691 ClassElement cls = element; | 2718 ClassElement cls = element; |
| 2692 Element result = cls.lookupLocalMember(name); | 2719 Element result = cls.lookupLocalMember(name); |
| 2693 if (result !== null) return result; | 2720 if (result !== null) return result; |
| 2694 if (!inStaticContext) { | 2721 if (!inStaticContext) { |
| 2695 // If not in a static context, we can lookup in the | 2722 // If not in a static context, we can lookup in the |
| 2696 // TypeDeclaration scope, which contains the type variables of | 2723 // TypeDeclaration scope, which contains the type variables of |
| 2697 // the class. | 2724 // the class. |
| 2698 result = super.lookup(name); | 2725 return super.localLookup(name); |
| 2699 } else { | |
| 2700 result = parent.lookup(name); | |
| 2701 } | 2726 } |
| 2702 if (result != null) return result; | 2727 return null; |
| 2728 } |
| 2729 |
| 2730 Element lookup(SourceString name) { |
| 2731 Element result = super.lookup(name); |
| 2732 if (result !== null) return result; |
| 2733 ClassElement cls = element; |
| 2703 return cls.lookupSuperMember(name); | 2734 return cls.lookupSuperMember(name); |
| 2704 } | 2735 } |
| 2705 | 2736 |
| 2706 Element add(Element newElement) { | 2737 Element add(Element newElement) { |
| 2707 throw "Cannot add an element in a class scope"; | 2738 throw "Cannot add an element in a class scope"; |
| 2708 } | 2739 } |
| 2709 | 2740 |
| 2710 String toString() => '$element > $parent'; | 2741 String toString() => '$element > $parent'; |
| 2711 } | 2742 } |
| 2712 | 2743 |
| 2713 class TopScope extends Scope { | 2744 class TopScope extends Scope { |
| 2714 LibraryElement get library => element; | 2745 LibraryElement get library => element; |
| 2715 | 2746 |
| 2716 TopScope(LibraryElement library) : super(null, library); | 2747 TopScope(LibraryElement library) : super(null, library); |
| 2717 Element lookup(SourceString name) { | 2748 |
| 2718 return library.find(name); | 2749 Element localLookup(SourceString name) => library.find(name); |
| 2719 } | 2750 Element lookup(SourceString name) => localLookup(name); |
| 2751 Element lexicalLookup(SourceString name) => localLookup(name); |
| 2720 | 2752 |
| 2721 Element add(Element newElement) { | 2753 Element add(Element newElement) { |
| 2722 throw "Cannot add an element in the top scope"; | 2754 throw "Cannot add an element in the top scope"; |
| 2723 } | 2755 } |
| 2724 String toString() => '$element'; | 2756 String toString() => '$element'; |
| 2725 } | 2757 } |
| OLD | NEW |