Index: pkg/analyzer/lib/src/dart/element/element.dart |
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart |
index ee873ac859a43288c17f43defaa80e38002e28eb..43d9e1077d12311cc407c1be49271b46238b566e 100644 |
--- a/pkg/analyzer/lib/src/dart/element/element.dart |
+++ b/pkg/analyzer/lib/src/dart/element/element.dart |
@@ -41,12 +41,12 @@ abstract class AbstractClassElementImpl extends ElementImpl |
* A list containing all of the accessors (getters and setters) contained in |
* this class. |
*/ |
- List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; |
+ List<PropertyAccessorElement> _accessors; |
/** |
* A list containing all of the fields contained in this class. |
*/ |
- List<FieldElement> _fields = FieldElement.EMPTY_LIST; |
+ List<FieldElement> _fields; |
/** |
* The type defined by the class. |
@@ -73,7 +73,9 @@ abstract class AbstractClassElementImpl extends ElementImpl |
: super.forSerialized(enclosingUnit); |
@override |
- List<PropertyAccessorElement> get accessors => _accessors; |
+ List<PropertyAccessorElement> get accessors { |
+ return _accessors ?? const <PropertyAccessorElement>[]; |
+ } |
/** |
* Set the accessors contained in this class to the given [accessors]. |
@@ -89,7 +91,7 @@ abstract class AbstractClassElementImpl extends ElementImpl |
String get displayName => name; |
@override |
- List<FieldElement> get fields => _fields; |
+ List<FieldElement> get fields => _fields ?? const <FieldElement>[]; |
/** |
* Set the fields contained in this class to the given [fields]. |
@@ -127,13 +129,13 @@ abstract class AbstractClassElementImpl extends ElementImpl |
// thrown a CCE if any of the elements in the arrays were not of the |
// expected types. |
// |
- for (PropertyAccessorElement accessor in _accessors) { |
+ for (PropertyAccessorElement accessor in accessors) { |
PropertyAccessorElementImpl accessorImpl = accessor; |
if (accessorImpl.identifier == identifier) { |
return accessorImpl; |
} |
} |
- for (FieldElement field in _fields) { |
+ for (FieldElement field in fields) { |
FieldElementImpl fieldImpl = field; |
if (fieldImpl.identifier == identifier) { |
return fieldImpl; |
@@ -144,7 +146,7 @@ abstract class AbstractClassElementImpl extends ElementImpl |
@override |
FieldElement getField(String name) { |
- for (FieldElement fieldElement in _fields) { |
+ for (FieldElement fieldElement in fields) { |
if (name == fieldElement.name) { |
return fieldElement; |
} |
@@ -154,9 +156,9 @@ abstract class AbstractClassElementImpl extends ElementImpl |
@override |
PropertyAccessorElement getGetter(String getterName) { |
- int length = _accessors.length; |
+ int length = accessors.length; |
for (int i = 0; i < length; i++) { |
- PropertyAccessorElement accessor = _accessors[i]; |
+ PropertyAccessorElement accessor = accessors[i]; |
if (accessor.isGetter && accessor.name == getterName) { |
return accessor; |
} |
@@ -172,7 +174,7 @@ abstract class AbstractClassElementImpl extends ElementImpl |
if (!StringUtilities.endsWithChar(setterName, 0x3D)) { |
setterName += '='; |
} |
- for (PropertyAccessorElement accessor in _accessors) { |
+ for (PropertyAccessorElement accessor in accessors) { |
if (accessor.isSetter && accessor.name == setterName) { |
return accessor; |
} |
@@ -226,8 +228,8 @@ abstract class AbstractClassElementImpl extends ElementImpl |
@override |
void visitChildren(ElementVisitor visitor) { |
super.visitChildren(visitor); |
- safelyVisitChildren(_accessors, visitor); |
- safelyVisitChildren(_fields, visitor); |
+ safelyVisitChildren(accessors, visitor); |
+ safelyVisitChildren(fields, visitor); |
} |
PropertyAccessorElement _internalLookUpConcreteGetter( |
@@ -503,6 +505,20 @@ class ClassElementImpl extends AbstractClassElementImpl |
} |
@override |
+ List<PropertyAccessorElement> get accessors { |
+ if (_unlinkedClass != null && _accessors == null) { |
+ _resynthesizeFieldsAndPropertyAccessors(); |
+ } |
+ return _accessors ?? const <PropertyAccessorElement>[]; |
+ } |
+ |
+ @override |
+ void set accessors(List<PropertyAccessorElement> accessors) { |
+ assert(_unlinkedClass == null); |
+ super.accessors = accessors; |
+ } |
+ |
+ @override |
List<InterfaceType> get allSupertypes { |
List<InterfaceType> list = new List<InterfaceType>(); |
_collectAllSupertypes(list); |
@@ -629,6 +645,20 @@ class ClassElementImpl extends AbstractClassElementImpl |
TypeParameterizedElementMixin get enclosingTypeParameterContext => null; |
@override |
+ List<FieldElement> get fields { |
+ if (_unlinkedClass != null && _fields == null) { |
+ _resynthesizeFieldsAndPropertyAccessors(); |
+ } |
+ return _fields ?? const <FieldElement>[]; |
+ } |
+ |
+ @override |
+ void set fields(List<FieldElement> fields) { |
+ assert(_unlinkedClass == null); |
+ super.fields = fields; |
+ } |
+ |
+ @override |
bool get hasNonFinalField { |
List<ClassElement> classesToVisit = new List<ClassElement>(); |
HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>(); |
@@ -681,7 +711,7 @@ class ClassElementImpl extends AbstractClassElementImpl |
return true; |
} |
} |
- for (PropertyAccessorElement accessor in _accessors) { |
+ for (PropertyAccessorElement accessor in accessors) { |
if (accessor.isStatic) { |
return true; |
} |
@@ -1123,6 +1153,75 @@ class ClassElementImpl extends AbstractClassElementImpl |
}).toList(growable: false); |
} |
+ /** |
+ * Resynthesize explicit fields and property accessors and fill [_fields] and |
+ * [_accessors]. |
+ */ |
+ void _resynthesizeFieldsAndPropertyAccessors() { |
+ assert(_fields == null); |
+ assert(_accessors == null); |
+ // Build explicit fields and implicit property accessors. |
+ var explicitFields = <FieldElement>[]; |
+ var implicitAccessors = <PropertyAccessorElement>[]; |
+ for (UnlinkedVariable v in _unlinkedClass.fields) { |
+ FieldElementImpl field = |
+ new FieldElementImpl.forSerializedFactory(v, this); |
+ explicitFields.add(field); |
+ implicitAccessors.add( |
+ new PropertyAccessorElementImpl_ImplicitGetter(field) |
+ ..enclosingElement = this); |
+ if (!field.isConst && !field.isFinal) { |
+ implicitAccessors.add( |
+ new PropertyAccessorElementImpl_ImplicitSetter(field) |
+ ..enclosingElement = this); |
+ } |
+ } |
+ // Build explicit fields and implicit property accessors. |
Paul Berry
2016/06/03 20:06:48
I think you mean "Build explicit property accessor
|
+ var explicitAccessors = <PropertyAccessorElement>[]; |
+ var implicitFields = <String, FieldElementImpl>{}; |
+ for (UnlinkedExecutable e in _unlinkedClass.executables) { |
+ if (e.kind == UnlinkedExecutableKind.getter || |
+ e.kind == UnlinkedExecutableKind.setter) { |
+ PropertyAccessorElementImpl accessor = |
+ new PropertyAccessorElementImpl.forSerialized(e, this); |
+ explicitAccessors.add(accessor); |
+ // Prepare the field type. |
+ DartType fieldType; |
+ if (e.kind == UnlinkedExecutableKind.getter) { |
+ fieldType = accessor.returnType; |
+ } else { |
+ fieldType = accessor.parameters[0].type; |
+ } |
+ // Create or update the implicit field. |
+ String fieldName = accessor.displayName; |
+ FieldElementImpl field = implicitFields[fieldName]; |
+ if (field == null) { |
+ field = new FieldElementImpl(fieldName, -1); |
+ implicitFields[fieldName] = field; |
+ field.enclosingElement = this; |
+ field.synthetic = true; |
+ field.final2 = e.kind == UnlinkedExecutableKind.getter; |
+ field.type = fieldType; |
+ } else { |
+ field.final2 = false; |
+ } |
+ accessor.variable = field; |
+ if (e.kind == UnlinkedExecutableKind.getter) { |
+ field.getter = accessor; |
+ } else { |
+ field.setter = accessor; |
+ } |
+ } |
+ } |
+ // Combine explicit and implicit fields and property accessors. |
+ _fields = <FieldElement>[] |
+ ..addAll(explicitFields) |
+ ..addAll(implicitFields.values); |
+ _accessors = <PropertyAccessorElement>[] |
+ ..addAll(explicitAccessors) |
+ ..addAll(implicitAccessors); |
+ } |
+ |
bool _safeIsOrInheritsProxy( |
ClassElement classElt, HashSet<ClassElement> visitedClassElts) { |
if (visitedClassElts.contains(classElt)) { |
@@ -3838,6 +3937,22 @@ class FieldElementImpl extends PropertyInducingElementImpl |
UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) |
: super.forSerialized(unlinkedVariable, enclosingElement); |
+ /** |
+ * Initialize using the given serialized information. |
+ */ |
+ factory FieldElementImpl.forSerializedFactory( |
+ UnlinkedVariable unlinkedVariable, ClassElementImpl enclosingClass) { |
+ if (unlinkedVariable.initializer?.bodyExpr != null && |
+ (unlinkedVariable.isConst || |
+ unlinkedVariable.isFinal && !unlinkedVariable.isStatic)) { |
+ return new ConstFieldElementImpl.forSerialized( |
+ unlinkedVariable, enclosingClass); |
+ } else { |
+ return new FieldElementImpl.forSerialized( |
+ unlinkedVariable, enclosingClass); |
+ } |
+ } |
+ |
@override |
ClassElement get enclosingElement => super.enclosingElement as ClassElement; |
@@ -3846,12 +3961,21 @@ class FieldElementImpl extends PropertyInducingElementImpl |
enclosingElement != null ? enclosingElement.isEnum : false; |
@override |
+ bool get isStatic { |
+ if (_unlinkedVariable != null) { |
+ return _unlinkedVariable.isStatic; |
+ } |
+ return hasModifier(Modifier.STATIC); |
+ } |
+ |
+ @override |
ElementKind get kind => ElementKind.FIELD; |
/** |
* Set whether this field is static. |
*/ |
void set static(bool isStatic) { |
+ assert(_unlinkedVariable == null); |
setModifier(Modifier.STATIC, isStatic); |
} |