// Copyright (c) 2024, 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.

/// Defines the elements and fragments that are part of the element model.
///
/// The element model describes the semantic (as opposed to syntactic) structure
/// of Dart code. The syntactic structure of the code is modeled by the
/// [AST structure](../dart_ast_ast/dart_ast_ast-library.html).
///
/// The element model consists of three closely related kinds of objects:
/// elements (instances of a subclass of [Element2]), fragments (instances of a
/// subclass of [Fragment]) and types. This library defines the elements and
/// fragments; the types are defined in
/// [type.dart](../dart_element_type/dart_element_type-library.html).
///
/// Generally speaking, an element represents something that is declared in the
/// code, such as a class, method, or variable. Elements are organized in a tree
/// structure in which the children of an element are the elements that are
/// logically (and often syntactically) part of the declaration of the parent.
/// For example, the elements representing the methods and fields in a class are
/// children of the element representing the class.
///
/// Some elements, such as a [LocalVariableElement2] are declared by a single
/// declaration, but most elements can be declared by multiple declarations. A
/// fragment represents a single declaration when the corresponding element
/// can have multiple declarations. There is no fragment for an element that can
/// only have one declaration.
///
/// As with elements, fragments are organized in a tree structure. The two
/// structures parallel each other.
///
/// Every complete element structure is rooted by an instance of the class
/// [LibraryElement2]. A library element represents a single Dart library. Every
/// library is defined by one or more compilation units (the library and all of
/// its parts). The compilation units are represented by the class
/// [LibraryFragment].
///
/// The element model does not contain everything in the code, only those things
/// that are declared by the code. For example, it does not include any
/// representation of the statements in a method body, but if one of those
/// statements declares a local variable then the local variable will be
/// represented by an element.
///
/// @docImport 'package:analyzer/dart/element/element.dart';
/// @docImport 'package:analyzer/src/dart/element/member.dart';
library;

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart'
    show
        DirectiveUri,
        ElementAnnotation,
        ElementKind,
        LibraryLanguageVersion,
        NamespaceCombinator;
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart' show Name;
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:pub_semver/pub_semver.dart';

export 'package:analyzer/dart/element/element.dart'
    show
        DirectiveUri,
        DirectiveUriWithLibrary,
        DirectiveUriWithRelativeUri,
        DirectiveUriWithRelativeUriString,
        DirectiveUriWithSource,
        DirectiveUriWithUnit,
        ElementAnnotation,
        ElementKind,
        ElementLocation,
        HideElementCombinator,
        NamespaceCombinator,
        ShowElementCombinator;
export 'package:analyzer/src/dart/element/inheritance_manager3.dart' show Name;

/// An element or fragment that can have either annotations (metadata), a
/// documentation comment, or both associated with it.
abstract class Annotatable {
  /// The content of the documentation comment (including delimiters) for this
  /// element or fragment.
  ///
  /// If the receiver is an element that has fragments, the comment will be a
  /// concatenation of the comments from all of the fragments.
  ///
  /// Returns `null` if the receiver doesn't have documentation.
  String? get documentationComment;

  /// The metadata associated with the element or fragment.
  ///
  /// If the receiver is an element that has fragments, the list will include
  /// all of the metadata from all of the fragments.
  ///
  /// The list will be empty if the receiver does not have any metadata or if
  /// the library containing this element has not yet been fully resolved.
  Metadata get metadata2;
}

/// A pattern variable that is explicitly declared.
///
/// Clients may not extend, implement or mix-in this class.
abstract class BindPatternVariableElement2 implements PatternVariableElement2 {
  @override
  BindPatternVariableFragment get firstFragment;

  @override
  List<BindPatternVariableFragment> get fragments;
}

/// The portion of a [BindPatternVariableElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class BindPatternVariableFragment implements PatternVariableFragment {
  @override
  BindPatternVariableElement2 get element;

  @override
  BindPatternVariableFragment? get nextFragment;

  @override
  BindPatternVariableFragment? get previousFragment;
}

/// A class.
///
/// The class can be defined by either a class declaration (with a class body),
/// or a mixin application (without a class body).
///
/// Clients may not extend, implement or mix-in this class.
abstract class ClassElement2 implements InterfaceElement2 {
  @override
  ClassFragment get firstFragment;

  @override
  List<ClassFragment> get fragments;

  /// Whether the class or its superclass declares a non-final instance field.
  bool get hasNonFinalField;

  /// Whether the class is abstract.
  ///
  /// A class is abstract if it has an explicit `abstract` modifier. Note, that
  /// this definition of <i>abstract</i> is different from <i>has unimplemented
  /// members</i>.
  bool get isAbstract;

  /// Whether this class is a base class.
  ///
  /// A class is a base class if it has an explicit `base` modifier, or the
  /// class has a `base` induced modifier and [isSealed] is `true` as well.
  /// The base modifier allows the class to be extended but not implemented.
  bool get isBase;

  /// Whether the class can be instantiated.
  bool get isConstructable;

  /// Whether the class represents the class 'Enum' defined in `dart:core`.
  bool get isDartCoreEnum;

  /// Whether the class represents the class 'Object' defined in `dart:core`.
  bool get isDartCoreObject;

  /// Whether the class is exhaustive.
  ///
  /// A class is exhaustive if it has the property where, in a switch, if you
  /// cover all of the subtypes of this element, then the compiler knows that
  /// you have covered all possible instances of the type.
  bool get isExhaustive;

  /// Whether the class is a final class.
  ///
  /// A class is a final class if it has an explicit `final` modifier, or the
  /// class has a `final` induced modifier and [isSealed] is `true` as well.
  /// The final modifier prohibits this class from being extended, implemented,
  /// or mixed in.
  bool get isFinal;

  /// Whether the class is an interface class.
  ///
  /// A class is an interface class if it has an explicit `interface` modifier,
  /// or the class has an `interface` induced modifier and [isSealed] is `true`
  /// as well. The interface modifier allows the class to be implemented, but
  /// not extended or mixed in.
  bool get isInterface;

  /// Whether the class is a mixin application.
  ///
  /// A class is a mixin application if it was declared using the syntax
  /// `class A = B with C;`.
  bool get isMixinApplication;

  /// Whether the class is a mixin class.
  ///
  /// A class is a mixin class if it has an explicit `mixin` modifier.
  bool get isMixinClass;

  /// Whether the class is a sealed class.
  ///
  /// A class is a sealed class if it has an explicit `sealed` modifier.
  bool get isSealed;

  /// Whether the class can validly be used as a mixin when defining another
  /// class.
  ///
  /// For classes defined by a class declaration or a mixin application, the
  /// behavior of this method is defined by the Dart Language Specification
  /// in section 9:
  /// <blockquote>
  /// It is a compile-time error if a declared or derived mixin refers to super.
  /// It is a compile-time error if a declared or derived mixin explicitly
  /// declares a constructor. It is a compile-time error if a mixin is derived
  /// from a class whose superclass is not Object.
  /// </blockquote>
  bool get isValidMixin;

  /// Whether the class, assuming that it is within scope, can be extended by
  /// classes in the given [library].
  bool isExtendableIn2(LibraryElement2 library);

  /// Whether the class, assuming that it is within scope, can be implemented by
  /// classes, mixins, and enums in the given [library].
  bool isImplementableIn2(LibraryElement2 library);

  /// Whether the class, assuming that it is within scope, can be mixed-in by
  /// classes and enums in the given [library].
  bool isMixableIn2(LibraryElement2 library);
}

/// The portion of a [ClassElement2] contributed by a single declaration.
///
/// The fragment can be defined by either a class declaration (with a class
/// body), or a mixin application (without a class body).
///
/// Clients may not extend, implement or mix-in this class.
abstract class ClassFragment implements InterfaceFragment {
  @override
  ClassElement2 get element;

  @override
  ClassFragment? get nextFragment;

  @override
  ClassFragment? get previousFragment;
}

/// The initializer of a constant variable, or the default value for a formal
/// parameter.
abstract class ConstantInitializer {
  /// The expression of the initializer.
  ///
  /// For variables that have multiple fragments, this is the expression from
  /// the last fragment. For formal parameters, only the first fragment can
  /// have the default value.
  Expression get expression;

  /// The [VariableFragment] that has [expression].
  ///
  /// The offsets are inside the [LibraryFragment] that contains [fragment].
  VariableFragment get fragment;

  /// Returns the result of evaluating [expression], computes it if necessary.
  ///
  /// Returns `null` if the value could not be computed because of errors.
  DartObject? evaluate();
}

/// An element representing a constructor defined by a class, enum, or extension
/// type.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ConstructorElement2
    implements ExecutableElement2, HasSinceSdkVersion {
  @override
  ConstructorElement2 get baseElement;

  @override
  InterfaceElement2 get enclosingElement2;

  @override
  ConstructorFragment get firstFragment;

  @override
  List<ConstructorFragment> get fragments;

  /// Whether the constructor is a const constructor.
  bool get isConst;

  /// Whether the constructor can be used as a default constructor - unnamed,
  /// and has no required parameters.
  bool get isDefaultConstructor;

  /// Whether the constructor represents a factory constructor.
  bool get isFactory;

  /// Whether the constructor represents a generative constructor.
  bool get isGenerative;

  /// The name of this constructor.
  ///
  /// The name of the unnamed constructor is `new`.
  @override
  String? get name3;

  /// The constructor to which this constructor is redirecting.
  ///
  /// Returns `null` if this constructor does not redirect to another
  /// constructor or if the library containing this constructor has not yet been
  /// resolved.
  ConstructorElement2? get redirectedConstructor2;

  @override
  InterfaceType get returnType;

  /// The constructor of the superclass that this constructor invokes, or
  /// `null` if this constructor redirects to another constructor, or if the
  /// library containing this constructor has not yet been resolved.
  ConstructorElement2? get superConstructor2;
}

/// The portion of a [ConstructorElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ConstructorFragment implements ExecutableFragment {
  @override
  ConstructorElement2 get element;

  @override
  InstanceFragment? get enclosingFragment;

  @override
  String get name2;

  @override
  ConstructorFragment? get nextFragment;

  /// The offset of the constructor name.
  ///
  /// For a named constructor (e.g., `ClassName.foo()``), this is the offset to
  /// the part of the constructor name that follows the `.`. For an unnamed
  /// constructor (e.g., `ClassName();`), this is the offset of the class name
  /// that appears in the constructor declaration.
  ///
  /// For an implicit constructor, this is the offset of the class name in the
  /// class declaration.
  @override
  int get offset;

  /// The offset of the `.` before the name.
  ///
  /// It is `null` if the fragment is synthetic, or does not specify an
  /// explicit name, even if [name2] is `new` in this case.
  int? get periodOffset;

  @override
  ConstructorFragment? get previousFragment;

  /// The specified name of the type (e.g. class).
  ///
  /// In valid code it is the name of the [enclosingFragment], however it
  /// could be anything in invalid code, e.g. `class A { A2.named(); }`.
  ///
  /// If the fragment is synthetic, the type name is the name of the
  /// enclosing type, which itself can be `null` if its name token is
  /// synthetic.
  String? get typeName;

  /// The offset of the type (e.g. class) name.
  ///
  /// It is `null` if the fragment is synthetic.
  int? get typeNameOffset;
}

