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 /** | 7 /** |
8 * Core implementation of resolution. | 8 * Core implementation of resolution. |
9 * | 9 * |
10 * Do not subclass or instantiate this class outside this library | 10 * Do not subclass or instantiate this class outside this library |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 if (node.isConditional) { | 533 if (node.isConditional) { |
534 sendIsMemberAccess = oldSendIsMemberAccess; | 534 sendIsMemberAccess = oldSendIsMemberAccess; |
535 allowedCategory = oldAllowedCategory; | 535 allowedCategory = oldAllowedCategory; |
536 } | 536 } |
537 | 537 |
538 allowedCategory = oldCategory; | 538 allowedCategory = oldCategory; |
539 | 539 |
540 Element target; | 540 Element target; |
541 String name = node.selector.asIdentifier().source; | 541 String name = node.selector.asIdentifier().source; |
542 if (identical(name, 'this')) { | 542 if (identical(name, 'this')) { |
543 error(node.selector, MessageKind.THIS_PROPERTY); | 543 // TODO(ahe): Why is this using GENERIC? |
| 544 error(node.selector, MessageKind.GENERIC, |
| 545 {'text': "expected an identifier"}); |
544 return const NoneResult(); | 546 return const NoneResult(); |
545 } else if (node.isSuperCall) { | 547 } else if (node.isSuperCall) { |
546 if (node.isOperator) { | 548 if (node.isOperator) { |
547 if (isUserDefinableOperator(name)) { | 549 if (isUserDefinableOperator(name)) { |
548 name = selector.name; | 550 name = selector.name; |
549 } else { | 551 } else { |
550 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name}); | 552 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name}); |
551 return const NoneResult(); | 553 return const NoneResult(); |
552 } | 554 } |
553 } | 555 } |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
948 target = error; | 950 target = error; |
949 } | 951 } |
950 // We still need to register the invocation, because we might | 952 // We still need to register the invocation, because we might |
951 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. | 953 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. |
952 registry.registerDynamicInvocation(selector); | 954 registry.registerDynamicInvocation(selector); |
953 registry.registerSuperNoSuchMethod(); | 955 registry.registerSuperNoSuchMethod(); |
954 } | 956 } |
955 return computeSuperAccessSemantics(node, target); | 957 return computeSuperAccessSemantics(node, target); |
956 } | 958 } |
957 | 959 |
958 /// Resolve [node] as a subexpression that is _not_ the prefix of a member | 960 /// Resolve [node] as subexpression that is _not_ the prefix of a member |
959 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. | 961 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. |
960 ResolutionResult visitExpression(Node node) { | 962 ResolutionResult visitExpression(Node node) { |
961 bool oldSendIsMemberAccess = sendIsMemberAccess; | 963 bool oldSendIsMemberAccess = sendIsMemberAccess; |
962 sendIsMemberAccess = false; | 964 sendIsMemberAccess = false; |
963 ResolutionResult result = visit(node); | 965 ResolutionResult result = visit(node); |
964 sendIsMemberAccess = oldSendIsMemberAccess; | 966 sendIsMemberAccess = oldSendIsMemberAccess; |
965 return result; | 967 return result; |
966 } | 968 } |
967 | 969 |
968 /// Resolve [node] as a subexpression that _is_ the prefix of a member access. | |
969 /// For instance `a` in `a.b`, as opposed to `a` in `a + b`. | |
970 ResolutionResult visitExpressionPrefix(Node node) { | |
971 int oldAllowedCategory = allowedCategory; | |
972 bool oldSendIsMemberAccess = sendIsMemberAccess; | |
973 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER; | |
974 sendIsMemberAccess = true; | |
975 ResolutionResult result = visit(node); | |
976 sendIsMemberAccess = oldSendIsMemberAccess; | |
977 allowedCategory = oldAllowedCategory; | |
978 return result; | |
979 } | |
980 | |
981 /// Resolved [node] as a subexpression that is the prefix of a conditional | |
982 /// access. For instance `a` in `a?.b`. | |
983 // TODO(johnniwinther): Is this equivalent to [visitExpression]? | |
984 ResolutionResult visitConditionalPrefix(Node node) { | |
985 // Conditional sends like `e?.foo` treat the receiver as an expression. So | |
986 // `C?.foo` needs to be treated like `(C).foo`, not like C.foo. Prefixes and | |
987 // super are not allowed on their own in that context. | |
988 int oldAllowedCategory = allowedCategory; | |
989 bool oldSendIsMemberAccess = sendIsMemberAccess; | |
990 sendIsMemberAccess = false; | |
991 allowedCategory = | |
992 ElementCategory.VARIABLE | | |
993 ElementCategory.FUNCTION | | |
994 ElementCategory.IMPLIES_TYPE; | |
995 ResolutionResult result = visit(node); | |
996 sendIsMemberAccess = oldSendIsMemberAccess; | |
997 allowedCategory = oldAllowedCategory; | |
998 return result; | |
999 } | |
1000 | |
1001 /// Handle a type test expression, like `a is T` and `a is! T`. | 970 /// Handle a type test expression, like `a is T` and `a is! T`. |
1002 ResolutionResult handleIs(Send node) { | 971 ResolutionResult handleIs(Send node) { |
1003 Node expression = node.receiver; | 972 Node expression = node.receiver; |
1004 visitExpression(expression); | 973 visitExpression(expression); |
1005 | 974 |
1006 // TODO(johnniwinther): Use seen type tests to avoid registration of | 975 // TODO(johnniwinther): Use seen type tests to avoid registration of |
1007 // mutation/access to unpromoted variables. | 976 // mutation/access to unpromoted variables. |
1008 | 977 |
1009 Send notTypeNode = node.arguments.head.asSend(); | 978 Send notTypeNode = node.arguments.head.asSend(); |
1010 DartType type; | 979 DartType type; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 sendStructure = const InvalidAssertStructure(); | 1382 sendStructure = const InvalidAssertStructure(); |
1414 } | 1383 } |
1415 registry.registerAssert(node); | 1384 registry.registerAssert(node); |
1416 registry.registerSendStructure(node, sendStructure); | 1385 registry.registerSendStructure(node, sendStructure); |
1417 return const AssertResult(); | 1386 return const AssertResult(); |
1418 } | 1387 } |
1419 | 1388 |
1420 /// Handle access of a property of [name] on `this`, like `this.name` and | 1389 /// Handle access of a property of [name] on `this`, like `this.name` and |
1421 /// `this.name()`, or `name` and `name()` in instance context. | 1390 /// `this.name()`, or `name` and `name()` in instance context. |
1422 ResolutionResult handleThisPropertyAccess(Send node, Name name) { | 1391 ResolutionResult handleThisPropertyAccess(Send node, Name name) { |
1423 AccessSemantics semantics = new AccessSemantics.thisProperty(); | 1392 AccessSemantics accessSemantics = new AccessSemantics.thisProperty(); |
1424 return handleDynamicAccessSemantics(node, name, semantics); | 1393 SendStructure sendStructure; |
| 1394 Selector selector; |
| 1395 if (node.isCall) { |
| 1396 CallStructure callStructure = resolveArguments(node.argumentsNode); |
| 1397 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 1398 registry.registerDynamicInvocation(selector); |
| 1399 sendStructure = new InvokeStructure(accessSemantics, selector); |
| 1400 } else { |
| 1401 assert(invariant(node, node.isPropertyAccess)); |
| 1402 selector = new Selector( |
| 1403 SelectorKind.GETTER, name, CallStructure.NO_ARGS); |
| 1404 registry.registerDynamicGetter(selector); |
| 1405 sendStructure = new GetStructure(accessSemantics, selector); |
| 1406 } |
| 1407 registry.registerSendStructure(node, sendStructure); |
| 1408 // TODO(johnniwinther): Remove this when all information goes through |
| 1409 // the [SendStructure]. |
| 1410 registry.setSelector(node, selector); |
| 1411 return const NoneResult(); |
1425 } | 1412 } |
1426 | 1413 |
1427 /// Handle access on `this`, like `this()` and `this` when it is parsed as a | 1414 /// Handle access on `this`, like `this()` and `this` when it is parsed as a |
1428 /// [Send] node. | 1415 /// [Send] node. |
1429 ResolutionResult handleThisAccess(Send node) { | 1416 ResolutionResult handleThisAccess(Send node) { |
1430 AccessSemantics accessSemantics = new AccessSemantics.thisAccess(); | 1417 AccessSemantics accessSemantics = new AccessSemantics.thisAccess(); |
1431 if (node.isCall) { | 1418 if (node.isCall) { |
1432 CallStructure callStructure = resolveArguments(node.argumentsNode); | 1419 CallStructure callStructure = resolveArguments(node.argumentsNode); |
1433 Selector selector = callStructure.callSelector; | 1420 Selector selector = callStructure.callSelector; |
1434 // TODO(johnniwinther): Handle invalid this access as an | 1421 // TODO(johnniwinther): Handle invalid this access as an |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1582 case BinaryOperatorKind.LT: | 1569 case BinaryOperatorKind.LT: |
1583 case BinaryOperatorKind.AND: | 1570 case BinaryOperatorKind.AND: |
1584 case BinaryOperatorKind.OR: | 1571 case BinaryOperatorKind.OR: |
1585 case BinaryOperatorKind.XOR: | 1572 case BinaryOperatorKind.XOR: |
1586 return handleUserDefinableBinary(node, operator); | 1573 return handleUserDefinableBinary(node, operator); |
1587 } | 1574 } |
1588 } | 1575 } |
1589 } | 1576 } |
1590 } | 1577 } |
1591 | 1578 |
1592 /// Handle qualified access to an unresolved static class member, like `a.b` | |
1593 /// or `a.b()` where `a` is a class and `b` is unresolved. | |
1594 ResolutionResult handleUnresolvedStaticMemberAccess( | |
1595 Send node, Name name, ClassElement receiverClass) { | |
1596 // TODO(johnniwinther): Share code with [handleStaticInstanceMemberAccess] | |
1597 // and [handlePrivateStaticMemberAccess]. | |
1598 registry.registerThrowNoSuchMethod(); | |
1599 // TODO(johnniwinther): Produce a different error if [name] is resolves to | |
1600 // a constructor. | |
1601 | |
1602 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
1603 // try to resolve injected elements if [currentClass] is in the patch | |
1604 // library of [receiverClass]. | |
1605 | |
1606 // TODO(karlklose): this should be reported by the caller of | |
1607 // [resolveSend] to select better warning messages for getters and | |
1608 // setters. | |
1609 ErroneousElement error = reportAndCreateErroneousElement( | |
1610 node, name.text, MessageKind.MEMBER_NOT_FOUND, | |
1611 {'className': receiverClass.name, 'memberName': name.text}); | |
1612 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | |
1613 // member access. | |
1614 return handleErroneousAccess( | |
1615 node, name, error, new StaticAccess.unresolved(error)); | |
1616 } | |
1617 | |
1618 /// Handle qualified access of an instance member, like `a.b` or `a.b()` where | |
1619 /// `a` is a class and `b` is a non-static member. | |
1620 ResolutionResult handleStaticInstanceMemberAccess( | |
1621 Send node, Name name, ClassElement receiverClass, Element member) { | |
1622 | |
1623 registry.registerThrowNoSuchMethod(); | |
1624 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
1625 // try to resolve injected elements if [currentClass] is in the patch | |
1626 // library of [receiverClass]. | |
1627 | |
1628 // TODO(karlklose): this should be reported by the caller of | |
1629 // [resolveSend] to select better warning messages for getters and | |
1630 // setters. | |
1631 ErroneousElement error = reportAndCreateErroneousElement( | |
1632 node, name.text, MessageKind.MEMBER_NOT_STATIC, | |
1633 {'className': receiverClass.name, 'memberName': name}); | |
1634 | |
1635 // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed | |
1636 // instance members. | |
1637 return handleErroneousAccess( | |
1638 node, name, error, new StaticAccess.unresolved(error)); | |
1639 } | |
1640 | |
1641 /// Handle qualified access of an inaccessible private static class member, | |
1642 /// like `a._b` or `a.b()` where `a` is class, `_b` is static member of `a` | |
1643 /// but `a` is not defined in the current library. | |
1644 ResolutionResult handlePrivateStaticMemberAccess( | |
1645 Send node, Name name, ClassElement receiverClass, Element member) { | |
1646 registry.registerThrowNoSuchMethod(); | |
1647 ErroneousElement error = reportAndCreateErroneousElement( | |
1648 node, name.text, MessageKind.PRIVATE_ACCESS, | |
1649 {'libraryName': member.library.getLibraryOrScriptName(), | |
1650 'name': name}); | |
1651 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | |
1652 // member access. | |
1653 return handleErroneousAccess( | |
1654 node, name, error, new StaticAccess.unresolved(error)); | |
1655 } | |
1656 | |
1657 /// Handle qualified access to a static member, like `a.b` or `a.b()` where | |
1658 /// `a` is a class and `b` is a static member of `a`. | |
1659 ResolutionResult handleStaticMemberAccess( | |
1660 Send node, Name memberName, ClassElement receiverClass) { | |
1661 String name = memberName.text; | |
1662 receiverClass.ensureResolved(compiler); | |
1663 if (node.isOperator) { | |
1664 // When the resolved receiver is a class, we can have two cases: | |
1665 // 1) a static send: C.foo, or | |
1666 // 2) an operator send, where the receiver is a class literal: 'C + 1'. | |
1667 // The following code that looks up the selector on the resolved | |
1668 // receiver will treat the second as the invocation of a static operator | |
1669 // if the resolved receiver is not null. | |
1670 return const NoneResult(); | |
1671 } | |
1672 MembersCreator.computeClassMembersByName( | |
1673 compiler, receiverClass.declaration, name); | |
1674 Element member = receiverClass.lookupLocalMember(name); | |
1675 if (member == null) { | |
1676 return handleUnresolvedStaticMemberAccess( | |
1677 node, memberName, receiverClass); | |
1678 } else if (member.isInstanceMember) { | |
1679 return handleStaticInstanceMemberAccess( | |
1680 node, memberName, receiverClass, member); | |
1681 } else if (memberName.isPrivate && memberName.library != member.library) { | |
1682 return handlePrivateStaticMemberAccess( | |
1683 node, memberName, receiverClass, member); | |
1684 } else { | |
1685 return handleStaticOrTopLevelAccess(node, memberName, member); | |
1686 } | |
1687 } | |
1688 | |
1689 /// Handle qualified [Send] where the receiver resolves to an [Element], like | |
1690 /// `a.b` where `a` is a local, field, class, or prefix, etc. | |
1691 ResolutionResult handleResolvedQualifiedSend( | |
1692 Send node, Name name, Element element) { | |
1693 if (element.isPrefix) { | |
1694 return oldVisitSend(node); | |
1695 } else if (element.isClass) { | |
1696 return handleStaticMemberAccess(node, name, element); | |
1697 } | |
1698 return oldVisitSend(node); | |
1699 } | |
1700 | |
1701 /// Handle dynamic access of [semantics]. | |
1702 ResolutionResult handleDynamicAccessSemantics( | |
1703 Send node, Name name, AccessSemantics semantics) { | |
1704 SendStructure sendStructure; | |
1705 Selector selector; | |
1706 if (node.isCall) { | |
1707 CallStructure callStructure = resolveArguments(node.argumentsNode); | |
1708 selector = new Selector(SelectorKind.CALL, name, callStructure); | |
1709 registry.registerDynamicInvocation(selector); | |
1710 sendStructure = new InvokeStructure(semantics, selector); | |
1711 } else { | |
1712 assert(invariant(node, node.isPropertyAccess)); | |
1713 selector = new Selector( | |
1714 SelectorKind.GETTER, name, CallStructure.NO_ARGS); | |
1715 registry.registerDynamicGetter(selector); | |
1716 sendStructure = new GetStructure(semantics, selector); | |
1717 } | |
1718 registry.registerSendStructure(node, sendStructure); | |
1719 // TODO(johnniwinther): Remove this when all information goes through | |
1720 // the [SendStructure]. | |
1721 registry.setSelector(node, selector); | |
1722 return const NoneResult(); | |
1723 } | |
1724 | |
1725 /// Handle dynamic property access, like `a.b` or `a.b()` where `a` is not a | |
1726 /// prefix or class. | |
1727 ResolutionResult handleDynamicPropertyAccess(Send node, Name name) { | |
1728 AccessSemantics semantics = | |
1729 new DynamicAccess.dynamicProperty(node.receiver); | |
1730 return handleDynamicAccessSemantics(node, name, semantics); | |
1731 } | |
1732 | |
1733 /// Handle conditional access, like `a?.b` or `a?.b()`. | |
1734 ResolutionResult handleConditionalAccess(Send node, Name name) { | |
1735 Node receiver = node.receiver; | |
1736 visitConditionalPrefix(receiver); | |
1737 AccessSemantics semantics = | |
1738 new DynamicAccess.ifNotNullProperty(receiver); | |
1739 return handleDynamicAccessSemantics(node, name, semantics); | |
1740 } | |
1741 | |
1742 /// Handle `this` as a qualified property, like `a.this`. | |
1743 ResolutionResult handleQualifiedThisAccess(Send node, Name name) { | |
1744 ErroneousElement error = reportAndCreateErroneousElement( | |
1745 node.selector, | |
1746 name.text, | |
1747 MessageKind.THIS_PROPERTY, {}, | |
1748 isError: true); | |
1749 // TODO(johnniwinther): Support `this` as property as an [AccessSemantics]. | |
1750 AccessSemantics accessSemantics = new StaticAccess.unresolved(error); | |
1751 return handleErroneousAccess(node, name, error, accessSemantics); | |
1752 } | |
1753 | |
1754 /// Handle a qualified [Send], that is where the receiver is non-null, like | 1579 /// Handle a qualified [Send], that is where the receiver is non-null, like |
1755 /// `a.b`, `a.b()`, `this.a()` and `super.a()`. | 1580 /// `a.b`, `a.b()`, `this.a()` and `super.a()`. |
1756 ResolutionResult handleQualifiedSend(Send node) { | 1581 ResolutionResult handleQualifiedSend(Send node) { |
1757 Identifier selector = node.selector.asIdentifier(); | 1582 Identifier selector = node.selector.asIdentifier(); |
1758 String text = selector.source; | 1583 Name name = new Name(selector.source, enclosingElement.library); |
1759 Name name = new Name(text, enclosingElement.library); | 1584 if (node.isSuperCall) { |
1760 if (text == 'this') { | |
1761 return handleQualifiedThisAccess(node, name); | |
1762 } else if (node.isSuperCall) { | |
1763 return handleSuperPropertyAccess(node, name); | 1585 return handleSuperPropertyAccess(node, name); |
1764 } else if (node.receiver.isThis()) { | 1586 } else if (node.receiver.isThis()) { |
1765 if (checkThisAccess(node)) { | 1587 if (checkThisAccess(node)) { |
1766 return handleThisPropertyAccess(node, name); | 1588 return handleThisPropertyAccess(node, name); |
1767 } | 1589 } |
1768 // TODO(johnniwinther): Handle invalid this access as an | 1590 // TODO(johnniwinther): Handle invalid this access as an |
1769 // [AccessSemantics]. | 1591 // [AccessSemantics]. |
1770 return const NoneResult(); | 1592 return const NoneResult(); |
1771 } else if (node.isConditional) { | |
1772 return handleConditionalAccess(node, name); | |
1773 } | 1593 } |
1774 ResolutionResult result = visitExpressionPrefix(node.receiver); | 1594 // TODO(johnniwinther): Handle remaining qualified sends. |
1775 if (result.element != null) { | 1595 return oldVisitSend(node); |
1776 return handleResolvedQualifiedSend(node, name, result.element); | |
1777 } else { | |
1778 return handleDynamicPropertyAccess(node, name); | |
1779 } | |
1780 } | 1596 } |
1781 | 1597 |
1782 /// Handle access unresolved access to [name] in a non-instance context. | 1598 /// Handle access unresolved access to [name] in a non-instance context. |
1783 ResolutionResult handleUnresolvedAccess( | 1599 ResolutionResult handleUnresolvedAccess( |
1784 Send node, Name name, Element element) { | 1600 Send node, Name name, Element element) { |
1785 // TODO(johnniwinther): Support unresolved top level access as an | 1601 // TODO(johnniwinther): Support unresolved top level access as an |
1786 // [AccessSemantics]. | 1602 // [AccessSemantics]. |
1787 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); | 1603 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); |
1788 return handleErroneousAccess(node, name, element, accessSemantics); | 1604 return handleErroneousAccess(node, name, element, accessSemantics); |
1789 } | 1605 } |
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2641 ResolutionResult visitWhile(While node) { | 2457 ResolutionResult visitWhile(While node) { |
2642 visit(node.condition); | 2458 visit(node.condition); |
2643 visitLoopBodyIn(node, node.body, new BlockScope(scope)); | 2459 visitLoopBodyIn(node, node.body, new BlockScope(scope)); |
2644 return const NoneResult(); | 2460 return const NoneResult(); |
2645 } | 2461 } |
2646 | 2462 |
2647 ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) { | 2463 ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) { |
2648 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2464 bool oldSendIsMemberAccess = sendIsMemberAccess; |
2649 sendIsMemberAccess = false; | 2465 sendIsMemberAccess = false; |
2650 var oldCategory = allowedCategory; | 2466 var oldCategory = allowedCategory; |
2651 allowedCategory = | 2467 allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
2652 ElementCategory.VARIABLE | | 2468 | ElementCategory.IMPLIES_TYPE; |
2653 ElementCategory.FUNCTION | | |
2654 ElementCategory.IMPLIES_TYPE; | |
2655 ResolutionResult result = visit(node.expression); | 2469 ResolutionResult result = visit(node.expression); |
2656 allowedCategory = oldCategory; | 2470 allowedCategory = oldCategory; |
2657 sendIsMemberAccess = oldSendIsMemberAccess; | 2471 sendIsMemberAccess = oldSendIsMemberAccess; |
2658 if (result.kind == ResultKind.CONSTANT) { | 2472 if (result.kind == ResultKind.CONSTANT) { |
2659 return result; | 2473 return result; |
2660 } | 2474 } |
2661 return const NoneResult(); | 2475 return const NoneResult(); |
2662 } | 2476 } |
2663 | 2477 |
2664 ResolutionResult visitNewExpression(NewExpression node) { | 2478 ResolutionResult visitNewExpression(NewExpression node) { |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3459 } | 3273 } |
3460 return const NoneResult(); | 3274 return const NoneResult(); |
3461 } | 3275 } |
3462 } | 3276 } |
3463 | 3277 |
3464 /// Looks up [name] in [scope] and unwraps the result. | 3278 /// Looks up [name] in [scope] and unwraps the result. |
3465 Element lookupInScope(Compiler compiler, Node node, | 3279 Element lookupInScope(Compiler compiler, Node node, |
3466 Scope scope, String name) { | 3280 Scope scope, String name) { |
3467 return Elements.unwrap(scope.lookup(name), compiler, node); | 3281 return Elements.unwrap(scope.lookup(name), compiler, node); |
3468 } | 3282 } |
OLD | NEW |