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 837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 | 848 |
849 @override | 849 @override |
850 void ensureMethodsReady() { | 850 void ensureMethodsReady() { |
851 _ensureExecutables(); | 851 _ensureExecutables(); |
852 } | 852 } |
853 | 853 |
854 /** | 854 /** |
855 * Ensure that we have [actualElement], and it has all executables. | 855 * Ensure that we have [actualElement], and it has all executables. |
856 */ | 856 */ |
857 void _ensureExecutables() { | 857 void _ensureExecutables() { |
858 if (!_executablesResynthesized) { | 858 // TODO(scheglov) remove and clean up Handle |
859 _executablesResynthesized = true; | |
860 unitResynthesizer.buildClassExecutables(actualElement, serializedClass); | |
861 } | |
862 } | 859 } |
863 } | 860 } |
864 | 861 |
865 /** | 862 /** |
866 * Local function element representing the initializer for a variable that has | 863 * Local function element representing the initializer for a variable that has |
867 * been resynthesized from a summary. The actual element won't be constructed | 864 * been resynthesized from a summary. The actual element won't be constructed |
868 * until it is requested. But properties [context] and [enclosingElement] can | 865 * until it is requested. But properties [context] and [enclosingElement] can |
869 * be used without creating the actual element. | 866 * be used without creating the actual element. |
870 */ | 867 */ |
871 class _DeferredInitializerElement extends FunctionElementHandle { | 868 class _DeferredInitializerElement extends FunctionElementHandle { |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 if (libraryResynthesizer.isCoreLibrary && | 1638 if (libraryResynthesizer.isCoreLibrary && |
1642 serializedClass.supertype == null) { | 1639 serializedClass.supertype == null) { |
1643 classElement = buildClassImpl(serializedClass, null); | 1640 classElement = buildClassImpl(serializedClass, null); |
1644 } else { | 1641 } else { |
1645 classElement = new _DeferredClassElement(this, unit, serializedClass); | 1642 classElement = new _DeferredClassElement(this, unit, serializedClass); |
1646 } | 1643 } |
1647 unitHolder.addType(classElement); | 1644 unitHolder.addType(classElement); |
1648 } | 1645 } |
1649 | 1646 |
1650 /** | 1647 /** |
1651 * Resynthesize an [ExecutableElement] and place it in the given [holder]. | |
1652 */ | |
1653 void buildClassExecutable(UnlinkedExecutable serializedExecutable, | |
1654 ElementImpl enclosingElement, ElementHolder holder) { | |
1655 bool isTopLevel = holder == null; | |
1656 if (holder == null) { | |
1657 holder = unitHolder; | |
1658 } | |
1659 UnlinkedExecutableKind kind = serializedExecutable.kind; | |
1660 String name = serializedExecutable.name; | |
1661 if (kind == UnlinkedExecutableKind.setter) { | |
1662 assert(name.endsWith('=')); | |
1663 name = name.substring(0, name.length - 1); | |
1664 } | |
1665 switch (kind) { | |
1666 case UnlinkedExecutableKind.getter: | |
1667 case UnlinkedExecutableKind.setter: | |
1668 // Top-level accessors are created lazily. | |
1669 if (isTopLevel) { | |
1670 break; | |
1671 } | |
1672 // Class member accessors. | |
1673 PropertyAccessorElementImpl executableElement = | |
1674 new PropertyAccessorElementImpl.forSerialized( | |
1675 serializedExecutable, enclosingElement); | |
1676 DartType type; | |
1677 if (kind == UnlinkedExecutableKind.getter) { | |
1678 type = executableElement.returnType; | |
1679 } else { | |
1680 type = executableElement.parameters[0].type; | |
1681 } | |
1682 holder.addAccessor(executableElement); | |
1683 FieldElementImpl field = buildImplicitField(name, type, kind, holder); | |
1684 field.static = serializedExecutable.isStatic; | |
1685 executableElement.variable = field; | |
1686 if (kind == UnlinkedExecutableKind.getter) { | |
1687 field.getter = executableElement; | |
1688 } else { | |
1689 field.setter = executableElement; | |
1690 } | |
1691 break; | |
1692 default: | |
1693 // The only other executable type is a constructor, and that is handled | |
1694 // separately (in [buildConstructor]. So this code should be | |
1695 // unreachable. | |
1696 assert(false); | |
1697 } | |
1698 } | |
1699 | |
1700 /** | |
1701 * Fill the given [ClassElementImpl] with executable elements and fields. | |
1702 */ | |
1703 void buildClassExecutables( | |
1704 ClassElementImpl classElement, UnlinkedClass serializedClass) { | |
1705 ElementHolder memberHolder = new ElementHolder(); | |
1706 for (UnlinkedVariable serializedVariable in serializedClass.fields) { | |
1707 buildField(classElement, serializedVariable, memberHolder); | |
1708 } | |
1709 for (UnlinkedExecutable serializedExecutable | |
1710 in serializedClass.executables) { | |
1711 switch (serializedExecutable.kind) { | |
1712 case UnlinkedExecutableKind.getter: | |
1713 case UnlinkedExecutableKind.setter: | |
1714 buildClassExecutable( | |
1715 serializedExecutable, classElement, memberHolder); | |
1716 break; | |
1717 case UnlinkedExecutableKind.constructor: | |
1718 case UnlinkedExecutableKind.functionOrMethod: | |
1719 // Resynthesized lazily. | |
1720 break; | |
1721 } | |
1722 } | |
1723 classElement.accessors = memberHolder.accessors; | |
1724 classElement.fields = memberHolder.fields; | |
1725 } | |
1726 | |
1727 /** | |
1728 * Resynthesize a [ClassElementImpl]. If [handle] is not `null`, then | 1648 * Resynthesize a [ClassElementImpl]. If [handle] is not `null`, then |
1729 * executables are not resynthesized, and [InterfaceTypeImpl] is created | 1649 * executables are not resynthesized, and [InterfaceTypeImpl] is created |
1730 * around the [handle], so that executables are resynthesized lazily. | 1650 * around the [handle], so that executables are resynthesized lazily. |
1731 */ | 1651 */ |
1732 ClassElementImpl buildClassImpl( | 1652 ClassElementImpl buildClassImpl( |
1733 UnlinkedClass serializedClass, ClassElementHandle handle) { | 1653 UnlinkedClass serializedClass, ClassElementHandle handle) { |
1734 ClassElementImpl classElement = | 1654 ClassElementImpl classElement = |
1735 new ClassElementImpl.forSerialized(serializedClass, unit); | 1655 new ClassElementImpl.forSerialized(serializedClass, unit); |
1736 classElement.hasBeenInferred = summaryResynthesizer.strongMode; | 1656 classElement.hasBeenInferred = summaryResynthesizer.strongMode; |
1737 InterfaceTypeImpl correspondingType = | 1657 InterfaceTypeImpl correspondingType = |
1738 new InterfaceTypeImpl(handle ?? classElement); | 1658 new InterfaceTypeImpl(handle ?? classElement); |
1739 // TODO(scheglov) move to ClassElementImpl | 1659 // TODO(scheglov) move to ClassElementImpl |
1740 correspondingType.typeArguments = classElement.typeParameterTypes; | 1660 correspondingType.typeArguments = classElement.typeParameterTypes; |
1741 classElement.type = correspondingType; | 1661 classElement.type = correspondingType; |
1742 // TODO(scheglov) Somehow Observatory shows too much time spent here | |
1743 // during DDC run on the large codebase. I would expect only Object here. | |
1744 if (handle == null) { | |
1745 buildClassExecutables(classElement, serializedClass); | |
1746 } | |
1747 return classElement; | 1662 return classElement; |
1748 } | 1663 } |
1749 | 1664 |
1750 /** | 1665 /** |
1751 * Build the documentation for the given [element]. Does nothing if | 1666 * Build the documentation for the given [element]. Does nothing if |
1752 * [serializedDocumentationComment] is `null`. | 1667 * [serializedDocumentationComment] is `null`. |
1753 */ | 1668 */ |
1754 void buildDocumentation(ElementImpl element, | 1669 void buildDocumentation(ElementImpl element, |
1755 UnlinkedDocumentationComment serializedDocumentationComment) { | 1670 UnlinkedDocumentationComment serializedDocumentationComment) { |
1756 if (serializedDocumentationComment != null) { | 1671 if (serializedDocumentationComment != null) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 classElement.fields = memberHolder.fields; | 1731 classElement.fields = memberHolder.fields; |
1817 classElement.accessors = memberHolder.accessors; | 1732 classElement.accessors = memberHolder.accessors; |
1818 unitHolder.addEnum(classElement); | 1733 unitHolder.addEnum(classElement); |
1819 } | 1734 } |
1820 | 1735 |
1821 /** | 1736 /** |
1822 * Resynthesize a [FieldElement]. | 1737 * Resynthesize a [FieldElement]. |
1823 */ | 1738 */ |
1824 void buildField(ClassElementImpl enclosingClass, | 1739 void buildField(ClassElementImpl enclosingClass, |
1825 UnlinkedVariable serializedVariable, ElementHolder holder) { | 1740 UnlinkedVariable serializedVariable, ElementHolder holder) { |
1826 FieldElementImpl element; | 1741 FieldElementImpl element = new FieldElementImpl.forSerializedFactory( |
1827 if (serializedVariable.initializer?.bodyExpr != null && | 1742 serializedVariable, enclosingClass); |
1828 (serializedVariable.isConst || | |
1829 serializedVariable.isFinal && !serializedVariable.isStatic)) { | |
1830 element = new ConstFieldElementImpl.forSerialized( | |
1831 serializedVariable, enclosingClass); | |
1832 } else { | |
1833 element = new FieldElementImpl.forSerialized( | |
1834 serializedVariable, enclosingClass); | |
1835 } | |
1836 element.static = serializedVariable.isStatic; | |
1837 holder.addField(element); | 1743 holder.addField(element); |
1838 buildImplicitAccessors(element, holder); | 1744 buildImplicitAccessors(element, holder); |
1839 } | 1745 } |
1840 | 1746 |
1841 /** | 1747 /** |
1842 * Build the implicit getter and setter associated with [element], and place | 1748 * Build the implicit getter and setter associated with [element], and place |
1843 * them in [holder]. | 1749 * them in [holder]. |
1844 */ | 1750 */ |
1845 void buildImplicitAccessors( | 1751 void buildImplicitAccessors( |
1846 PropertyInducingElementImpl element, ElementHolder holder) { | 1752 PropertyInducingElementImpl element, ElementHolder holder) { |
1847 PropertyAccessorElementImpl getter = buildImplicitGetter(element); | 1753 PropertyAccessorElementImpl getter = buildImplicitGetter(element); |
1848 holder?.addAccessor(getter); | 1754 holder?.addAccessor(getter); |
1849 if (!(element.isConst || element.isFinal)) { | 1755 if (!(element.isConst || element.isFinal)) { |
1850 PropertyAccessorElementImpl setter = buildImplicitSetter(element); | 1756 PropertyAccessorElementImpl setter = buildImplicitSetter(element); |
1851 holder?.addAccessor(setter); | 1757 holder?.addAccessor(setter); |
1852 } | 1758 } |
1853 } | 1759 } |
1854 | 1760 |
1855 /** | 1761 /** |
1856 * Build the implicit field associated with a getter or setter, and place it | |
1857 * in [holder]. | |
1858 */ | |
1859 FieldElementImpl buildImplicitField(String name, DartType type, | |
1860 UnlinkedExecutableKind kind, ElementHolder holder) { | |
1861 FieldElementImpl field = holder.getField(name); | |
1862 if (field == null) { | |
1863 field = new FieldElementImpl(name, -1); | |
1864 field.synthetic = true; | |
1865 field.final2 = kind == UnlinkedExecutableKind.getter; | |
1866 field.type = type; | |
1867 holder.addField(field); | |
1868 return field; | |
1869 } else { | |
1870 // TODO(paulberry): what if the getter and setter have a type mismatch? | |
1871 field.final2 = false; | |
1872 return field; | |
1873 } | |
1874 } | |
1875 | |
1876 /** | |
1877 * Build an implicit getter for the given [property] and bind it to the | 1762 * Build an implicit getter for the given [property] and bind it to the |
1878 * [property] and to its enclosing element. | 1763 * [property] and to its enclosing element. |
1879 */ | 1764 */ |
1880 PropertyAccessorElementImpl buildImplicitGetter( | 1765 PropertyAccessorElementImpl buildImplicitGetter( |
1881 PropertyInducingElementImpl property) { | 1766 PropertyInducingElementImpl property) { |
1882 PropertyAccessorElementImpl_ImplicitGetter getter = | 1767 PropertyAccessorElementImpl_ImplicitGetter getter = |
1883 new PropertyAccessorElementImpl_ImplicitGetter(property); | 1768 new PropertyAccessorElementImpl_ImplicitGetter(property); |
1884 getter.enclosingElement = property.enclosingElement; | 1769 getter.enclosingElement = property.enclosingElement; |
1885 return getter; | 1770 return getter; |
1886 } | 1771 } |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 static String _getElementIdentifier(String name, ReferenceKind kind) { | 2106 static String _getElementIdentifier(String name, ReferenceKind kind) { |
2222 if (kind == ReferenceKind.topLevelPropertyAccessor || | 2107 if (kind == ReferenceKind.topLevelPropertyAccessor || |
2223 kind == ReferenceKind.propertyAccessor) { | 2108 kind == ReferenceKind.propertyAccessor) { |
2224 if (!name.endsWith('=')) { | 2109 if (!name.endsWith('=')) { |
2225 return name + '?'; | 2110 return name + '?'; |
2226 } | 2111 } |
2227 } | 2112 } |
2228 return name; | 2113 return name; |
2229 } | 2114 } |
2230 } | 2115 } |
OLD | NEW |