| 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 |