Chromium Code Reviews| 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/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 * creating the actual element. This allows to put these elements into | 707 * creating the actual element. This allows to put these elements into |
| 708 * namespaces without creating actual elements until they are really needed. | 708 * namespaces without creating actual elements until they are really needed. |
| 709 */ | 709 */ |
| 710 class _DeferredClassElement extends ClassElementHandle { | 710 class _DeferredClassElement extends ClassElementHandle { |
| 711 final _UnitResynthesizer unitResynthesizer; | 711 final _UnitResynthesizer unitResynthesizer; |
| 712 final CompilationUnitElement unitElement; | 712 final CompilationUnitElement unitElement; |
| 713 final UnlinkedClass serializedClass; | 713 final UnlinkedClass serializedClass; |
| 714 | 714 |
| 715 ClassElementImpl _actualElement; | 715 ClassElementImpl _actualElement; |
| 716 | 716 |
| 717 /** | |
| 718 * We don't resynthesize executables of classes until they are requested. | |
|
Paul Berry
2016/05/11 22:09:37
Nit: based on the name, I made the incorrect assum
| |
| 719 * TODO(scheglov) Check whether we need separate flags for separate kinds. | |
| 720 */ | |
| 721 bool _hasExecutables = false; | |
| 722 | |
| 717 @override | 723 @override |
| 718 final String name; | 724 final String name; |
| 719 | 725 |
| 720 factory _DeferredClassElement(_UnitResynthesizer unitResynthesizer, | 726 factory _DeferredClassElement(_UnitResynthesizer unitResynthesizer, |
| 721 CompilationUnitElement unitElement, UnlinkedClass serializedClass) { | 727 CompilationUnitElement unitElement, UnlinkedClass serializedClass) { |
| 722 String name = serializedClass.name; | 728 String name = serializedClass.name; |
| 723 List<String> components = | 729 List<String> components = |
| 724 unitResynthesizer.unit.location.components.toList(); | 730 unitResynthesizer.unit.location.components.toList(); |
| 725 components.add(name); | 731 components.add(name); |
| 726 ElementLocationImpl location = new ElementLocationImpl.con3(components); | 732 ElementLocationImpl location = new ElementLocationImpl.con3(components); |
| 727 return new _DeferredClassElement._( | 733 return new _DeferredClassElement._( |
| 728 unitResynthesizer, unitElement, serializedClass, name, location); | 734 unitResynthesizer, unitElement, serializedClass, name, location); |
| 729 } | 735 } |
| 730 | 736 |
| 731 _DeferredClassElement._(this.unitResynthesizer, this.unitElement, | 737 _DeferredClassElement._(this.unitResynthesizer, this.unitElement, |
| 732 this.serializedClass, this.name, ElementLocation location) | 738 this.serializedClass, this.name, ElementLocation location) |
| 733 : super(null, location); | 739 : super(null, location); |
| 734 | 740 |
| 735 @override | 741 @override |
| 742 List<PropertyAccessorElement> get accessors { | |
| 743 _ensureExecutables(); | |
| 744 return actualElement.accessors; | |
| 745 } | |
| 746 | |
| 747 @override | |
| 736 ClassElementImpl get actualElement { | 748 ClassElementImpl get actualElement { |
| 737 if (_actualElement == null) { | 749 if (_actualElement == null) { |
| 738 _actualElement = unitResynthesizer.buildClassImpl(serializedClass); | 750 _actualElement = unitResynthesizer.buildClassImpl(serializedClass, this); |
| 739 _actualElement.enclosingElement = unitElement; | 751 _actualElement.enclosingElement = unitElement; |
| 740 } | 752 } |
| 741 return _actualElement; | 753 return _actualElement; |
| 742 } | 754 } |
| 743 | 755 |
| 744 @override | 756 @override |
| 757 List<ConstructorElement> get constructors { | |
| 758 _ensureExecutables(); | |
| 759 return actualElement.constructors; | |
| 760 } | |
| 761 | |
| 762 @override | |
| 745 AnalysisContext get context => unitElement.context; | 763 AnalysisContext get context => unitElement.context; |
| 746 | 764 |
| 747 @override | 765 @override |
| 748 String get displayName => name; | 766 String get displayName => name; |
| 749 | 767 |
| 750 @override | 768 @override |
| 751 CompilationUnitElement get enclosingElement { | 769 CompilationUnitElement get enclosingElement { |
| 752 return unitElement; | 770 return unitElement; |
| 753 } | 771 } |
| 772 | |
| 773 @override | |
| 774 List<MethodElement> get methods { | |
| 775 _ensureExecutables(); | |
| 776 return actualElement.methods; | |
| 777 } | |
| 778 | |
| 779 @override | |
| 780 void ensureAccessorsReady() { | |
| 781 _ensureExecutables(); | |
| 782 } | |
| 783 | |
| 784 @override | |
| 785 void ensureActualElementComplete() { | |
| 786 _ensureExecutables(); | |
| 787 } | |
| 788 | |
| 789 @override | |
| 790 void ensureConstructorsReady() { | |
| 791 _ensureExecutables(); | |
| 792 } | |
| 793 | |
| 794 @override | |
| 795 void ensureMethodsReady() { | |
| 796 _ensureExecutables(); | |
| 797 } | |
| 798 | |
| 799 /** | |
| 800 * Ensure that we have [actualElement], and it has all executables. | |
| 801 */ | |
| 802 void _ensureExecutables() { | |
| 803 if (!_hasExecutables) { | |
| 804 _hasExecutables = true; | |
| 805 unitResynthesizer.buildClassExecutables(actualElement, serializedClass); | |
| 806 } | |
| 807 } | |
| 754 } | 808 } |
| 755 | 809 |
| 756 /** | 810 /** |
| 757 * The constructor element that has been resynthesized from a summary. The | 811 * The constructor element that has been resynthesized from a summary. The |
| 758 * actual element won't be constructed until it is requested. But properties | 812 * actual element won't be constructed until it is requested. But properties |
| 759 * [displayName], [enclosingElement] and [name] can be used without creating | 813 * [displayName], [enclosingElement] and [name] can be used without creating |
| 760 * the actual element. | 814 * the actual element. |
| 761 */ | 815 */ |
| 762 class _DeferredConstructorElement extends ConstructorElementHandle { | 816 class _DeferredConstructorElement extends ConstructorElementHandle { |
| 763 /** | 817 /** |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1603 } | 1657 } |
| 1604 } | 1658 } |
| 1605 | 1659 |
| 1606 /** | 1660 /** |
| 1607 * Resynthesize a [ClassElement] and place it in [unitHolder]. | 1661 * Resynthesize a [ClassElement] and place it in [unitHolder]. |
| 1608 */ | 1662 */ |
| 1609 void buildClass(UnlinkedClass serializedClass) { | 1663 void buildClass(UnlinkedClass serializedClass) { |
| 1610 ClassElement classElement; | 1664 ClassElement classElement; |
| 1611 if (libraryResynthesizer.isCoreLibrary && | 1665 if (libraryResynthesizer.isCoreLibrary && |
| 1612 serializedClass.supertype == null) { | 1666 serializedClass.supertype == null) { |
| 1613 classElement = buildClassImpl(serializedClass); | 1667 classElement = buildClassImpl(serializedClass, null); |
| 1614 if (!serializedClass.hasNoSupertype) { | 1668 if (!serializedClass.hasNoSupertype) { |
| 1615 libraryResynthesizer.delayedObjectSubclasses.add(classElement); | 1669 libraryResynthesizer.delayedObjectSubclasses.add(classElement); |
| 1616 } | 1670 } |
| 1617 } else { | 1671 } else { |
| 1618 classElement = new _DeferredClassElement(this, unit, serializedClass); | 1672 classElement = new _DeferredClassElement(this, unit, serializedClass); |
| 1619 } | 1673 } |
| 1620 unitHolder.addType(classElement); | 1674 unitHolder.addType(classElement); |
| 1621 } | 1675 } |
| 1622 | 1676 |
| 1623 /** | 1677 /** |
| 1624 * Resynthesize a [ClassElementImpl]. | 1678 * Fill the given [ClassElementImpl] with executable elements and fields. |
| 1625 */ | 1679 */ |
| 1626 ClassElementImpl buildClassImpl(UnlinkedClass serializedClass) { | 1680 void buildClassExecutables( |
| 1627 ClassElementImpl classElement = | 1681 ClassElementImpl classElement, UnlinkedClass serializedClass) { |
| 1628 new ClassElementImpl(serializedClass.name, serializedClass.nameOffset); | 1682 currentTypeParameters.add(classElement.typeParameters); |
| 1629 classElement.hasBeenInferred = summaryResynthesizer.strongMode; | |
| 1630 classElement.typeParameters = | |
| 1631 buildTypeParameters(serializedClass.typeParameters); | |
| 1632 classElement.abstract = serializedClass.isAbstract; | |
| 1633 classElement.mixinApplication = serializedClass.isMixinApplication; | |
| 1634 InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement); | |
| 1635 if (serializedClass.supertype != null) { | |
| 1636 classElement.supertype = buildType(serializedClass.supertype); | |
| 1637 } else if (!libraryResynthesizer.isCoreLibrary) { | |
| 1638 classElement.supertype = typeProvider.objectType; | |
| 1639 } | |
| 1640 classElement.interfaces = | |
| 1641 serializedClass.interfaces.map(buildType).toList(); | |
| 1642 classElement.mixins = serializedClass.mixins.map(buildType).toList(); | |
| 1643 ElementHolder memberHolder = new ElementHolder(); | 1683 ElementHolder memberHolder = new ElementHolder(); |
| 1644 fields = <String, FieldElementImpl>{}; | 1684 fields = <String, FieldElementImpl>{}; |
| 1645 for (UnlinkedVariable serializedVariable in serializedClass.fields) { | 1685 for (UnlinkedVariable serializedVariable in serializedClass.fields) { |
| 1646 buildVariable(serializedVariable, memberHolder); | 1686 buildVariable(serializedVariable, memberHolder); |
| 1647 } | 1687 } |
| 1648 bool constructorFound = false; | 1688 bool constructorFound = false; |
| 1649 constructors = <String, ConstructorElementImpl>{}; | 1689 constructors = <String, ConstructorElementImpl>{}; |
| 1650 for (UnlinkedExecutable serializedExecutable | 1690 for (UnlinkedExecutable serializedExecutable |
| 1651 in serializedClass.executables) { | 1691 in serializedClass.executables) { |
| 1652 switch (serializedExecutable.kind) { | 1692 switch (serializedExecutable.kind) { |
| 1653 case UnlinkedExecutableKind.constructor: | 1693 case UnlinkedExecutableKind.constructor: |
| 1654 constructorFound = true; | 1694 constructorFound = true; |
| 1655 buildConstructor( | 1695 buildConstructor( |
| 1656 serializedExecutable, memberHolder, correspondingType); | 1696 serializedExecutable, memberHolder, classElement.type); |
| 1657 break; | 1697 break; |
| 1658 case UnlinkedExecutableKind.functionOrMethod: | 1698 case UnlinkedExecutableKind.functionOrMethod: |
| 1659 case UnlinkedExecutableKind.getter: | 1699 case UnlinkedExecutableKind.getter: |
| 1660 case UnlinkedExecutableKind.setter: | 1700 case UnlinkedExecutableKind.setter: |
| 1661 if (serializedExecutable.isStatic) { | 1701 if (serializedExecutable.isStatic) { |
| 1662 currentTypeParameters.removeLast(); | 1702 currentTypeParameters.removeLast(); |
| 1663 } | 1703 } |
| 1664 buildExecutable(serializedExecutable, memberHolder); | 1704 buildExecutable(serializedExecutable, memberHolder); |
| 1665 if (serializedExecutable.isStatic) { | 1705 if (serializedExecutable.isStatic) { |
| 1666 currentTypeParameters.add(classElement.typeParameters); | 1706 currentTypeParameters.add(classElement.typeParameters); |
| 1667 } | 1707 } |
| 1668 break; | 1708 break; |
| 1669 } | 1709 } |
| 1670 } | 1710 } |
| 1671 if (!serializedClass.isMixinApplication) { | 1711 if (!serializedClass.isMixinApplication) { |
| 1672 if (!constructorFound) { | 1712 if (!constructorFound) { |
| 1673 // Synthesize implicit constructors. | 1713 // Synthesize implicit constructors. |
| 1674 ConstructorElementImpl constructor = new ConstructorElementImpl('', -1); | 1714 ConstructorElementImpl constructor = new ConstructorElementImpl('', -1); |
| 1675 constructor.synthetic = true; | 1715 constructor.synthetic = true; |
| 1676 constructor.returnType = correspondingType; | 1716 constructor.returnType = classElement.type; |
| 1677 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( | 1717 constructor.type = new FunctionTypeImpl.elementWithNameAndArgs( |
| 1678 constructor, null, getCurrentTypeArguments(), false); | 1718 constructor, null, getCurrentTypeArguments(), false); |
| 1679 memberHolder.addConstructor(constructor); | 1719 memberHolder.addConstructor(constructor); |
| 1680 } | 1720 } |
| 1681 classElement.constructors = memberHolder.constructors; | 1721 classElement.constructors = memberHolder.constructors; |
| 1682 } | 1722 } |
| 1683 classElement.accessors = memberHolder.accessors; | 1723 classElement.accessors = memberHolder.accessors; |
| 1684 classElement.fields = memberHolder.fields; | 1724 classElement.fields = memberHolder.fields; |
| 1685 classElement.methods = memberHolder.methods; | 1725 classElement.methods = memberHolder.methods; |
| 1726 resolveConstructorInitializers(classElement); | |
| 1727 currentTypeParameters.removeLast(); | |
| 1728 assert(currentTypeParameters.isEmpty); | |
| 1729 } | |
| 1730 | |
| 1731 /** | |
| 1732 * Resynthesize a [ClassElementImpl]. If [handle] is not `null`, then | |
| 1733 * executables are not resynthesized, and [InterfaceTypeImpl] is created | |
| 1734 * around the [handle], so that executables are resynthesized lazily. | |
| 1735 */ | |
| 1736 ClassElementImpl buildClassImpl( | |
| 1737 UnlinkedClass serializedClass, ClassElementHandle handle) { | |
| 1738 ClassElementImpl classElement = | |
| 1739 new ClassElementImpl(serializedClass.name, serializedClass.nameOffset); | |
| 1740 classElement.hasBeenInferred = summaryResynthesizer.strongMode; | |
| 1741 classElement.typeParameters = | |
| 1742 buildTypeParameters(serializedClass.typeParameters); | |
| 1743 classElement.abstract = serializedClass.isAbstract; | |
| 1744 classElement.mixinApplication = serializedClass.isMixinApplication; | |
| 1745 InterfaceTypeImpl correspondingType = | |
| 1746 new InterfaceTypeImpl(handle ?? classElement); | |
| 1747 if (serializedClass.supertype != null) { | |
| 1748 classElement.supertype = buildType(serializedClass.supertype); | |
| 1749 } else if (!libraryResynthesizer.isCoreLibrary) { | |
| 1750 classElement.supertype = typeProvider.objectType; | |
| 1751 } | |
| 1752 classElement.interfaces = | |
| 1753 serializedClass.interfaces.map(buildType).toList(); | |
| 1754 classElement.mixins = serializedClass.mixins.map(buildType).toList(); | |
| 1686 correspondingType.typeArguments = getCurrentTypeArguments(); | 1755 correspondingType.typeArguments = getCurrentTypeArguments(); |
| 1687 classElement.type = correspondingType; | 1756 classElement.type = correspondingType; |
| 1688 buildDocumentation(classElement, serializedClass.documentationComment); | 1757 buildDocumentation(classElement, serializedClass.documentationComment); |
| 1689 buildAnnotations(classElement, serializedClass.annotations); | 1758 buildAnnotations(classElement, serializedClass.annotations); |
| 1690 buildCodeRange(classElement, serializedClass.codeRange); | 1759 buildCodeRange(classElement, serializedClass.codeRange); |
| 1691 resolveConstructorInitializers(classElement); | |
| 1692 currentTypeParameters.removeLast(); | 1760 currentTypeParameters.removeLast(); |
| 1693 assert(currentTypeParameters.isEmpty); | 1761 assert(currentTypeParameters.isEmpty); |
| 1762 // TODO(scheglov) Somehow Observatory shows too much time spent here | |
| 1763 // during DDC run on the large codebase. I would expect only Object here. | |
| 1764 if (handle == null) { | |
| 1765 buildClassExecutables(classElement, serializedClass); | |
| 1766 } | |
| 1694 fields = null; | 1767 fields = null; |
| 1695 constructors = null; | 1768 constructors = null; |
| 1696 return classElement; | 1769 return classElement; |
| 1697 } | 1770 } |
| 1698 | 1771 |
| 1699 void buildCodeRange(ElementImpl element, CodeRange codeRange) { | 1772 void buildCodeRange(ElementImpl element, CodeRange codeRange) { |
| 1700 if (codeRange != null) { | 1773 if (codeRange != null) { |
| 1701 element.setCodeRange(codeRange.offset, codeRange.length); | 1774 element.setCodeRange(codeRange.offset, codeRange.length); |
| 1702 } | 1775 } |
| 1703 } | 1776 } |
| (...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2719 static String _getElementIdentifier(String name, ReferenceKind kind) { | 2792 static String _getElementIdentifier(String name, ReferenceKind kind) { |
| 2720 if (kind == ReferenceKind.topLevelPropertyAccessor || | 2793 if (kind == ReferenceKind.topLevelPropertyAccessor || |
| 2721 kind == ReferenceKind.propertyAccessor) { | 2794 kind == ReferenceKind.propertyAccessor) { |
| 2722 if (!name.endsWith('=')) { | 2795 if (!name.endsWith('=')) { |
| 2723 return name + '?'; | 2796 return name + '?'; |
| 2724 } | 2797 } |
| 2725 } | 2798 } |
| 2726 return name; | 2799 return name; |
| 2727 } | 2800 } |
| 2728 } | 2801 } |
| OLD | NEW |