/// The base class for all of the elements in the element model.
///
/// Generally speaking, the element model is a semantic model of the program
/// that represents things that are declared with a name and hence can be
/// referenced elsewhere in the code. There are two exceptions to the general
/// case.
///
/// First, there are elements in the element model that are created for the
/// convenience of various kinds of analysis but that don't have any
/// corresponding declaration within the source code. Such elements are marked
/// as being <i>synthetic</i>. Examples of synthetic elements include
/// - default constructors in classes that don't define any explicit
///   constructors,
/// - getters and setters that are induced by explicit field declarations,
/// - fields that are induced by explicit declarations of getters and setters,
///   and
/// - functions representing the initialization expression for a variable.
///
/// Second, there are elements in the element model that don't have, or are not
/// required to have a name. These correspond to things like unnamed functions
/// or extensions. They exist in order to more accurately represent the semantic
/// structure of the program.
///
/// Clients may not extend, implement or mix-in this class.
abstract class Element2 {
  /// The non-[Member] version of this element.
  ///
  /// If the receiver is a view on an element, such as a method from an
  /// interface type with substituted type parameters, this getter will return
  /// the corresponding element from the class, without any substitutions.
  ///
  /// If the receiver is already a non-[Member] element (or a synthetic element,
  /// such as a synthetic property accessor), this getter will return the
  /// receiver.
  Element2 get baseElement;

  /// The children of this element.
  ///
  /// There is no guarantee of the order in which the children will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<Element2> get children2;

  /// The display name of this element, or an empty string if the element does
  /// not have a name.
  ///
  /// In most cases the name and the display name are the same. They differ in
  /// cases such as setters where the `name` of some setter (`set s(x)`) is `s=`
  /// but the `displayName` is `s`.
  String get displayName;

  /// The element that either physically or logically encloses this element.
  ///
  /// Returns `null` if this element is a library because libraries are the
  /// top-level elements in the model.
  Element2? get enclosingElement2;

  /// The first fragment in the chain of fragments that are merged to make this
  /// element.
  ///
  /// The other fragments in the chain can be accessed using successive
  /// invocations of [Fragment.nextFragment].
  Fragment get firstFragment;

  /// The fragments this element consists of.
  List<Fragment> get fragments;

  /// The unique integer identifier of this element.
  int get id;

  /// Whether this element is private.
  ///
  /// Private elements are visible only within the library in which they are
  /// declared.
  bool get isPrivate;

  /// Whether this element is public.
  ///
  /// Public elements are visible within any library that imports the library
  /// in which they are declared.
  bool get isPublic;

  /// Whether this element is synthetic.
  ///
  /// A synthetic element is an element that is not represented in the source
  /// code explicitly, but is implied by the source code, such as the default
  /// constructor for a class that does not explicitly define any constructors.
  bool get isSynthetic;

  /// The kind of this element.
  ElementKind get kind;

  /// Library that contains this element.
  ///
  /// This will be the element itself if it's a library element. This will be
  /// `null` if this element is a [MultiplyDefinedElement2] that isn't contained
  /// in a single library.
  LibraryElement2? get library2;

  /// The name to use for lookup in maps.
  ///
  /// It is usually the same as [name3], with a few special cases.
  ///
  /// Just like [name3], it can be `null` if the element does not have
  /// a name, for example an unnamed extension, or because of parser recovery.
  ///
  /// For a [SetterElement] the result has `=` at the end.
  ///
  /// For an unary operator `-` the result is `unary-`.
  /// For a binary operator `-` the result is just `-`.
  String? get lookupName;

  /// The name of this element.
  ///
  /// Returns `null` if this element doesn't have a name.
  ///
  /// See [Fragment.name2] for details.
  String? get name3;

  /// The non-synthetic element that caused this element to be created.
  ///
  /// If this element is not synthetic, then the element itself is returned.
  ///
  /// If this element is synthetic, then the corresponding non-synthetic
  /// element is returned. For example, for a synthetic getter of a
  /// non-synthetic field the field is returned; for a synthetic constructor
  /// the enclosing class is returned.
  Element2 get nonSynthetic2;

  /// The analysis session in which this element is defined.
  AnalysisSession? get session;

  /// Uses the given [visitor] to visit this element.
  ///
  /// Returns the value returned by the visitor as a result of visiting this
  /// element.
  T? accept2<T>(ElementVisitor2<T> visitor);

  /// The presentation of this element as it should appear when presented to
  /// users.
  ///
  /// If [multiline] is `true`, then the string may be wrapped over multiple
  /// lines with newlines to improve formatting. For example, function
  /// signatures may be formatted as if they had trailing commas.
  ///
  /// If [preferTypeAlias] is `true` and the element represents a type defined
  /// by a type alias, then the name of the type alias will be used in the
  /// returned string rather than the name of the type being aliased.
  ///
  /// Clients should not depend on the content of the returned value as it will
  /// be changed if doing so would improve the UX.
  String displayString2({bool multiline = false, bool preferTypeAlias = false});

  /// Returns a display name for the given element that includes the path to the
  /// compilation unit in which the type is defined. If [shortName] is `null`
  /// then [displayName] will be used as the name of this element. Otherwise
  /// the provided name will be used.
  String getExtendedDisplayName2({String? shortName});

  /// Whether the element, assuming that it is within scope, is accessible to
  /// code in the given [library].
  ///
  /// This is defined by the Dart Language Specification in section 6.2:
  /// <blockquote>
  /// A declaration <i>m</i> is accessible to a library <i>L</i> if <i>m</i> is
  /// declared in <i>L</i> or if <i>m</i> is public.
  /// </blockquote>
  bool isAccessibleIn2(LibraryElement2 library);

  /// Returns either this element or the most immediate ancestor of this element
  /// for which the [predicate] returns `true`.
  ///
  /// Returns `null` if there is no such element.
  Element2? thisOrAncestorMatching2(
    bool Function(Element2) predicate,
  );

  /// Returns either this element or the most immediate ancestor of this element
  /// that has the given type.
  ///
  /// Returns `null` if there is no such element.
  E? thisOrAncestorOfType2<E extends Element2>();

  /// Uses the given [visitor] to visit all of the children of this element.
  /// There is no guarantee of the order in which the children will be visited.
  void visitChildren2<T>(ElementVisitor2<T> visitor);
}

/// A directive within a library fragment.
///
/// Clients may not extend, implement or mix-in this class.
sealed class ElementDirective implements Annotatable {
  /// The library fragment that contains this object.
  LibraryFragment get libraryFragment;

  /// The interpretation of the URI specified in the directive.
  DirectiveUri get uri;
}

/// An object that can be used to visit an element structure.
///
/// Clients may not extend, implement or mix-in this class. There are classes
/// that implement this interface that provide useful default behaviors in
/// `package:analyzer/dart/element/visitor.dart`. A couple of the most useful
/// include
/// * SimpleElementVisitor which implements every visit method by doing nothing,
/// * RecursiveElementVisitor which will cause every node in a structure to be
///   visited, and
/// * ThrowingElementVisitor which implements every visit method by throwing an
///   exception.
abstract class ElementVisitor2<R> {
  R? visitClassElement(ClassElement2 element);

  R? visitConstructorElement(ConstructorElement2 element);

  R? visitEnumElement(EnumElement2 element);

  R? visitExtensionElement(ExtensionElement2 element);

  R? visitExtensionTypeElement(ExtensionTypeElement2 element);

  R? visitFieldElement(FieldElement2 element);

  R? visitFieldFormalParameterElement(FieldFormalParameterElement2 element);

  R? visitFormalParameterElement(FormalParameterElement element);

  R? visitGenericFunctionTypeElement(GenericFunctionTypeElement2 element);

  R? visitGetterElement(GetterElement element);

  R? visitLabelElement(LabelElement2 element);

  R? visitLibraryElement(LibraryElement2 element);

  R? visitLocalFunctionElement(LocalFunctionElement element);

  R? visitLocalVariableElement(LocalVariableElement2 element);

  R? visitMethodElement(MethodElement2 element);

  R? visitMixinElement(MixinElement2 element);

  R? visitMultiplyDefinedElement(MultiplyDefinedElement2 element);

  R? visitPrefixElement(PrefixElement2 element);

  R? visitSetterElement(SetterElement element);

  R? visitSuperFormalParameterElement(SuperFormalParameterElement2 element);

  R? visitTopLevelFunctionElement(TopLevelFunctionElement element);

  R? visitTopLevelVariableElement(TopLevelVariableElement2 element);

  R? visitTypeAliasElement(TypeAliasElement2 element);

  R? visitTypeParameterElement(TypeParameterElement2 element);
}

/// An element that represents an enum.
///
/// Clients may not extend, implement or mix-in this class.
abstract class EnumElement2 implements InterfaceElement2 {
  /// The constants defined by the enum.
  List<FieldElement2> get constants2;

  @override
  EnumFragment get firstFragment;

  @override
  List<EnumFragment> get fragments;
}

/// The portion of an [EnumElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class EnumFragment implements InterfaceFragment {
  /// The constants defined by this fragment of the enum.
  List<FieldElement2> get constants2;

  @override
  EnumElement2 get element;

  @override
  EnumFragment? get nextFragment;

  @override
  EnumFragment? get previousFragment;
}

/// An element representing an executable object, including functions, methods,
/// constructors, getters, and setters.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ExecutableElement2 implements FunctionTypedElement2 {
  @override
  ExecutableElement2 get baseElement;

  @override
  ExecutableFragment get firstFragment;

  @override
  List<ExecutableFragment> get fragments;

  /// Whether the executable element did not have an explicit return type
  /// specified for it in the original source.
  bool get hasImplicitReturnType;

  /// Whether the executable element is abstract.
  ///
  /// Executable elements are abstract if they are not external, and have no
  /// body.
  bool get isAbstract;

  /// Whether the executable element is an extension type member.
  bool get isExtensionTypeMember;

  /// Whether the executable element is external.
  ///
  /// Executable elements are external if they are explicitly marked as such
  /// using the 'external' keyword.
  bool get isExternal;

  /// Whether the element is a static element.
  ///
  /// A static element is an element that is not associated with a particular
  /// instance, but rather with an entire library or class.
  bool get isStatic;
}

