[analyzer] Make two derived classes for PropertyAccessorElementImpl.

Derived class `GetterFragmentImpl` is used for getters and
`SetterFragmentImpl` is used for setters. Only `GetterFragmentImpl`
implements `GetterFragment` and only `SetterFragmentImpl` implements
`SetterFragment`. This ensures that clients performing `is
GetterFragment` and `is SetterFragment` checks get the expected
behavior. (Previously, any instance of `PropertyAccessorElementImpl`
would satisfy *both* `is GetterFragment` and `is SetterFragment`
tests).

This made it possible for the types of getters defined in
`GetterFragment` and `SetterFragment` to be more precise, which in
turn allowed some casts to be removed from the analyzer.

Change-Id: I243e8f6547d9aed77175e8c14c48af8970bfd528
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/412140
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry
2025-02-26 13:40:37 -08:00
committed by Commit Queue
parent b5ff3b80b8
commit 462bcaf52a
16 changed files with 279 additions and 255 deletions
@@ -105,7 +105,7 @@ class ConvertGetterToMethodRefactoringImpl extends RefactoringImpl
for (
GetterFragment? fragment = element.firstFragment;
fragment != null;
fragment = fragment.nextFragment as GetterFragment?
fragment = fragment.nextFragment
) {
var nameRange = range.fragmentName(fragment);
if (nameRange == null) {
+6
View File
@@ -3873,6 +3873,9 @@ package:analyzer/dart/element/element2.dart:
GetterFragment (class extends Object implements PropertyAccessorFragment):
new (constructor: GetterFragment Function())
correspondingSetter2 (getter: SetterFragment?)
element (getter: GetterElement)
nextFragment (getter: GetterFragment?)
previousFragment (getter: GetterFragment?)
HasSinceSdkVersion (class extends Object):
new (constructor: HasSinceSdkVersion Function())
sinceSdkVersion (getter: Version?)
@@ -4203,6 +4206,9 @@ package:analyzer/dart/element/element2.dart:
SetterFragment (class extends Object implements PropertyAccessorFragment):
new (constructor: SetterFragment Function())
correspondingGetter2 (getter: GetterFragment?)
element (getter: SetterElement)
nextFragment (getter: SetterFragment?)
previousFragment (getter: SetterFragment?)
ShowElementCombinator (see above)
SuperFormalParameterElement2 (class extends Object implements FormalParameterElement):
new (constructor: SuperFormalParameterElement2 Function())
+12 -28
View File
@@ -1181,22 +1181,14 @@ abstract class GetterFragment implements PropertyAccessorFragment {
/// `null` if there is no corresponding setter.
SetterFragment? get correspondingSetter2;
// TODO(brianwilkerson): This should override `nextFragment` to be more
// specific, but can't because the Impl class supports both getters and
// setters.
// @override
// GetterFragment? get nextFragment;
@override
GetterElement get element;
// TODO(brianwilkerson): This should override `previousFragment` to be more
// specific, but can't because the Impl class supports both getters and
// setters.
// @override
// GetterFragment? get previousFragment;
@override
GetterFragment? get nextFragment;
// TODO(brianwilkerson): This should override `element` to be more specific,
// but can't because the Impl class supports both getters and setters.
// @override
// GetterElement get element;
@override
GetterFragment? get previousFragment;
}
/// The interface that is implemented by elements that can have `@Since()`
@@ -2502,22 +2494,14 @@ abstract class SetterFragment implements PropertyAccessorFragment {
/// `null` if there is no corresponding getter.
GetterFragment? get correspondingGetter2;
// TODO(brianwilkerson): This should override `element` to be more specific,
// but can't because the Impl class supports both getters and setters.
// @override
// SetterElement get element;
@override
SetterElement get element;
// TODO(brianwilkerson): This should override `nextFragment` to be more
// specific, but can't because the Impl class supports both getters and
// setters.
// @override
// SetterFragment? get nextFragment;
@override
SetterFragment? get nextFragment;
// TODO(brianwilkerson): This should override `previousFragment` to be more
// specific, but can't because the Impl class supports both getters and
// setters.
// @override
// SetterFragment? get previousFragment;
@override
SetterFragment? get previousFragment;
}
/// A super formal parameter.
+156 -128
View File
@@ -5610,18 +5610,18 @@ abstract class GetterElement2OrMember
class GetterElementImpl extends PropertyAccessorElementImpl2
with
FragmentedExecutableElementMixin<PropertyAccessorElementImpl>,
FragmentedFunctionTypedElementMixin<PropertyAccessorElementImpl>,
FragmentedTypeParameterizedElementMixin<PropertyAccessorElementImpl>,
FragmentedAnnotatableElementMixin<PropertyAccessorElementImpl>,
FragmentedElementMixin<PropertyAccessorElementImpl>,
FragmentedExecutableElementMixin<GetterFragmentImpl>,
FragmentedFunctionTypedElementMixin<GetterFragmentImpl>,
FragmentedTypeParameterizedElementMixin<GetterFragmentImpl>,
FragmentedAnnotatableElementMixin<GetterFragmentImpl>,
FragmentedElementMixin<GetterFragmentImpl>,
_HasSinceSdkVersionMixin
implements GetterElement2OrMember {
@override
final PropertyAccessorElementImpl firstFragment;
final GetterFragmentImpl firstFragment;
GetterElementImpl(this.firstFragment) {
PropertyAccessorElementImpl? fragment = firstFragment;
GetterFragmentImpl? fragment = firstFragment;
while (fragment != null) {
fragment.element = this;
fragment = fragment.nextFragment;
@@ -5633,12 +5633,12 @@ class GetterElementImpl extends PropertyAccessorElementImpl2
@override
SetterElement? get correspondingSetter2 =>
firstFragment.correspondingSetter2?.element as SetterElement?;
firstFragment.correspondingSetter2?.element;
@override
List<PropertyAccessorElementImpl> get fragments {
List<GetterFragmentImpl> get fragments {
return [
for (PropertyAccessorElementImpl? fragment = firstFragment;
for (GetterFragmentImpl? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
@@ -5672,6 +5672,67 @@ class GetterElementImpl extends PropertyAccessorElementImpl2
}
}
class GetterFragmentImpl extends PropertyAccessorElementImpl
with AugmentableElement<GetterFragmentImpl>
implements GetterFragment {
/// The element corresponding to this fragment.
GetterElementImpl? _element;
GetterFragmentImpl(super.name, super.offset);
GetterFragmentImpl.forVariable(super.variable, {super.reference})
: super.forVariable();
@override
GetterFragmentImpl? get augmentationTarget {
if (super.augmentationTarget case var target?) {
if (target.kind == kind) {
return target;
}
}
return null;
}
@override
PropertyAccessorElement? get correspondingGetter => null;
@override
PropertyAccessorElement? get correspondingSetter => variable2?.setter;
@override
SetterFragment? get correspondingSetter2 => variable2?.setter;
@override
GetterElementImpl get element {
if (_element != null) {
return _element!;
}
GetterFragmentImpl firstFragment = this;
var previousFragment = firstFragment.previousFragment;
while (previousFragment != null) {
firstFragment = previousFragment;
previousFragment = firstFragment.previousFragment;
}
// As a side-effect of creating the element, all of the fragments in the
// chain will have their `_element` set to the newly created element.
return GetterElementImpl(firstFragment);
}
set element(GetterElementImpl element) => _element = element;
@override
bool get isGetter => true;
@override
bool get isSetter => false;
@override
GetterFragmentImpl? get nextFragment => augmentation;
@override
GetterFragmentImpl? get previousFragment => augmentationTarget;
}
/// A concrete implementation of a [HideElementCombinator].
class HideElementCombinatorImpl implements HideElementCombinator {
@override
@@ -7391,8 +7452,7 @@ class LibraryElementImpl extends ElementImpl
for (var unit in units) {
declarations.addAll(unit._accessors
.where((accessor) => accessor.isGetter)
.map((accessor) =>
(accessor as GetterFragment).element as GetterElement));
.map((accessor) => (accessor as GetterFragment).element));
}
return declarations.toList();
}
@@ -7490,8 +7550,7 @@ class LibraryElementImpl extends ElementImpl
for (var unit in units) {
declarations.addAll(unit._accessors
.where((accessor) => accessor.isSetter)
.map((accessor) =>
(accessor as SetterFragment).element as SetterElement));
.map((accessor) => (accessor as SetterFragment).element));
}
return declarations.toList();
}
@@ -10106,13 +10165,8 @@ abstract class PropertyAccessorElement2OrMember
}
/// A concrete implementation of a [PropertyAccessorElement].
class PropertyAccessorElementImpl extends ExecutableElementImpl
with AugmentableElement<PropertyAccessorElementImpl>
implements
PropertyAccessorElementOrMember,
PropertyAccessorFragment,
GetterFragment,
SetterFragment {
sealed class PropertyAccessorElementImpl extends ExecutableElementImpl
implements PropertyAccessorElementOrMember, PropertyAccessorFragment {
@override
String? name2;
@@ -10121,12 +10175,6 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl
PropertyInducingElementImpl? _variable;
/// The element corresponding to this fragment.
///
/// The element will always be an instance of either `GetterElement` or
/// `SetterElement`.
PropertyAccessorElementImpl2? _element;
/// Initialize a newly created property accessor element to have the given
/// [name] and [offset].
PropertyAccessorElementImpl(super.name, super.offset);
@@ -10142,69 +10190,16 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl
isSynthetic = true;
}
@override
PropertyAccessorElementImpl? get augmentationTarget {
if (super.augmentationTarget case var target?) {
if (target.kind == kind) {
return target;
}
}
return null;
}
@override
List<Element2> get children2 {
throw StateError('This is a fragment');
}
@override
PropertyAccessorElement? get correspondingGetter {
if (isGetter) {
return null;
}
return variable2?.getter;
}
@override
GetterFragment? get correspondingGetter2 =>
correspondingGetter as GetterFragment?;
@override
PropertyAccessorElement? get correspondingSetter {
if (isSetter) {
return null;
}
return variable2?.setter;
}
@override
SetterFragment? get correspondingSetter2 =>
correspondingSetter as SetterFragment?;
@override
PropertyAccessorElementImpl get declaration => this;
@override
PropertyAccessorElementImpl2 get element {
if (_element != null) {
return _element!;
}
PropertyAccessorElementImpl firstFragment = this;
var previousFragment = firstFragment.previousFragment;
while (previousFragment != null) {
firstFragment = previousFragment;
previousFragment = firstFragment.previousFragment;
}
// As a side-effect of creating the element, all of the fragments in the
// chain will have their `_element` set to the newly created element.
if (isGetter) {
return GetterElementImpl(firstFragment);
} else {
return SetterElementImpl(firstFragment);
}
}
set element(PropertyAccessorElementImpl2 element) => _element = element;
PropertyAccessorElementImpl2 get element;
@override
Fragment get enclosingFragment {
@@ -10229,25 +10224,7 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl
setModifier(Modifier.ABSTRACT, isAbstract);
}
@override
bool get isGetter {
return hasModifier(Modifier.GETTER);
}
/// Set whether this accessor is a getter.
set isGetter(bool isGetter) {
setModifier(Modifier.GETTER, isGetter);
}
@override
bool get isSetter {
return hasModifier(Modifier.SETTER);
}
/// Set whether this accessor is a setter.
set isSetter(bool isSetter) {
setModifier(Modifier.SETTER, isSetter);
}
set isAugmentation(bool isAugmentation);
@override
ElementKind get kind {
@@ -10271,12 +10248,6 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl
return super.name;
}
@override
PropertyAccessorElementImpl? get nextFragment => augmentation;
@override
PropertyAccessorElementImpl? get previousFragment => augmentationTarget;
@override
PropertyInducingElementImpl? get variable2 {
linkedData?.read(this);
@@ -10334,8 +10305,7 @@ abstract class PropertyAccessorElementImpl2 extends ExecutableElementImpl2
/// Implicit getter for a [PropertyInducingElementImpl].
// Pre-existing name.
// ignore: camel_case_types
class PropertyAccessorElementImpl_ImplicitGetter
extends PropertyAccessorElementImpl {
class PropertyAccessorElementImpl_ImplicitGetter extends GetterFragmentImpl {
/// Create the implicit getter and bind it to the [property].
PropertyAccessorElementImpl_ImplicitGetter(
PropertyInducingElementImpl property,
@@ -10399,8 +10369,7 @@ class PropertyAccessorElementImpl_ImplicitGetter
/// Implicit setter for a [PropertyInducingElementImpl].
// Pre-existing name.
// ignore: camel_case_types
class PropertyAccessorElementImpl_ImplicitSetter
extends PropertyAccessorElementImpl {
class PropertyAccessorElementImpl_ImplicitSetter extends SetterFragmentImpl {
/// Create the implicit setter and bind it to the [property].
PropertyAccessorElementImpl_ImplicitSetter(
PropertyInducingElementImpl property,
@@ -10490,13 +10459,13 @@ abstract class PropertyInducingElementImpl
/// The getter associated with this element.
@override
PropertyAccessorElementImpl? getter;
GetterFragmentImpl? getter;
/// The setter associated with this element, or `null` if the element is
/// effectively `final` and therefore does not have a setter associated with
/// it.
@override
PropertyAccessorElementImpl? setter;
SetterFragmentImpl? setter;
/// This field is set during linking, and performs type inference for
/// this property. After linking this field is always `null`.
@@ -10634,7 +10603,7 @@ abstract class PropertyInducingElementImpl
reference.element = this;
}
PropertyAccessorElementImpl createImplicitGetter(Reference reference) {
GetterFragmentImpl createImplicitGetter(Reference reference) {
assert(getter == null);
return getter = PropertyAccessorElementImpl_ImplicitGetter(
this,
@@ -10642,7 +10611,7 @@ abstract class PropertyInducingElementImpl
);
}
PropertyAccessorElementImpl createImplicitSetter(Reference reference) {
SetterFragmentImpl createImplicitSetter(Reference reference) {
assert(hasSetter);
assert(setter == null);
return setter = PropertyAccessorElementImpl_ImplicitSetter(
@@ -10722,18 +10691,18 @@ abstract class SetterElement2OrMember
class SetterElementImpl extends PropertyAccessorElementImpl2
with
FragmentedExecutableElementMixin<PropertyAccessorElementImpl>,
FragmentedFunctionTypedElementMixin<PropertyAccessorElementImpl>,
FragmentedTypeParameterizedElementMixin<PropertyAccessorElementImpl>,
FragmentedAnnotatableElementMixin<PropertyAccessorElementImpl>,
FragmentedElementMixin<PropertyAccessorElementImpl>,
FragmentedExecutableElementMixin<SetterFragmentImpl>,
FragmentedFunctionTypedElementMixin<SetterFragmentImpl>,
FragmentedTypeParameterizedElementMixin<SetterFragmentImpl>,
FragmentedAnnotatableElementMixin<SetterFragmentImpl>,
FragmentedElementMixin<SetterFragmentImpl>,
_HasSinceSdkVersionMixin
implements SetterElement2OrMember {
@override
final PropertyAccessorElementImpl firstFragment;
final SetterFragmentImpl firstFragment;
SetterElementImpl(this.firstFragment) {
PropertyAccessorElementImpl? fragment = firstFragment;
SetterFragmentImpl? fragment = firstFragment;
while (fragment != null) {
fragment.element = this;
fragment = fragment.nextFragment;
@@ -10745,15 +10714,15 @@ class SetterElementImpl extends PropertyAccessorElementImpl2
@override
GetterElement? get correspondingGetter2 =>
firstFragment.correspondingGetter2?.element as GetterElement?;
firstFragment.correspondingGetter2?.element;
@override
Element2 get enclosingElement2 => firstFragment.enclosingFragment.element;
@override
List<PropertyAccessorElementImpl> get fragments {
List<SetterFragmentImpl> get fragments {
return [
for (PropertyAccessorElementImpl? fragment = firstFragment;
for (SetterFragmentImpl? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
@@ -10795,6 +10764,67 @@ class SetterElementImpl extends PropertyAccessorElementImpl2
}
}
class SetterFragmentImpl extends PropertyAccessorElementImpl
with AugmentableElement<SetterFragmentImpl>
implements SetterFragment {
/// The element corresponding to this fragment.
SetterElementImpl? _element;
SetterFragmentImpl(super.name, super.offset);
SetterFragmentImpl.forVariable(super.variable, {super.reference})
: super.forVariable();
@override
SetterFragmentImpl? get augmentationTarget {
if (super.augmentationTarget case var target?) {
if (target.kind == kind) {
return target;
}
}
return null;
}
@override
PropertyAccessorElement? get correspondingGetter => variable2?.getter;
@override
GetterFragment? get correspondingGetter2 => variable2?.getter;
@override
PropertyAccessorElement? get correspondingSetter => null;
@override
SetterElementImpl get element {
if (_element != null) {
return _element!;
}
SetterFragmentImpl firstFragment = this;
var previousFragment = firstFragment.previousFragment;
while (previousFragment != null) {
firstFragment = previousFragment;
previousFragment = firstFragment.previousFragment;
}
// As a side-effect of creating the element, all of the fragments in the
// chain will have their `_element` set to the newly created element.
return SetterElementImpl(firstFragment);
}
set element(SetterElementImpl element) => _element = element;
@override
bool get isGetter => false;
@override
bool get isSetter => true;
@override
SetterFragmentImpl? get nextFragment => augmentation;
@override
SetterFragmentImpl? get previousFragment => augmentationTarget;
}
/// A concrete implementation of a [ShowElementCombinator].
class ShowElementCombinatorImpl implements ShowElementCombinator {
@override
@@ -11074,8 +11104,7 @@ class TopLevelVariableElementImpl2 extends PropertyInducingElementImpl2
}
@override
GetterElement? get getter2 =>
firstFragment.getter2?.element as GetterElement?;
GetterElement? get getter2 => firstFragment.getter2?.element;
@override
bool get hasImplicitType => firstFragment.hasImplicitType;
@@ -11107,8 +11136,7 @@ class TopLevelVariableElementImpl2 extends PropertyInducingElementImpl2
String? get name3 => firstFragment.name2;
@override
SetterElement? get setter2 =>
firstFragment.setter2?.element as SetterElement?;
SetterElement? get setter2 => firstFragment.setter2?.element;
@override
TypeImpl get type => firstFragment.type;
@@ -1095,9 +1095,8 @@ class InheritanceManager3 {
return result;
}
if (executable is PropertyAccessorElementImpl) {
assert(executable.isSetter);
var result = PropertyAccessorElementImpl(executable.name, -1);
if (executable is SetterFragmentImpl) {
var result = SetterFragmentImpl(executable.name, -1);
result.enclosingElement3 = class_;
result.isSynthetic = true;
result.parameters = transformedParameters;
@@ -1175,24 +1174,25 @@ class InheritanceManager3 {
var firstAccessor = first as PropertyAccessorElement;
var fragmentName = first.asElement2.firstFragment.name2;
var variableName = firstAccessor.displayName;
var field = FieldElementImpl(variableName, -1);
var result = PropertyAccessorElementImpl(variableName, -1);
PropertyAccessorElementImpl result;
if (firstAccessor.isGetter) {
field.getter = result = GetterFragmentImpl(variableName, -1);
} else {
field.setter = result = SetterFragmentImpl(variableName, -1);
}
result.enclosingElement3 = targetClass;
result.name2 = fragmentName;
result.isGetter = firstAccessor.isGetter;
result.isSetter = firstAccessor.isSetter;
result.returnType = resultType.returnType;
// TODO(scheglov): check if can type cast instead
result.parameters = resultType.parameters.cast();
var field = FieldElementImpl(variableName, -1);
field.enclosingElement3 = targetClass;
field.name2 = fragmentName;
if (firstAccessor.isGetter) {
field.getter = result;
field.type = result.returnType;
} else {
field.setter = result;
field.type = result.parameters[0].type;
}
result.variable2 = field;
@@ -780,7 +780,7 @@ class GetterMember extends PropertyAccessorMember
return [
for (GetterFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment as GetterFragment?)
fragment = fragment.nextFragment)
fragment,
];
}
@@ -1558,7 +1558,7 @@ class SetterMember extends PropertyAccessorMember
return [
for (SetterFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment as SetterFragment?)
fragment = fragment.nextFragment)
fragment,
];
}
+2 -3
View File
@@ -689,8 +689,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
List<GetterElement2OrMember> get getters => accessors
.where((accessor) => accessor.isGetter)
.map((fragment) => switch (fragment) {
PropertyAccessorElementImpl(:var element) =>
element as GetterElement2OrMember,
GetterFragmentImpl(:var element) => element,
GetterMember() => fragment,
_ => throw StateError(
'unexpected fragment type: ${fragment.runtimeType}',
@@ -834,7 +833,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
List<SetterElement> get setters => accessors
.where((accessor) => accessor.isSetter)
.map((fragment) => switch (fragment) {
SetterFragment(:var element) => element as SetterElement,
SetterFragment(:var element) => element,
SetterMember() => fragment,
_ => throw StateError(
'unexpected fragment type: ${fragment.runtimeType}',
+3 -6
View File
@@ -1395,10 +1395,8 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
if (node is AugmentedExpressionImpl) {
var augmentation = enclosingAugmentation;
var augmentationTarget = augmentation?.augmentationTarget;
if (augmentation is PropertyAccessorElementImpl &&
augmentation.isSetter &&
augmentationTarget is PropertyAccessorElementImpl &&
augmentationTarget.isSetter) {
if (augmentation is SetterFragmentImpl &&
augmentationTarget is SetterFragmentImpl) {
node.element = augmentationTarget;
inferenceLogWriter?.exitLValue(node);
return PropertyElementResolverResult(
@@ -1912,8 +1910,7 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
inferenceLogWriter?.enterExpression(node, contextType);
if (enclosingAugmentation case var augmentation?) {
var augmentedFragment = augmentation.augmentationTarget;
if (augmentation is PropertyAccessorElementImpl &&
augmentation.isGetter &&
if (augmentation is GetterFragmentImpl &&
augmentedFragment is PropertyAccessorElementImpl &&
augmentedFragment.isGetter) {
node.element = augmentedFragment;
@@ -186,16 +186,15 @@ class ElementFactory {
_objectElement = null;
}
static PropertyAccessorElementImpl getterElement(
static GetterFragmentImpl getterElement(
String name, bool isStatic, TypeImpl type) {
FieldElementImpl field = FieldElementImpl(name, -1);
field.isStatic = isStatic;
field.isSynthetic = true;
field.type = type;
field.isFinal = true;
PropertyAccessorElementImpl getter = PropertyAccessorElementImpl(name, 0);
GetterFragmentImpl getter = GetterFragmentImpl(name, 0);
getter.isSynthetic = false;
getter.isGetter = true;
getter.variable2 = field;
getter.returnType = type;
getter.isStatic = isStatic;
@@ -345,14 +344,12 @@ class ElementFactory {
field.isStatic = isStatic;
field.isSynthetic = true;
field.type = type;
PropertyAccessorElementImpl getter = PropertyAccessorElementImpl(name, -1);
getter.isGetter = true;
GetterFragmentImpl getter = GetterFragmentImpl(name, -1);
getter.variable2 = field;
getter.returnType = type;
field.getter = getter;
ParameterElementImpl parameter = requiredParameter2("a", type);
PropertyAccessorElementImpl setter = PropertyAccessorElementImpl(name, -1);
setter.isSetter = true;
SetterFragmentImpl setter = SetterFragmentImpl(name, -1);
setter.isSynthetic = true;
setter.variable2 = field;
setter.parameters = [parameter];
+29 -28
View File
@@ -140,14 +140,14 @@ class FragmentedElementBuilder<E extends Element2, F extends Fragment> {
}
}
class GetterElementBuilder extends FragmentedElementBuilder<GetterElementImpl,
PropertyAccessorElementImpl> {
class GetterElementBuilder
extends FragmentedElementBuilder<GetterElementImpl, GetterFragmentImpl> {
GetterElementBuilder({
required super.element,
required super.firstFragment,
});
void addFragment(PropertyAccessorElementImpl fragment) {
void addFragment(GetterFragmentImpl fragment) {
if (!identical(fragment, firstFragment)) {
lastFragment.augmentation = fragment;
lastFragment = fragment;
@@ -160,8 +160,8 @@ abstract class InstanceElementBuilder<E extends InstanceElementImpl2,
F extends InstanceElementImpl> extends FragmentedElementBuilder<E, F> {
final Map<String, FieldElementImpl> fields = {};
final Map<String, ConstructorElementImpl> constructors = {};
final Map<String, PropertyAccessorElementImpl> getters = {};
final Map<String, PropertyAccessorElementImpl> setters = {};
final Map<String, GetterFragmentImpl> getters = {};
final Map<String, SetterFragmentImpl> setters = {};
final Map<String, MethodElementImpl> methods = {};
final Map<String, ElementImpl> fragmentGetters = {};
@@ -176,28 +176,29 @@ abstract class InstanceElementBuilder<E extends InstanceElementImpl2,
void addAccessors(List<PropertyAccessorElementImpl> fragments) {
for (var fragment in fragments) {
var name = fragment.name;
if (fragment.isGetter) {
if (fragment.isAugmentation) {
if (getters[name] case var target?) {
target.augmentation = fragment;
fragment.augmentationTargetAny = target;
} else {
var target = _recoveryAugmentationTarget(name);
fragment.augmentationTargetAny = target;
switch (fragment) {
case GetterFragmentImpl():
if (fragment.isAugmentation) {
if (getters[name] case var target?) {
target.augmentation = fragment;
fragment.augmentationTargetAny = target;
} else {
var target = _recoveryAugmentationTarget(name);
fragment.augmentationTargetAny = target;
}
}
}
getters[name] = fragment;
} else {
if (fragment.isAugmentation) {
if (setters[name] case var target?) {
target.augmentation = fragment;
fragment.augmentationTargetAny = target;
} else {
var target = _recoveryAugmentationTarget(name);
fragment.augmentationTargetAny = target;
getters[name] = fragment;
case SetterFragmentImpl():
if (fragment.isAugmentation) {
if (setters[name] case var target?) {
target.augmentation = fragment;
fragment.augmentationTargetAny = target;
} else {
var target = _recoveryAugmentationTarget(name);
fragment.augmentationTargetAny = target;
}
}
}
setters[name] = fragment;
setters[name] = fragment;
}
}
}
@@ -398,14 +399,14 @@ class MixinElementBuilder
}
}
class SetterElementBuilder extends FragmentedElementBuilder<SetterElementImpl,
PropertyAccessorElementImpl> {
class SetterElementBuilder
extends FragmentedElementBuilder<SetterElementImpl, SetterFragmentImpl> {
SetterElementBuilder({
required super.element,
required super.firstFragment,
});
void addFragment(PropertyAccessorElementImpl fragment) {
void addFragment(SetterFragmentImpl fragment) {
if (!identical(fragment, firstFragment)) {
lastFragment.augmentation = fragment;
lastFragment = fragment;
@@ -1204,12 +1204,12 @@ class LibraryReader {
variables.add(variable);
var getter = variable.getter;
if (getter is PropertyAccessorElementImpl) {
if (getter is GetterFragmentImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is PropertyAccessorElementImpl) {
if (setter is SetterFragmentImpl) {
accessors.add(setter);
}
}
@@ -1577,8 +1577,11 @@ class LibraryReader {
var reference = _readReference();
var fragmentName = _readFragmentName();
var name = reference.elementName;
var flags = _reader.readUInt30();
var fragment = PropertyAccessorElementImpl(name, -1);
var fragment = PropertyAccessorElementFlags.isGetter(flags)
? GetterFragmentImpl(name, -1)
: SetterFragmentImpl(name, -1);
fragment.name2 = fragmentName;
var linkedData = PropertyAccessorElementLinkedData(
@@ -1589,8 +1592,13 @@ class LibraryReader {
);
fragment.setLinkedData(reference, linkedData);
PropertyAccessorElementFlags.read(_reader, fragment);
_readAugmentationTargetAny(fragment);
PropertyAccessorElementFlags.setFlagsBasedOnFlagByte(fragment, flags);
switch (fragment) {
case GetterFragmentImpl():
_readAugmentationTargetAny(fragment);
case SetterFragmentImpl():
_readAugmentationTargetAny(fragment);
}
fragment.parameters = _readParameters();
return fragment;
}
@@ -1623,7 +1631,6 @@ class LibraryReader {
var propertyElementReference = _readOptionalReference();
var name = accessor.displayName;
var isGetter = accessor.isGetter;
bool canUseExisting(PropertyInducingElement property) {
return property.isSynthetic ||
@@ -1672,13 +1679,14 @@ class LibraryReader {
}
accessor.variable2 = propertyFragment;
if (isGetter) {
propertyFragment.getter = accessor;
} else {
propertyFragment.setter = accessor;
if (propertyFragment.isSynthetic) {
propertyFragment.isFinal = false;
}
switch (accessor) {
case GetterFragmentImpl():
propertyFragment.getter = accessor;
case SetterFragmentImpl():
propertyFragment.setter = accessor;
if (propertyFragment.isSynthetic) {
propertyFragment.isFinal = false;
}
}
}
}
@@ -1767,12 +1775,12 @@ class LibraryReader {
variables.add(variable);
var getter = variable.getter;
if (getter is PropertyAccessorElementImpl) {
if (getter is GetterFragmentImpl) {
accessors.add(getter);
}
var setter = variable.setter;
if (setter is PropertyAccessorElementImpl) {
if (setter is SetterFragmentImpl) {
accessors.add(setter);
}
}
@@ -614,7 +614,12 @@ class BundleWriter {
_writeReference(fragment);
_writeFragmentName(fragment);
PropertyAccessorElementFlags.write(_sink, fragment);
_writeAugmentationTargetAny(fragment);
switch (fragment) {
case SetterFragmentImpl():
_writeAugmentationTargetAny(fragment);
case GetterFragmentImpl():
_writeAugmentationTargetAny(fragment);
}
_resolutionSink._writeAnnotationList(fragment.metadata);
_resolutionSink.writeType(fragment.returnType);
@@ -807,11 +807,10 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
ExecutableElementImpl executableElement;
FragmentedElementBuilder? elementBuilder;
if (node.isGetter) {
var getterFragment = PropertyAccessorElementImpl(name, nameOffset);
var getterFragment = GetterFragmentImpl(name, nameOffset);
getterFragment.name2 = _getFragmentName(nameToken);
getterFragment.nameOffset2 = _getFragmentNameOffset(nameToken);
getterFragment.isAugmentation = node.augmentKeyword != null;
getterFragment.isGetter = true;
getterFragment.isStatic = true;
var refName = getterFragment.name2 ?? '${_nextUnnamedId++}';
@@ -845,11 +844,10 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
_libraryBuilder.elementBuilderGetters[name] = elementBuilder;
}
} else if (node.isSetter) {
var setterFragment = PropertyAccessorElementImpl(name, nameOffset);
var setterFragment = SetterFragmentImpl(name, nameOffset);
setterFragment.name2 = _getFragmentName(nameToken);
setterFragment.nameOffset2 = _getFragmentNameOffset(nameToken);
setterFragment.isAugmentation = node.augmentKeyword != null;
setterFragment.isSetter = true;
setterFragment.isStatic = true;
var refName = setterFragment.name2 ?? '${_nextUnnamedId++}';
@@ -1175,12 +1173,11 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
Reference reference;
ExecutableElementImpl executableFragment;
if (node.isGetter) {
var fragment = PropertyAccessorElementImpl(name, nameOffset);
var fragment = GetterFragmentImpl(name, nameOffset);
fragment.name2 = _getFragmentName(nameToken);
fragment.nameOffset2 = _getFragmentNameOffset(nameToken);
fragment.isAbstract = node.isAbstract;
fragment.isAugmentation = node.augmentKeyword != null;
fragment.isGetter = true;
fragment.isStatic = node.isStatic;
// `class Enum {}` in `dart:core` declares `int get index` as abstract.
@@ -1199,12 +1196,11 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
_buildSyntheticVariable(name: refName, accessorElement: fragment);
}
} else if (node.isSetter) {
var fragment = PropertyAccessorElementImpl(name, nameOffset);
var fragment = SetterFragmentImpl(name, nameOffset);
fragment.name2 = _getFragmentName(nameToken);
fragment.nameOffset2 = _getFragmentNameOffset(nameToken);
fragment.isAbstract = node.isAbstract;
fragment.isAugmentation = node.augmentKeyword != null;
fragment.isSetter = true;
fragment.isStatic = node.isStatic;
var refName = fragment.name2 ?? '${_nextUnnamedId++}';
@@ -1735,10 +1731,11 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
}
accessorElement.variable2 = property;
if (accessorElement.isGetter) {
property.getter = accessorElement;
} else {
property.setter = accessorElement;
switch (accessorElement) {
case GetterFragmentImpl():
property.getter = accessorElement;
case SetterFragmentImpl():
property.setter = accessorElement;
}
return property;
}
@@ -378,15 +378,20 @@ class PropertyAccessorElementFlags {
static const int _isGenerator = 1 << 9;
static const int _isStatic = 1 << 10;
static bool isGetter(int flags) => (flags & _isGetter) != 0;
static void read(
SummaryDataReader reader,
PropertyAccessorElementImpl element,
) {
var byte = reader.readUInt30();
setFlagsBasedOnFlagByte(element, byte);
}
static void setFlagsBasedOnFlagByte(
PropertyAccessorElementImpl element, int byte) {
element.invokesSuperSelf = (byte & _invokesSuperSelf) != 0;
element.isAugmentation = (byte & _isAugmentation) != 0;
element.isGetter = (byte & _isGetter) != 0;
element.isSetter = (byte & _isSetter) != 0;
element.hasImplicitReturnType = (byte & _hasImplicitReturnType) != 0;
element.isAbstract = (byte & _isAbstract) != 0;
element.isAsynchronous = (byte & _isAsynchronous) != 0;
@@ -1054,8 +1054,7 @@ class _MockSdkElementsBuilder {
field.isSynthetic = true;
field.type = type;
var getter = PropertyAccessorElementImpl(name, 0);
getter.isGetter = true;
var getter = GetterFragmentImpl(name, 0);
getter.isStatic = isStatic;
getter.isSynthetic = false;
getter.returnType = type;
@@ -128,22 +128,20 @@ String? longMethodName(
}
void test_property_getter() {
var getterA = PropertyAccessorElementImpl.forVariable(
TopLevelVariableElementImpl('a', 0))
..isGetter = true
..returnType = stringNone;
var getterA =
GetterFragmentImpl.forVariable(TopLevelVariableElementImpl('a', 0))
..returnType = stringNone;
expect(getterA.getDisplayString(), 'String get a');
}
void test_property_setter() {
var setterA = PropertyAccessorElementImpl.forVariable(
TopLevelVariableElementImpl('a', 0))
..isSetter = true
..returnType = voidNone
..parameters = [
requiredParameter(name: 'value', type: stringNone).asElement,
];
var setterA =
SetterFragmentImpl.forVariable(TopLevelVariableElementImpl('a', 0))
..returnType = voidNone
..parameters = [
requiredParameter(name: 'value', type: stringNone).asElement,
];
expect(
setterA.getDisplayString(),