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

Side by Side Diff: pkg/analyzer/lib/src/dart/element/element.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
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/summary/resynthesize.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 analyzer.src.dart.element.element; 5 library analyzer.src.dart.element.element;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' show min; 8 import 'dart:math' show min;
9 9
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 23 matching lines...) Expand all
34 34
35 /** 35 /**
36 * A concrete implementation of a [ClassElement]. 36 * A concrete implementation of a [ClassElement].
37 */ 37 */
38 abstract class AbstractClassElementImpl extends ElementImpl 38 abstract class AbstractClassElementImpl extends ElementImpl
39 implements ClassElement { 39 implements ClassElement {
40 /** 40 /**
41 * A list containing all of the accessors (getters and setters) contained in 41 * A list containing all of the accessors (getters and setters) contained in
42 * this class. 42 * this class.
43 */ 43 */
44 List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; 44 List<PropertyAccessorElement> _accessors;
45 45
46 /** 46 /**
47 * A list containing all of the fields contained in this class. 47 * A list containing all of the fields contained in this class.
48 */ 48 */
49 List<FieldElement> _fields = FieldElement.EMPTY_LIST; 49 List<FieldElement> _fields;
50 50
51 /** 51 /**
52 * The type defined by the class. 52 * The type defined by the class.
53 */ 53 */
54 @override 54 @override
55 InterfaceType type; 55 InterfaceType type;
56 56
57 /** 57 /**
58 * Initialize a newly created class element to have the given [name] at the 58 * Initialize a newly created class element to have the given [name] at the
59 * given [offset] in the file that contains the declaration of this element. 59 * given [offset] in the file that contains the declaration of this element.
60 */ 60 */
61 AbstractClassElementImpl(String name, int offset) : super(name, offset); 61 AbstractClassElementImpl(String name, int offset) : super(name, offset);
62 62
63 /** 63 /**
64 * Initialize a newly created class element to have the given [name]. 64 * Initialize a newly created class element to have the given [name].
65 */ 65 */
66 AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name); 66 AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
67 67
68 /** 68 /**
69 * Initialize using the given serialized information. 69 * Initialize using the given serialized information.
70 */ 70 */
71 AbstractClassElementImpl.forSerialized( 71 AbstractClassElementImpl.forSerialized(
72 CompilationUnitElementImpl enclosingUnit) 72 CompilationUnitElementImpl enclosingUnit)
73 : super.forSerialized(enclosingUnit); 73 : super.forSerialized(enclosingUnit);
74 74
75 @override 75 @override
76 List<PropertyAccessorElement> get accessors => _accessors; 76 List<PropertyAccessorElement> get accessors {
77 return _accessors ?? const <PropertyAccessorElement>[];
78 }
77 79
78 /** 80 /**
79 * Set the accessors contained in this class to the given [accessors]. 81 * Set the accessors contained in this class to the given [accessors].
80 */ 82 */
81 void set accessors(List<PropertyAccessorElement> accessors) { 83 void set accessors(List<PropertyAccessorElement> accessors) {
82 for (PropertyAccessorElement accessor in accessors) { 84 for (PropertyAccessorElement accessor in accessors) {
83 (accessor as PropertyAccessorElementImpl).enclosingElement = this; 85 (accessor as PropertyAccessorElementImpl).enclosingElement = this;
84 } 86 }
85 this._accessors = accessors; 87 this._accessors = accessors;
86 } 88 }
87 89
88 @override 90 @override
89 String get displayName => name; 91 String get displayName => name;
90 92
91 @override 93 @override
92 List<FieldElement> get fields => _fields; 94 List<FieldElement> get fields => _fields ?? const <FieldElement>[];
93 95
94 /** 96 /**
95 * Set the fields contained in this class to the given [fields]. 97 * Set the fields contained in this class to the given [fields].
96 */ 98 */
97 void set fields(List<FieldElement> fields) { 99 void set fields(List<FieldElement> fields) {
98 for (FieldElement field in fields) { 100 for (FieldElement field in fields) {
99 (field as FieldElementImpl).enclosingElement = this; 101 (field as FieldElementImpl).enclosingElement = this;
100 } 102 }
101 this._fields = fields; 103 this._fields = fields;
102 } 104 }
(...skipping 17 matching lines...) Expand all
120 } 122 }
121 } 123 }
122 124
123 @override 125 @override
124 ElementImpl getChild(String identifier) { 126 ElementImpl getChild(String identifier) {
125 // 127 //
126 // The casts in this method are safe because the set methods would have 128 // The casts in this method are safe because the set methods would have
127 // thrown a CCE if any of the elements in the arrays were not of the 129 // thrown a CCE if any of the elements in the arrays were not of the
128 // expected types. 130 // expected types.
129 // 131 //
130 for (PropertyAccessorElement accessor in _accessors) { 132 for (PropertyAccessorElement accessor in accessors) {
131 PropertyAccessorElementImpl accessorImpl = accessor; 133 PropertyAccessorElementImpl accessorImpl = accessor;
132 if (accessorImpl.identifier == identifier) { 134 if (accessorImpl.identifier == identifier) {
133 return accessorImpl; 135 return accessorImpl;
134 } 136 }
135 } 137 }
136 for (FieldElement field in _fields) { 138 for (FieldElement field in fields) {
137 FieldElementImpl fieldImpl = field; 139 FieldElementImpl fieldImpl = field;
138 if (fieldImpl.identifier == identifier) { 140 if (fieldImpl.identifier == identifier) {
139 return fieldImpl; 141 return fieldImpl;
140 } 142 }
141 } 143 }
142 return null; 144 return null;
143 } 145 }
144 146
145 @override 147 @override
146 FieldElement getField(String name) { 148 FieldElement getField(String name) {
147 for (FieldElement fieldElement in _fields) { 149 for (FieldElement fieldElement in fields) {
148 if (name == fieldElement.name) { 150 if (name == fieldElement.name) {
149 return fieldElement; 151 return fieldElement;
150 } 152 }
151 } 153 }
152 return null; 154 return null;
153 } 155 }
154 156
155 @override 157 @override
156 PropertyAccessorElement getGetter(String getterName) { 158 PropertyAccessorElement getGetter(String getterName) {
157 int length = _accessors.length; 159 int length = accessors.length;
158 for (int i = 0; i < length; i++) { 160 for (int i = 0; i < length; i++) {
159 PropertyAccessorElement accessor = _accessors[i]; 161 PropertyAccessorElement accessor = accessors[i];
160 if (accessor.isGetter && accessor.name == getterName) { 162 if (accessor.isGetter && accessor.name == getterName) {
161 return accessor; 163 return accessor;
162 } 164 }
163 } 165 }
164 return null; 166 return null;
165 } 167 }
166 168
167 @override 169 @override
168 PropertyAccessorElement getSetter(String setterName) { 170 PropertyAccessorElement getSetter(String setterName) {
169 // TODO (jwren) revisit- should we append '=' here or require clients to 171 // TODO (jwren) revisit- should we append '=' here or require clients to
170 // include it? 172 // include it?
171 // Do we need the check for isSetter below? 173 // Do we need the check for isSetter below?
172 if (!StringUtilities.endsWithChar(setterName, 0x3D)) { 174 if (!StringUtilities.endsWithChar(setterName, 0x3D)) {
173 setterName += '='; 175 setterName += '=';
174 } 176 }
175 for (PropertyAccessorElement accessor in _accessors) { 177 for (PropertyAccessorElement accessor in accessors) {
176 if (accessor.isSetter && accessor.name == setterName) { 178 if (accessor.isSetter && accessor.name == setterName) {
177 return accessor; 179 return accessor;
178 } 180 }
179 } 181 }
180 return null; 182 return null;
181 } 183 }
182 184
183 @override 185 @override
184 MethodElement lookUpConcreteMethod( 186 MethodElement lookUpConcreteMethod(
185 String methodName, LibraryElement library) => 187 String methodName, LibraryElement library) =>
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 methodName, library, true, new HashSet<ClassElement>()); 221 methodName, library, true, new HashSet<ClassElement>());
220 222
221 @override 223 @override
222 PropertyAccessorElement lookUpSetter( 224 PropertyAccessorElement lookUpSetter(
223 String setterName, LibraryElement library) => 225 String setterName, LibraryElement library) =>
224 _internalLookUpSetter(setterName, library, true); 226 _internalLookUpSetter(setterName, library, true);
225 227
226 @override 228 @override
227 void visitChildren(ElementVisitor visitor) { 229 void visitChildren(ElementVisitor visitor) {
228 super.visitChildren(visitor); 230 super.visitChildren(visitor);
229 safelyVisitChildren(_accessors, visitor); 231 safelyVisitChildren(accessors, visitor);
230 safelyVisitChildren(_fields, visitor); 232 safelyVisitChildren(fields, visitor);
231 } 233 }
232 234
233 PropertyAccessorElement _internalLookUpConcreteGetter( 235 PropertyAccessorElement _internalLookUpConcreteGetter(
234 String getterName, LibraryElement library, bool includeThisClass) { 236 String getterName, LibraryElement library, bool includeThisClass) {
235 PropertyAccessorElement getter = 237 PropertyAccessorElement getter =
236 _internalLookUpGetter(getterName, library, includeThisClass); 238 _internalLookUpGetter(getterName, library, includeThisClass);
237 while (getter != null && getter.isAbstract) { 239 while (getter != null && getter.isAbstract) {
238 Element definingClass = getter.enclosingElement; 240 Element definingClass = getter.enclosingElement;
239 if (definingClass is! ClassElement) { 241 if (definingClass is! ClassElement) {
240 return null; 242 return null;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 498
497 /** 499 /**
498 * Set whether this class is abstract. 500 * Set whether this class is abstract.
499 */ 501 */
500 void set abstract(bool isAbstract) { 502 void set abstract(bool isAbstract) {
501 assert(_unlinkedClass == null); 503 assert(_unlinkedClass == null);
502 setModifier(Modifier.ABSTRACT, isAbstract); 504 setModifier(Modifier.ABSTRACT, isAbstract);
503 } 505 }
504 506
505 @override 507 @override
508 List<PropertyAccessorElement> get accessors {
509 if (_unlinkedClass != null && _accessors == null) {
510 _resynthesizeFieldsAndPropertyAccessors();
511 }
512 return _accessors ?? const <PropertyAccessorElement>[];
513 }
514
515 @override
516 void set accessors(List<PropertyAccessorElement> accessors) {
517 assert(_unlinkedClass == null);
518 super.accessors = accessors;
519 }
520
521 @override
506 List<InterfaceType> get allSupertypes { 522 List<InterfaceType> get allSupertypes {
507 List<InterfaceType> list = new List<InterfaceType>(); 523 List<InterfaceType> list = new List<InterfaceType>();
508 _collectAllSupertypes(list); 524 _collectAllSupertypes(list);
509 return list; 525 return list;
510 } 526 }
511 527
512 @override 528 @override
513 int get codeLength { 529 int get codeLength {
514 if (_unlinkedClass != null) { 530 if (_unlinkedClass != null) {
515 return _unlinkedClass.codeRange?.length; 531 return _unlinkedClass.codeRange?.length;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 nearestNonMixinClass = nearestNonMixinClass.supertype.element; 638 nearestNonMixinClass = nearestNonMixinClass.supertype.element;
623 } 639 }
624 } 640 }
625 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); 641 return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible);
626 } 642 }
627 643
628 @override 644 @override
629 TypeParameterizedElementMixin get enclosingTypeParameterContext => null; 645 TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
630 646
631 @override 647 @override
648 List<FieldElement> get fields {
649 if (_unlinkedClass != null && _fields == null) {
650 _resynthesizeFieldsAndPropertyAccessors();
651 }
652 return _fields ?? const <FieldElement>[];
653 }
654
655 @override
656 void set fields(List<FieldElement> fields) {
657 assert(_unlinkedClass == null);
658 super.fields = fields;
659 }
660
661 @override
632 bool get hasNonFinalField { 662 bool get hasNonFinalField {
633 List<ClassElement> classesToVisit = new List<ClassElement>(); 663 List<ClassElement> classesToVisit = new List<ClassElement>();
634 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); 664 HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
635 classesToVisit.add(this); 665 classesToVisit.add(this);
636 while (!classesToVisit.isEmpty) { 666 while (!classesToVisit.isEmpty) {
637 ClassElement currentElement = classesToVisit.removeAt(0); 667 ClassElement currentElement = classesToVisit.removeAt(0);
638 if (visitedClasses.add(currentElement)) { 668 if (visitedClasses.add(currentElement)) {
639 // check fields 669 // check fields
640 for (FieldElement field in currentElement.fields) { 670 for (FieldElement field in currentElement.fields) {
641 if (!field.isFinal && 671 if (!field.isFinal &&
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper); 704 setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
675 } 705 }
676 706
677 @override 707 @override
678 bool get hasStaticMember { 708 bool get hasStaticMember {
679 for (MethodElement method in methods) { 709 for (MethodElement method in methods) {
680 if (method.isStatic) { 710 if (method.isStatic) {
681 return true; 711 return true;
682 } 712 }
683 } 713 }
684 for (PropertyAccessorElement accessor in _accessors) { 714 for (PropertyAccessorElement accessor in accessors) {
685 if (accessor.isStatic) { 715 if (accessor.isStatic) {
686 return true; 716 return true;
687 } 717 }
688 } 718 }
689 return false; 719 return false;
690 } 720 }
691 721
692 @override 722 @override
693 List<InterfaceType> get interfaces { 723 List<InterfaceType> get interfaces {
694 if (_unlinkedClass != null && _interfaces == null) { 724 if (_unlinkedClass != null && _interfaces == null) {
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 superParameter.type.substitute2(argumentTypes, parameterTypes); 1146 superParameter.type.substitute2(argumentTypes, parameterTypes);
1117 implicitParameters[i] = implicitParameter; 1147 implicitParameters[i] = implicitParameter;
1118 } 1148 }
1119 implicitConstructor.parameters = implicitParameters; 1149 implicitConstructor.parameters = implicitParameters;
1120 } 1150 }
1121 implicitConstructor.enclosingElement = this; 1151 implicitConstructor.enclosingElement = this;
1122 return implicitConstructor; 1152 return implicitConstructor;
1123 }).toList(growable: false); 1153 }).toList(growable: false);
1124 } 1154 }
1125 1155
1156 /**
1157 * Resynthesize explicit fields and property accessors and fill [_fields] and
1158 * [_accessors].
1159 */
1160 void _resynthesizeFieldsAndPropertyAccessors() {
1161 assert(_fields == null);
1162 assert(_accessors == null);
1163 // Build explicit fields and implicit property accessors.
1164 var explicitFields = <FieldElement>[];
1165 var implicitAccessors = <PropertyAccessorElement>[];
1166 for (UnlinkedVariable v in _unlinkedClass.fields) {
1167 FieldElementImpl field =
1168 new FieldElementImpl.forSerializedFactory(v, this);
1169 explicitFields.add(field);
1170 implicitAccessors.add(
1171 new PropertyAccessorElementImpl_ImplicitGetter(field)
1172 ..enclosingElement = this);
1173 if (!field.isConst && !field.isFinal) {
1174 implicitAccessors.add(
1175 new PropertyAccessorElementImpl_ImplicitSetter(field)
1176 ..enclosingElement = this);
1177 }
1178 }
1179 // Build explicit fields and implicit property accessors.
Paul Berry 2016/06/03 20:06:48 I think you mean "Build explicit property accessor
1180 var explicitAccessors = <PropertyAccessorElement>[];
1181 var implicitFields = <String, FieldElementImpl>{};
1182 for (UnlinkedExecutable e in _unlinkedClass.executables) {
1183 if (e.kind == UnlinkedExecutableKind.getter ||
1184 e.kind == UnlinkedExecutableKind.setter) {
1185 PropertyAccessorElementImpl accessor =
1186 new PropertyAccessorElementImpl.forSerialized(e, this);
1187 explicitAccessors.add(accessor);
1188 // Prepare the field type.
1189 DartType fieldType;
1190 if (e.kind == UnlinkedExecutableKind.getter) {
1191 fieldType = accessor.returnType;
1192 } else {
1193 fieldType = accessor.parameters[0].type;
1194 }
1195 // Create or update the implicit field.
1196 String fieldName = accessor.displayName;
1197 FieldElementImpl field = implicitFields[fieldName];
1198 if (field == null) {
1199 field = new FieldElementImpl(fieldName, -1);
1200 implicitFields[fieldName] = field;
1201 field.enclosingElement = this;
1202 field.synthetic = true;
1203 field.final2 = e.kind == UnlinkedExecutableKind.getter;
1204 field.type = fieldType;
1205 } else {
1206 field.final2 = false;
1207 }
1208 accessor.variable = field;
1209 if (e.kind == UnlinkedExecutableKind.getter) {
1210 field.getter = accessor;
1211 } else {
1212 field.setter = accessor;
1213 }
1214 }
1215 }
1216 // Combine explicit and implicit fields and property accessors.
1217 _fields = <FieldElement>[]
1218 ..addAll(explicitFields)
1219 ..addAll(implicitFields.values);
1220 _accessors = <PropertyAccessorElement>[]
1221 ..addAll(explicitAccessors)
1222 ..addAll(implicitAccessors);
1223 }
1224
1126 bool _safeIsOrInheritsProxy( 1225 bool _safeIsOrInheritsProxy(
1127 ClassElement classElt, HashSet<ClassElement> visitedClassElts) { 1226 ClassElement classElt, HashSet<ClassElement> visitedClassElts) {
1128 if (visitedClassElts.contains(classElt)) { 1227 if (visitedClassElts.contains(classElt)) {
1129 return false; 1228 return false;
1130 } 1229 }
1131 visitedClassElts.add(classElt); 1230 visitedClassElts.add(classElt);
1132 if (classElt.isProxy) { 1231 if (classElt.isProxy) {
1133 return true; 1232 return true;
1134 } else if (classElt.supertype != null && 1233 } else if (classElt.supertype != null &&
1135 _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) { 1234 _safeIsOrInheritsProxy(classElt.supertype.element, visitedClassElts)) {
(...skipping 2695 matching lines...) Expand 10 before | Expand all | Expand 10 after
3831 */ 3930 */
3832 FieldElementImpl.forNode(Identifier name) : super.forNode(name); 3931 FieldElementImpl.forNode(Identifier name) : super.forNode(name);
3833 3932
3834 /** 3933 /**
3835 * Initialize using the given serialized information. 3934 * Initialize using the given serialized information.
3836 */ 3935 */
3837 FieldElementImpl.forSerialized( 3936 FieldElementImpl.forSerialized(
3838 UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) 3937 UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement)
3839 : super.forSerialized(unlinkedVariable, enclosingElement); 3938 : super.forSerialized(unlinkedVariable, enclosingElement);
3840 3939
3940 /**
3941 * Initialize using the given serialized information.
3942 */
3943 factory FieldElementImpl.forSerializedFactory(
3944 UnlinkedVariable unlinkedVariable, ClassElementImpl enclosingClass) {
3945 if (unlinkedVariable.initializer?.bodyExpr != null &&
3946 (unlinkedVariable.isConst ||
3947 unlinkedVariable.isFinal && !unlinkedVariable.isStatic)) {
3948 return new ConstFieldElementImpl.forSerialized(
3949 unlinkedVariable, enclosingClass);
3950 } else {
3951 return new FieldElementImpl.forSerialized(
3952 unlinkedVariable, enclosingClass);
3953 }
3954 }
3955
3841 @override 3956 @override
3842 ClassElement get enclosingElement => super.enclosingElement as ClassElement; 3957 ClassElement get enclosingElement => super.enclosingElement as ClassElement;
3843 3958
3844 @override 3959 @override
3845 bool get isEnumConstant => 3960 bool get isEnumConstant =>
3846 enclosingElement != null ? enclosingElement.isEnum : false; 3961 enclosingElement != null ? enclosingElement.isEnum : false;
3847 3962
3848 @override 3963 @override
3964 bool get isStatic {
3965 if (_unlinkedVariable != null) {
3966 return _unlinkedVariable.isStatic;
3967 }
3968 return hasModifier(Modifier.STATIC);
3969 }
3970
3971 @override
3849 ElementKind get kind => ElementKind.FIELD; 3972 ElementKind get kind => ElementKind.FIELD;
3850 3973
3851 /** 3974 /**
3852 * Set whether this field is static. 3975 * Set whether this field is static.
3853 */ 3976 */
3854 void set static(bool isStatic) { 3977 void set static(bool isStatic) {
3978 assert(_unlinkedVariable == null);
3855 setModifier(Modifier.STATIC, isStatic); 3979 setModifier(Modifier.STATIC, isStatic);
3856 } 3980 }
3857 3981
3858 @override 3982 @override
3859 accept(ElementVisitor visitor) => visitor.visitFieldElement(this); 3983 accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
3860 3984
3861 @override 3985 @override
3862 AstNode computeNode() { 3986 AstNode computeNode() {
3863 if (isEnumConstant) { 3987 if (isEnumConstant) {
3864 return getNodeMatching((node) => node is EnumConstantDeclaration); 3988 return getNodeMatching((node) => node is EnumConstantDeclaration);
(...skipping 4204 matching lines...) Expand 10 before | Expand all | Expand 10 after
8069 8193
8070 @override 8194 @override
8071 void visitElement(Element element) { 8195 void visitElement(Element element) {
8072 int offset = element.nameOffset; 8196 int offset = element.nameOffset;
8073 if (offset != -1) { 8197 if (offset != -1) {
8074 map[offset] = element; 8198 map[offset] = element;
8075 } 8199 }
8076 super.visitElement(element); 8200 super.visitElement(element);
8077 } 8201 }
8078 } 8202 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/summary/resynthesize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698