/// The portion of an [ExecutableElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ExecutableFragment implements FunctionTypedFragment {
  @override
  ExecutableElement2 get element;

  /// Whether the body is marked as being asynchronous.
  bool get isAsynchronous;

  /// Whether the element is an augmentation.
  ///
  /// Executable elements are augmentations if they are explicitly marked as
  /// such using the 'augment' modifier.
  bool get isAugmentation;

  /// Whether the body is marked as being a generator.
  bool get isGenerator;

  /// Whether the body is marked as being synchronous.
  bool get isSynchronous;

  /// Whether this fragment is synthetic.
  ///
  /// A synthetic fragment is a fragment that is not represented in the source
  /// code explicitly, but is implied by the source code, such as the default
  /// constructor for a class that does not explicitly define any constructors.
  bool get isSynthetic;

  @override
  LibraryFragment get libraryFragment;

  @override
  ExecutableFragment? get nextFragment;

  @override
  ExecutableFragment? get previousFragment;
}

/// An extension.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ExtensionElement2 implements InstanceElement2 {
  /// The type that is extended by this extension.
  DartType get extendedType;

  @override
  ExtensionFragment get firstFragment;

  @override
  List<ExtensionFragment> get fragments;
}

/// The portion of an [ExtensionElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class ExtensionFragment implements InstanceFragment {
  @override
  ExtensionElement2 get element;

  @override
  ExtensionFragment? get nextFragment;

  /// The offset of the extension name.
  ///
  /// If the extension has no name, this is the offset of the `extension`
  /// keyword.
  @override
  int get offset;

  @override
  ExtensionFragment? get previousFragment;
}

/// An extension type.
///
/// Clients may not extend, implement or mix-in this class.
abstract class ExtensionTypeElement2 implements InterfaceElement2 {
  @override
  ExtensionTypeFragment get firstFragment;

  @override
  List<ExtensionTypeFragment> get fragments;

  /// The primary constructor of this extension.
  ConstructorElement2 get primaryConstructor2;

  /// The representation of this extension.
  FieldElement2 get representation2;

  /// The extension type erasure, obtained by recursively replacing every
  /// subterm which is an extension type by the corresponding representation
  /// type.
  DartType get typeErasure;
}

/// The portion of an [ExtensionTypeElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class ExtensionTypeFragment implements InterfaceFragment {
  @override
  ExtensionTypeElement2 get element;

  @override
  ExtensionTypeFragment? get nextFragment;

  @override
  ExtensionTypeFragment? get previousFragment;

  ConstructorFragment get primaryConstructor2;

  /// The representation of this extension.
  FieldFragment get representation2;
}

/// A field defined within a class, enum, extension, or mixin.
///
/// Clients may not extend, implement or mix-in this class.
abstract class FieldElement2 implements PropertyInducingElement2 {
  @override
  FieldElement2 get baseElement;

  @override
  InstanceElement2 get enclosingElement2;

  @override
  FieldFragment get firstFragment;

  @override
  List<FieldFragment> get fragments;

  /// Whether the field is abstract.
  ///
  /// Executable fields are abstract if they are declared with the `abstract`
  /// keyword.
  bool get isAbstract;

  /// Whether the field was explicitly marked as being covariant.
  bool get isCovariant;

  /// Whether the element is an enum constant.
  bool get isEnumConstant;

  /// Whether the field was explicitly marked as being external.
  bool get isExternal;

  /// Whether the field can be type promoted.
  bool get isPromotable;
}

/// A field formal parameter defined within a constructor element.
///
/// Clients may not extend, implement or mix-in this class.
abstract class FieldFormalParameterElement2 implements FormalParameterElement {
  /// The field element associated with this field formal parameter.
  ///
  /// Returns `null` if the parameter references a field that doesn't exist.
  FieldElement2? get field2;

  @override
  FieldFormalParameterFragment get firstFragment;

  @override
  List<FieldFormalParameterFragment> get fragments;
}

/// The portion of a [FieldFormalParameterElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class FieldFormalParameterFragment implements FormalParameterFragment {
  @override
  FieldFormalParameterElement2 get element;

  @override
  FieldFormalParameterFragment? get nextFragment;

  @override
  FieldFormalParameterFragment? get previousFragment;
}

/// The portion of a [FieldElement2] contributed by a single declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class FieldFragment implements PropertyInducingFragment {
  @override
  FieldElement2 get element;

  @override
  FieldFragment? get nextFragment;

  /// The offset of the field name.
  ///
  /// If the field declaration is implicit, this is the offset of the name of
  /// the containing element (e.g., for the `values` field of an enum, this is
  /// the offset of the enum name).
  @override
  int get offset;

  @override
  FieldFragment? get previousFragment;
}

/// A formal parameter defined by an executable element.
///
/// Clients may not extend, implement or mix-in this class.
abstract class FormalParameterElement
    implements
        PromotableElement2,
        Annotatable,
        HasSinceSdkVersion,
        LocalElement2 {
  @override
  FormalParameterElement get baseElement;

  /// The code of the default value.
  ///
  /// Returns `null` if no default value.
  String? get defaultValueCode;

  @override
  FormalParameterFragment get firstFragment;

  /// The formal parameters defined by this formal parameter.
  ///
  /// A parameter will only define other parameters if it is a function typed
  /// formal parameter.
  List<FormalParameterElement> get formalParameters;

  @override
  List<FormalParameterFragment> get fragments;

  /// Whether the parameter has a default value.
  bool get hasDefaultValue;

  /// Whether the parameter is covariant, meaning it is allowed to have a
  /// narrower type in an override.
  bool get isCovariant;

  /// Whether the parameter is an initializing formal parameter.
  bool get isInitializingFormal;

  /// Whether the parameter is a named parameter.
  ///
  /// Named parameters that are annotated with the `@required` annotation are
  /// considered optional. Named parameters that are annotated with the
  /// `required` syntax are considered required.
  bool get isNamed;

  /// Whether the parameter is an optional parameter.
  ///
  /// Optional parameters can either be positional or named. Named parameters
  /// that are annotated with the `@required` annotation are considered
  /// optional. Named parameters that are annotated with the `required` syntax
  /// are considered required.
  bool get isOptional;

  /// Whether the parameter is both an optional and named parameter.
  ///
  /// Named parameters that are annotated with the `@required` annotation are
  /// considered optional. Named parameters that are annotated with the
  /// `required` syntax are considered required.
  bool get isOptionalNamed;

  /// Whether the parameter is both an optional and positional parameter.
  bool get isOptionalPositional;

  /// Whether the parameter is a positional parameter.
  ///
  /// Positional parameters can either be required or optional.
  bool get isPositional;

  /// Whether the parameter is either a required positional parameter, or a
  /// named parameter with the `required` keyword.
  ///
  /// Note: the presence or absence of the `@required` annotation does not
  /// change the meaning of this getter. The parameter `{@required int x}`
  /// will return `false` and the parameter `{@required required int x}`
  /// will return `true`.
  bool get isRequired;

  /// Whether the parameter is both a required and named parameter.
  ///
  /// Named parameters that are annotated with the `@required` annotation are
  /// considered optional. Named parameters that are annotated with the
  /// `required` syntax are considered required.
  bool get isRequiredNamed;

  /// Whether the parameter is both a required and positional parameter.
  bool get isRequiredPositional;

  /// Whether the parameter is a super formal parameter.
  bool get isSuperFormal;

  /// The type parameters defined by this parameter.
  ///
  /// A parameter will only define type parameters if it is a function typed
  /// parameter.
  List<TypeParameterElement2> get typeParameters2;

  /// Appends the type, name and possibly the default value of this parameter
  /// to the given [buffer].
  void appendToWithoutDelimiters2(StringBuffer buffer);
}

/// The portion of a [FormalParameterElement] contributed by a single
/// declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class FormalParameterFragment
    implements PromotableFragment, Annotatable, LocalFragment {
  @override
  FormalParameterElement get element;

  @override
  FormalParameterFragment? get nextFragment;

  /// The offset of the parameter name.
  ///
  /// If the parameter is implicit (because it's the parameter of an implicit
  /// setter that's induced by a field or top level variable declaration), this
  /// is the offset of the field or top level variable name.
  @override
  int get offset;

  @override
  FormalParameterFragment? get previousFragment;
}

/// A fragment that wholly or partially defines an element.
///
/// When an element is defined by one or more fragments, those fragments form an
/// augmentation chain. This is represented in the element model as a
/// doubly-linked list.
///
/// In valid code the first fragment is the base declaration and all of the
/// other fragments are augmentations. This can be violated in the element model
/// in the case of invalid code, such as when an augmentation is declared even
/// though there is no base declaration.
abstract class Fragment {
  /// The children of this fragment.
  ///
  /// There is no guarantee of the order in which the children will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<Fragment> get children3;

  /// The element composed from this fragment and possibly other fragments.
  Element2 get element;

  /// The fragment that either physically or logically encloses this fragment.
  ///
  /// Returns `null` if this fragment is the root fragment of a library because
  /// there are no fragments above the root fragment of a library.
  Fragment? get enclosingFragment;

  /// The library fragment that contains this fragment.
  ///
  /// This will be the fragment itself if it is a library fragment.
  LibraryFragment? get libraryFragment;

  /// The name of the fragment.
  ///
  /// Never empty.
  ///
  /// If a fragment, e.g. an [ExtensionFragment], does not have a name,
  /// then the name is `null`.
  ///
  /// For an unnamed [ConstructorFragment] the name is `new`, but [nameOffset2]
  /// is `null`. If there is an explicit `ClassName.new`, the name is also
  /// `new`, and [nameOffset2] is not `null`. For a synthetic default unnamed
  /// [ConstructorElement2] there is always a synthetic [ConstructorFragment]
  /// with the name `new`, and [nameOffset2] is `null`.
  ///
  /// If the fragment declaration node does not have the name specified, and
  /// the parser inserted a synthetic token, then the name is `null`, and
  /// [nameOffset2] is `null`.
  ///
  /// For a synthetic [GetterFragment] or [SetterFragment] the name is the
  /// name of the corresponding non-synthetic [PropertyInducingFragment],
  /// which is usually not `null`, but could be. And `nameOffset2` is `null`
  /// for such synthetic fragments.
  ///
  /// For a [SetterFragment] this is the identifier, without `=` at the end.
  ///
  /// For both unary and binary `-` operator this is `-`.
  String? get name2;

  /// The offset of the [name2] of this element.
  ///
  /// If a fragment, e.g. an [ExtensionFragment], does not have a name,
  /// then the name offset is `null`.
  ///
  /// If the fragment declaration node does not have the name specified, and
  /// the parser inserted a synthetic token, then the name is `null`, and
  /// the name offset is `null`.
  ///
  /// For a synthetic fragment, e.g. [ConstructorFragment] the name offset
  /// is `null`.
  int? get nameOffset2;

  /// The next fragment in the augmentation chain.
  ///
  /// Returns `null` if this is the last fragment in the chain.
  Fragment? get nextFragment;

