blob: 398e5c53bbbb9181bb193e169f5650671e186314 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/element/display_string_builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:pub_semver/pub_semver.dart';
/// A constructor element defined in a parameterized type where the values of
/// the type parameters are known.
class ConstructorMember extends ExecutableMember
with
ConstructorElementMixin,
ConstructorElementMixin2
implements
// ignore:deprecated_member_use_from_same_package,analyzer_use_new_elements
ConstructorElement,
ConstructorElement2 {
/// Initialize a newly created element to represent a constructor, based on
/// the [declaration], and applied [substitution].
ConstructorMember({
required ConstructorElementImpl super.declaration,
required super.substitution,
}) : super(
typeParameters: const <TypeParameterElementImpl>[],
);
@override
ConstructorElementImpl2 get baseElement => _element2;
@override
ConstructorElementImpl get declaration =>
_declaration as ConstructorElementImpl;
@override
String get displayName => declaration.displayName;
@override
InterfaceElementImpl2 get enclosingElement2 => _element2.enclosingElement2;
@override
InterfaceElementImpl get enclosingElement3 => declaration.enclosingElement3;
@override
ConstructorFragment get firstFragment => _element2.firstFragment;
@override
List<ConstructorFragment> get fragments {
return [
for (ConstructorFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
bool get isConst => declaration.isConst;
@override
bool get isConstantEvaluated => declaration.isConstantEvaluated;
@override
bool get isFactory => declaration.isFactory;
@override
LibraryElementImpl get library {
return _declaration.library!;
}
@override
String? get lookupName => _element2.lookupName;
@override
String get name => declaration.name;
@override
String? get name3 => _element2.name3;
@override
int? get nameEnd => declaration.nameEnd;
@override
int? get periodOffset => declaration.periodOffset;
@override
ConstructorElementMixin? get redirectedConstructor {
var element = declaration.redirectedConstructor;
return _redirect(element);
}
@override
ConstructorElementMixin2? get redirectedConstructor2 {
return redirectedConstructor?.asElement2;
}
@override
InterfaceTypeImpl get returnType {
var returnType = declaration.returnType;
return substitution.mapInterfaceType(returnType);
}
@override
Source get source => _declaration.source!;
@override
ConstructorElementMixin? get superConstructor {
var element = declaration.superConstructor;
return _redirect(element);
}
@override
ConstructorElementMixin2? get superConstructor2 {
return superConstructor?.asElement2;
}
@override
ConstructorElementImpl2 get _element2 => declaration.asElement2;
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitConstructorElement(this);
}
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeConstructorElement(this);
}
ConstructorElementMixin? _redirect(ConstructorElementMixin? element) {
switch (element) {
case null:
return null;
case ConstructorElementImpl():
return element;
case ConstructorMember():
var memberMap = element.substitution.map;
var map = <TypeParameterElement2, DartType>{
for (var MapEntry(:key, :value) in memberMap.entries)
key: substitution.substituteType(value),
};
return ConstructorMember(
declaration: element.declaration,
substitution: Substitution.fromMap2(map),
);
default:
throw UnimplementedError('(${element.runtimeType}) $element');
}
}
/// If the given [element]'s type is different when any type parameters
/// from the defining type's declaration are replaced with the actual type
/// arguments from the [definingType], create a constructor member
/// representing the given constructor. Return the member that was created, or
/// the original constructor if no member was created.
static ConstructorElementMixin from(
ConstructorElementImpl element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return ConstructorMember(
declaration: element,
substitution: Substitution.fromInterfaceType(definingType),
);
}
/// If the given [element]'s type is different when any type parameters
/// from the defining type's declaration are replaced with the actual type
/// arguments from the [definingType], create a constructor member
/// representing the given constructor. Return the member that was created, or
/// the original constructor if no member was created.
static ConstructorElementMixin2 from2(
ConstructorElementImpl2 element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return ConstructorMember(
declaration: element.asElement,
substitution: Substitution.fromInterfaceType(definingType),
);
}
}
/// An executable element defined in a parameterized type where the values of
/// the type parameters are known.
abstract class ExecutableMember extends Member
implements ExecutableElementOrMember, ExecutableElement2OrMember {
@override
final List<TypeParameterElementImpl> typeParameters;
FunctionTypeImpl? _type;
/// Initialize a newly created element to represent a callable element (like a
/// method or function or property), based on the [declaration], and applied
/// [substitution].
///
/// The [typeParameters] are fresh, and [substitution] is already applied to
/// their bounds. The [substitution] includes replacing [declaration] type
/// parameters with the provided fresh [typeParameters].
ExecutableMember({
required ExecutableElementImpl super.declaration,
required super.substitution,
required this.typeParameters,
});
@Deprecated('Use Element2 instead')
@override
List<Element> get children => parameters;
@override
List<Element2> get children2 {
return [
...typeParameters2,
...formalParameters,
];
}
@override
ExecutableElementImpl get declaration =>
_declaration as ExecutableElementImpl;
@override
String get displayName => declaration.displayName;
@override
Element2? get enclosingElement2 => _element2.enclosingElement2;
@override
List<FormalParameterElementMixin> get formalParameters =>
parameters.map((fragment) => fragment.asElement2).toList();
@override
List<ExecutableFragment> get fragments {
return [
for (ExecutableFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
bool get hasImplicitReturnType => declaration.hasImplicitReturnType;
@override
bool get isAbstract => declaration.isAbstract;
@override
bool get isAsynchronous => declaration.isAsynchronous;
@override
bool get isAugmentation => declaration.isAugmentation;
@override
bool get isExtensionTypeMember => declaration.isExtensionTypeMember;
@override
bool get isExternal => declaration.isExternal;
@override
bool get isGenerator => declaration.isGenerator;
@override
bool get isOperator => declaration.isOperator;
@override
bool get isSimplyBounded => declaration.isSimplyBounded;
@override
bool get isStatic => declaration.isStatic;
@override
bool get isSynchronous => declaration.isSynchronous;
@Deprecated('Use ExecutableElement2 instead')
@override
LibraryElement get library => _declaration.library!;
@override
LibraryElement2 get library2 => _element2.library2;
@override
Source get librarySource => _declaration.librarySource!;
@override
int get nameOffset => declaration.nameOffset;
@override
Element2 get nonSynthetic2 => _element2;
@override
List<ParameterElementMixin> get parameters {
return declaration.parameters.map<ParameterElementMixin>((element) {
switch (element) {
case FieldFormalParameterElementImpl():
return FieldFormalParameterMember(
declaration: element,
substitution: substitution,
);
case SuperFormalParameterElementImpl():
return SuperFormalParameterMember(
declaration: element,
substitution: substitution,
);
default:
return ParameterMember(
declaration: element,
substitution: substitution,
);
}
}).toList();
}
@override
TypeImpl get returnType {
var result = declaration.returnType;
result = substitution.substituteType(result);
return result;
}
@override
FunctionTypeImpl get type {
return _type ??= substitution.mapFunctionType(declaration.type);
}
@override
List<TypeParameterElementImpl2> get typeParameters2 =>
typeParameters.map((fragment) => fragment.asElement2).toList();
@override
ExecutableElement2 get _element2 => declaration.asElement2;
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeExecutableElement(this, displayName);
}
@override
String displayString2({
bool multiline = false,
bool preferTypeAlias = false,
}) {
var builder = ElementDisplayStringBuilder(
multiline: multiline,
preferTypeAlias: preferTypeAlias,
);
appendTo(builder);
return builder.toString();
}
@override
bool isAccessibleIn2(LibraryElement2 library) =>
_element2.isAccessibleIn2(library);
@override
Element2? thisOrAncestorMatching2(bool Function(Element2 p1) predicate) =>
_element2.thisOrAncestorMatching2(predicate);
@override
E? thisOrAncestorOfType2<E extends Element2>() =>
_element2.thisOrAncestorOfType2();
@override
void visitChildren2<T>(ElementVisitor2<T> visitor) {
for (var child in children2) {
child.accept2(visitor);
}
}
static ExecutableElement2OrMember from(
ExecutableElement2 element,
MapSubstitution substitution,
) {
return from2(element.asElement, substitution).asElement2;
}
static ExecutableElementOrMember from2(
ExecutableElementOrMember element,
MapSubstitution substitution,
) {
if (identical(substitution, Substitution.empty)) {
return element;
}
ExecutableElementImpl declaration;
var combined = substitution;
if (element is ExecutableMember) {
declaration = element.declaration;
var map = <TypeParameterElement2, DartType>{
for (var MapEntry(:key, :value) in element.substitution.map.entries)
key: substitution.substituteType(value),
};
combined = Substitution.fromMap2(map);
} else {
declaration = element as ExecutableElementImpl;
if (!declaration.hasEnclosingTypeParameterReference) {
return declaration;
}
}
switch (declaration) {
case ConstructorElementImpl():
return ConstructorMember(
declaration: declaration,
substitution: combined,
);
case MethodElementImpl():
return MethodMember(
declaration: declaration,
substitution: combined,
);
case PropertyAccessorElementImpl():
return PropertyAccessorMember(
declaration: declaration,
substitution: combined,
);
default:
throw UnimplementedError('(${declaration.runtimeType}) $element');
}
}
}
/// A parameter element defined in a parameterized type where the values of the
/// type parameters are known.
class FieldFormalParameterMember extends ParameterMember
implements FieldFormalParameterElementOrMember {
factory FieldFormalParameterMember({
required FieldFormalParameterElementImpl declaration,
required MapSubstitution substitution,
}) {
var freshTypeParameters = _SubstitutedTypeParameters(
declaration.typeParameters,
substitution,
);
return FieldFormalParameterMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
}
FieldFormalParameterMember._({
required FieldFormalParameterElementImpl super.declaration,
required super.substitution,
required super.typeParameters,
}) : super._();
@override
FieldFormalParameterElementImpl get declaration {
return _declaration as FieldFormalParameterElementImpl;
}
@override
FieldElementOrMember? get field {
var field = declaration.field;
if (field == null) {
return null;
}
return FieldMember(
declaration: field,
substitution: substitution,
);
}
@override
bool get hasDefaultValue => declaration.hasDefaultValue;
@override
bool get isCovariant => declaration.isCovariant;
}
/// A field element defined in a parameterized type where the values of the type
/// parameters are known.
class FieldMember extends VariableMember
implements FieldElementOrMember, FieldElement2OrMember {
/// Initialize a newly created element to represent a field, based on the
/// [declaration], with applied [substitution].
FieldMember({
required FieldElementImpl super.declaration,
required super.substitution,
});
@override
FieldElement2 get baseElement => _element2;
@override
List<Element2> get children2 => const [];
@override
ConstantInitializer? get constantInitializer2 {
return baseElement.constantInitializer2;
}
@override
FieldElementImpl get declaration => _declaration as FieldElementImpl;
@override
String get displayName => declaration.displayName;
@override
InstanceElement2 get enclosingElement2 => _element2.enclosingElement2;
@Deprecated('Use Element2.enclosingElement2 instead or '
'Fragment.enclosingFragment instead')
@override
Element get enclosingElement3 => declaration.enclosingElement3;
@override
FieldFragment get firstFragment => _element2.firstFragment;
@override
List<FieldFragment> get fragments {
return [
for (FieldFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
PropertyAccessorElementOrMember? get getter {
var baseGetter = declaration.getter;
if (baseGetter == null) {
return null;
}
return PropertyAccessorMember(
declaration: baseGetter,
substitution: substitution,
);
}
@override
GetterElement2OrMember? get getter2 {
var baseGetter = declaration.getter;
if (baseGetter == null) {
return null;
}
return GetterMember._(
declaration: baseGetter,
substitution: substitution,
typeParameters: baseGetter.typeParameters,
);
}
@override
bool get hasInitializer => declaration.hasInitializer;
@override
bool get isAbstract => declaration.isAbstract;
@override
bool get isAugmentation => declaration.isAugmentation;
@override
bool get isCovariant => declaration.isCovariant;
@override
bool get isEnumConstant => declaration.isEnumConstant;
@override
bool get isExternal => declaration.isExternal;
@override
bool get isPromotable => declaration.isPromotable;
@Deprecated('Use FieldElement2 instead')
@override
LibraryElement get library => _declaration.library!;
@override
LibraryElement2 get library2 => _element2.library2;
@override
String? get lookupName => _element2.lookupName;
@override
String get name => declaration.name;
@override
String? get name3 => _element2.name3;
@override
Element2 get nonSynthetic2 => _element2.nonSynthetic2;
@override
PropertyAccessorElementOrMember? get setter {
var baseSetter = declaration.setter;
if (baseSetter == null) {
return null;
}
return PropertyAccessorMember(
declaration: baseSetter,
substitution: substitution,
);
}
@override
SetterElement2OrMember? get setter2 {
var baseSetter = declaration.setter;
if (baseSetter == null) {
return null;
}
return SetterMember._(
declaration: baseSetter,
substitution: substitution,
typeParameters: baseSetter.typeParameters,
);
}
@override
Source? get source => _declaration.source;
@override
FieldElement2 get _element2 => declaration.asElement2;
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitFieldElement(this);
}
@override
String displayString2(
{bool multiline = false, bool preferTypeAlias = false}) {
return _element2.displayString2(
multiline: multiline, preferTypeAlias: preferTypeAlias);
}
@override
bool isAccessibleIn2(LibraryElement2 library) {
return _element2.isAccessibleIn2(library);
}
@override
Element2? thisOrAncestorMatching2(bool Function(Element2 e) predicate) {
return _element2.thisOrAncestorMatching2(predicate);
}
@override
E? thisOrAncestorOfType2<E extends Element2>() {
return _element2.thisOrAncestorOfType2<E>();
}
@override
void visitChildren2<T>(ElementVisitor2<T> visitor) {}
/// If the given [element]'s type is different when any type parameters from the
/// defining type's declaration are replaced with the actual type arguments
/// from the [definingType], create a field member representing the given
/// field. Return the member that was created, or the base field if no member
/// was created.
static FieldElementOrMember from(
FieldElementImpl element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return FieldMember(
declaration: element,
substitution: Substitution.fromInterfaceType(definingType),
);
}
static FieldElementOrMember from2(
FieldElementImpl element,
MapSubstitution substitution,
) {
if (substitution.map.isEmpty) {
return element;
}
return FieldMember(
declaration: element,
substitution: substitution,
);
}
}
/// A getter element defined in a parameterized type where the values of the
/// type parameters are known.
class GetterMember extends PropertyAccessorMember
implements GetterElement2OrMember {
GetterMember._({
required super.declaration,
required super.substitution,
required super.typeParameters,
}) : super._();
@override
GetterElementImpl get baseElement => _element2;
@override
SetterElement2OrMember? get correspondingSetter2 {
var setter = correspondingSetter;
if (setter is SetterMember) {
return setter;
}
return setter.asElement2 as SetterElementImpl?;
}
@override
GetterFragment get firstFragment => _element2.firstFragment;
@override
List<GetterFragment> get fragments {
return [
for (GetterFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
String? get lookupName => _element2.lookupName;
@override
Element2 get nonSynthetic2 {
if (!isSynthetic) {
return this;
} else if (variable3 case var variable?) {
return variable.nonSynthetic2;
}
throw StateError('Synthetic getter has no variable');
}
@override
PropertyInducingElement2OrMember? get variable3 =>
variable2.asElement2 as PropertyInducingElement2OrMember?;
@override
GetterElementImpl get _element2 {
return declaration.asElement2 as GetterElementImpl;
}
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitGetterElement(this);
}
static GetterElement2OrMember from(
GetterElementImpl element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return GetterMember._(
declaration: element.asElement,
substitution: Substitution.fromInterfaceType(definingType),
typeParameters: const [],
);
}
}
/// An element defined in a parameterized type where the values of the type
/// parameters are known.
abstract class Member
implements
// ignore:deprecated_member_use_from_same_package,analyzer_use_new_elements
Element,
ElementOrMember {
/// The element on which the parameterized element was created.
final ElementImpl _declaration;
/// The substitution for type parameters referenced in the base element.
final MapSubstitution substitution;
/// Initialize a newly created element to represent a member, based on the
/// [declaration], and applied [substitution].
Member({
required ElementImpl declaration,
required this.substitution,
}) : _declaration = declaration {
if (_declaration is Member) {
throw StateError('Members must be created from a declaration, but is '
'(${_declaration.runtimeType}) "$_declaration".');
}
}
Element2 get baseElement;
@Deprecated('Use Element2 instead')
@override
List<Element> get children => const [];
@override
AnalysisContext get context => _declaration.context;
@override
ElementImpl get declaration => _declaration;
@override
String get displayName => _declaration.displayName;
@override
String? get documentationComment => _declaration.documentationComment;
@Deprecated('Use Element2.enclosingElement2 instead or '
'Fragment.enclosingFragment instead')
@override
Element? get enclosingElement3 => _declaration.enclosingElement3;
@override
bool get hasAlwaysThrows => _declaration.hasAlwaysThrows;
@override
bool get hasDeprecated => _declaration.hasDeprecated;
@override
bool get hasDoNotStore => _declaration.hasDoNotStore;
@override
bool get hasDoNotSubmit => _declaration.hasDoNotSubmit;
@override
bool get hasFactory => _declaration.hasFactory;
@override
bool get hasImmutable => _declaration.hasImmutable;
@override
bool get hasInternal => _declaration.hasInternal;
@override
bool get hasIsTest => _declaration.hasIsTest;
@override
bool get hasIsTestGroup => _declaration.hasIsTestGroup;
@override
bool get hasJS => _declaration.hasJS;
@override
bool get hasLiteral => _declaration.hasLiteral;
@override
bool get hasMustBeConst => _declaration.hasMustBeConst;
@override
bool get hasMustBeOverridden => _declaration.hasMustBeOverridden;
@override
bool get hasMustCallSuper => _declaration.hasMustCallSuper;
@override
bool get hasNonVirtual => _declaration.hasNonVirtual;
@override
bool get hasOptionalTypeArgs => _declaration.hasOptionalTypeArgs;
@override
bool get hasOverride => _declaration.hasOverride;
@override
bool get hasProtected => _declaration.hasProtected;
@override
bool get hasRedeclare => _declaration.hasRedeclare;
@override
bool get hasReopen => _declaration.hasReopen;
@override
bool get hasRequired => _declaration.hasRequired;
@override
bool get hasSealed => _declaration.hasSealed;
@override
bool get hasUseResult => _declaration.hasUseResult;
@override
bool get hasVisibleForOverriding => _declaration.hasVisibleForOverriding;
@override
bool get hasVisibleForTemplate => _declaration.hasVisibleForTemplate;
@override
bool get hasVisibleForTesting => _declaration.hasVisibleForTesting;
@override
bool get hasVisibleOutsideTemplate => _declaration.hasVisibleOutsideTemplate;
@override
int get id => _declaration.id;
@override
bool get isPrivate => _declaration.isPrivate;
@override
bool get isPublic => _declaration.isPublic;
@override
bool get isSynthetic => _declaration.isSynthetic;
@override
ElementKind get kind => _declaration.kind;
@Deprecated('Use Element2 instead')
@override
LibraryElement? get library => _declaration.library;
@override
Source? get librarySource => _declaration.librarySource;
@override
ElementLocation get location => _declaration.location;
@override
List<ElementAnnotation> get metadata => _declaration.metadata;
MetadataImpl get metadata2 => declaration.metadata2;
@override
String? get name => _declaration.name;
@override
int get nameLength => _declaration.nameLength;
@override
int get nameOffset => _declaration.nameOffset;
@Deprecated('Use Element2.nonSynthetic instead')
@override
Element get nonSynthetic => _declaration.nonSynthetic;
@override
AnalysisSession? get session => _declaration.session;
@override
Version? get sinceSdkVersion => _declaration.sinceSdkVersion;
Element2 get _element2;
/// Append a textual representation of this element to the given [builder].
void appendTo(ElementDisplayStringBuilder builder);
@override
String getDisplayString({
@Deprecated('Only non-nullable by default mode is supported')
bool withNullability = true,
bool multiline = false,
bool preferTypeAlias = false,
}) {
var builder = ElementDisplayStringBuilder(
multiline: multiline,
preferTypeAlias: preferTypeAlias,
);
appendTo(builder);
return builder.toString();
}
@override
String getExtendedDisplayName(String? shortName) =>
_declaration.getExtendedDisplayName(shortName);
String getExtendedDisplayName2({String? shortName}) {
return _element2.getExtendedDisplayName2(
shortName: shortName,
);
}
@Deprecated('Use Element2 instead')
@override
bool isAccessibleIn(LibraryElement library) =>
_declaration.isAccessibleIn(library);
@Deprecated('Use Element2.thisOrAncestorMatching2() instead')
@override
E? thisOrAncestorMatching<E extends Element>(
bool Function(Element) predicate,
) {
return declaration.thisOrAncestorMatching(predicate);
}
@Deprecated('Use Element2.thisOrAncestorMatching2() instead')
@override
E? thisOrAncestorMatching3<E extends Element>(
bool Function(Element) predicate,
) {
return declaration.thisOrAncestorMatching3(predicate);
}
@Deprecated('Use Element2.thisOrAncestorOfType2() instead')
@override
E? thisOrAncestorOfType<E extends Element>() =>
declaration.thisOrAncestorOfType<E>();
@Deprecated('Use Element2.thisOrAncestorOfType2() instead')
@override
E? thisOrAncestorOfType3<E extends Element>() =>
declaration.thisOrAncestorOfType3<E>();
@override
String toString() {
return getDisplayString();
}
}
/// A method element defined in a parameterized type where the values of the
/// type parameters are known.
class MethodMember extends ExecutableMember
implements MethodElementOrMember, MethodElement2OrMember {
factory MethodMember({
required MethodElementImpl declaration,
required MapSubstitution substitution,
}) {
var freshTypeParameters = _SubstitutedTypeParameters(
declaration.typeParameters,
substitution,
);
return MethodMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
}
MethodMember._({
required MethodElementImpl super.declaration,
required super.substitution,
required super.typeParameters,
});
@override
MethodElementImpl2 get baseElement => _element2;
@override
MethodElementImpl get declaration => _declaration as MethodElementImpl;
@Deprecated('Use Element2.enclosingElement2 instead or '
'Fragment.enclosingFragment instead')
@override
Element get enclosingElement3 => declaration.enclosingElement3;
@override
MethodFragment get firstFragment => _element2.firstFragment;
@override
List<MethodFragment> get fragments {
return [
for (MethodFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
LibraryElement2 get library2 => _element2.library2;
@override
String? get lookupName => name3;
@override
String get name => declaration.name;
@override
String? get name3 => _element2.name3;
@override
Source get source => _declaration.source!;
@override
MethodElementImpl2 get _element2 => declaration.asElement2;
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitMethodElement(this);
}
/// If [definingType] has type parameters, returns [MethodMember] with
/// type substitutions. Otherwise returns [element] as is.
static MethodElement2OrMember from2(
MethodElementImpl2 element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return MethodMember(
declaration: element.asElement,
substitution: Substitution.fromInterfaceType(definingType),
);
}
}
/// A parameter element defined in a parameterized type where the values of the
/// type parameters are known.
class ParameterMember extends VariableMember
with
ParameterElementMixin,
FormalParameterElementMixin
implements
// ignore:deprecated_member_use_from_same_package,analyzer_use_new_elements
ParameterElement {
@override
final List<TypeParameterElementImpl> typeParameters;
factory ParameterMember({
required ParameterElementImpl declaration,
required MapSubstitution substitution,
}) {
var freshTypeParameters = _SubstitutedTypeParameters(
declaration.typeParameters,
substitution,
);
return ParameterMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
}
/// Initialize a newly created element to represent a parameter, based on the
/// [declaration], with applied [substitution].
ParameterMember._({
required ParameterElementImpl super.declaration,
required super.substitution,
required this.typeParameters,
});
@override
FormalParameterElement get baseElement => _element2;
@Deprecated('Use Element2 instead')
@override
List<Element> get children => parameters;
@override
List<Element2> get children2 {
return [
...typeParameters2,
...formalParameters,
];
}
@override
ConstantInitializer? get constantInitializer2 {
return baseElement.constantInitializer2;
}
@override
ParameterElementImpl get declaration => _declaration as ParameterElementImpl;
@override
String? get defaultValueCode => declaration.defaultValueCode;
@override
FormalParameterElementImpl get element => declaration.element;
@override
Element2? get enclosingElement2 => _element2.enclosingElement2;
@Deprecated('Use Element2.enclosingElement2 instead or '
'Fragment.enclosingFragment instead')
@override
Element? get enclosingElement3 => declaration.enclosingElement3;
@override
FormalParameterFragment get firstFragment => _element2.firstFragment;
@override
List<FormalParameterElementImpl> get formalParameters =>
_element2.formalParameters;
@override
List<FormalParameterFragment> get fragments {
return [
for (FormalParameterFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
bool get hasDefaultValue => declaration.hasDefaultValue;
@override
bool get isCovariant => declaration.isCovariant;
@override
bool get isInitializingFormal => declaration.isInitializingFormal;
@override
bool get isSuperFormal => declaration.isSuperFormal;
@override
LibraryElement2? get library2 => _element2.library2;
@override
String? get lookupName => _element2.lookupName;
@override
String get name => declaration.name;
@override
String? get name3 => _element2.name3;
@override
String get nameShared => name;
@override
Element2 get nonSynthetic2 => _element2;
@deprecated
@override
ParameterKind get parameterKind {
return declaration.parameterKind;
}
@override
List<ParameterElementMixin> get parameters {
var type = this.type;
if (type is FunctionTypeImpl) {
return type.parameters;
}
return const <ParameterElementMixin>[];
}
@override
Source? get source => _declaration.source;
@override
List<TypeParameterElement2> get typeParameters2 => _element2.typeParameters2;
@override
TypeImpl get typeShared => type;
@override
FormalParameterElementImpl get _element2 => declaration.asElement2;
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitFormalParameterElement(this);
}
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeFormalParameter(this);
}
@override
String displayString2(
{bool multiline = false, bool preferTypeAlias = false}) {
return _element2.displayString2(
multiline: multiline, preferTypeAlias: preferTypeAlias);
}
@override
bool isAccessibleIn2(LibraryElement2 library) =>
_element2.isAccessibleIn2(library);
@override
Element2? thisOrAncestorMatching2(bool Function(Element2 p1) predicate) {
return _element2.thisOrAncestorMatching2(predicate);
}
@override
E? thisOrAncestorOfType2<E extends Element2>() {
return _element2.thisOrAncestorOfType2();
}
@override
void visitChildren2<T>(ElementVisitor2<T> visitor) {
_element2.visitChildren2(visitor);
}
static ParameterElementMixin from(
ParameterElementMixin element, MapSubstitution substitution) {
ParameterElementImpl declaration;
var combined = substitution;
if (element is ParameterMember) {
var member = element;
declaration = member.declaration;
var map = <TypeParameterElement2, DartType>{
for (var MapEntry(:key, :value) in member.substitution.map.entries)
key: substitution.substituteType(value),
};
combined = Substitution.fromMap2(map);
} else {
declaration = element as ParameterElementImpl;
}
if (combined.map.isEmpty) {
return element;
}
return ParameterMember(
declaration: declaration,
substitution: combined,
);
}
}
/// A property accessor element defined in a parameterized type where the values
/// of the type parameters are known.
abstract class PropertyAccessorMember extends ExecutableMember
implements
PropertyAccessorElementOrMember,
PropertyAccessorElement2OrMember {
factory PropertyAccessorMember({
required PropertyAccessorElementImpl declaration,
required MapSubstitution substitution,
}) {
var freshTypeParameters = _SubstitutedTypeParameters(
declaration.typeParameters,
substitution,
);
if (declaration.isGetter) {
return GetterMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
} else {
return SetterMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
}
}
PropertyAccessorMember._({
required PropertyAccessorElementImpl super.declaration,
required super.substitution,
required super.typeParameters,
});
@override
PropertyAccessorElementOrMember? get correspondingGetter {
var baseGetter = declaration.correspondingGetter;
if (baseGetter == null) {
return null;
}
return PropertyAccessorMember(
declaration: baseGetter,
substitution: substitution,
);
}
@override
PropertyAccessorElementOrMember? get correspondingSetter {
var baseSetter = declaration.correspondingSetter;
if (baseSetter == null) {
return null;
}
return PropertyAccessorMember(
declaration: baseSetter,
substitution: substitution,
);
}
@override
PropertyAccessorElementImpl get declaration =>
_declaration as PropertyAccessorElementImpl;
@override
Element2 get enclosingElement2 {
return super.enclosingElement2!;
}
@Deprecated('Use Element2.enclosingElement2 instead or '
'Fragment.enclosingFragment instead')
@override
Element get enclosingElement3 => declaration.enclosingElement3;
@override
bool get isGetter => declaration.isGetter;
@override
bool get isSetter => declaration.isSetter;
@override
String get name => declaration.name;
@override
String? get name3 => _element2.name3;
@override
Source get source => _declaration.source!;
@override
PropertyInducingElementOrMember? get variable2 {
var variable = declaration.variable2;
switch (variable) {
case FieldElementImpl():
return FieldMember(
declaration: variable,
substitution: substitution,
);
default:
return variable;
}
}
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeExecutableElement(
this,
(isGetter ? 'get ' : 'set ') + displayName,
);
}
/// If the given [element]'s type is different when any type parameters from
/// the defining type's declaration are replaced with the actual type
/// arguments from the [definingType], create an accessor member representing
/// the given accessor. Return the member that was created, or the base
/// accessor if no member was created.
static PropertyAccessorElementOrMember? from(
PropertyAccessorElementImpl? element,
InterfaceType definingType,
) {
if (element == null || definingType.typeArguments.isEmpty) {
return element;
}
return PropertyAccessorMember(
declaration: element,
substitution: Substitution.fromInterfaceType(definingType),
);
}
}
/// A setter element defined in a parameterized type where the values of the
/// type parameters are known.
class SetterMember extends PropertyAccessorMember
implements SetterElement2OrMember {
SetterMember._({
required super.declaration,
required super.substitution,
required super.typeParameters,
}) : super._();
@override
SetterElementImpl get baseElement => _element2;
@override
GetterElement2OrMember? get correspondingGetter2 {
var getter = correspondingGetter;
if (getter is GetterMember) {
return getter;
}
return getter.asElement2 as GetterElementImpl?;
}
@override
SetterFragment get firstFragment => _element2.firstFragment;
@override
List<SetterFragment> get fragments {
return [
for (SetterFragment? fragment = firstFragment;
fragment != null;
fragment = fragment.nextFragment)
fragment,
];
}
@override
String? get lookupName => _element2.lookupName;
@override
Element2 get nonSynthetic2 {
if (!isSynthetic) {
return this;
} else if (variable3 case var variable?) {
return variable.nonSynthetic2;
}
throw StateError('Synthetic setter has no variable');
}
@override
PropertyInducingElement2OrMember? get variable3 =>
variable2.asElement2 as PropertyInducingElement2OrMember?;
@override
SetterElementImpl get _element2 {
return declaration.asElement2 as SetterElementImpl;
}
@override
T? accept2<T>(ElementVisitor2<T> visitor) {
return visitor.visitSetterElement(this);
}
static SetterElement2OrMember from(
SetterElementImpl element,
InterfaceType definingType,
) {
if (definingType.typeArguments.isEmpty) {
return element;
}
return SetterMember._(
declaration: element.asElement,
substitution: Substitution.fromInterfaceType(definingType),
typeParameters: const [],
);
}
}
class SuperFormalParameterMember extends ParameterMember
implements SuperFormalParameterElementOrMember {
factory SuperFormalParameterMember({
required SuperFormalParameterElementImpl declaration,
required MapSubstitution substitution,
}) {
var freshTypeParameters = _SubstitutedTypeParameters(
declaration.typeParameters,
substitution,
);
return SuperFormalParameterMember._(
declaration: declaration,
substitution: freshTypeParameters.substitution,
typeParameters: freshTypeParameters.elements,
);
}
SuperFormalParameterMember._({
required SuperFormalParameterElementImpl super.declaration,
required super.substitution,
required super.typeParameters,
}) : super._();
@override
SuperFormalParameterElementImpl get declaration {
return _declaration as SuperFormalParameterElementImpl;
}
@override
bool get hasDefaultValue => declaration.hasDefaultValue;
@override
bool get isCovariant => declaration.isCovariant;
@override
ParameterElementMixin? get superConstructorParameter {
var superConstructorParameter = declaration.superConstructorParameter;
if (superConstructorParameter == null) {
return null;
}
return ParameterMember.from(superConstructorParameter, substitution);
}
FormalParameterElement? get superConstructorParameter2 =>
superConstructorParameter?.asElement2;
}
/// A variable element defined in a parameterized type where the values of the
/// type parameters are known.
abstract class VariableMember extends Member
implements VariableElementOrMember {
TypeImpl? _type;
/// Initialize a newly created element to represent a variable, based on the
/// [declaration], with applied [substitution].
VariableMember({
required VariableElementImpl super.declaration,
required super.substitution,
});
@override
VariableElementImpl get declaration => _declaration as VariableElementImpl;
@override
bool get hasImplicitType => declaration.hasImplicitType;
@override
bool get isConst => declaration.isConst;
@override
bool get isConstantEvaluated => declaration.isConstantEvaluated;
@override
bool get isFinal => declaration.isFinal;
@override
bool get isLate => declaration.isLate;
@override
bool get isStatic => declaration.isStatic;
@override
TypeImpl get type {
if (_type != null) return _type!;
var result = declaration.type;
result = substitution.substituteType(result);
return _type = result;
}
@override
void appendTo(ElementDisplayStringBuilder builder) {
builder.writeVariableElement(this);
}
@override
DartObject? computeConstantValue() => declaration.computeConstantValue();
}
class _SubstitutedTypeParameters {
final List<TypeParameterElementImpl> elements;
final MapSubstitution substitution;
factory _SubstitutedTypeParameters(
List<TypeParameterElementImpl> elements,
MapSubstitution substitution,
) {
if (elements.isEmpty) {
return _SubstitutedTypeParameters._(const [], substitution);
}
// Create type formals with specialized bounds.
// For example `<U extends T>` where T comes from an outer scope.
var newElements = <TypeParameterElementImpl>[];
var newTypes = <TypeParameterType>[];
for (int i = 0; i < elements.length; i++) {
var element = elements[i];
var newElement = TypeParameterElementImpl.synthetic(element.name);
newElements.add(newElement);
newTypes.add(
newElement.instantiate(
nullabilitySuffix: NullabilitySuffix.none,
),
);
}
// Update bounds to reference new TypeParameterElement(s).
var substitution2 = Substitution.fromPairs(elements, newTypes);
for (int i = 0; i < newElements.length; i++) {
var element = elements[i];
var newElement = newElements[i];
var bound = element.bound;
if (bound != null) {
var newBound = substitution2.substituteType(bound);
newBound = substitution.substituteType(newBound);
newElement.bound = newBound;
}
}
if (substitution.map.isEmpty) {
return _SubstitutedTypeParameters._(newElements, substitution2);
}
return _SubstitutedTypeParameters._(
newElements,
Substitution.fromMap2({
...substitution.map,
...substitution2.map,
}),
);
}
_SubstitutedTypeParameters._(this.elements, this.substitution);
}