| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library summary_resynthesizer; | 5 library summary_resynthesizer; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 case UnlinkedConstOperation.pushReference: | 411 case UnlinkedConstOperation.pushReference: |
| 412 case UnlinkedConstOperation.invokeConstructor: | 412 case UnlinkedConstOperation.invokeConstructor: |
| 413 case UnlinkedConstOperation.length: | 413 case UnlinkedConstOperation.length: |
| 414 return AstFactory.nullLiteral(); | 414 return AstFactory.nullLiteral(); |
| 415 // throw new StateError('Unsupported constant operation $operation'); | 415 // throw new StateError('Unsupported constant operation $operation'); |
| 416 } | 416 } |
| 417 } | 417 } |
| 418 return stack.single; | 418 return stack.single; |
| 419 } | 419 } |
| 420 | 420 |
| 421 void _pushMap(TypeArgumentList typeArguments) { | |
| 422 int count = uc.ints[intPtr++]; | |
| 423 List<MapLiteralEntry> entries = <MapLiteralEntry>[]; | |
| 424 for (int i = 0; i < count; i++) { | |
| 425 Expression value = _pop(); | |
| 426 Expression key = _pop(); | |
| 427 entries.insert(0, AstFactory.mapLiteralEntry2(key, value)); | |
| 428 } | |
| 429 _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries)); | |
| 430 } | |
| 431 | |
| 432 TypeName _buildTypeAst(DartType type) { | 421 TypeName _buildTypeAst(DartType type) { |
| 433 if (type is DynamicTypeImpl) { | 422 if (type is DynamicTypeImpl) { |
| 434 return AstFactory.typeName4('dynamic')..type = type; | 423 return AstFactory.typeName4('dynamic')..type = type; |
| 435 } else if (type is InterfaceType) { | 424 } else if (type is InterfaceType) { |
| 436 List<TypeName> argumentNodes = | 425 List<TypeName> argumentNodes = |
| 437 type.typeArguments.map(_buildTypeAst).toList(); | 426 type.typeArguments.map(_buildTypeAst).toList(); |
| 438 TypeName node = AstFactory.typeName4(type.name, argumentNodes); | 427 TypeName node = AstFactory.typeName4(type.name, argumentNodes); |
| 439 node.type = type; | 428 node.type = type; |
| 440 return node; | 429 return node; |
| 441 } | 430 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 | 466 |
| 478 void _pushList(TypeArgumentList typeArguments) { | 467 void _pushList(TypeArgumentList typeArguments) { |
| 479 int count = uc.ints[intPtr++]; | 468 int count = uc.ints[intPtr++]; |
| 480 List<Expression> elements = <Expression>[]; | 469 List<Expression> elements = <Expression>[]; |
| 481 for (int i = 0; i < count; i++) { | 470 for (int i = 0; i < count; i++) { |
| 482 elements.insert(0, _pop()); | 471 elements.insert(0, _pop()); |
| 483 } | 472 } |
| 484 _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements)); | 473 _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements)); |
| 485 } | 474 } |
| 486 | 475 |
| 476 void _pushMap(TypeArgumentList typeArguments) { |
| 477 int count = uc.ints[intPtr++]; |
| 478 List<MapLiteralEntry> entries = <MapLiteralEntry>[]; |
| 479 for (int i = 0; i < count; i++) { |
| 480 Expression value = _pop(); |
| 481 Expression key = _pop(); |
| 482 entries.insert(0, AstFactory.mapLiteralEntry2(key, value)); |
| 483 } |
| 484 _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries)); |
| 485 } |
| 486 |
| 487 void _pushPrefix(TokenType operator) { | 487 void _pushPrefix(TokenType operator) { |
| 488 Expression operand = _pop(); | 488 Expression operand = _pop(); |
| 489 _push(AstFactory.prefixExpression(operator, operand)); | 489 _push(AstFactory.prefixExpression(operator, operand)); |
| 490 } | 490 } |
| 491 } | 491 } |
| 492 | 492 |
| 493 /** | 493 /** |
| 494 * A single constant variable for which the constant value should be computed. | 494 * A single constant variable for which the constant value should be computed. |
| 495 * | 495 * |
| 496 * TODO(scheglov) we will probably need to add dependency list | 496 * TODO(scheglov) we will probably need to add dependency list |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 .type; | 1292 .type; |
| 1293 } else { | 1293 } else { |
| 1294 DartType getTypeParameter(int i) { | 1294 DartType getTypeParameter(int i) { |
| 1295 if (i < type.typeArguments.length) { | 1295 if (i < type.typeArguments.length) { |
| 1296 return buildType(type.typeArguments[i]); | 1296 return buildType(type.typeArguments[i]); |
| 1297 } else { | 1297 } else { |
| 1298 return summaryResynthesizer.typeProvider.dynamicType; | 1298 return summaryResynthesizer.typeProvider.dynamicType; |
| 1299 } | 1299 } |
| 1300 } | 1300 } |
| 1301 _ReferenceInfo referenceInfo = referenceInfos[type.reference]; | 1301 _ReferenceInfo referenceInfo = referenceInfos[type.reference]; |
| 1302 return referenceInfo.buildType(getTypeParameter); | 1302 return referenceInfo.buildType( |
| 1303 getTypeParameter, type.implicitFunctionTypeIndices); |
| 1303 } | 1304 } |
| 1304 } | 1305 } |
| 1305 | 1306 |
| 1306 /** | 1307 /** |
| 1307 * Resynthesize a [FunctionTypeAliasElement] and place it in the | 1308 * Resynthesize a [FunctionTypeAliasElement] and place it in the |
| 1308 * [unitHolder]. | 1309 * [unitHolder]. |
| 1309 */ | 1310 */ |
| 1310 void buildTypedef(UnlinkedTypedef serializedTypedef) { | 1311 void buildTypedef(UnlinkedTypedef serializedTypedef) { |
| 1311 try { | 1312 try { |
| 1312 currentTypeParameters = | 1313 currentTypeParameters = |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 * Populate [referenceInfos] with the correct information for the current | 1457 * Populate [referenceInfos] with the correct information for the current |
| 1457 * compilation unit. | 1458 * compilation unit. |
| 1458 */ | 1459 */ |
| 1459 void populateReferenceInfos() { | 1460 void populateReferenceInfos() { |
| 1460 int numLinkedReferences = linkedUnit.references.length; | 1461 int numLinkedReferences = linkedUnit.references.length; |
| 1461 int numUnlinkedReferences = unlinkedUnit.references.length; | 1462 int numUnlinkedReferences = unlinkedUnit.references.length; |
| 1462 referenceInfos = new List<_ReferenceInfo>(numLinkedReferences); | 1463 referenceInfos = new List<_ReferenceInfo>(numLinkedReferences); |
| 1463 for (int i = 0; i < numLinkedReferences; i++) { | 1464 for (int i = 0; i < numLinkedReferences; i++) { |
| 1464 LinkedReference linkedReference = linkedUnit.references[i]; | 1465 LinkedReference linkedReference = linkedUnit.references[i]; |
| 1465 String name; | 1466 String name; |
| 1467 int containingReference; |
| 1466 if (i < numUnlinkedReferences) { | 1468 if (i < numUnlinkedReferences) { |
| 1467 name = unlinkedUnit.references[i].name; | 1469 name = unlinkedUnit.references[i].name; |
| 1470 containingReference = unlinkedUnit.references[i].prefixReference; |
| 1468 } else { | 1471 } else { |
| 1469 name = linkedUnit.references[i].name; | 1472 name = linkedUnit.references[i].name; |
| 1473 containingReference = linkedUnit.references[i].containingReference; |
| 1470 } | 1474 } |
| 1471 ElementHandle element; | 1475 ElementHandle element; |
| 1472 DartType type; | 1476 DartType type; |
| 1473 if (linkedReference.kind == ReferenceKind.unresolved) { | 1477 if (linkedReference.kind == ReferenceKind.unresolved) { |
| 1474 type = summaryResynthesizer.typeProvider.undefinedType; | 1478 type = summaryResynthesizer.typeProvider.undefinedType; |
| 1475 } else if (name == 'dynamic') { | 1479 } else if (name == 'dynamic') { |
| 1476 type = summaryResynthesizer.typeProvider.dynamicType; | 1480 type = summaryResynthesizer.typeProvider.dynamicType; |
| 1477 } else if (name == 'void') { | 1481 } else if (name == 'void') { |
| 1478 type = VoidTypeImpl.instance; | 1482 type = VoidTypeImpl.instance; |
| 1479 } else { | 1483 } else { |
| 1480 ElementLocation location = new ElementLocationImpl.con3( | 1484 List<String> locationComponents; |
| 1481 getReferencedLocationComponents( | 1485 if (containingReference != 0 && |
| 1482 linkedReference.dependency, linkedReference.unit, name)); | 1486 referenceInfos[containingReference].element is ClassElement) { |
| 1487 locationComponents = referenceInfos[containingReference] |
| 1488 .element |
| 1489 .location |
| 1490 .components |
| 1491 .toList(); |
| 1492 locationComponents.add(name); |
| 1493 } else { |
| 1494 locationComponents = getReferencedLocationComponents( |
| 1495 linkedReference.dependency, linkedReference.unit, name); |
| 1496 } |
| 1497 ElementLocation location = |
| 1498 new ElementLocationImpl.con3(locationComponents); |
| 1483 switch (linkedReference.kind) { | 1499 switch (linkedReference.kind) { |
| 1484 case ReferenceKind.classOrEnum: | 1500 case ReferenceKind.classOrEnum: |
| 1485 element = new ClassElementHandle(summaryResynthesizer, location); | 1501 element = new ClassElementHandle(summaryResynthesizer, location); |
| 1486 break; | 1502 break; |
| 1487 case ReferenceKind.typedef: | 1503 case ReferenceKind.typedef: |
| 1488 element = new FunctionTypeAliasElementHandle( | 1504 element = new FunctionTypeAliasElementHandle( |
| 1489 summaryResynthesizer, location); | 1505 summaryResynthesizer, location); |
| 1490 break; | 1506 break; |
| 1507 case ReferenceKind.propertyAccessor: |
| 1508 assert(location.components.length == 4); |
| 1509 element = new PropertyAccessorElementHandle( |
| 1510 summaryResynthesizer, location); |
| 1511 break; |
| 1512 case ReferenceKind.method: |
| 1513 assert(location.components.length == 4); |
| 1514 element = new MethodElementHandle(summaryResynthesizer, location); |
| 1515 break; |
| 1491 default: | 1516 default: |
| 1492 // This is an element that doesn't (yet) need to be referred to | 1517 // This is an element that doesn't (yet) need to be referred to |
| 1493 // directly, so don't bother populating an element for it. | 1518 // directly, so don't bother populating an element for it. |
| 1494 // TODO(paulberry): add support for more kinds, as needed. | 1519 // TODO(paulberry): add support for more kinds, as needed. |
| 1495 break; | 1520 break; |
| 1496 } | 1521 } |
| 1497 } | 1522 } |
| 1498 referenceInfos[i] = new _ReferenceInfo( | 1523 referenceInfos[i] = new _ReferenceInfo( |
| 1499 name, element, type, linkedReference.numTypeParameters); | 1524 name, element, type, linkedReference.numTypeParameters); |
| 1500 } | 1525 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 /** | 1590 /** |
| 1566 * The name of the entity referred to by this reference. | 1591 * The name of the entity referred to by this reference. |
| 1567 */ | 1592 */ |
| 1568 final String name; | 1593 final String name; |
| 1569 | 1594 |
| 1570 /** | 1595 /** |
| 1571 * The element referred to by this reference, or `null` if there is no | 1596 * The element referred to by this reference, or `null` if there is no |
| 1572 * associated element (e.g. because it is a reference to an undefined | 1597 * associated element (e.g. because it is a reference to an undefined |
| 1573 * entity). | 1598 * entity). |
| 1574 */ | 1599 */ |
| 1575 final ElementHandle element; | 1600 final Element element; |
| 1576 | 1601 |
| 1577 /** | 1602 /** |
| 1578 * If this reference refers to a non-generic type, the type it refers to. | 1603 * If this reference refers to a non-generic type, the type it refers to. |
| 1579 * Otherwise `null`. | 1604 * Otherwise `null`. |
| 1580 */ | 1605 */ |
| 1581 DartType type; | 1606 DartType type; |
| 1582 | 1607 |
| 1583 /** | 1608 /** |
| 1584 * The number of type parameters accepted by the entity referred to by this | 1609 * The number of type parameters accepted by the entity referred to by this |
| 1585 * reference, or zero if it doesn't accept any type parameters. | 1610 * reference, or zero if it doesn't accept any type parameters. |
| 1586 */ | 1611 */ |
| 1587 final int numTypeParameters; | 1612 final int numTypeParameters; |
| 1588 | 1613 |
| 1589 /** | 1614 /** |
| 1590 * Create a new [_ReferenceInfo] object referring to an element called [name] | 1615 * Create a new [_ReferenceInfo] object referring to an element called [name] |
| 1591 * via the element handle [elementHandle], and having [numTypeParameters] | 1616 * via the element handle [elementHandle], and having [numTypeParameters] |
| 1592 * type parameters. | 1617 * type parameters. |
| 1593 * | 1618 * |
| 1594 * For the special types `dynamic` and `void`, [specialType] should point to | 1619 * For the special types `dynamic` and `void`, [specialType] should point to |
| 1595 * the type itself. Otherwise, pass `null` and the type will be computed | 1620 * the type itself. Otherwise, pass `null` and the type will be computed |
| 1596 * when appropriate. | 1621 * when appropriate. |
| 1597 */ | 1622 */ |
| 1598 _ReferenceInfo( | 1623 _ReferenceInfo( |
| 1599 this.name, this.element, DartType specialType, this.numTypeParameters) { | 1624 this.name, this.element, DartType specialType, this.numTypeParameters) { |
| 1600 if (specialType != null) { | 1625 if (specialType != null) { |
| 1601 type = specialType; | 1626 type = specialType; |
| 1602 } else if (numTypeParameters == 0) { | 1627 } else if (numTypeParameters == 0) { |
| 1603 // We can precompute the type because it doesn't depend on type | 1628 // We can precompute the type because it doesn't depend on type |
| 1604 // parameters. | 1629 // parameters. |
| 1605 type = _buildType(null); | 1630 type = _buildType(null, null); |
| 1606 } | 1631 } |
| 1607 } | 1632 } |
| 1608 | 1633 |
| 1609 /** | 1634 /** |
| 1610 * Build a [DartType] corresponding to the result of applying some type | 1635 * Build a [DartType] corresponding to the result of applying some type |
| 1611 * arguments to the entity referred to by this [_ReferenceInfo]. The type | 1636 * arguments to the entity referred to by this [_ReferenceInfo]. The type |
| 1612 * arguments are retrieved by calling [getTypeArgument]. | 1637 * arguments are retrieved by calling [getTypeArgument]. |
| 1613 * | 1638 * |
| 1639 * If [implicitFunctionTypeIndices] is not empty, a [DartType] should be |
| 1640 * created which refers to a function type implicitly defined by one of the |
| 1641 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in |
| 1642 * [EntityRef.implicitFunctionTypeIndices]. |
| 1643 * |
| 1614 * If the entity referred to by this [_ReferenceInfo] is not a type, `null` | 1644 * If the entity referred to by this [_ReferenceInfo] is not a type, `null` |
| 1615 * is returned. | 1645 * is returned. |
| 1616 */ | 1646 */ |
| 1617 DartType buildType(DartType getTypeArgument(int i)) { | 1647 DartType buildType( |
| 1648 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) { |
| 1618 DartType result = | 1649 DartType result = |
| 1619 numTypeParameters == 0 ? type : _buildType(getTypeArgument); | 1650 (numTypeParameters == 0 && implicitFunctionTypeIndices.isEmpty) |
| 1651 ? type |
| 1652 : _buildType(getTypeArgument, implicitFunctionTypeIndices); |
| 1620 if (result == null) { | 1653 if (result == null) { |
| 1621 // TODO(paulberry): figure out how to handle this case (which should | 1654 // TODO(paulberry): figure out how to handle this case (which should |
| 1622 // only occur in the event of erroneous code). | 1655 // only occur in the event of erroneous code). |
| 1623 throw new UnimplementedError(); | 1656 throw new UnimplementedError(); |
| 1624 } | 1657 } |
| 1625 return result; | 1658 return result; |
| 1626 } | 1659 } |
| 1627 | 1660 |
| 1628 /** | 1661 /** |
| 1629 * If this reference refers to a type, build a [DartType] which instantiates | 1662 * If this reference refers to a type, build a [DartType] which instantiates |
| 1630 * it with type arguments returned by [getTypeArgument]. Otherwise return | 1663 * it with type arguments returned by [getTypeArgument]. Otherwise return |
| 1631 * `null`. | 1664 * `null`. |
| 1665 * |
| 1666 * If [implicitFunctionTypeIndices] is not null, a [DartType] should be |
| 1667 * created which refers to a function type implicitly defined by one of the |
| 1668 * element's parameters. [implicitFunctionTypeIndices] is interpreted as in |
| 1669 * [EntityRef.implicitFunctionTypeIndices]. |
| 1632 */ | 1670 */ |
| 1633 DartType _buildType(DartType getTypeArgument(int i)) { | 1671 DartType _buildType( |
| 1672 DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) { |
| 1634 List<DartType> typeArguments = const <DartType>[]; | 1673 List<DartType> typeArguments = const <DartType>[]; |
| 1635 if (numTypeParameters != 0) { | 1674 if (numTypeParameters != 0) { |
| 1636 typeArguments = <DartType>[]; | 1675 typeArguments = <DartType>[]; |
| 1637 for (int i = 0; i < numTypeParameters; i++) { | 1676 for (int i = 0; i < numTypeParameters; i++) { |
| 1638 typeArguments.add(getTypeArgument(i)); | 1677 typeArguments.add(getTypeArgument(i)); |
| 1639 } | 1678 } |
| 1640 } | 1679 } |
| 1641 ElementHandle element = this.element; // To allow type promotion | 1680 ElementHandle element = this.element; // To allow type promotion |
| 1642 if (element is ClassElementHandle) { | 1681 if (element is ClassElementHandle) { |
| 1643 return new InterfaceTypeImpl.elementWithNameAndArgs( | 1682 return new InterfaceTypeImpl.elementWithNameAndArgs( |
| 1644 element, name, typeArguments); | 1683 element, name, typeArguments); |
| 1645 } else if (element is FunctionTypeAliasElementHandle) { | 1684 } else if (element is FunctionTypeAliasElementHandle) { |
| 1646 return new FunctionTypeImpl.elementWithNameAndArgs( | 1685 return new FunctionTypeImpl.elementWithNameAndArgs( |
| 1647 element, name, typeArguments, typeArguments.isNotEmpty); | 1686 element, name, typeArguments, typeArguments.isNotEmpty); |
| 1687 } else if (element is FunctionTypedElement && |
| 1688 implicitFunctionTypeIndices != null) { |
| 1689 FunctionTypedElementComputer computer = () { |
| 1690 FunctionTypedElement element = this.element; |
| 1691 for (int index in implicitFunctionTypeIndices) { |
| 1692 element = element.parameters[index].type.element; |
| 1693 } |
| 1694 return element; |
| 1695 }; |
| 1696 return new DeferredFunctionTypeImpl( |
| 1697 computer, null, typeArguments, typeArguments.isNotEmpty); |
| 1648 } else { | 1698 } else { |
| 1649 return null; | 1699 return null; |
| 1650 } | 1700 } |
| 1651 } | 1701 } |
| 1652 } | 1702 } |
| OLD | NEW |