  /// A canonical offset to the fragment within the source file.
  ///
  /// If the fragment has a name, this is equal to [nameOffset2]. Otherwise it
  /// is the offset of some character within the fragment; see subclasses for
  /// more information.
  ///
  /// If the fragment is of a kind that would normally have a name, but there is
  /// no name due to error recovery, then the exact offset is unspecified, but
  /// is guaranteed to be within the span of the tokens that constitute the
  /// fragment's declaration.
  int get offset;

  /// The previous fragment in the augmentation chain.
  ///
  /// Returns `null` if this is the first fragment in the chain.
  Fragment? get previousFragment;
}

/// An element that has a [FunctionType] as its [type].
///
/// This also provides convenient access to the parameters and return type.
///
/// Clients may not extend, implement or mix-in this class.
abstract class FunctionTypedElement2 implements TypeParameterizedElement2 {
  @override
  FunctionTypedFragment get firstFragment;

  /// The formal parameters defined by this element.
  List<FormalParameterElement> get formalParameters;

  @override
  List<FunctionTypedFragment> get fragments;

  /// The return type defined by this element.
  DartType get returnType;

  /// The type defined by this element.
  FunctionType get type;
}

/// The portion of a [FunctionTypedElement2] contributed by a single declaration.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class FunctionTypedFragment implements TypeParameterizedFragment {
  @override
  FunctionTypedElement2 get element;

  /// The formal parameters defined by this fragment.
  List<FormalParameterFragment> get formalParameters;

  @override
  FunctionTypedFragment? get nextFragment;

  @override
  FunctionTypedFragment? get previousFragment;
}

/// The pseudo-declaration that defines a generic function type.
///
/// Clients may not extend, implement, or mix-in this class.
abstract class GenericFunctionTypeElement2 implements FunctionTypedElement2 {
  @override
  GenericFunctionTypeFragment get firstFragment;

  @override
  List<GenericFunctionTypeFragment> get fragments;
}

/// The portion of a [GenericFunctionTypeElement2] coming from a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class GenericFunctionTypeFragment implements FunctionTypedFragment {
  @override
  GenericFunctionTypeElement2 get element;

  @override
  GenericFunctionTypeFragment? get nextFragment;

  /// The offset of the generic function type.
  ///
  /// Generic function types are not named, so the offset is the offset of the
  /// first token in the generic function type.
  @override
  int get offset;

  @override
  GenericFunctionTypeFragment? get previousFragment;
}

/// A getter.
///
/// Getters can either be defined explicitly or they can be induced by either a
/// top-level variable or a field. Induced getters are synthetic.
///
/// Clients may not extend, implement or mix-in this class.
abstract class GetterElement implements PropertyAccessorElement2 {
  @override
  GetterElement get baseElement;

  /// The setter that corresponds to (has the same name as) this getter, or
  /// `null` if there is no corresponding setter.
  SetterElement? get correspondingSetter2;

  @override
  GetterFragment get firstFragment;

  @override
  List<GetterFragment> get fragments;
}

/// The portion of a [GetterElement] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class GetterFragment implements PropertyAccessorFragment {
  @override
  GetterElement get element;

  @override
  GetterFragment? get nextFragment;

  /// The offset of the getter name.
  ///
  /// If the getter is implicit (because it's induced by a field or top level
  /// variable declaration), this is the offset of the field or top level
  /// variable name.
  @override
  int get offset;

  @override
  GetterFragment? get previousFragment;
}

/// The interface that is implemented by elements that can have `@Since()`
/// annotation.
abstract class HasSinceSdkVersion {
  /// The version where the associated SDK API was added.
  ///
  /// A `@Since()` annotation can be applied to a library declaration,
  /// any public declaration in a library, or in a class, or to an optional
  /// parameter, etc.
  ///
  /// The returned version is "effective", so that if a library is annotated
  /// then all elements of the library inherit it; or if a class is annotated
  /// then all members and constructors of the class inherit it.
  ///
  /// If multiple `@Since()` annotations apply to the same element, the latest
  /// version takes precedence.
  ///
  /// Returns `null` if the element is not declared in the SDK, or doesn't have
  /// a `@Since()` annotation applied to it.
  Version? get sinceSdkVersion;
}

/// An element whose instance members can refer to `this`.
///
/// Clients may not extend, implement or mix-in this class.
abstract class InstanceElement2
    implements
        TypeDefiningElement2,
        TypeParameterizedElement2,
        HasSinceSdkVersion {
  @override
  LibraryElement2 get enclosingElement2;

  /// The fields declared in this element.
  List<FieldElement2> get fields2;

  @override
  InstanceFragment get firstFragment;

  @override
  List<InstanceFragment> get fragments;

  /// The getters declared in this element.
  List<GetterElement> get getters2;

  /// The methods declared in this element.
  List<MethodElement2> get methods2;

  /// The setters declared in this element.
  List<SetterElement> get setters2;

  /// The type of a `this` expression.
  DartType get thisType;

  /// Returns the field from [fields2] that has the given [name].
  FieldElement2? getField2(String name);

  /// Returns the getter from [getters2] that has the given [name].
  GetterElement? getGetter2(String name);

  /// Returns the method from [methods2] that has the given [name].
  MethodElement2? getMethod2(String name);

  /// Returns the setter from [setters2] that has the given [name].
  SetterElement? getSetter2(String name);

  /// Returns the element representing the getter that results from looking up
  /// the given [name] in this class with respect to the given [library],
  /// or `null` if the look up fails.
  ///
  /// The behavior of this method is defined by the Dart Language Specification
  /// in section 17.18 Lookup.
  GetterElement? lookUpGetter2({
    required String name,
    required LibraryElement2 library,
  });

  /// Returns the element representing the method that results from looking up
  /// the given [name] in this class with respect to the given [library],
  /// or `null` if the look up fails.
  ///
  /// The behavior of this method is defined by the Dart Language Specification
  /// in section 17.18 Lookup.
  MethodElement2? lookUpMethod2({
    required String name,
    required LibraryElement2 library,
  });

  /// Returns the element representing the setter that results from looking up
  /// the given [name] in this class with respect to the given [library],
  /// or `null` if the look up fails.
  ///
  /// The behavior of this method is defined by the Dart Language Specification
  /// in section 17.18 Lookup.
  SetterElement? lookUpSetter2({
    required String name,
    required LibraryElement2 library,
  });
}

/// The portion of an [InstanceElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class InstanceFragment
    implements TypeDefiningFragment, TypeParameterizedFragment {
  @override
  InstanceElement2 get element;

  @override
  LibraryFragment? get enclosingFragment;

  /// The fields declared in this fragment.
  List<FieldFragment> get fields2;

  /// The getters declared in this fragment.
  List<GetterFragment> get getters;

  /// Whether the fragment is an augmentation.
  ///
  /// If `true`, the declaration has the explicit `augment` modifier.
  bool get isAugmentation;

  @override
  LibraryFragment get libraryFragment;

  /// The methods declared in this fragment.
  List<MethodFragment> get methods2;

  @override
  InstanceFragment? get nextFragment;

  @override
  InstanceFragment? get previousFragment;

  /// The setters declared in this fragment.
  List<SetterFragment> get setters;
}

/// An element that defines an [InterfaceType].
///
/// Clients may not extend, implement or mix-in this class.
abstract class InterfaceElement2 implements InstanceElement2 {
  /// All the supertypes defined for this element and its supertypes.
  ///
  /// This includes superclasses, mixins, interfaces, and superclass
  /// constraints.
  List<InterfaceType> get allSupertypes;

  /// The constructors defined for this element.
  ///
  /// The list is empty for [MixinElement2].
  List<ConstructorElement2> get constructors2;

  @override
  InterfaceFragment get firstFragment;

  @override
  List<InterfaceFragment> get fragments;

  /// Returns a map of all concrete members that this type inherits from
  /// superclasses and mixins, keyed by the member's [Name].
  ///
  /// Members declared in this type have no effect on the map. This means that:
  /// - If this type contains a member named `foo`, but none of its superclasses
  ///   or mixins contains a member named `foo`, then there will be no entry for
  ///   `foo` in the map.
  /// - If this type contains a member named `foo`, and one of its superclasses
  ///   or mixins contains a member named `foo`, then there will be an entry for
  ///   `foo` in this map, pointing to the declaration inherited from the
  ///   superclass or mixin.
  ///
  /// This method is potentially expensive, since it needs to consider all
  /// possible inherited names. If you only need to look up a certain specific
  /// name (or names), use [getInheritedConcreteMember] instead.
  Map<Name, ExecutableElement2> get inheritedConcreteMembers;

  /// Returns a map of all members that this type inherits from supertypes via
  /// `extends`, `with`, `implements`, or `on` clauses, keyed by the member's
  /// [Name].
  ///
  /// Members declared in this type have no effect on the map. This means that:
  /// - If this type contains a member named `foo`, but none of its supertypes
  ///   contains a member named `foo`, then there will be no entry for `foo` in
  ///   the map.
  /// - If this type contains a member named `foo`, and one of its supertypes
  ///   contains a member named `foo`, then there will be an entry for `foo` in
  ///   this map, pointing to the declaration inherited from the supertype.
  ///
  /// This method is potentially expensive, since it needs to consider all
  /// possible inherited names. If you only need to look up a certain specific
  /// name (or names), use [getInheritedMember] instead.
  Map<Name, ExecutableElement2> get inheritedMembers;

  /// Returns a map of all members in the type's interface, keyed by the
  /// member's [Name].
  ///
  /// Note that some names are not declared directly on [thisType], but are
  /// inherited from supertypes.
  ///
  /// This method is potentially expensive, since it needs to consider all
  /// possible interface names. If you only need to look up a certain specific
  /// name (or names), use [getInterfaceMember] instead.
  Map<Name, ExecutableElement2> get interfaceMembers;

  /// The interfaces that are implemented by this class.
  ///
  /// <b>Note:</b> Because the element model represents the state of the code,
  /// it is possible for it to be semantically invalid. In particular, it is not
  /// safe to assume that the inheritance structure of a class does not contain
  /// a cycle. Clients that traverse the inheritance structure must explicitly
  /// guard against infinite loops.
  List<InterfaceType> get interfaces;

  /// The mixins that are applied to the class being extended in order to
  /// derive the superclass of this class.
  ///
  /// [ClassElement2] and [EnumElement2] can have mixins.
  ///
  /// [MixinElement2] cannot have mixins, so an empty list is returned.
  ///
  /// <b>Note:</b> Because the element model represents the state of the code,
  /// it is possible for it to be semantically invalid. In particular, it is not
  /// safe to assume that the inheritance structure of a class does not contain
  /// a cycle. Clients that traverse the inheritance structure must explicitly
  /// guard against infinite loops.
  List<InterfaceType> get mixins;

