[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:
+1
-1
@@ -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) {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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}',
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user