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

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

Issue 2039573002: Resynthesize ClassElementImpl fields and property accessors lazily. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698