  /// The superclass of this element.
  ///
  /// For [ClassElement2] returns `null` only if this class is `Object`. If the
  /// superclass is not explicitly specified, or the superclass cannot be
  /// resolved, then the implicit superclass `Object` is returned.
  ///
  /// For [EnumElement2] returns `Enum` from `dart:core`.
  ///
  /// For [MixinElement2] always returns `null`.
  ///
  /// <b>Note:</b> Because the element model represents the state of the code,
  /// it is possible for it to be semantically invalid. In particular, it is not
  /// safe to assume that the inheritance structure of a class does not contain
  /// a cycle. Clients that traverse the inheritance structure must explicitly
  /// guard against infinite loops.
  InterfaceType? get supertype;

  @override
  InterfaceType get thisType;

  /// The unnamed constructor declared directly in this class.
  ///
  /// If the class does not declare any constructors, a synthetic default
  /// constructor will be returned.
  ConstructorElement2? get unnamedConstructor2;

  /// Returns the most specific member with the given [name] that this type
  /// inherits from a superclass or mixin.
  ///
  /// Returns `null` if no member is inherited.
  ///
  /// This method is semantically equivalent to calling
  /// [inheritedConcreteMembers] and then using the `[]` operator, but it
  /// potentially has better performance, since it does not need to consider all
  /// possible inherited names.
  ExecutableElement2? getInheritedConcreteMember(Name name);

  /// Returns the most specific member with the given [name] that this type
  /// inherits from a supertype via an `extends`, `with`, `implements`, or `on`
  /// clause.
  ///
  /// Returns `null` if no member is inherited because the member is not
  /// declared at all, or because there is no the most specific signature.
  ///
  /// This method is semantically equivalent to calling [inheritedMembers] and
  /// then using the `[]` operator, but it potentially has better performance,
  /// since it does not need to consider all possible inherited names.
  ExecutableElement2? getInheritedMember(Name name);

  /// Returns the most specific member with the given [name] in this type's
  /// interface.
  ///
  /// Returns `null` if there is no member with the given [name] in this type's
  /// interface, either because the member is not declared at all, or because of
  /// a conflict between inherited members.
  ///
  /// This method is semantically equivalent to calling [interfaceMembers] and
  /// then using the `[]` operator, but it potentially has better performance,
  /// since it does not need to consider all possible interface names.
  ExecutableElement2? getInterfaceMember(Name name);

  /// Returns the constructor from [constructors2] that has the given [name].
  ConstructorElement2? getNamedConstructor2(String name);

  /// Returns all members of mixins, superclasses, and interfaces that a member
  /// with the given [name], defined in this element, would override; or `null`
  /// if no members would be overridden.
  ///
  /// Transitive overrides are not included unless there is a direct path to
  /// them. For example, if classes `A`, `B`, and `C` are defined as follows:
  ///
  ///     class A { void m() {} }
  ///     class B extends A { void m() {} }
  ///     class C extends B { void m() {} }
  ///
  /// Then a [getOverridden] query for name `m` on class `C` would return just a
  /// single result: the element for `B.m`.
  ///
  /// However, if the example were changed so that `class C` both `extends B`
  /// *and* `implements A`, then a list containing both `A.m` and `B.m` would be
  /// returned.
  List<ExecutableElement2>? getOverridden(Name name);

  /// Create the [InterfaceType] for this element with the given
  /// [typeArguments] and [nullabilitySuffix].
  InterfaceType instantiate({
    required List<DartType> typeArguments,
    required NullabilitySuffix nullabilitySuffix,
  });

  /// Returns the element representing the method that results from looking up
  /// the given [methodName] in this class with respect to the given [library],
  /// ignoring abstract methods, or `null` if the look up fails.
  ///
  /// The behavior of this method is defined by the Dart Language Specification
  /// in section 16.15.1:
  /// <blockquote>
  /// The result of looking up method <i>m</i> in class <i>C</i> with respect to
  /// library <i>L</i> is: If <i>C</i> declares an instance method named
  /// <i>m</i> that is accessible to <i>L</i>, then that method is the result of
  /// the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the
  /// result of the lookup is the result of looking up method <i>m</i> in
  /// <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has
  /// failed.
  /// </blockquote>
  // TODO(scheglov): Deprecate and remove it.
  MethodElement2? lookUpConcreteMethod(
      String methodName, LibraryElement2 library);

  /// Returns the element representing the method that results from looking up
  /// the given [methodName] in the superclass of this class with respect to the
  /// given [library], or `null` if the look up fails.
  ///
  /// The behavior of this method is defined by the Dart Language Specification
  /// in section 16.15.1:
  /// <blockquote>
  /// The result of looking up method <i>m</i> in class <i>C</i> with respect to
  /// library <i>L</i> is:  If <i>C</i> declares an instance method named
  /// <i>m</i> that is accessible to <i>L</i>, then that method is the result of
  /// the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then the
  /// result of the lookup is the result of looking up method <i>m</i> in
  /// <i>S</i> with respect to <i>L</i>. Otherwise, we say that the lookup has
  /// failed.
  /// </blockquote>
  // TODO(scheglov): Deprecate and remove it.
  MethodElement2? lookUpInheritedMethod2({
    required String methodName,
    required LibraryElement2 library,
  });
}

/// The portion of an [InterfaceElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class InterfaceFragment implements InstanceFragment {
  /// The constructors declared in this fragment.
  ///
  /// The list is empty for [MixinFragment].
  List<ConstructorFragment> get constructors2;

  @override
  InterfaceElement2 get element;

  /// The interfaces that are implemented by this fragment.
  List<InterfaceType> get interfaces;

  /// The mixins that are applied by this fragment.
  ///
  /// [ClassFragment] and [EnumFragment] can have mixins.
  ///
  /// [MixinFragment] cannot have mixins, so the empty list is returned.
  List<InterfaceType> get mixins;

  @override
  InterfaceFragment? get nextFragment;

  @override
  InterfaceFragment? get previousFragment;

  /// The superclass declared by this fragment.
  InterfaceType? get supertype;
}

/// A pattern variable that is a join of other pattern variables, created
/// for a logical-or patterns, or shared `case` bodies in `switch` statements.
///
/// Clients may not extend, implement or mix-in this class.
abstract class JoinPatternVariableElement2 implements PatternVariableElement2 {
  @override
  JoinPatternVariableFragment get firstFragment;

  @override
  List<JoinPatternVariableFragment> get fragments;

  /// Whether the [variables2] are consistent.
  ///
  /// The variables are consistent if they are present in all branches, and have
  /// the same type and finality.
  bool get isConsistent;

  /// The variables that join into this variable.
  List<PatternVariableElement2> get variables2;
}

/// The portion of a [JoinPatternVariableElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class JoinPatternVariableFragment implements PatternVariableFragment {
  @override
  JoinPatternVariableElement2 get element;

  /// Whether the [variables2] are consistent.
  ///
  /// The variables are consistent if they are present in all branches, and have
  /// the same type and finality.
  bool get isConsistent;

  @override
  JoinPatternVariableFragment? get nextFragment;

  /// The offset of the first variable in the join.
  @override
  int get offset;

  @override
  JoinPatternVariableFragment? get previousFragment;

  /// The variables that join into this variable.
  List<PatternVariableFragment> get variables2;
}

/// A label associated with a statement.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LabelElement2 implements Element2 {
  @override
  // TODO(brianwilkerson): We shouldn't be inheriting this member.
  ExecutableElement2? get enclosingElement2;

  @override
  LabelFragment get firstFragment;

  @override
  List<LabelFragment> get fragments;

  @override
  LibraryElement2 get library2;
}

/// The portion of a [LabelElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LabelFragment implements Fragment {
  @override
  LabelElement2 get element;

  @override
  LabelFragment? get nextFragment;

  @override
  LabelFragment? get previousFragment;
}

/// A library.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LibraryElement2
    implements Element2, Annotatable, HasSinceSdkVersion {
  /// The classes defined in this library.
  ///
  /// There is no guarantee of the order in which the classes will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<ClassElement2> get classes;

  /// The entry point for this library.
  ///
  /// Returns `null` if this library doesn't have an entry point.
  ///
  /// The entry point is defined to be a zero, one, or two argument top-level
  /// function whose name is `main`.
  TopLevelFunctionElement? get entryPoint2;

  /// The enums defined in this library.
  ///
  /// There is no guarantee of the order in which the enums will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<EnumElement2> get enums;

  /// The libraries that are exported from this library.
  ///
  /// There is no guarantee of the order in which the libraries will be
  /// returned. In particular, they are not guaranteed to be in lexical order.
  // TODO(brianwilkerson): Consider removing this from the public API. It isn't
  //  clear that it's useful, given that it ignores hide and show clauses.
  List<LibraryElement2> get exportedLibraries2;

  /// The export [Namespace] of this library.
  Namespace get exportNamespace;

  /// The extensions defined in this library.
  ///
  /// There is no guarantee of the order in which the extensions will be
  /// returned. In particular, they are not guaranteed to be in lexical order.
  List<ExtensionElement2> get extensions;

  /// The extension types defined in this library.
  ///
  /// There is no guarantee of the order in which the extension types will be
  /// returned. In particular, they are not guaranteed to be in lexical order.
  List<ExtensionTypeElement2> get extensionTypes;

  /// The set of features available to this library.
  ///
  /// Determined by the combination of the language version for the enclosing
  /// package, enabled experiments, and the presence of a `// @dart` language
  /// version override comment at the top of the files that make up the library.
  FeatureSet get featureSet;

  @override
  LibraryFragment get firstFragment;

  /// The fragments this library consists of.
  ///
  /// This includes the defining fragment, and fragments included using the
  /// `part` directive.
  @override
  List<LibraryFragment> get fragments;

  /// The getters defined in this library.
  ///
  /// There is no guarantee of the order in which the getters will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<GetterElement> get getters;

  /// The identifier that uniquely identifies this element among the children
  /// of this element's parent.
  String get identifier;

  /// Whether the library is the `dart:async` library.
  bool get isDartAsync;

  /// Whether the library is the `dart:core` library.
  bool get isDartCore;

  /// Whether the library is part of the SDK.
  bool get isInSdk;

  /// The language version for this library.
  LibraryLanguageVersion get languageVersion;

  @override
  LibraryElement2 get library2;

  /// The element representing the synthetic function `loadLibrary`.
  ///
  /// Technically the function is implicitly defined for this library only if
  /// the library is imported using a deferred import, but the element is always
  /// defined for performance reasons.
  TopLevelFunctionElement get loadLibraryFunction2;

  /// The mixins defined in this library.
  ///
  /// There is no guarantee of the order in which the mixins will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<MixinElement2> get mixins;

  /// The public [Namespace] of this library.
  Namespace get publicNamespace;

  /// The analysis session in which this library is defined.
  @override
  AnalysisSession get session;

  /// The setters defined in this library.
  ///
  /// There is no guarantee of the order in which the setters will be returned.
  /// In particular, they are not guaranteed to be in lexical order.
  List<SetterElement> get setters;

  /// The functions defined in this library.
  ///
  /// There is no guarantee of the order in which the functions will be
  /// returned. In particular, they are not guaranteed to be in lexical order.
  List<TopLevelFunctionElement> get topLevelFunctions;

  /// The top level variables defined in this library.
  ///
  /// There is no guarantee of the order in which the top level variables will
  /// be returned. In particular, they are not guaranteed to be in lexical
  /// order.
  List<TopLevelVariableElement2> get topLevelVariables;

  /// The type aliases defined in this library.
  ///
  /// There is no guarantee of the order in which the type aliases will be
  /// returned. In particular, they are not guaranteed to be in lexical order.
  List<TypeAliasElement2> get typeAliases;

  /// The [TypeProvider] that is used in this library.
  TypeProvider get typeProvider;

  /// The [TypeSystem] that is used in this library.
  TypeSystem get typeSystem;

  /// The canonical URI of the library.
  ///
  /// This is the same URI as `firstFragment.source.uri` returns.
  Uri get uri;

  /// Returns the class defined in this library that has the given [name].
  ClassElement2? getClass2(String name);

  /// Returns the enum defined in this library that has the given [name].
  EnumElement2? getEnum2(String name);

  /// Returns the extension defined in this library that has the given [name].
  ExtensionElement2? getExtension(String name);

  /// Returns the extension type defined in this library that has the
  /// given [name].
  ExtensionTypeElement2? getExtensionType(String name);

  /// Returns the getter defined in this library that has the given [name].
  GetterElement? getGetter(String name);

  /// Returns the mixin defined in this library that has the given [name].
  MixinElement2? getMixin2(String name);

  /// Returns the setter defined in this library that has the given [name].
  SetterElement? getSetter(String name);

  /// Returns the function defined in this library that has the given [name].
  TopLevelFunctionElement? getTopLevelFunction(String name);

  /// Returns the top-level variable defined in this library that has the
  /// given [name].
  TopLevelVariableElement2? getTopLevelVariable(String name);

  /// Returns the type alias defined in this library that has the given [name].
  TypeAliasElement2? getTypeAlias(String name);
}

