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 Element get currentElement; | 8 Element get currentElement; |
9 Set<Node> get superUses; | 9 Set<Node> get superUses; |
10 | 10 |
(...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1400 if (identical(stringValue, 'void')) { | 1400 if (identical(stringValue, 'void')) { |
1401 return compiler.types.voidType.element; | 1401 return compiler.types.voidType.element; |
1402 } else if (identical(stringValue, 'dynamic')) { | 1402 } else if (identical(stringValue, 'dynamic')) { |
1403 return compiler.dynamicClass; | 1403 return compiler.dynamicClass; |
1404 } else { | 1404 } else { |
1405 return scope.lookup(typeName.source); | 1405 return scope.lookup(typeName.source); |
1406 } | 1406 } |
1407 } | 1407 } |
1408 } | 1408 } |
1409 | 1409 |
1410 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean | 1410 DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node, |
1411 // flags instead of closures. | 1411 {bool malformedIsError: false, |
1412 DartType resolveTypeAnnotation( | 1412 bool ambiguousIsError: false}) { |
1413 MappingVisitor visitor, | |
1414 TypeAnnotation node, | |
1415 {onFailure(Node node, MessageKind kind, [Map arguments])}) { | |
1416 if (onFailure == null) { | |
1417 onFailure = (n, k, [arguments]) {}; | |
1418 } | |
1419 return resolveTypeAnnotationInContext(visitor, node, onFailure); | |
1420 } | |
1421 | |
1422 DartType resolveTypeAnnotationInContext(MappingVisitor visitor, | |
1423 TypeAnnotation node, | |
1424 onFailure) { | |
1425 Identifier typeName; | 1413 Identifier typeName; |
1426 SourceString prefixName; | 1414 SourceString prefixName; |
1427 Send send = node.typeName.asSend(); | 1415 Send send = node.typeName.asSend(); |
1428 if (send != null) { | 1416 if (send != null) { |
1429 // The type name is of the form [: prefix . identifier :]. | 1417 // The type name is of the form [: prefix . identifier :]. |
1430 prefixName = send.receiver.asIdentifier().source; | 1418 prefixName = send.receiver.asIdentifier().source; |
1431 typeName = send.selector.asIdentifier(); | 1419 typeName = send.selector.asIdentifier(); |
1432 } else { | 1420 } else { |
1433 typeName = node.typeName.asIdentifier(); | 1421 typeName = node.typeName.asIdentifier(); |
1434 } | 1422 } |
1435 | 1423 |
1436 Element element = resolveTypeName(visitor.scope, prefixName, typeName); | 1424 Element element = resolveTypeName(visitor.scope, prefixName, typeName); |
1437 DartType type; | 1425 DartType type; |
1438 | 1426 |
1439 DartType reportFailureAndCreateType(MessageKind messageKind, | 1427 DartType reportFailureAndCreateType(MessageKind messageKind, |
1440 Map messageArguments) { | 1428 Map messageArguments, |
1441 onFailure(node, messageKind, messageArguments); | 1429 {DartType userProvidedBadType, |
| 1430 bool isError: false, |
| 1431 bool isAmbiguous: false}) { |
| 1432 if (isError) { |
| 1433 visitor.error(node, messageKind, messageArguments); |
| 1434 } else { |
| 1435 visitor.warning(node, messageKind, messageArguments); |
| 1436 } |
1442 var erroneousElement = new ErroneousElementX( | 1437 var erroneousElement = new ErroneousElementX( |
1443 messageKind, messageArguments, typeName.source, | 1438 messageKind, messageArguments, typeName.source, |
1444 visitor.enclosingElement); | 1439 visitor.enclosingElement); |
1445 var arguments = new LinkBuilder<DartType>(); | 1440 var arguments = new LinkBuilder<DartType>(); |
1446 resolveTypeArguments( | 1441 resolveTypeArguments(visitor, node, null, arguments); |
1447 visitor, node, null, | 1442 return isAmbiguous |
1448 onFailure, arguments); | 1443 ? new AmbiguousType(erroneousElement, arguments.toLink()) |
1449 return new MalformedType(erroneousElement, null, arguments.toLink()); | 1444 : new MalformedType(erroneousElement, |
| 1445 userProvidedBadType, arguments.toLink()); |
1450 } | 1446 } |
1451 | 1447 |
1452 DartType checkNoTypeArguments(DartType type) { | 1448 DartType checkNoTypeArguments(DartType type) { |
1453 var arguments = new LinkBuilder<DartType>(); | 1449 var arguments = new LinkBuilder<DartType>(); |
1454 bool hashTypeArgumentMismatch = resolveTypeArguments( | 1450 bool hasTypeArgumentMismatch = resolveTypeArguments( |
1455 visitor, node, const Link<DartType>(), | 1451 visitor, node, const Link<DartType>(), arguments); |
1456 onFailure, arguments); | 1452 if (hasTypeArgumentMismatch) { |
1457 if (hashTypeArgumentMismatch) { | |
1458 type = new MalformedType( | 1453 type = new MalformedType( |
1459 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, | 1454 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
1460 {'type': node}, typeName.source, visitor.enclosingElement), | 1455 {'type': node}, typeName.source, visitor.enclosingElement), |
1461 type, arguments.toLink()); | 1456 type, arguments.toLink()); |
1462 } | 1457 } |
1463 return type; | 1458 return type; |
1464 } | 1459 } |
1465 | 1460 |
1466 if (element == null) { | 1461 if (element == null) { |
1467 type = reportFailureAndCreateType( | 1462 type = reportFailureAndCreateType( |
1468 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); | 1463 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}, |
| 1464 isError: malformedIsError); |
1469 } else if (element.isAmbiguous()) { | 1465 } else if (element.isAmbiguous()) { |
1470 AmbiguousElement ambiguous = element; | 1466 AmbiguousElement ambiguous = element; |
1471 type = reportFailureAndCreateType( | 1467 type = reportFailureAndCreateType( |
1472 ambiguous.messageKind, ambiguous.messageArguments); | 1468 ambiguous.messageKind, ambiguous.messageArguments, |
| 1469 isError: ambiguousIsError, isAmbiguous: true); |
1473 ambiguous.diagnose(visitor.mapping.currentElement, compiler); | 1470 ambiguous.diagnose(visitor.mapping.currentElement, compiler); |
1474 } else if (!element.impliesType()) { | 1471 } else if (!element.impliesType()) { |
1475 type = reportFailureAndCreateType( | 1472 type = reportFailureAndCreateType( |
1476 MessageKind.NOT_A_TYPE, {'node': node.typeName}); | 1473 MessageKind.NOT_A_TYPE, {'node': node.typeName}, |
| 1474 isError: malformedIsError); |
1477 } else { | 1475 } else { |
1478 if (identical(element, compiler.types.voidType.element) || | 1476 if (identical(element, compiler.types.voidType.element) || |
1479 identical(element, compiler.types.dynamicType.element)) { | 1477 identical(element, compiler.dynamicClass)) { |
1480 type = checkNoTypeArguments(element.computeType(compiler)); | 1478 type = checkNoTypeArguments(element.computeType(compiler)); |
1481 } else if (element.isClass()) { | 1479 } else if (element.isClass()) { |
1482 ClassElement cls = element; | 1480 ClassElement cls = element; |
1483 compiler.resolver._ensureClassWillBeResolved(cls); | 1481 compiler.resolver._ensureClassWillBeResolved(cls); |
1484 element.computeType(compiler); | 1482 element.computeType(compiler); |
1485 var arguments = new LinkBuilder<DartType>(); | 1483 var arguments = new LinkBuilder<DartType>(); |
1486 bool hashTypeArgumentMismatch = resolveTypeArguments( | 1484 bool hasTypeArgumentMismatch = resolveTypeArguments( |
1487 visitor, node, cls.typeVariables, | 1485 visitor, node, cls.typeVariables, arguments); |
1488 onFailure, arguments); | 1486 if (hasTypeArgumentMismatch) { |
1489 if (hashTypeArgumentMismatch) { | 1487 type = new BadInterfaceType(cls.declaration, |
1490 type = new MalformedType( | |
1491 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, | |
1492 {'type': node}, typeName.source, visitor.enclosingElement), | |
1493 new InterfaceType.userProvidedBadType(cls.declaration, | 1488 new InterfaceType.userProvidedBadType(cls.declaration, |
1494 arguments.toLink())); | 1489 arguments.toLink())); |
1495 } else { | 1490 } else { |
1496 if (arguments.isEmpty) { | 1491 if (arguments.isEmpty) { |
1497 type = cls.rawType; | 1492 type = cls.rawType; |
1498 } else { | 1493 } else { |
1499 type = new InterfaceType(cls.declaration, arguments.toLink()); | 1494 type = new InterfaceType(cls.declaration, arguments.toLink()); |
1500 } | 1495 } |
1501 } | 1496 } |
1502 } else if (element.isTypedef()) { | 1497 } else if (element.isTypedef()) { |
1503 TypedefElement typdef = element; | 1498 TypedefElement typdef = element; |
1504 // TODO(ahe): Should be [ensureResolved]. | 1499 // TODO(ahe): Should be [ensureResolved]. |
1505 compiler.resolveTypedef(typdef); | 1500 compiler.resolveTypedef(typdef); |
1506 var arguments = new LinkBuilder<DartType>(); | 1501 var arguments = new LinkBuilder<DartType>(); |
1507 bool hashTypeArgumentMismatch = resolveTypeArguments( | 1502 bool hasTypeArgumentMismatch = resolveTypeArguments( |
1508 visitor, node, typdef.typeVariables, | 1503 visitor, node, typdef.typeVariables, arguments); |
1509 onFailure, arguments); | 1504 if (hasTypeArgumentMismatch) { |
1510 if (hashTypeArgumentMismatch) { | 1505 type = new BadTypedefType(typdef, |
1511 type = new MalformedType( | |
1512 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, | |
1513 {'type': node}, typeName.source, visitor.enclosingElement), | |
1514 new TypedefType.userProvidedBadType(typdef, arguments.toLink())); | 1506 new TypedefType.userProvidedBadType(typdef, arguments.toLink())); |
1515 } else { | 1507 } else { |
1516 if (arguments.isEmpty) { | 1508 if (arguments.isEmpty) { |
1517 type = typdef.rawType; | 1509 type = typdef.rawType; |
1518 } else { | 1510 } else { |
1519 type = new TypedefType(typdef, arguments.toLink()); | 1511 type = new TypedefType(typdef, arguments.toLink()); |
1520 } | 1512 } |
1521 } | 1513 } |
1522 } else if (element.isTypeVariable()) { | 1514 } else if (element.isTypeVariable()) { |
1523 Element outer = | 1515 Element outer = |
1524 visitor.enclosingElement.getOutermostEnclosingMemberOrTopLevel(); | 1516 visitor.enclosingElement.getOutermostEnclosingMemberOrTopLevel(); |
1525 bool isInFactoryConstructor = | 1517 bool isInFactoryConstructor = |
1526 outer != null && outer.isFactoryConstructor(); | 1518 outer != null && outer.isFactoryConstructor(); |
1527 if (!outer.isClass() && | 1519 if (!outer.isClass() && |
1528 !outer.isTypedef() && | 1520 !outer.isTypedef() && |
1529 !isInFactoryConstructor && | 1521 !isInFactoryConstructor && |
1530 Elements.isInStaticContext(visitor.enclosingElement)) { | 1522 Elements.isInStaticContext(visitor.enclosingElement)) { |
1531 compiler.backend.registerThrowRuntimeError(visitor.mapping); | 1523 type = reportFailureAndCreateType( |
1532 compiler.reportWarning(node, | 1524 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
1533 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( | 1525 {'typeVariableName': node}, |
1534 {'typeVariableName': node})); | 1526 userProvidedBadType: element.computeType(compiler), |
1535 type = new MalformedType( | 1527 isError: malformedIsError); |
1536 new ErroneousElementX( | |
1537 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | |
1538 {'typeVariableName': node}, | |
1539 typeName.source, visitor.enclosingElement), | |
1540 element.computeType(compiler)); | |
1541 } else { | 1528 } else { |
1542 type = element.computeType(compiler); | 1529 type = element.computeType(compiler); |
1543 } | 1530 } |
1544 type = checkNoTypeArguments(type); | 1531 type = checkNoTypeArguments(type); |
1545 } else { | 1532 } else { |
1546 compiler.cancel("unexpected element kind ${element.kind}", | 1533 compiler.cancel("unexpected element kind ${element.kind}", |
1547 node: node); | 1534 node: node); |
1548 } | 1535 } |
1549 } | 1536 } |
1550 visitor.useType(node, type); | 1537 visitor.useType(node, type); |
1551 return type; | 1538 return type; |
1552 } | 1539 } |
1553 | 1540 |
1554 /** | 1541 /** |
1555 * Resolves the type arguments of [node] and adds these to [arguments]. | 1542 * Resolves the type arguments of [node] and adds these to [arguments]. |
1556 * | 1543 * |
1557 * Returns [: true :] if the number of type arguments did not match the | 1544 * Returns [: true :] if the number of type arguments did not match the |
1558 * number of type variables. | 1545 * number of type variables. |
1559 */ | 1546 */ |
1560 bool resolveTypeArguments( | 1547 bool resolveTypeArguments( |
1561 MappingVisitor visitor, | 1548 MappingVisitor visitor, |
1562 TypeAnnotation node, | 1549 TypeAnnotation node, |
1563 Link<DartType> typeVariables, | 1550 Link<DartType> typeVariables, |
1564 onFailure, | 1551 LinkBuilder<DartType> arguments, |
1565 LinkBuilder<DartType> arguments) { | 1552 {bool ambiguousIsError: false}) { |
1566 if (node.typeArguments == null) { | 1553 if (node.typeArguments == null) { |
1567 return false; | 1554 return false; |
1568 } | 1555 } |
1569 bool typeArgumentCountMismatch = false; | 1556 bool typeArgumentCountMismatch = false; |
1570 for (Link<Node> typeArguments = node.typeArguments.nodes; | 1557 for (Link<Node> typeArguments = node.typeArguments.nodes; |
1571 !typeArguments.isEmpty; | 1558 !typeArguments.isEmpty; |
1572 typeArguments = typeArguments.tail) { | 1559 typeArguments = typeArguments.tail) { |
1573 if (typeVariables != null && typeVariables.isEmpty) { | 1560 if (typeVariables != null && typeVariables.isEmpty) { |
1574 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 1561 visitor.warning( |
| 1562 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
1575 typeArgumentCountMismatch = true; | 1563 typeArgumentCountMismatch = true; |
1576 } | 1564 } |
1577 DartType argType = resolveTypeAnnotationInContext(visitor, | 1565 DartType argType = resolveTypeAnnotation(visitor, typeArguments.head, |
1578 typeArguments.head, | 1566 ambiguousIsError: ambiguousIsError); |
1579 onFailure); | |
1580 arguments.addLast(argType); | 1567 arguments.addLast(argType); |
1581 if (typeVariables != null && !typeVariables.isEmpty) { | 1568 if (typeVariables != null && !typeVariables.isEmpty) { |
1582 typeVariables = typeVariables.tail; | 1569 typeVariables = typeVariables.tail; |
1583 } | 1570 } |
1584 } | 1571 } |
1585 if (typeVariables != null && !typeVariables.isEmpty) { | 1572 if (typeVariables != null && !typeVariables.isEmpty) { |
1586 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 1573 visitor.warning(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
1587 typeArgumentCountMismatch = true; | 1574 typeArgumentCountMismatch = true; |
1588 } | 1575 } |
1589 return typeArgumentCountMismatch; | 1576 return typeArgumentCountMismatch; |
1590 } | 1577 } |
1591 } | 1578 } |
1592 | 1579 |
1593 /** | 1580 /** |
1594 * Common supertype for resolver visitors that record resolutions in a | 1581 * Common supertype for resolver visitors that record resolutions in a |
1595 * [TreeElements] mapping. | 1582 * [TreeElements] mapping. |
1596 */ | 1583 */ |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1632 * | 1619 * |
1633 * This field is updated when nested closures are visited. | 1620 * This field is updated when nested closures are visited. |
1634 */ | 1621 */ |
1635 Element enclosingElement; | 1622 Element enclosingElement; |
1636 bool inInstanceContext; | 1623 bool inInstanceContext; |
1637 bool inCheckContext; | 1624 bool inCheckContext; |
1638 bool inCatchBlock; | 1625 bool inCatchBlock; |
1639 Scope scope; | 1626 Scope scope; |
1640 ClassElement currentClass; | 1627 ClassElement currentClass; |
1641 ExpressionStatement currentExpressionStatement; | 1628 ExpressionStatement currentExpressionStatement; |
1642 bool typeRequired = false; | |
1643 bool sendIsMemberAccess = false; | 1629 bool sendIsMemberAccess = false; |
1644 StatementScope statementScope; | 1630 StatementScope statementScope; |
1645 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION | 1631 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
1646 | ElementCategory.IMPLIES_TYPE; | 1632 | ElementCategory.IMPLIES_TYPE; |
1647 | 1633 |
1648 // TODO(ahe): Find a way to share this with runtime implementation. | 1634 // TODO(ahe): Find a way to share this with runtime implementation. |
1649 static final RegExp symbolValidationPattern = | 1635 static final RegExp symbolValidationPattern = |
1650 new RegExp(r'^(?:[a-zA-Z$][a-zA-Z$0-9_]*\.)*(?:[a-zA-Z$][a-zA-Z$0-9_]*=?|' | 1636 new RegExp(r'^(?:[a-zA-Z$][a-zA-Z$0-9_]*\.)*(?:[a-zA-Z$][a-zA-Z$0-9_]*=?|' |
1651 r'-|' | 1637 r'-|' |
1652 r'unary-|' | 1638 r'unary-|' |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 mapping.setType(node, compiler.typeClass.computeType(compiler)); | 2237 mapping.setType(node, compiler.typeClass.computeType(compiler)); |
2252 world.registerTypeLiteral(target, mapping); | 2238 world.registerTypeLiteral(target, mapping); |
2253 } | 2239 } |
2254 } | 2240 } |
2255 | 2241 |
2256 bool resolvedArguments = false; | 2242 bool resolvedArguments = false; |
2257 if (node.isOperator) { | 2243 if (node.isOperator) { |
2258 String operatorString = node.selector.asOperator().source.stringValue; | 2244 String operatorString = node.selector.asOperator().source.stringValue; |
2259 if (operatorString == 'is') { | 2245 if (operatorString == 'is') { |
2260 DartType type = | 2246 DartType type = |
2261 resolveTypeRequired(node.typeAnnotationFromIsCheckOrCast); | 2247 resolveTypeExpression(node.typeAnnotationFromIsCheckOrCast); |
2262 if (type != null) { | 2248 if (type != null) { |
2263 compiler.enqueuer.resolution.registerIsCheck(type, mapping); | 2249 compiler.enqueuer.resolution.registerIsCheck(type, mapping); |
2264 } | 2250 } |
2265 resolvedArguments = true; | 2251 resolvedArguments = true; |
2266 } else if (operatorString == 'as') { | 2252 } else if (operatorString == 'as') { |
2267 DartType type = resolveTypeRequired(node.arguments.head); | 2253 DartType type = resolveTypeExpression(node.arguments.head); |
2268 if (type != null) { | 2254 if (type != null) { |
2269 compiler.enqueuer.resolution.registerAsCheck(type, mapping); | 2255 compiler.enqueuer.resolution.registerAsCheck(type, mapping); |
2270 } | 2256 } |
2271 resolvedArguments = true; | 2257 resolvedArguments = true; |
2272 } | 2258 } |
2273 } | 2259 } |
2274 | 2260 |
2275 if (!resolvedArguments) { | 2261 if (!resolvedArguments) { |
2276 oldSendIsMemberAccess = sendIsMemberAccess; | 2262 oldSendIsMemberAccess = sendIsMemberAccess; |
2277 sendIsMemberAccess = false; | 2263 sendIsMemberAccess = false; |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2667 * [null], if there is no corresponding constructor, class or library. | 2653 * [null], if there is no corresponding constructor, class or library. |
2668 */ | 2654 */ |
2669 FunctionElement resolveConstructor(NewExpression node) { | 2655 FunctionElement resolveConstructor(NewExpression node) { |
2670 return node.accept(new ConstructorResolver(compiler, this)); | 2656 return node.accept(new ConstructorResolver(compiler, this)); |
2671 } | 2657 } |
2672 | 2658 |
2673 FunctionElement resolveRedirectingFactory(Return node) { | 2659 FunctionElement resolveRedirectingFactory(Return node) { |
2674 return node.accept(new ConstructorResolver(compiler, this)); | 2660 return node.accept(new ConstructorResolver(compiler, this)); |
2675 } | 2661 } |
2676 | 2662 |
2677 DartType resolveTypeRequired(TypeAnnotation node) { | 2663 DartType resolveTypeExpression(TypeAnnotation node) { |
2678 bool old = typeRequired; | 2664 return resolveTypeAnnotation(node, isTypeExpression: true); |
2679 typeRequired = true; | |
2680 DartType result = resolveTypeAnnotation(node); | |
2681 typeRequired = old; | |
2682 return result; | |
2683 } | 2665 } |
2684 | 2666 |
2685 DartType resolveTypeAnnotation(TypeAnnotation node) { | 2667 DartType resolveTypeAnnotation(TypeAnnotation node, |
2686 Function report = typeRequired ? error : warning; | 2668 {bool isTypeExpression: false}) { |
2687 DartType type = typeResolver.resolveTypeAnnotation( | 2669 DartType type = typeResolver.resolveTypeAnnotation( |
2688 this, node, onFailure: report); | 2670 this, node, ambiguousIsError: isTypeExpression); |
2689 if (type == null) return null; | 2671 if (type == null) return null; |
2690 if (inCheckContext) { | 2672 if (inCheckContext) { |
2691 compiler.enqueuer.resolution.registerIsCheck(type, mapping); | 2673 compiler.enqueuer.resolution.registerIsCheck(type, mapping); |
2692 } | |
2693 if (typeRequired || inCheckContext) { | |
2694 compiler.backend.registerRequiredType(type, enclosingElement); | 2674 compiler.backend.registerRequiredType(type, enclosingElement); |
2695 } | 2675 } |
2696 return type; | 2676 return type; |
2697 } | 2677 } |
2698 | 2678 |
2699 visitModifiers(Modifiers node) { | 2679 visitModifiers(Modifiers node) { |
2700 // TODO(ngeoffray): Implement this. | 2680 // TODO(ngeoffray): Implement this. |
2701 unimplemented(node, 'modifiers'); | 2681 unimplemented(node, 'modifiers'); |
2702 } | 2682 } |
2703 | 2683 |
2704 visitLiteralList(LiteralList node) { | 2684 visitLiteralList(LiteralList node) { |
2705 NodeList arguments = node.typeArguments; | 2685 NodeList arguments = node.typeArguments; |
2706 DartType typeArgument; | 2686 DartType typeArgument; |
2707 if (arguments != null) { | 2687 if (arguments != null) { |
2708 Link<Node> nodes = arguments.nodes; | 2688 Link<Node> nodes = arguments.nodes; |
2709 if (nodes.isEmpty) { | 2689 if (nodes.isEmpty) { |
| 2690 // The syntax [: <>[] :] is not allowed. |
2710 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2691 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); |
2711 } else { | 2692 } else { |
2712 typeArgument = resolveTypeRequired(nodes.head); | 2693 typeArgument = resolveTypeExpression(nodes.head); |
2713 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { | 2694 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
2714 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 2695 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
2715 resolveTypeRequired(nodes.head); | 2696 resolveTypeAnnotation(nodes.head); |
2716 } | 2697 } |
2717 } | 2698 } |
2718 } | 2699 } |
2719 DartType listType; | 2700 DartType listType; |
2720 if (typeArgument != null) { | 2701 if (typeArgument != null) { |
2721 if (node.isConst() && typeArgument.containsTypeVariables) { | 2702 if (node.isConst() && typeArgument.containsTypeVariables) { |
2722 compiler.reportErrorCode(arguments.nodes.head, | 2703 compiler.reportErrorCode(arguments.nodes.head, |
2723 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 2704 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
2724 } | 2705 } |
2725 listType = new InterfaceType(compiler.listClass, | 2706 listType = new InterfaceType(compiler.listClass, |
2726 new Link<DartType>.fromList([typeArgument])); | 2707 new Link<DartType>.fromList([typeArgument])); |
2727 } else { | 2708 } else { |
2728 compiler.listClass.computeType(compiler); | 2709 compiler.listClass.computeType(compiler); |
2729 listType = compiler.listClass.rawType; | 2710 listType = compiler.listClass.rawType; |
2730 } | 2711 } |
2731 mapping.setType(node, listType); | 2712 mapping.setType(node, listType); |
2732 world.registerInstantiatedType(listType, mapping); | 2713 world.registerInstantiatedType(listType, mapping); |
| 2714 compiler.backend.registerRequiredType(listType, enclosingElement); |
2733 visit(node.elements); | 2715 visit(node.elements); |
2734 } | 2716 } |
2735 | 2717 |
2736 visitConditional(Conditional node) { | 2718 visitConditional(Conditional node) { |
2737 node.visitChildren(this); | 2719 node.visitChildren(this); |
2738 } | 2720 } |
2739 | 2721 |
2740 visitStringInterpolation(StringInterpolation node) { | 2722 visitStringInterpolation(StringInterpolation node) { |
2741 world.registerInstantiatedClass(compiler.stringClass, mapping); | 2723 world.registerInstantiatedClass(compiler.stringClass, mapping); |
2742 compiler.backend.registerStringInterpolation(mapping); | 2724 compiler.backend.registerStringInterpolation(mapping); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2904 } | 2886 } |
2905 } | 2887 } |
2906 | 2888 |
2907 visitLiteralMap(LiteralMap node) { | 2889 visitLiteralMap(LiteralMap node) { |
2908 NodeList arguments = node.typeArguments; | 2890 NodeList arguments = node.typeArguments; |
2909 DartType keyTypeArgument; | 2891 DartType keyTypeArgument; |
2910 DartType valueTypeArgument; | 2892 DartType valueTypeArgument; |
2911 if (arguments != null) { | 2893 if (arguments != null) { |
2912 Link<Node> nodes = arguments.nodes; | 2894 Link<Node> nodes = arguments.nodes; |
2913 if (nodes.isEmpty) { | 2895 if (nodes.isEmpty) { |
| 2896 // The syntax [: <>{} :] is not allowed. |
2914 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2897 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); |
2915 } else { | 2898 } else { |
2916 keyTypeArgument = resolveTypeRequired(nodes.head); | 2899 keyTypeArgument = resolveTypeExpression(nodes.head); |
2917 nodes = nodes.tail; | 2900 nodes = nodes.tail; |
2918 if (nodes.isEmpty) { | 2901 if (nodes.isEmpty) { |
2919 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2902 warning(arguments, MessageKind.MISSING_TYPE_ARGUMENT); |
2920 } else { | 2903 } else { |
2921 valueTypeArgument = resolveTypeRequired(nodes.head); | 2904 valueTypeArgument = resolveTypeExpression(nodes.head); |
2922 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { | 2905 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
2923 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 2906 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
2924 resolveTypeRequired(nodes.head); | 2907 resolveTypeAnnotation(nodes.head); |
2925 } | 2908 } |
2926 } | 2909 } |
2927 } | 2910 } |
2928 } | 2911 } |
2929 DartType mapType; | 2912 DartType mapType; |
2930 if (valueTypeArgument != null) { | 2913 if (valueTypeArgument != null) { |
2931 mapType = new InterfaceType(compiler.mapClass, | 2914 mapType = new InterfaceType(compiler.mapClass, |
2932 new Link<DartType>.fromList([keyTypeArgument, valueTypeArgument])); | 2915 new Link<DartType>.fromList([keyTypeArgument, valueTypeArgument])); |
2933 } else { | 2916 } else { |
2934 compiler.mapClass.computeType(compiler); | 2917 compiler.mapClass.computeType(compiler); |
2935 mapType = compiler.mapClass.rawType; | 2918 mapType = compiler.mapClass.rawType; |
2936 } | 2919 } |
2937 if (node.isConst() && mapType.containsTypeVariables) { | 2920 if (node.isConst() && mapType.containsTypeVariables) { |
2938 compiler.reportErrorCode(arguments, | 2921 compiler.reportErrorCode(arguments, |
2939 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 2922 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
2940 } | 2923 } |
2941 mapping.setType(node, mapType); | 2924 mapping.setType(node, mapType); |
2942 world.registerInstantiatedClass(compiler.mapClass, mapping); | 2925 world.registerInstantiatedClass(compiler.mapClass, mapping); |
2943 if (node.isConst()) { | 2926 if (node.isConst()) { |
2944 compiler.backend.registerConstantMap(mapping); | 2927 compiler.backend.registerConstantMap(mapping); |
2945 } | 2928 } |
| 2929 compiler.backend.registerRequiredType(mapType, enclosingElement); |
2946 node.visitChildren(this); | 2930 node.visitChildren(this); |
2947 } | 2931 } |
2948 | 2932 |
2949 visitLiteralMapEntry(LiteralMapEntry node) { | 2933 visitLiteralMapEntry(LiteralMapEntry node) { |
2950 node.visitChildren(this); | 2934 node.visitChildren(this); |
2951 } | 2935 } |
2952 | 2936 |
2953 visitNamedArgument(NamedArgument node) { | 2937 visitNamedArgument(NamedArgument node) { |
2954 visit(node.expression); | 2938 visit(node.expression); |
2955 } | 2939 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3076 } | 3060 } |
3077 TypeAnnotation type = declaration.type; | 3061 TypeAnnotation type = declaration.type; |
3078 if (type != null) { | 3062 if (type != null) { |
3079 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); | 3063 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); |
3080 } | 3064 } |
3081 } | 3065 } |
3082 } | 3066 } |
3083 } | 3067 } |
3084 | 3068 |
3085 Scope blockScope = new BlockScope(scope); | 3069 Scope blockScope = new BlockScope(scope); |
3086 var wasTypeRequired = typeRequired; | |
3087 typeRequired = true; | |
3088 doInCheckContext(() => visitIn(node.type, blockScope)); | 3070 doInCheckContext(() => visitIn(node.type, blockScope)); |
3089 typeRequired = wasTypeRequired; | |
3090 visitIn(node.formals, blockScope); | 3071 visitIn(node.formals, blockScope); |
3091 var oldInCatchBlock = inCatchBlock; | 3072 var oldInCatchBlock = inCatchBlock; |
3092 inCatchBlock = true; | 3073 inCatchBlock = true; |
3093 visitIn(node.block, blockScope); | 3074 visitIn(node.block, blockScope); |
3094 inCatchBlock = oldInCatchBlock; | 3075 inCatchBlock = oldInCatchBlock; |
3095 | 3076 |
3096 if (node.type != null && exceptionDefinition != null) { | 3077 if (node.type != null && exceptionDefinition != null) { |
3097 DartType exceptionType = mapping.getType(node.type); | 3078 DartType exceptionType = mapping.getType(node.type); |
3098 Node exceptionVariable = exceptionDefinition.definitions.nodes.head; | 3079 Node exceptionVariable = exceptionDefinition.definitions.nodes.head; |
3099 VariableElementX exceptionElement = mapping[exceptionVariable]; | 3080 VariableElementX exceptionElement = mapping[exceptionVariable]; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3137 TypeVariable typeNode = nodeLink.head; | 3118 TypeVariable typeNode = nodeLink.head; |
3138 if (nameSet.contains(typeName)) { | 3119 if (nameSet.contains(typeName)) { |
3139 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, | 3120 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, |
3140 {'typeVariableName': typeName}); | 3121 {'typeVariableName': typeName}); |
3141 } | 3122 } |
3142 nameSet.add(typeName); | 3123 nameSet.add(typeName); |
3143 | 3124 |
3144 TypeVariableElement variableElement = typeVariable.element; | 3125 TypeVariableElement variableElement = typeVariable.element; |
3145 if (typeNode.bound != null) { | 3126 if (typeNode.bound != null) { |
3146 DartType boundType = typeResolver.resolveTypeAnnotation( | 3127 DartType boundType = typeResolver.resolveTypeAnnotation( |
3147 this, typeNode.bound, onFailure: warning); | 3128 this, typeNode.bound); |
3148 variableElement.bound = boundType; | 3129 variableElement.bound = boundType; |
3149 | 3130 |
3150 void checkTypeVariableBound() { | 3131 void checkTypeVariableBound() { |
3151 Link<TypeVariableElement> seenTypeVariables = | 3132 Link<TypeVariableElement> seenTypeVariables = |
3152 const Link<TypeVariableElement>(); | 3133 const Link<TypeVariableElement>(); |
3153 seenTypeVariables = seenTypeVariables.prepend(variableElement); | 3134 seenTypeVariables = seenTypeVariables.prepend(variableElement); |
3154 DartType bound = boundType; | 3135 DartType bound = boundType; |
3155 while (bound.element.isTypeVariable()) { | 3136 while (bound.element.isTypeVariable()) { |
3156 TypeVariableElement element = bound.element; | 3137 TypeVariableElement element = bound.element; |
3157 if (seenTypeVariables.contains(element)) { | 3138 if (seenTypeVariables.contains(element)) { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3402 return mixin; | 3383 return mixin; |
3403 } | 3384 } |
3404 | 3385 |
3405 DartType resolveType(TypeAnnotation node) { | 3386 DartType resolveType(TypeAnnotation node) { |
3406 // TODO(johnniwinther): Report errors/warnings on resolution failures. | 3387 // TODO(johnniwinther): Report errors/warnings on resolution failures. |
3407 return typeResolver.resolveTypeAnnotation(this, node); | 3388 return typeResolver.resolveTypeAnnotation(this, node); |
3408 } | 3389 } |
3409 | 3390 |
3410 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 3391 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
3411 DartType supertype = typeResolver.resolveTypeAnnotation( | 3392 DartType supertype = typeResolver.resolveTypeAnnotation( |
3412 this, superclass, onFailure: error); | 3393 this, superclass, malformedIsError: true); |
3413 if (supertype != null) { | 3394 if (supertype != null) { |
3414 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { | 3395 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { |
3415 // Error has already been reported. | 3396 // Error has already been reported. |
3416 return null; | 3397 return null; |
3417 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { | 3398 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { |
3418 // TODO(johnniwinther): Handle dynamic. | 3399 // TODO(johnniwinther): Handle dynamic. |
3419 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); | 3400 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
3420 return null; | 3401 return null; |
3421 } else if (isBlackListed(supertype)) { | 3402 } else if (isBlackListed(supertype)) { |
3422 error(superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); | 3403 error(superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
3423 return null; | 3404 return null; |
3424 } | 3405 } |
3425 } | 3406 } |
3426 return supertype; | 3407 return supertype; |
3427 } | 3408 } |
3428 | 3409 |
3429 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 3410 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { |
3430 Link<DartType> result = const Link<DartType>(); | 3411 Link<DartType> result = const Link<DartType>(); |
3431 if (interfaces == null) return result; | 3412 if (interfaces == null) return result; |
3432 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 3413 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
3433 DartType interfaceType = typeResolver.resolveTypeAnnotation( | 3414 DartType interfaceType = typeResolver.resolveTypeAnnotation( |
3434 this, link.head, onFailure: error); | 3415 this, link.head, malformedIsError: true); |
3435 if (interfaceType != null) { | 3416 if (interfaceType != null) { |
3436 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { | 3417 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { |
3437 // Error has already been reported. | 3418 // Error has already been reported. |
3438 } else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) { | 3419 } else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) { |
3439 // TODO(johnniwinther): Handle dynamic. | 3420 // TODO(johnniwinther): Handle dynamic. |
3440 TypeAnnotation typeAnnotation = link.head; | 3421 TypeAnnotation typeAnnotation = link.head; |
3441 error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); | 3422 error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); |
3442 } else { | 3423 } else { |
3443 if (interfaceType == element.supertype) { | 3424 if (interfaceType == element.supertype) { |
3444 compiler.reportErrorCode( | 3425 compiler.reportErrorCode( |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3506 supertypes = supertypes.tail; | 3487 supertypes = supertypes.tail; |
3507 } | 3488 } |
3508 } | 3489 } |
3509 | 3490 |
3510 isBlackListed(DartType type) { | 3491 isBlackListed(DartType type) { |
3511 LibraryElement lib = element.getLibrary(); | 3492 LibraryElement lib = element.getLibrary(); |
3512 return | 3493 return |
3513 !identical(lib, compiler.coreLibrary) && | 3494 !identical(lib, compiler.coreLibrary) && |
3514 !identical(lib, compiler.jsHelperLibrary) && | 3495 !identical(lib, compiler.jsHelperLibrary) && |
3515 !identical(lib, compiler.interceptorsLibrary) && | 3496 !identical(lib, compiler.interceptorsLibrary) && |
3516 (identical(type.element, compiler.dynamicClass) || | 3497 (identical(type, compiler.types.dynamicType) || |
3517 identical(type.element, compiler.boolClass) || | 3498 identical(type.element, compiler.boolClass) || |
3518 identical(type.element, compiler.numClass) || | 3499 identical(type.element, compiler.numClass) || |
3519 identical(type.element, compiler.intClass) || | 3500 identical(type.element, compiler.intClass) || |
3520 identical(type.element, compiler.doubleClass) || | 3501 identical(type.element, compiler.doubleClass) || |
3521 identical(type.element, compiler.stringClass) || | 3502 identical(type.element, compiler.stringClass) || |
3522 identical(type.element, compiler.nullClass) || | 3503 identical(type.element, compiler.nullClass) || |
3523 identical(type.element, compiler.functionClass)); | 3504 identical(type.element, compiler.functionClass)); |
3524 } | 3505 } |
3525 } | 3506 } |
3526 | 3507 |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3948 // Find the unnamed constructor if the reference resolved to a | 3929 // Find the unnamed constructor if the reference resolved to a |
3949 // class. | 3930 // class. |
3950 if (!Elements.isUnresolved(e) && e.isClass()) { | 3931 if (!Elements.isUnresolved(e) && e.isClass()) { |
3951 ClassElement cls = e; | 3932 ClassElement cls = e; |
3952 cls.ensureResolved(compiler); | 3933 cls.ensureResolved(compiler); |
3953 // The unnamed constructor may not exist, so [e] may become unresolved. | 3934 // The unnamed constructor may not exist, so [e] may become unresolved. |
3954 e = lookupConstructor(cls, diagnosticNode, const SourceString('')); | 3935 e = lookupConstructor(cls, diagnosticNode, const SourceString('')); |
3955 } | 3936 } |
3956 if (type == null) { | 3937 if (type == null) { |
3957 if (Elements.isUnresolved(e)) { | 3938 if (Elements.isUnresolved(e)) { |
3958 type = compiler.dynamicClass.computeType(compiler); | 3939 type = compiler.types.dynamicType; |
3959 } else { | 3940 } else { |
3960 type = e.getEnclosingClass().computeType(compiler).asRaw(); | 3941 type = e.getEnclosingClass().computeType(compiler).asRaw(); |
3961 } | 3942 } |
3962 } | 3943 } |
3963 resolver.mapping.setType(expression, type); | 3944 resolver.mapping.setType(expression, type); |
3964 return e; | 3945 return e; |
3965 } | 3946 } |
3966 | 3947 |
3967 visitTypeAnnotation(TypeAnnotation node) { | 3948 visitTypeAnnotation(TypeAnnotation node) { |
3968 assert(invariant(node, type == null)); | 3949 assert(invariant(node, type == null)); |
3969 type = resolver.resolveTypeRequired(node); | 3950 type = resolver.resolveTypeExpression(node); |
| 3951 compiler.backend.registerRequiredType(type, resolver.enclosingElement); |
3970 return resolver.mapping[node]; | 3952 return resolver.mapping[node]; |
3971 } | 3953 } |
3972 | 3954 |
3973 visitSend(Send node) { | 3955 visitSend(Send node) { |
3974 Element e = visit(node.receiver); | 3956 Element e = visit(node.receiver); |
3975 if (Elements.isUnresolved(e)) return e; | 3957 if (Elements.isUnresolved(e)) return e; |
3976 Identifier name = node.selector.asIdentifier(); | 3958 Identifier name = node.selector.asIdentifier(); |
3977 if (name == null) internalError(node.selector, 'unexpected node'); | 3959 if (name == null) internalError(node.selector, 'unexpected node'); |
3978 | 3960 |
3979 if (identical(e.kind, ElementKind.CLASS)) { | 3961 if (identical(e.kind, ElementKind.CLASS)) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4020 return e; | 4002 return e; |
4021 } | 4003 } |
4022 | 4004 |
4023 /// Assumed to be called by [resolveRedirectingFactory]. | 4005 /// Assumed to be called by [resolveRedirectingFactory]. |
4024 Element visitReturn(Return node) { | 4006 Element visitReturn(Return node) { |
4025 Node expression = node.expression; | 4007 Node expression = node.expression; |
4026 return finishConstructorReference(visit(expression), | 4008 return finishConstructorReference(visit(expression), |
4027 expression, expression); | 4009 expression, expression); |
4028 } | 4010 } |
4029 } | 4011 } |
OLD | NEW |