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 abstract class TreeElements { | 5 abstract class 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 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1406 return scope.lexicalLookup(const SourceString("assert")) !== null; | 1406 return scope.lexicalLookup(const SourceString("assert")) !== null; |
1407 } | 1407 } |
1408 | 1408 |
1409 /** Check if [node] is the expression of the current expression statement. */ | 1409 /** Check if [node] is the expression of the current expression statement. */ |
1410 bool isExpressionStatementExpression(Node node) { | 1410 bool isExpressionStatementExpression(Node node) { |
1411 return currentExpressionStatement !== null && | 1411 return currentExpressionStatement !== null && |
1412 currentExpressionStatement.expression === node; | 1412 currentExpressionStatement.expression === node; |
1413 } | 1413 } |
1414 | 1414 |
1415 Element resolveSend(Send node) { | 1415 Element resolveSend(Send node) { |
1416 void withAdditionalCategories(int categories, void f()) { | |
1417 var oldCategory = allowedCategory; | |
1418 allowedCategory |= categories; | |
1419 f(); | |
1420 allowedCategory = oldCategory; | |
1421 } | |
1422 | |
1416 Selector selector = resolveSelector(node); | 1423 Selector selector = resolveSelector(node); |
1417 | |
1418 if (node.receiver === null) { | 1424 if (node.receiver === null) { |
1419 // If this send is the expression of an expression statement, and is on | 1425 // If this send is the expression of an expression statement, and is of |
1420 // the form "assert(expr);", and there is no declaration with name | 1426 // the form "assert(expr);", and there is no declaration with name |
1421 // "assert" in the lexical scope, then this is actually an assertion. | 1427 // "assert" in the lexical scope, then this is actually an assertion. |
1422 if (isExpressionStatementExpression(node) && | 1428 if (isExpressionStatementExpression(node) && |
1423 selector.isAssertSyntax() && | 1429 selector.isAssertSyntax() && |
1424 !isAssertInLexicalScope()) { | 1430 !isAssertInLexicalScope()) { |
1425 return compiler.assertMethod; | 1431 return compiler.assertMethod; |
1426 } | 1432 } |
1427 return node.selector.accept(this); | 1433 |
1434 Element result; | |
1435 withAdditionalCategories(ElementCategory.CLASS, () { | |
1436 result = node.selector.accept(this); | |
1437 }); | |
1438 return result; | |
1428 } | 1439 } |
1429 | 1440 |
1430 var oldCategory = allowedCategory; | 1441 Element resolvedReceiver; |
1431 allowedCategory |= | 1442 withAdditionalCategories( |
1432 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER; | 1443 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER, |
1433 Element resolvedReceiver = visit(node.receiver); | 1444 () { resolvedReceiver = visit(node.receiver); }); |
1434 allowedCategory = oldCategory; | 1445 |
1446 if (resolvedReceiver != null && node.isOperator | |
ahe
2012/10/08 09:09:36
I don't understand why it is important to test for
karlklose
2012/10/23 10:33:52
For class literals that are targets for operators,
| |
1447 && resolvedReceiver.kind == ElementKind.CLASS) { | |
1448 // In operator expressions like 'Class + 1', the operator call goes the | |
1449 // instance of [Type] that is the result of the expression 'Class'. | |
1450 ClassElement classElement = resolvedReceiver; | |
1451 resolvedReceiver = null; | |
1452 // We still have to make sure that the class is resolved, because we need | |
1453 // to build its runtime type representation. | |
1454 classElement.ensureResolved(compiler); | |
1455 } | |
1435 | 1456 |
1436 Element target; | 1457 Element target; |
1437 SourceString name = node.selector.asIdentifier().source; | 1458 SourceString name = node.selector.asIdentifier().source; |
1438 if (name.stringValue === 'this') { | 1459 if (name.stringValue === 'this') { |
1439 error(node.selector, MessageKind.GENERIC, ["expected an identifier"]); | 1460 error(node.selector, MessageKind.GENERIC, ["expected an identifier"]); |
1440 } else if (node.isSuperCall) { | 1461 } else if (node.isSuperCall) { |
1441 if (node.isOperator) { | 1462 if (node.isOperator) { |
1442 if (isUserDefinableOperator(name.stringValue)) { | 1463 if (isUserDefinableOperator(name.stringValue)) { |
1443 name = selector.name; | 1464 name = selector.name; |
1444 } else { | 1465 } else { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1515 string === '===' || string === '!==' || | 1536 string === '===' || string === '!==' || |
1516 string === '>>>') { | 1537 string === '>>>') { |
1517 return null; | 1538 return null; |
1518 } | 1539 } |
1519 return node.arguments.isEmpty() | 1540 return node.arguments.isEmpty() |
1520 ? new Selector.unaryOperator(source) | 1541 ? new Selector.unaryOperator(source) |
1521 : new Selector.binaryOperator(source); | 1542 : new Selector.binaryOperator(source); |
1522 } | 1543 } |
1523 | 1544 |
1524 Identifier identifier = node.selector.asIdentifier(); | 1545 Identifier identifier = node.selector.asIdentifier(); |
1525 if (node.isPropertyAccess) { | 1546 if (node.isPropertyAccessOrTypeReference) { |
1526 assert(!isSet); | 1547 assert(!isSet); |
1527 return new Selector.getter(identifier.source, library); | 1548 return new Selector.getter(identifier.source, library); |
1528 } else if (isSet) { | 1549 } else if (isSet) { |
1529 return new Selector.setter(identifier.source, library); | 1550 return new Selector.setter(identifier.source, library); |
1530 } | 1551 } |
1531 | 1552 |
1532 // Compute the arity and the list of named arguments. | 1553 // Compute the arity and the list of named arguments. |
1533 int arity = 0; | 1554 int arity = 0; |
1534 List<SourceString> named = <SourceString>[]; | 1555 List<SourceString> named = <SourceString>[]; |
1535 for (Link<Node> link = node.argumentsNode.nodes; | 1556 for (Link<Node> link = node.argumentsNode.nodes; |
(...skipping 29 matching lines...) Expand all Loading... | |
1565 if (argument.asNamedArgument() != null) { | 1586 if (argument.asNamedArgument() != null) { |
1566 seenNamedArgument = true; | 1587 seenNamedArgument = true; |
1567 } else if (seenNamedArgument) { | 1588 } else if (seenNamedArgument) { |
1568 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); | 1589 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); |
1569 } | 1590 } |
1570 } | 1591 } |
1571 } | 1592 } |
1572 | 1593 |
1573 visitSend(Send node) { | 1594 visitSend(Send node) { |
1574 Element target = resolveSend(node); | 1595 Element target = resolveSend(node); |
1575 if (!Elements.isUnresolved(target) | 1596 |
1576 && target.kind == ElementKind.ABSTRACT_FIELD) { | 1597 if (!Elements.isUnresolved(target)) { |
1577 AbstractFieldElement field = target; | 1598 if (target.kind == ElementKind.ABSTRACT_FIELD) { |
1578 target = field.getter; | 1599 AbstractFieldElement field = target; |
1579 if (target == null && !inInstanceContext) { | 1600 target = field.getter; |
1580 target = | 1601 if (target == null && !inInstanceContext) { |
1581 warnAndCreateErroneousElement(node.selector, field.name, | 1602 target = |
1582 MessageKind.CANNOT_RESOLVE_GETTER, | 1603 warnAndCreateErroneousElement(node.selector, field.name, |
1583 [node.selector]); | 1604 MessageKind.CANNOT_RESOLVE_GETTER, |
1605 [node.selector]); | |
1606 } | |
1607 } else if (target.kind == ElementKind.CLASS) { | |
1608 ClassElement classElement = target; | |
1609 classElement.ensureResolved(compiler); | |
ahe
2012/10/08 09:09:36
Why is this not done in resolveSend?
karlklose
2012/10/23 10:33:52
Moved.
| |
1584 } | 1610 } |
1585 } | 1611 } |
1586 | 1612 |
1587 bool resolvedArguments = false; | 1613 bool resolvedArguments = false; |
1588 if (node.isOperator) { | 1614 if (node.isOperator) { |
1589 String operatorString = node.selector.asOperator().source.stringValue; | 1615 String operatorString = node.selector.asOperator().source.stringValue; |
1590 if (operatorString === 'is' || operatorString === 'as') { | 1616 if (operatorString === 'is' || operatorString === 'as') { |
1591 assert(node.arguments.tail.isEmpty()); | 1617 assert(node.arguments.tail.isEmpty()); |
1592 DartType type = resolveTypeTest(node.arguments.head); | 1618 DartType type = resolveTypeTest(node.arguments.head); |
1593 if (type != null) { | 1619 if (type != null) { |
(...skipping 27 matching lines...) Expand all Loading... | |
1621 target.isGetter() || | 1647 target.isGetter() || |
1622 Elements.isClosureSend(node, target))) { | 1648 Elements.isClosureSend(node, target))) { |
1623 Selector call = new Selector.callClosureFrom(selector); | 1649 Selector call = new Selector.callClosureFrom(selector); |
1624 world.registerDynamicInvocation(call.name, call); | 1650 world.registerDynamicInvocation(call.name, call); |
1625 } | 1651 } |
1626 | 1652 |
1627 // TODO(ngeoffray): Warn if target is null and the send is | 1653 // TODO(ngeoffray): Warn if target is null and the send is |
1628 // unqualified. | 1654 // unqualified. |
1629 useElement(node, target); | 1655 useElement(node, target); |
1630 registerSend(selector, target); | 1656 registerSend(selector, target); |
1631 return node.isPropertyAccess ? target : null; | 1657 return node.isPropertyAccessOrTypeReference ? target : null; |
1632 } | 1658 } |
1633 | 1659 |
1634 visitSendSet(SendSet node) { | 1660 visitSendSet(SendSet node) { |
1635 Element target = resolveSend(node); | 1661 Element target = resolveSend(node); |
1662 if (!Elements.isUnresolved(target) && target.kind == ElementKind.CLASS) { | |
1663 ClassElement classElement = target; | |
1664 classElement.ensureResolved(compiler); | |
ahe
2012/10/08 09:09:36
Why is this not done in resolveSend?
karlklose
2012/10/23 10:33:52
Done.
| |
1665 } | |
1636 Element setter = target; | 1666 Element setter = target; |
1637 Element getter = target; | 1667 Element getter = target; |
1638 SourceString operatorName = node.assignmentOperator.source; | 1668 SourceString operatorName = node.assignmentOperator.source; |
1639 String source = operatorName.stringValue; | 1669 String source = operatorName.stringValue; |
1640 bool isComplex = source !== '='; | 1670 bool isComplex = source !== '='; |
1641 if (!Elements.isUnresolved(target) | 1671 if (!Elements.isUnresolved(target) |
1642 && target.kind == ElementKind.ABSTRACT_FIELD) { | 1672 && target.kind == ElementKind.ABSTRACT_FIELD) { |
1643 AbstractFieldElement field = target; | 1673 AbstractFieldElement field = target; |
1644 setter = field.setter; | 1674 setter = field.setter; |
1645 getter = field.getter; | 1675 getter = field.getter; |
(...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3137 return result; | 3167 return result; |
3138 } | 3168 } |
3139 Element lookup(SourceString name) => localLookup(name); | 3169 Element lookup(SourceString name) => localLookup(name); |
3140 Element lexicalLookup(SourceString name) => localLookup(name); | 3170 Element lexicalLookup(SourceString name) => localLookup(name); |
3141 | 3171 |
3142 Element add(Element newElement) { | 3172 Element add(Element newElement) { |
3143 throw "Cannot add an element in a patch library scope"; | 3173 throw "Cannot add an element in a patch library scope"; |
3144 } | 3174 } |
3145 String toString() => 'PatchLibraryScope($origin,$patch)'; | 3175 String toString() => 'PatchLibraryScope($origin,$patch)'; |
3146 } | 3176 } |
OLD | NEW |