/// An `export` directive within a library fragment.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LibraryExport implements ElementDirective {
  /// The combinators that were specified as part of the `export` directive.
  ///
  /// The combinators are in the order in which they were specified.
  List<NamespaceCombinator> get combinators;

  /// The [LibraryElement2], if [uri] is a [DirectiveUriWithLibrary].
  LibraryElement2? get exportedLibrary2;

  /// The offset of the `export` keyword.
  int get exportKeywordOffset;
}

/// The portion of a [LibraryElement2] coming from a single compilation unit.
abstract class LibraryFragment implements Fragment, Annotatable {
  /// The extension elements accessible within this fragment.
  List<ExtensionElement2> get accessibleExtensions2;

  /// The fragments of the classes declared in this fragment.
  List<ClassFragment> get classes2;

  @override
  LibraryElement2 get element;

  @override
  LibraryFragment? get enclosingFragment;

  /// The fragments of the enums declared in this fragment.
  List<EnumFragment> get enums2;

  /// The fragments of the extensions declared in this fragment.
  List<ExtensionFragment> get extensions2;

  /// The fragments of the extension types declared in this fragment.
  List<ExtensionTypeFragment> get extensionTypes2;

  /// The fragments of the top-level functions declared in this fragment.
  List<TopLevelFunctionFragment> get functions2;

  /// The fragments of the top-level getters declared in this fragment.
  List<GetterFragment> get getters;

  /// The libraries that are imported by this unit.
  ///
  /// This includes all of the libraries that are imported using a prefix, and
  /// those that are imported without a prefix.
  List<LibraryElement2> get importedLibraries2;

  /// The libraries exported by this unit.
  List<LibraryExport> get libraryExports2;

  /// The libraries imported by this unit.
  List<LibraryImport> get libraryImports2;

  /// The [LineInfo] for the fragment.
  LineInfo get lineInfo;

  /// The fragments of the mixins declared in this fragment.
  List<MixinFragment> get mixins2;

  @override
  LibraryFragment? get nextFragment;

  /// If this is the first fragment in the library and the library has `library`
  /// declaration that specifies a name, the offset of the name; otherwise zero.
  @override
  int get offset;

  /// The `part` directives within this fragment.
  List<PartInclude> get partIncludes;

  /// The prefixes used by [libraryImports2].
  ///
  /// Each prefix can be used in more than one `import` directive.
  List<PrefixElement2> get prefixes;

  @override
  LibraryFragment? get previousFragment;

  /// The scope used to resolve names within the fragment.
  ///
  /// It includes all of the elements that are declared in the library, and all
  /// of the elements imported into this fragment or parent fragments.
  Scope get scope;

  /// The fragments of the top-level setters declared in this fragment.
  List<SetterFragment> get setters;

  /// The source associated with this fragment.
  Source get source;

  /// The fragments of the top-level variables declared in this fragment.
  List<TopLevelVariableFragment> get topLevelVariables2;

  /// The fragments of the type aliases declared in this fragment.
  List<TypeAliasFragment> get typeAliases2;
}

/// An `import` directive within a library fragment.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LibraryImport implements ElementDirective {
  /// The combinators that were specified as part of the `import` directive.
  ///
  /// The combinators are in the order in which they were specified.
  List<NamespaceCombinator> get combinators;

  /// The [LibraryElement2], if [uri] is a [DirectiveUriWithLibrary].
  LibraryElement2? get importedLibrary2;

  /// The offset of the `import` keyword.
  int get importKeywordOffset;

  /// Whether this import is synthetic.
  ///
  /// A synthetic import is an import that is not represented in the source
  /// code explicitly, but is implied by the source code. This only happens for
  /// an implicit import of `dart:core`.
  bool get isSynthetic;

  /// The [Namespace] that this directive contributes to the containing library.
  Namespace get namespace;

  /// The prefix fragment that was specified as part of the import directive.
  ///
  /// Returns `null` if there was no prefix specified.
  PrefixFragment? get prefix2;
}

/// An element that can be (but is not required to be) defined within a method
/// or function (an [ExecutableFragment]).
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalElement2 implements Element2 {}

/// The portion of an [LocalElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalFragment implements Fragment {}

/// A local function.
///
/// This can be either a local function, a closure, or the initialization
/// expression for a field or variable.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalFunctionElement
    implements ExecutableElement2, LocalElement2 {
  @override
  LocalFunctionFragment get firstFragment;

  @override
  List<LocalFunctionFragment> get fragments;
}

/// The portion of a [LocalFunctionElement] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalFunctionFragment
    implements ExecutableFragment, LocalFragment {
  @override
  LocalFunctionElement get element;

  @override
  LocalFunctionFragment? get nextFragment;

  /// The offset of the local function name.
  ///
  /// If the local function has no name (because it's a function expression),
  /// this is the offset of the `(` that begins the function expression.
  @override
  int get offset;

  @override
  LocalFunctionFragment? get previousFragment;
}

/// A local variable.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalVariableElement2
    implements PromotableElement2, LocalElement2, Annotatable {
  @override
  LocalVariableElement2 get baseElement;

  @override
  LocalVariableFragment get firstFragment;

  @override
  List<LocalVariableFragment> get fragments;

  /// Whether the variable has an initializer at declaration.
  bool get hasInitializer;
}

/// The portion of a [LocalVariableElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class LocalVariableFragment
    implements PromotableFragment, LocalFragment {
  @override
  LocalVariableElement2 get element;

  /// Whether the variable has an initializer at declaration.
  bool get hasInitializer;

  /// The offset of the name in this element.
  int get nameOffset;

  @override
  LocalVariableFragment? get nextFragment;

  @override
  LocalVariableFragment? get previousFragment;
}

/// The metadata (annotations) associated with an element or fragment.
abstract class Metadata {
  /// The annotations associated with the associated element or fragment.
  ///
  /// If the metadata is associated with an element that has fragments, the list
  /// will include all of the annotations from all of the fragments.
  ///
  /// The list will be empty if the associated element or fragment does not have
  /// any annotations or if the library containing the holder has not yet been
  /// fully resolved.
  List<ElementAnnotation> get annotations;

  /// Whether the receiver has an annotation of the form `@alwaysThrows`.
  bool get hasAlwaysThrows;

  /// Whether the receiver has an annotation of the form `@deprecated`
  /// or `@Deprecated('..')`.
  bool get hasDeprecated;

  /// Whether the receiver has an annotation of the form `@doNotStore`.
  bool get hasDoNotStore;

  /// Whether the receiver has an annotation of the form `@doNotSubmit`.
  bool get hasDoNotSubmit;

  /// Whether the receiver has an annotation of the form `@factory`.
  bool get hasFactory;

  /// Whether the receiver has an annotation of the form `@immutable`.
  bool get hasImmutable;

  /// Whether the receiver has an annotation of the form `@internal`.
  bool get hasInternal;

  /// Whether the receiver has an annotation of the form `@isTest`.
  bool get hasIsTest;

  /// Whether the receiver has an annotation of the form `@isTestGroup`.
  bool get hasIsTestGroup;

  /// Whether the receiver has an annotation of the form `@JS(..)`.
  bool get hasJS;

  /// Whether the receiver has an annotation of the form `@literal`.
  bool get hasLiteral;

  /// Whether the receiver has an annotation of the form `@mustBeConst`.
  bool get hasMustBeConst;

  /// Whether the receiver has an annotation of the form `@mustBeOverridden`.
  bool get hasMustBeOverridden;

  /// Whether the receiver has an annotation of the form `@mustCallSuper`.
  bool get hasMustCallSuper;

  /// Whether the receiver has an annotation of the form `@nonVirtual`.
  bool get hasNonVirtual;

  /// Whether the receiver has an annotation of the form `@optionalTypeArgs`.
  bool get hasOptionalTypeArgs;

  /// Whether the receiver has an annotation of the form `@override`.
  bool get hasOverride;

  /// Whether the receiver has an annotation of the form `@protected`.
  bool get hasProtected;

  /// Whether the receiver has an annotation of the form `@redeclare`.
  bool get hasRedeclare;

  /// Whether the receiver has an annotation of the form `@reopen`.
  bool get hasReopen;

  /// Whether the receiver has an annotation of the form `@required`.
  bool get hasRequired;

  /// Whether the receiver has an annotation of the form `@sealed`.
  bool get hasSealed;

  /// Whether the receiver has an annotation of the form `@useResult`
  /// or `@UseResult('..')`.
  bool get hasUseResult;

  /// Whether the receiver has an annotation of the form `@visibleForOverriding`.
  bool get hasVisibleForOverriding;

  /// Whether the receiver has an annotation of the form `@visibleForTemplate`.
  bool get hasVisibleForTemplate;

