Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: pkg/analyzer/lib/src/summary/resynthesize.dart

Issue 1647253002: Add the ability to summarize inferred types based on function-typed parameters. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698