Chromium Code Reviews| 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 |