  /// Whether the receiver has an annotation of the form `@visibleForTesting`.
  bool get hasVisibleForTesting;

  /// Whether the receiver has an annotation of the form
  /// `@visibleOutsideTemplate`.
  bool get hasVisibleOutsideTemplate;

  /// Whether the receiver has an annotation of the form `@widgetFactory`.
  bool get hasWidgetFactory;
}

/// A method.
///
/// The method can be either an instance method, an operator, or a static
/// method.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MethodElement2
    implements ExecutableElement2, HasSinceSdkVersion {
  /// The name of the method that can be implemented by a class to allow its
  /// instances to be invoked as if they were a function.
  static final String CALL_METHOD_NAME = "call";

  /// The name of the method that will be invoked if an attempt is made to
  /// invoke an undefined method on an object.
  static final String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod";

  @override
  MethodElement2 get baseElement;

  @override
  MethodFragment get firstFragment;

  @override
  List<MethodFragment> get fragments;

  /// Whether the method defines an operator.
  ///
  /// The test might be based on the name of the executable element, in which
  /// case the result will be correct when the name is legal.
  bool get isOperator;
}

/// The portion of a [MethodElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MethodFragment implements ExecutableFragment {
  @override
  MethodElement2 get element;

  @override
  InstanceFragment? get enclosingFragment;

  @override
  MethodFragment? get nextFragment;

  @override
  MethodFragment? get previousFragment;
}

/// An element that represents a mixin.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MixinElement2 implements InterfaceElement2 {
  @override
  MixinFragment get firstFragment;

  @override
  List<MixinFragment> get fragments;

  /// Whether the mixin is a base mixin.
  ///
  /// A mixin is a base mixin if it has an explicit `base` modifier.
  /// The base modifier allows a mixin to be mixed in, but not implemented.
  bool get isBase;

  /// The superclass constraints defined for this mixin.
  ///
  /// If the declaration does not have an `on` clause, then the list will
  /// contain the type for the class `Object`.
  ///
  /// <b>Note:</b> Because the element model represents the state of the code,
  /// it is possible for it to be semantically invalid. In particular, it is not
  /// safe to assume that the inheritance structure of a class does not contain
  /// a cycle. Clients that traverse the inheritance structure must explicitly
  /// guard against infinite loops.
  List<InterfaceType> get superclassConstraints;

  /// Whether the element, assuming that it is within scope, is
  /// implementable to classes, mixins, and enums in the given [library].
  bool isImplementableIn2(LibraryElement2 library);
}

/// The portion of a [PrefixElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MixinFragment implements InterfaceFragment {
  @override
  MixinElement2 get element;

  @override
  MixinFragment? get nextFragment;

  @override
  MixinFragment? get previousFragment;

  /// The superclass constraints defined for this mixin.
  ///
  /// If the declaration does not have an `on` clause, then the list will
  /// contain the type for the class `Object`.
  ///
  /// <b>Note:</b> Because the element model represents the state of the code,
  /// it is possible for it to be semantically invalid. In particular, it is not
  /// safe to assume that the inheritance structure of a class does not contain
  /// a cycle. Clients that traverse the inheritance structure must explicitly
  /// guard against infinite loops.
  List<InterfaceType> get superclassConstraints;
}

/// A pseudo-element that represents multiple elements defined within a single
/// scope that have the same name. This situation is not allowed by the
/// language, so objects implementing this interface always represent an error.
/// As a result, most of the normal operations on elements do not make sense
/// and will return useless results.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MultiplyDefinedElement2 implements Element2 {
  /// The elements that were defined within the scope to have the same name.
  List<Element2> get conflictingElements2;

  @override
  MultiplyDefinedFragment get firstFragment;

  @override
  List<MultiplyDefinedFragment> get fragments;
}

/// The fragment for a [MultiplyDefinedElement2].
///
/// It has no practical use, and exists for consistency, so that the
/// corresponding element has a fragment.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MultiplyDefinedFragment implements Fragment {
  @override
  MultiplyDefinedElement2 get element;

  @override
  Null get nextFragment;

  /// Always returns zero.
  @override
  int get offset;

  @override
  Null get previousFragment;
}

/// A 'part' directive within a library fragment.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PartInclude implements ElementDirective {
  /// The [LibraryFragment], if [uri] is a [DirectiveUriWithUnit].
  LibraryFragment? get includedFragment;
}

/// A pattern variable.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PatternVariableElement2 implements LocalVariableElement2 {
  @override
  PatternVariableFragment get firstFragment;

  @override
  List<PatternVariableFragment> get fragments;

  /// The variable in which this variable joins with other pattern variables
  /// with the same name, in a logical-or pattern, or shared case scope.
  JoinPatternVariableElement2? get join2;
}

/// The portion of a [PatternVariableElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PatternVariableFragment implements LocalVariableFragment {
  @override
  PatternVariableElement2 get element;

  /// The variable in which this variable joins with other pattern variables
  /// with the same name, in a logical-or pattern, or shared case scope.
  JoinPatternVariableFragment? get join2;

  @override
  PatternVariableFragment? get nextFragment;

  @override
  PatternVariableFragment? get previousFragment;
}

/// A prefix used to import one or more libraries into another library.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PrefixElement2 implements Element2 {
  /// There is no enclosing element for import prefixes, which are elements,
  /// but exist inside a single [LibraryFragment], not an element.
  @override
  Null get enclosingElement2;

  @override
  PrefixFragment get firstFragment;

  @override
  List<PrefixFragment> get fragments;

  /// The imports that share this prefix.
  List<LibraryImport> get imports;

  @override
  LibraryElement2 get library2;

  /// The name lookup scope for this import prefix.
  ///
  /// It consists of elements imported into the enclosing library with this
  /// prefix. The namespace combinators of the import directives are taken
  /// into account.
  Scope get scope;
}

/// The portion of a [PrefixElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PrefixFragment implements Fragment {
  @override
  PrefixElement2 get element;

  @override
  LibraryFragment? get enclosingFragment;

  /// Whether the [LibraryImport] is deferred.
  bool get isDeferred;

  @override
  PrefixFragment? get nextFragment;

  @override
  PrefixFragment? get previousFragment;
}

/// A variable that might be subject to type promotion.  This might be a local
/// variable or a parameter.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PromotableElement2 implements VariableElement2 {
  @override
  PromotableFragment get firstFragment;

  @override
  List<PromotableFragment> get fragments;
}

/// The portion of a [PromotableElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PromotableFragment implements VariableFragment {
  @override
  PromotableElement2 get element;

  @override
  PromotableFragment? get nextFragment;

  @override
  PromotableFragment? get previousFragment;
}

/// A getter or a setter.
///
/// Property accessors can either be defined explicitly or they can be induced
/// by either a top-level variable or a field. Induced property accessors are
/// synthetic.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PropertyAccessorElement2 implements ExecutableElement2 {
  @override
  PropertyAccessorElement2 get baseElement;

  @override
  Element2 get enclosingElement2;

  @override
  PropertyAccessorFragment get firstFragment;

  @override
  List<PropertyAccessorFragment> get fragments;

  /// The field or top-level variable associated with this getter.
  ///
  /// If this getter was explicitly defined (is not synthetic) then the variable
  /// associated with it will be synthetic.
  PropertyInducingElement2? get variable3;
}

/// The portion of a [GetterElement] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PropertyAccessorFragment implements ExecutableFragment {
  @override
  PropertyAccessorElement2 get element;

  @override
  PropertyAccessorFragment? get nextFragment;

  @override
  PropertyAccessorFragment? get previousFragment;

  /// The field or top-level variable associated with this property accessors.
  ///
  /// If this property accessor was explicitly defined (is not synthetic) then
  /// the variable associated with it will be synthetic.
  PropertyInducingFragment? get variable3;
}

/// A variable that has an associated getter and possibly a setter. Note that
/// explicitly defined variables implicitly define a synthetic getter and that
/// non-`final` explicitly defined variables implicitly define a synthetic
/// setter. Symmetrically, synthetic fields are implicitly created for
/// explicitly defined getters and setters. The following rules apply:
///
/// * Every explicit variable is represented by a non-synthetic
///   [PropertyInducingElement2].
/// * Every explicit variable induces a synthetic [GetterElement],
///   possibly a synthetic [SetterElement.
/// * Every explicit getter by a non-synthetic [GetterElement].
/// * Every explicit setter by a non-synthetic [SetterElement].
/// * Every explicit getter or setter (or pair thereof if they have the same
///   name) induces a variable that is represented by a synthetic
///   [PropertyInducingElement2].
///
/// Clients may not extend, implement or mix-in this class.
abstract class PropertyInducingElement2
    implements VariableElement2, Annotatable, HasSinceSdkVersion {
  @override
  PropertyInducingFragment get firstFragment;

  @override
  List<PropertyInducingFragment> get fragments;

  /// The getter associated with this variable.
  ///
  /// If this variable was explicitly defined (is not synthetic) then the
  /// getter associated with it will be synthetic.
  GetterElement? get getter2;

  /// Whether any fragment of this variable has an initializer at declaration.
  bool get hasInitializer;

  @override
  LibraryElement2 get library2;

  /// The setter associated with this variable.
  ///
  /// Returns `null` if the variable is effectively `final` and therefore does
  /// not have a setter associated with it.
  ///
  /// This can happen either because the variable is explicitly defined as
  /// being `final` or because the variable is induced by an explicit getter
  /// that does not have a corresponding setter. If this variable was
  /// explicitly defined (is not synthetic) then the setter associated with
  /// it will be synthetic.
  SetterElement? get setter2;
}

/// The portion of a [PropertyInducingElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class PropertyInducingFragment
    implements VariableFragment, Annotatable {
  @override
  PropertyInducingElement2 get element;

  /// The getter associated with this variable.
  ///
  /// If this variable was explicitly defined (is not synthetic) then the
  /// getter associated with it will be synthetic.
  GetterFragment? get getter2;

  /// Whether the variable has an initializer at declaration.
  bool get hasInitializer;

  /// Whether the element is an augmentation.
  ///
  /// Property inducing fragments are augmentations if they are explicitly
  /// marked as such using the 'augment' modifier.
  bool get isAugmentation;

  /// Whether this fragment is synthetic.
  ///
  /// A synthetic fragment is a fragment that is not represented in the source
  /// code explicitly, but is implied by the source code, such as the default
  /// constructor for a class that does not explicitly define any constructors.
  bool get isSynthetic;

  @override
  LibraryFragment get libraryFragment;

  @override
  PropertyInducingFragment? get nextFragment;

  @override
  PropertyInducingFragment? get previousFragment;

  /// The setter associated with this variable.
  ///
  /// Returns `null` if the variable is effectively `final` and therefore
  /// doesn't have a setter associated with it.
  ///
  /// This can happen either because the variable is explicitly defined as
  /// being `final` or because the variable is induced by an explicit getter
  /// that does not have a corresponding setter. If this variable was
  /// explicitly defined (is not synthetic) then the setter associated with
  /// it will be synthetic.
  SetterFragment? get setter2;
}

/// A setter.
///
/// Setters can either be defined explicitly or they can be induced by either a
/// top-level variable or a field. Induced setters are synthetic.
///
/// Clients may not extend, implement or mix-in this class.
abstract class SetterElement implements PropertyAccessorElement2 {
  @override
  SetterElement get baseElement;

  /// The getter that corresponds to (has the same name as) this setter, or
  /// `null` if there is no corresponding getter.
  GetterElement? get correspondingGetter2;

  @override
  SetterFragment get firstFragment;

  @override
  List<SetterFragment> get fragments;
}

/// The portion of a [SetterElement] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class SetterFragment implements PropertyAccessorFragment {
  @override
  SetterElement get element;

  @override
  SetterFragment? get nextFragment;

  /// The offset of the setter name.
  ///
  /// If the setter is implicit (because it's induced by a field or top level
  /// variable declaration), this is the offset of the field or top level
  /// variable name.
  @override
  int get offset;

  @override
  SetterFragment? get previousFragment;
}

/// A super formal parameter.
///
/// Super formal parameters can only be defined within a constructor element.
///
/// Clients may not extend, implement or mix-in this class.
abstract class SuperFormalParameterElement2 implements FormalParameterElement {
  @override
  SuperFormalParameterFragment get firstFragment;

  @override
  List<SuperFormalParameterFragment> get fragments;

  /// The associated super-constructor parameter, from the super-constructor
  /// that is referenced by the implicit or explicit super-constructor
  /// invocation.
  ///
  /// Can be `null` for erroneous code - not existing super-constructor,
  /// no corresponding parameter in the super-constructor.
  FormalParameterElement? get superConstructorParameter2;
}

/// The portion of a [SuperFormalParameterElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class SuperFormalParameterFragment implements FormalParameterFragment {
  @override
  SuperFormalParameterElement2 get element;

  @override
  SuperFormalParameterFragment? get nextFragment;

  @override
  SuperFormalParameterFragment? get previousFragment;
}

/// A top-level function.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TopLevelFunctionElement
    implements ExecutableElement2, HasSinceSdkVersion {
  /// The name of the function used as an entry point.
  static const String MAIN_FUNCTION_NAME = "main";

  /// The name of the synthetic function defined for libraries that are
  /// deferred.
  static final String LOAD_LIBRARY_NAME = "loadLibrary";

  @override
  TopLevelFunctionElement get baseElement;

  @override
  TopLevelFunctionFragment get firstFragment;

  @override
  List<TopLevelFunctionFragment> get fragments;

  /// Whether the function represents `identical` from the `dart:core` library.
  bool get isDartCoreIdentical;

  /// Whether the function is an entry point.
  ///
  /// A top-level function is an entry point if it has the name `main`.
  bool get isEntryPoint;
}

/// The portion of a [TopLevelFunctionElement] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TopLevelFunctionFragment implements ExecutableFragment {
  @override
  TopLevelFunctionElement get element;

  @override
  TopLevelFunctionFragment? get nextFragment;

  @override
  TopLevelFunctionFragment? get previousFragment;
}

/// A top-level variable.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TopLevelVariableElement2 implements PropertyInducingElement2 {
  @override
  TopLevelVariableElement2 get baseElement;

  @override
  TopLevelVariableFragment get firstFragment;

  @override
  List<TopLevelVariableFragment> get fragments;

  /// Whether the field was explicitly marked as being external.
  bool get isExternal;
}

/// The portion of a [TopLevelVariableElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TopLevelVariableFragment implements PropertyInducingFragment {
  @override
  TopLevelVariableElement2 get element;

  @override
  TopLevelVariableFragment? get nextFragment;

  @override
  TopLevelVariableFragment? get previousFragment;
}

/// A type alias (`typedef`).
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeAliasElement2
    implements
        TypeParameterizedElement2,
        TypeDefiningElement2,
        HasSinceSdkVersion {
  /// If the aliased type has structure, return the corresponding element.
  /// For example, it could be [GenericFunctionTypeElement2].
  ///
  /// If there is no structure, return `null`.
  Element2? get aliasedElement2;

  /// The aliased type.
  ///
  /// If non-function type aliases feature is enabled for the enclosing library,
  /// this type might be just anything. If the feature is disabled, return
  /// a [FunctionType].
  DartType get aliasedType;

  @override
  LibraryElement2 get enclosingElement2;

  @override
  TypeAliasFragment get firstFragment;

  @override
  List<TypeAliasFragment> get fragments;

  /// Returns the type resulting from instantiating this typedef with the given
  /// [typeArguments] and [nullabilitySuffix].
  ///
  /// Note that this always instantiates the typedef itself, so for a
  /// [TypeAliasElement2] the returned [DartType] might still be a generic
  /// type, with type formals. For example, if the typedef is:
  ///
  ///     typedef F<T> = void Function<U>(T, U);
  ///
  /// then `F<int>` will produce `void Function<U>(int, U)`.
  DartType instantiate({
    required List<DartType> typeArguments,
    required NullabilitySuffix nullabilitySuffix,
  });
}

/// The portion of a [TypeAliasElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeAliasFragment
    implements TypeParameterizedFragment, TypeDefiningFragment {
  @override
  TypeAliasElement2 get element;

  @override
  LibraryFragment? get enclosingFragment;

  @override
  TypeAliasFragment? get nextFragment;

  @override
  TypeAliasFragment? get previousFragment;
}

/// An element that defines a type.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeDefiningElement2 implements Element2, Annotatable {
  // TODO(brianwilkerson): Evaluate to see whether this type is actually needed
  //  after converting clients to the new API.

  @override
  TypeDefiningFragment get firstFragment;

  @override
  List<TypeDefiningFragment> get fragments;
}

/// The portion of a [TypeDefiningElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeDefiningFragment implements Fragment, Annotatable {
  @override
  TypeDefiningElement2 get element;

  @override
  TypeDefiningFragment? get nextFragment;

  /// The offset of the type name.
  ///
  /// If the type in the language specification and not in any source file
  /// (e.g., `dynamic`), this value is zero.
  @override
  int get offset;

  @override
  TypeDefiningFragment? get previousFragment;
}

/// A type parameter.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeParameterElement2 implements TypeDefiningElement2 {
  @override
  TypeParameterElement2 get baseElement;

  /// The type representing the bound associated with this parameter.
  ///
  /// Returns `null` if this parameter does not have an explicit bound. Being
  /// able to distinguish between an implicit and explicit bound is needed by
  /// the instantiate to bounds algorithm.`
  DartType? get bound;

  @override
  TypeParameterFragment get firstFragment;

  @override
  List<TypeParameterFragment> get fragments;

  /// Returns the [TypeParameterType] with the given [nullabilitySuffix] for
  /// this type parameter.
  TypeParameterType instantiate({
    required NullabilitySuffix nullabilitySuffix,
  });
}

/// The portion of a [TypeParameterElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeParameterFragment implements TypeDefiningFragment {
  @override
  TypeParameterElement2 get element;

  @override
  TypeParameterFragment? get nextFragment;

  @override
  TypeParameterFragment? get previousFragment;
}

/// An element that has type parameters, such as a class, typedef, or method.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeParameterizedElement2 implements Element2, Annotatable {
  @override
  TypeParameterizedFragment get firstFragment;

  @override
  List<TypeParameterizedFragment> get fragments;

  /// If the element defines a type, indicates whether the type may safely
  /// appear without explicit type arguments as the bounds of a type parameter
  /// declaration.
  ///
  /// If the element does not define a type, returns `true`.
  bool get isSimplyBounded;

  @override
  LibraryElement2 get library2;

  /// The type parameters declared by this element directly.
  ///
  /// This does not include type parameters that are declared by any enclosing
  /// elements.
  List<TypeParameterElement2> get typeParameters2;
}

/// The portion of a [TypeParameterizedElement2] contributed by a single
/// declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeParameterizedFragment implements Fragment, Annotatable {
  @override
  TypeParameterizedElement2 get element;

  @override
  TypeParameterizedFragment? get nextFragment;

  @override
  TypeParameterizedFragment? get previousFragment;

  /// The type parameters declared by this fragment directly.
  ///
  /// This does not include type parameters that are declared by any enclosing
  /// fragments.
  List<TypeParameterFragment> get typeParameters2;
}

/// A variable.
///
/// There are more specific subclasses for more specific kinds of variables.
///
/// Clients may not extend, implement or mix-in this class.
abstract class VariableElement2 implements Element2 {
  /// The constant initializer for this constant variable, or the default
  /// value for this formal parameter.
  ///
  /// Is `null` if this variable is not a constant, or does not have the
  /// initializer or the default value specified.
  ConstantInitializer? get constantInitializer2;

  @override
  VariableFragment get firstFragment;

  @override
  List<VariableFragment> get fragments;

  /// Whether the variable element did not have an explicit type specified
  /// for it.
  bool get hasImplicitType;

  /// Whether the variable was declared with the 'const' modifier.
  bool get isConst;

  /// Whether the variable was declared with the 'final' modifier.
  ///
  /// Variables that are declared with the 'const' modifier will return `false`
  /// even though they are implicitly final.
  bool get isFinal;

  /// Whether the variable uses late evaluation semantics.
  bool get isLate;

  /// Whether the element is a static variable, as per section 8 of the Dart
  /// Language Specification:
  ///
  /// > A static variable is a variable that is not associated with a particular
  /// > instance, but rather with an entire library or class. Static variables
  /// > include library variables and class variables. Class variables are
  /// > variables whose declaration is immediately nested inside a class
  /// > declaration and includes the modifier static. A library variable is
  /// > implicitly static.
  bool get isStatic;

  /// The declared type of this variable.
  DartType get type;

  /// Returns a representation of the value of this variable.
  ///
  /// If the value had not previously been computed, it will be computed as a
  /// result of invoking this method.
  ///
  /// Returns `null` if either this variable was not declared with the 'const'
  /// modifier or if the value of this variable could not be computed because of
  /// errors.
  DartObject? computeConstantValue();
}

/// The portion of a [VariableElement2] contributed by a single declaration.
///
/// Clients may not extend, implement or mix-in this class.
abstract class VariableFragment implements Fragment {
  @override
  VariableElement2 get element;

  /// The initializer for this constant variable fragment, or the default value
  /// for this formal parameter fragment.
  ///
  /// Is `null` if this variable fragment is not a constant, or does not have
  /// the initializer or the default value specified.
  Expression? get initializer;

  @override
  VariableFragment? get nextFragment;

  @override
  VariableFragment? get previousFragment;
}
