[analyzer] Add Fragment.offset getter.

This getter behaves similarly to `nameOffset`, however, if the
fragment is synthetic or does not have a name, it returns a suitably
chosen canonical offset. The intention is to provide a convenient API
that clients can use to point the user to the any fragment, saving
them from having to write special case code to handle the less common
cases of synthetic and unnamed fragments.

Change-Id: I42187a47053904ff73700698a670debe91082938
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/411660
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/api.txt b/pkg/analyzer/api.txt
index 3c85676..d93bd97 100644
--- a/pkg/analyzer/api.txt
+++ b/pkg/analyzer/api.txt
@@ -3667,6 +3667,7 @@
     enclosingFragment (getter: InstanceFragment?)
     name2 (getter: String)
     nextFragment (getter: ConstructorFragment?)
+    offset (getter: int)
     periodOffset (getter: int?)
     previousFragment (getter: ConstructorFragment?)
     typeName (getter: String?)
@@ -3775,6 +3776,7 @@
     new (constructor: ExtensionFragment Function())
     element (getter: ExtensionElement2)
     nextFragment (getter: ExtensionFragment?)
+    offset (getter: int)
     previousFragment (getter: ExtensionFragment?)
   ExtensionTypeElement2 (class extends Object implements InterfaceElement2):
     new (constructor: ExtensionTypeElement2 Function())
@@ -3815,6 +3817,7 @@
     new (constructor: FieldFragment Function())
     element (getter: FieldElement2)
     nextFragment (getter: FieldFragment?)
+    offset (getter: int)
     previousFragment (getter: FieldFragment?)
   FormalParameterElement (class extends Object implements PromotableElement2, Annotatable, HasSinceSdkVersion, LocalElement2):
     new (constructor: FormalParameterElement Function())
@@ -3841,6 +3844,7 @@
     new (constructor: FormalParameterFragment Function())
     element (getter: FormalParameterElement)
     nextFragment (getter: FormalParameterFragment?)
+    offset (getter: int)
     previousFragment (getter: FormalParameterFragment?)
   Fragment (class extends Object):
     new (constructor: Fragment Function())
@@ -3851,6 +3855,7 @@
     name2 (getter: String?)
     nameOffset2 (getter: int?)
     nextFragment (getter: Fragment?)
+    offset (getter: int)
     previousFragment (getter: Fragment?)
   FunctionTypedElement2 (class extends Object implements TypeParameterizedElement2):
     new (constructor: FunctionTypedElement2 Function())
@@ -3873,6 +3878,7 @@
     new (constructor: GenericFunctionTypeFragment Function())
     element (getter: GenericFunctionTypeElement2)
     nextFragment (getter: GenericFunctionTypeFragment?)
+    offset (getter: int)
     previousFragment (getter: GenericFunctionTypeFragment?)
   GetterElement (class extends Object implements PropertyAccessorElement2):
     new (constructor: GetterElement Function())
@@ -3884,6 +3890,7 @@
     new (constructor: GetterFragment Function())
     element (getter: GetterElement)
     nextFragment (getter: GetterFragment?)
+    offset (getter: int)
     previousFragment (getter: GetterFragment?)
   HasSinceSdkVersion (class extends Object):
     new (constructor: HasSinceSdkVersion Function())
@@ -3960,6 +3967,7 @@
     element (getter: JoinPatternVariableElement2)
     isConsistent (getter: bool)
     nextFragment (getter: JoinPatternVariableFragment?)
+    offset (getter: int)
     previousFragment (getter: JoinPatternVariableFragment?)
     variables2 (getter: List<PatternVariableFragment>)
   LabelElement2 (class extends Object implements Element2):
@@ -4035,6 +4043,7 @@
     lineInfo (getter: LineInfo)
     mixins2 (getter: List<MixinFragment>)
     nextFragment (getter: LibraryFragment?)
+    offset (getter: int)
     partIncludes (getter: List<PartInclude>)
     prefixes (getter: List<PrefixElement2>)
     previousFragment (getter: LibraryFragment?)
@@ -4061,6 +4070,7 @@
     fragments (getter: List<LocalFunctionFragment>)
   LocalFunctionFragment (class extends Object implements ExecutableFragment, LocalFragment):
     new (constructor: LocalFunctionFragment Function())
+    offset (getter: int)
   LocalVariableElement2 (class extends Object implements PromotableElement2, LocalElement2, Annotatable):
     new (constructor: LocalVariableElement2 Function())
     baseElement (getter: LocalVariableElement2)
@@ -4141,6 +4151,7 @@
     new (constructor: MultiplyDefinedFragment Function())
     element (getter: MultiplyDefinedElement2)
     nextFragment (getter: Null)
+    offset (getter: int)
     previousFragment (getter: Null)
   Name (class extends Object):
     forElement (static method: Name? Function(Element2))
@@ -4236,6 +4247,7 @@
     new (constructor: SetterFragment Function())
     element (getter: SetterElement)
     nextFragment (getter: SetterFragment?)
+    offset (getter: int)
     previousFragment (getter: SetterFragment?)
   ShowElementCombinator (see above)
   SuperFormalParameterElement2 (class extends Object implements FormalParameterElement):
@@ -4291,6 +4303,7 @@
     new (constructor: TypeDefiningFragment Function())
     element (getter: TypeDefiningElement2)
     nextFragment (getter: TypeDefiningFragment?)
+    offset (getter: int)
     previousFragment (getter: TypeDefiningFragment?)
   TypeParameterElement2 (class extends Object implements TypeDefiningElement2):
     new (constructor: TypeParameterElement2 Function())
diff --git a/pkg/analyzer/lib/dart/element/element2.dart b/pkg/analyzer/lib/dart/element/element2.dart
index 241417d..820b090 100644
--- a/pkg/analyzer/lib/dart/element/element2.dart
+++ b/pkg/analyzer/lib/dart/element/element2.dart
@@ -344,6 +344,18 @@
   @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
@@ -763,6 +775,13 @@
   @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;
 }
@@ -885,6 +904,14 @@
   @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;
 }
@@ -1003,6 +1030,14 @@
   @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;
 }
@@ -1083,6 +1118,18 @@
   /// 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.
@@ -1150,6 +1197,13 @@
   @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;
 }
@@ -1185,6 +1239,14 @@
   @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;
 }
@@ -1616,6 +1678,10 @@
   @override
   JoinPatternVariableFragment? get nextFragment;
 
+  /// The offset of the first variable in the join.
+  @override
+  int get offset;
+
   @override
   JoinPatternVariableFragment? get previousFragment;
 
@@ -1900,6 +1966,11 @@
   @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;
 
@@ -2010,6 +2081,13 @@
   //  top-level functions.
   // @override
   // LocalFunctionFragment? get previousFragment;
+
+  /// 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;
 }
 
 /// A local variable.
@@ -2291,6 +2369,10 @@
   @override
   Null get nextFragment;
 
+  /// Always returns zero.
+  @override
+  int get offset;
+
   @override
   Null get previousFragment;
 }
@@ -2593,6 +2675,14 @@
   @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;
 }
@@ -2804,6 +2894,13 @@
   @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;
 }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9a64f7b..2142b61 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1115,6 +1115,19 @@
   }
 
   @override
+  int get offset {
+    if (!identical(this, library.definingCompilationUnit)) {
+      // Not the first fragment, so there is no name; return an offset of 0
+      return 0;
+    }
+    if (library.nameOffset < 0) {
+      // There is no name, so return an offset of 0
+      return 0;
+    }
+    return library.nameOffset;
+  }
+
+  @override
   List<PartInclude> get partIncludes => parts.cast<PartInclude>();
 
   @override
@@ -1567,6 +1580,9 @@
   }
 
   @override
+  int get offset => isSynthetic ? enclosingElement3.offset : _nameOffset;
+
+  @override
   ConstructorFragment? get previousFragment => augmentationTarget;
 
   @override
@@ -2129,6 +2145,9 @@
   Null get nextFragment => null;
 
   @override
+  int get offset => 0;
+
+  @override
   Null get previousFragment => null;
 
   @override
@@ -3918,6 +3937,9 @@
   }
 
   @override
+  int get offset => _nameOffset;
+
+  @override
   List<ParameterElementImpl> get parameters {
     linkedData?.read(this);
     return _parameters;
@@ -4102,6 +4124,9 @@
       super.nextFragment as ExtensionElementImpl?;
 
   @override
+  int get offset => nameOffset2 ?? _codeOffset ?? 0;
+
+  @override
   ExtensionElementImpl? get previousFragment =>
       super.previousFragment as ExtensionElementImpl?;
 
@@ -4449,6 +4474,9 @@
   FieldElementImpl? get nextFragment => super.nextFragment as FieldElementImpl?;
 
   @override
+  int get offset => isSynthetic ? enclosingFragment!.offset : _nameOffset;
+
+  @override
   FieldElementImpl? get previousFragment =>
       super.previousFragment as FieldElementImpl?;
 
@@ -5479,6 +5507,9 @@
   GenericFunctionTypeElementImpl? get nextFragment => null;
 
   @override
+  int get offset => _nameOffset;
+
+  @override
   List<ParameterElementImpl> get parameters {
     return _parameters;
   }
@@ -5880,6 +5911,9 @@
   InstanceFragment? get nextFragment => augmentation as InstanceFragment?;
 
   @override
+  int get offset => _nameOffset;
+
+  @override
   InstanceFragment? get previousFragment =>
       augmentationTarget as InstanceFragment?;
 
@@ -7101,6 +7135,9 @@
       super.nextFragment as JoinPatternVariableElementImpl?;
 
   @override
+  int get offset => variables[0].offset;
+
+  @override
   JoinPatternVariableElementImpl? get previousFragment =>
       super.previousFragment as JoinPatternVariableElementImpl?;
 
@@ -7252,6 +7289,9 @@
   LabelElementImpl? get nextFragment => null;
 
   @override
+  int get offset => _nameOffset;
+
+  @override
   LabelElementImpl? get previousFragment => null;
 
   @override
@@ -9446,6 +9486,9 @@
   Null get nextFragment => null;
 
   @override
+  int get offset => 0;
+
+  @override
   Null get previousFragment => null;
 }
 
@@ -9494,6 +9537,9 @@
   Null get nextFragment => null;
 
   @override
+  int get offset => 0;
+
+  @override
   Null get previousFragment => null;
 
   @override
@@ -9842,6 +9888,9 @@
   }
 
   @override
+  int get offset => setter.offset;
+
+  @override
   TypeImpl get type => setter.variable2.type;
 
   @override
@@ -10209,6 +10258,9 @@
   int? nameOffset2;
 
   @override
+  int offset = 0;
+
+  @override
   final bool isDeferred;
 
   @override
@@ -10418,6 +10470,9 @@
   }
 
   @override
+  int get offset => variable2.offset;
+
+  @override
   TypeImpl get returnType => variable2.type;
 
   @override
@@ -10472,6 +10527,9 @@
   Element get nonSynthetic => variable2;
 
   @override
+  int get offset => variable2.offset;
+
+  @override
   List<ParameterElementImpl> get parameters {
     if (_parameters.isNotEmpty) {
       return _parameters;
@@ -11371,6 +11429,9 @@
   TypeAliasElementImpl? get nextFragment => null;
 
   @override
+  int get offset => nameOffset;
+
+  @override
   // TODO(augmentations): Support the fragment chain.
   TypeAliasElementImpl? get previousFragment => null;
 
@@ -11697,6 +11758,9 @@
   TypeParameterElementImpl? get nextFragment => null;
 
   @override
+  int get offset => nameOffset;
+
+  @override
   // TODO(augmentations): Support chaining between the fragments.
   TypeParameterElementImpl? get previousFragment => null;
 
@@ -12070,6 +12134,9 @@
   String get name => super.name!;
 
   @override
+  int get offset => nameOffset;
+
+  @override
   TypeImpl get type => _type!;
 
   set type(TypeImpl type) {
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index f686f25..ffdbdd7 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -662,6 +662,7 @@
 
         if (element.prefix2 case var prefixFragment?) {
           prefixFragment.nameOffset2 = info.prefixOffset2;
+          prefixFragment.offset = info.prefixOffset;
         }
         _applyToCombinators(element.combinators, info.combinators);
       },
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index f721d99..364a18e 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -541,6 +541,7 @@
       return _buildLibraryImportPrefixFragment(
         libraryFragment: containerUnit,
         unlinkedName: unlinked.name,
+        offset: unlinked.nameOffset,
         isDeferred: unlinked.deferredOffset != null,
       );
     });
@@ -642,6 +643,7 @@
   PrefixFragmentImpl _buildLibraryImportPrefixFragment({
     required CompilationUnitElementImpl libraryFragment,
     required UnlinkedLibraryImportPrefixName? unlinkedName,
+    required int offset,
     required bool isDeferred,
   }) {
     var fragment = PrefixFragmentImpl(
@@ -649,7 +651,7 @@
       name2: unlinkedName?.name,
       nameOffset2: unlinkedName?.nameOffset,
       isDeferred: isDeferred,
-    );
+    )..offset = offset;
 
     var containerRef = libraryFragment.reference!;
     var refName = unlinkedName?.name ?? '${_nextUnnamedId++}';
diff --git a/pkg/analyzer/test/dart/element/fragment_offset_test.dart b/pkg/analyzer/test/dart/element/fragment_offset_test.dart
new file mode 100644
index 0000000..bcd28eb
--- /dev/null
+++ b/pkg/analyzer/test/dart/element/fragment_offset_test.dart
@@ -0,0 +1,900 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element2.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../src/dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FragmentOffsetTest);
+  });
+}
+
+@reflectiveTest
+class FragmentOffsetTest extends PubPackageResolutionTest {
+  void checkOffset<F extends Fragment>(
+      AstNode declaration, Fragment fragment, int expectedOffset) {
+    var offset = checkOffsetInRange<F>(declaration, fragment);
+    expect(offset, expectedOffset);
+  }
+
+  /// Checks that the offset is in the range of the declaration, but doesn't
+  /// check the precise offset.
+  ///
+  /// Used in the case of error recovery, where the precise offset is
+  /// unspecified.
+  int checkOffsetInRange<F extends Fragment>(
+      AstNode declaration, Fragment fragment) {
+    expect(fragment, isA<F>());
+    var offset = fragment.offset;
+    expect(offset, greaterThanOrEqualTo(declaration.offset));
+    expect(offset, lessThanOrEqualTo(declaration.end));
+    return offset;
+  }
+
+  test_bindPatternVariableFragment() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore: unused_local_variable
+  var (int i,) = (0,);
+}
+''');
+    var declaredVariablePattern = findNode.declaredVariablePattern('int i');
+    checkOffset<BindPatternVariableFragment>(
+        declaredVariablePattern,
+        declaredVariablePattern.declaredFragment!,
+        declaredVariablePattern.name.offset);
+  }
+
+  test_classFragment() async {
+    await assertNoErrorsInCode(r'''
+class C {}
+''');
+    var classDeclaration = findNode.classDeclaration('C');
+    checkOffset<ClassFragment>(classDeclaration,
+        classDeclaration.declaredFragment!, classDeclaration.name.offset);
+  }
+
+  test_classFragment_classTypeAlias() async {
+    await assertNoErrorsInCode(r'''
+mixin M {}
+class C = Object with M;
+''');
+    var classTypeAlias = findNode.classTypeAlias('C');
+    checkOffset<ClassFragment>(classTypeAlias, classTypeAlias.declaredFragment!,
+        classTypeAlias.name.offset);
+  }
+
+  test_classFragment_classTypeAlias_missingName() async {
+    await assertErrorsInCode(r'''
+mixin M {}
+class = Object with M;
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
+    ]);
+    var classTypeAlias = findNode.classTypeAlias('Object with M');
+    checkOffsetInRange<ClassFragment>(
+        classTypeAlias, classTypeAlias.declaredFragment!);
+  }
+
+  test_classFragment_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the class declaration isn't at offset 0
+
+class {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 72, 1),
+    ]);
+    var classDeclaration = findNode.classDeclaration('class {}');
+    checkOffsetInRange<ClassFragment>(
+        classDeclaration, classDeclaration.declaredFragment!);
+  }
+
+  test_constructorFragment_implicit() async {
+    await assertNoErrorsInCode(r'''
+class C {}
+''');
+    var classDeclaration = findNode.classDeclaration('C');
+    checkOffset<ConstructorFragment>(
+        classDeclaration,
+        classDeclaration
+            .declaredFragment!.element.unnamedConstructor2!.firstFragment,
+        classDeclaration.name.offset);
+  }
+
+  test_constructorFragment_missingName() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.();
+}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
+    ]);
+    var constructorDeclaration = findNode.constructor('C.()');
+    checkOffsetInRange<ConstructorFragment>(
+        constructorDeclaration, constructorDeclaration.declaredFragment!);
+  }
+
+  test_constructorFragment_named() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C.foo();
+}
+''');
+    var constructorDeclaration = findNode.constructor('foo');
+    checkOffset<ConstructorFragment>(
+        constructorDeclaration,
+        constructorDeclaration.declaredFragment!,
+        constructorDeclaration.name!.offset);
+  }
+
+  test_constructorFragment_unnamed() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C();
+}
+''');
+    var constructorDeclaration = findNode.constructor('C()');
+    checkOffset<ConstructorFragment>(
+        constructorDeclaration,
+        constructorDeclaration.declaredFragment!,
+        constructorDeclaration.returnType.offset);
+  }
+
+  test_dynamicFragment() async {
+    await assertNoErrorsInCode(r'''
+dynamic d;
+''');
+    var namedType = findNode
+        .topLevelVariableDeclaration('dynamic d')
+        .variables
+        .type as NamedType;
+    expect(namedType.element2!.kind, ElementKind.DYNAMIC);
+    // `dynamic` isn't defined in the source code anywhere, so its offset is 0.
+    expect(namedType.element2!.firstFragment.offset, 0);
+  }
+
+  test_enumFragment() async {
+    await assertNoErrorsInCode(r'''
+enum E { e1 }
+''');
+    var enumDeclaration = findNode.enumDeclaration('E');
+    checkOffset<EnumFragment>(enumDeclaration,
+        enumDeclaration.declaredFragment!, enumDeclaration.name.offset);
+  }
+
+  test_enumFragment_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the enum declaration isn't at offset 0
+
+enum { e1 }
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 70, 1),
+    ]);
+    var enumDeclaration = findNode.enumDeclaration('enum { e1 }');
+    checkOffsetInRange<EnumFragment>(
+        enumDeclaration, enumDeclaration.declaredFragment!);
+  }
+
+  test_extensionFragment_named() async {
+    await assertNoErrorsInCode(r'''
+library; // Ensures that the extension declaration isn't at offset 0
+
+/// Documentation comment
+extension E on int {}
+''');
+    var extensionDeclaration = findNode.extensionDeclaration('on int');
+    checkOffset<ExtensionFragment>(
+        extensionDeclaration,
+        extensionDeclaration.declaredFragment!,
+        extensionDeclaration.name!.offset);
+  }
+
+  test_extensionFragment_unnamed() async {
+    await assertNoErrorsInCode(r'''
+extension on int {}
+''');
+    var extensionDeclaration = findNode.extensionDeclaration('on int');
+    checkOffset<ExtensionFragment>(
+        extensionDeclaration,
+        extensionDeclaration.declaredFragment!,
+        extensionDeclaration.extensionKeyword.offset);
+  }
+
+  test_extensionTypeFragment() async {
+    await assertNoErrorsInCode(r'''
+extension type E(int i) {}
+''');
+    var extensionTypeDeclaration = findNode.extensionTypeDeclaration('E');
+    checkOffset<ExtensionTypeFragment>(
+        extensionTypeDeclaration,
+        extensionTypeDeclaration.declaredFragment!,
+        extensionTypeDeclaration.name.offset);
+  }
+
+  test_extensionTypeFragment_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the extension type declaration isn't at offset 0
+
+extension type(int i) {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 89, 1),
+    ]);
+    var extensionTypeDeclaration =
+        findNode.extensionTypeDeclaration('extension type(int i)');
+    checkOffsetInRange<ExtensionTypeFragment>(
+        extensionTypeDeclaration, extensionTypeDeclaration.declaredFragment!);
+  }
+
+  test_fieldFormalParameterFragment() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  final int i;
+  C(this.i);
+}
+''');
+    var parameter = findNode.fieldFormalParameter('this.i');
+    checkOffset<FieldFormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name.offset);
+  }
+
+  test_fieldFormalParameterFragment_missingName() async {
+    await assertErrorsInCode(r'''
+class C {
+  int? x;
+  C(this.);
+}
+''', [
+      error(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD, 24,
+          5),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 29, 1),
+    ]);
+    var parameter = findNode.fieldFormalParameter('this.');
+    checkOffsetInRange<FieldFormalParameterFragment>(
+        parameter, parameter.declaredFragment!);
+  }
+
+  test_fieldFormalParameterFragment_withDefaultValue() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  final int i;
+  C({this.i = 0});
+}
+''');
+    var parameter = findNode.fieldFormalParameter('this.i');
+    checkOffset<FieldFormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name.offset);
+  }
+
+  test_fieldFragment() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int? x;
+}
+''');
+    var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
+    checkOffset<FieldFragment>(fieldDeclaration,
+        fieldDeclaration.declaredFragment!, fieldDeclaration.name.offset);
+  }
+
+  test_fieldFragment_const() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static const int x = 0;
+}
+''');
+    var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
+    checkOffset<FieldFragment>(fieldDeclaration,
+        fieldDeclaration.declaredFragment!, fieldDeclaration.name.offset);
+  }
+
+  test_fieldFragment_enum_constant() async {
+    await assertNoErrorsInCode(r'''
+enum E { e1 }
+''');
+    var enumConstantDeclaration = findNode.enumConstantDeclaration('e1');
+    checkOffset<FieldFragment>(
+        enumConstantDeclaration,
+        enumConstantDeclaration.declaredFragment!,
+        enumConstantDeclaration.name.offset);
+  }
+
+  test_fieldFragment_enum_values() async {
+    await assertNoErrorsInCode(r'''
+enum E { e1 }
+''');
+    var enumDeclaration = findNode.enumDeclaration('E');
+    checkOffset<FieldFragment>(
+        enumDeclaration,
+        enumDeclaration.declaredFragment!.element
+            .getField2('values')!
+            .firstFragment,
+        enumDeclaration.name.offset);
+  }
+
+  test_fieldFragment_extensionTypeRepresentationField() async {
+    await assertNoErrorsInCode(r'''
+extension type E(int i) {}
+''');
+    var representationDeclaration =
+        findNode.extensionTypeDeclaration('int i').representation;
+    checkOffset<FieldFragment>(
+        representationDeclaration,
+        representationDeclaration.fieldFragment!,
+        representationDeclaration.fieldName.offset);
+  }
+
+  test_formalParameterFragment() async {
+    await assertNoErrorsInCode(r'''
+void f(int x) {}
+''');
+    var parameter = findNode.simpleFormalParameter('x');
+    checkOffset<FormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name!.offset);
+  }
+
+  test_formalParameterFragment_missingName() async {
+    await assertErrorsInCode(r'''
+void f((int x)) {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 7, 1),
+    ]);
+    var function = findNode.functionDeclaration('f(');
+    var parameter = function.functionExpression.parameters!.parameters[0]
+        as FunctionTypedFormalParameter;
+    expect(parameter.name.isSynthetic, true);
+    checkOffsetInRange<FormalParameterFragment>(
+        parameter, parameter.declaredFragment!);
+  }
+
+  test_formalParameterFragment_missingName2() async {
+    await assertErrorsInCode(r'''
+void f(void (int x)) {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
+    ]);
+    var function = findNode.functionDeclaration('f(');
+    var parameter = function.functionExpression.parameters!.parameters[0]
+        as FunctionTypedFormalParameter;
+    expect(parameter.name.isSynthetic, true);
+    checkOffsetInRange<FormalParameterFragment>(
+        parameter, parameter.declaredFragment!);
+  }
+
+  test_formalParameterFragment_ofImplicitSetter_member_implicit() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int? x;
+}
+''');
+    var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
+    checkOffset<FormalParameterFragment>(
+        fieldDeclaration,
+        (fieldDeclaration.declaredFragment as FieldFragment)
+            .element
+            .setter2!
+            .formalParameters
+            .single
+            .firstFragment,
+        fieldDeclaration.name.offset);
+  }
+
+  test_formalParameterFragment_ofImplicitSetter_topLevel_implicit() async {
+    await assertNoErrorsInCode(r'''
+int? x;
+''');
+    var topLevelVariableDeclaration =
+        findNode.topLevelVariableDeclaration('x').variables.variables[0];
+    checkOffset<FormalParameterFragment>(
+        topLevelVariableDeclaration,
+        (topLevelVariableDeclaration.declaredFragment
+                as TopLevelVariableFragment)
+            .element
+            .setter2!
+            .formalParameters
+            .single
+            .firstFragment,
+        topLevelVariableDeclaration.name.offset);
+  }
+
+  test_formalParameterFragment_withDefaultValue() async {
+    await assertNoErrorsInCode(r'''
+void f({int x = 0}) {}
+''');
+    var parameter = findNode.simpleFormalParameter('x');
+    checkOffset<FormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name!.offset);
+  }
+
+  test_genericFunctionTypeFragment() async {
+    await assertNoErrorsInCode(r'''
+library; // Ensures that the generic function type isn't at offset 0
+
+void Function(int x)? f;
+''');
+    var genericFunctionType =
+        findNode.genericFunctionType('void Function(int x)?');
+    checkOffset<GenericFunctionTypeFragment>(genericFunctionType,
+        genericFunctionType.declaredFragment!, genericFunctionType.offset);
+  }
+
+  test_getterFragment_member() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int get foo => 0;
+}
+''');
+    var getterDeclaration = findNode.methodDeclaration('foo');
+    checkOffset<GetterFragment>(getterDeclaration,
+        getterDeclaration.declaredFragment!, getterDeclaration.name.offset);
+  }
+
+  test_getterFragment_member_implicit() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int? x;
+}
+''');
+    var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
+    checkOffset<GetterFragment>(
+        fieldDeclaration,
+        (fieldDeclaration.declaredFragment as FieldFragment)
+            .element
+            .getter2!
+            .firstFragment,
+        fieldDeclaration.name.offset);
+  }
+
+  test_getterFragment_topLevel() async {
+    await assertNoErrorsInCode(r'''
+int get foo => 0;
+''');
+    var getterDeclaration = findNode.functionDeclaration('foo');
+    checkOffset<GetterFragment>(getterDeclaration,
+        getterDeclaration.declaredFragment!, getterDeclaration.name.offset);
+  }
+
+  test_getterFragment_topLevel_implicit() async {
+    await assertNoErrorsInCode(r'''
+int? x;
+''');
+    var topLevelVariableDeclaration =
+        findNode.topLevelVariableDeclaration('x').variables.variables[0];
+    checkOffset<GetterFragment>(
+        topLevelVariableDeclaration,
+        (topLevelVariableDeclaration.declaredFragment
+                as TopLevelVariableFragment)
+            .element
+            .getter2!
+            .firstFragment,
+        topLevelVariableDeclaration.name.offset);
+  }
+
+  test_joinPatternVariableFragment() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  switch ((0,) as dynamic) {
+    // ignore: unused_local_variable
+    case (var i,) || (:var i,):
+      break;
+  }
+}
+''');
+    var firstDeclaredVariablePattern =
+        findNode.declaredVariablePattern('var i,) ||');
+    checkOffset<JoinPatternVariableFragment>(
+        firstDeclaredVariablePattern,
+        firstDeclaredVariablePattern.declaredFragment!.join2!,
+        firstDeclaredVariablePattern.name.offset);
+  }
+
+  test_labelFragment() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore: unused_label
+  L: while(true) {}
+}
+''');
+    var label = findNode.label('L');
+    checkOffset<LabelFragment>(
+        label, label.declaredFragment!, label.label.offset);
+  }
+
+  test_libraryFragment_first_named() async {
+    await assertNoErrorsInCode(r'''
+// Comment to ensure that the library declaration isn't at offset 0
+library L;
+
+class C {}
+''');
+    var unit = findNode.unit;
+    checkOffset<LibraryFragment>(
+        unit, unit.declaredFragment!, findNode.library('L').name2!.offset);
+  }
+
+  test_libraryFragment_first_unnamed_withLibraryDeclaration() async {
+    await assertNoErrorsInCode(r'''
+// Comment to ensure that the library declaration isn't at offset 0
+library;
+
+class C {}
+''');
+    var unit = findNode.unit;
+    checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
+  }
+
+  test_libraryFragment_first_unnamed_withoutLibraryDeclaration() async {
+    await assertNoErrorsInCode(r'''
+// Comment to ensure that the class declaration isn't at offset 0
+class C {}
+''');
+    var unit = findNode.unit;
+    checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
+  }
+
+  test_libraryFragment_notFirst_named() async {
+    newFile('$testPackageLibPath/lib.dart', r'''
+library L;
+
+part 'part.dart';
+''');
+    newFile('$testPackageLibPath/part.dart', r'''
+// Comment to ensure that the "part of" declaration isn't at offset 0
+part of 'lib.dart';
+
+class C {}
+''');
+    await resolveFile2(getFile('$testPackageLibPath/part.dart'));
+    assertErrorsInResolvedUnit(result, const []);
+
+    var unit = findNode.unit;
+    checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
+  }
+
+  test_libraryFragment_notFirst_unnamed() async {
+    newFile('$testPackageLibPath/lib.dart', r'''
+part 'part.dart';
+''');
+    newFile('$testPackageLibPath/part.dart', r'''
+// Comment to ensure that the "part of" declaration isn't at offset 0
+part of 'lib.dart';
+
+class C {}
+''');
+    await resolveFile2(getFile('$testPackageLibPath/part.dart'));
+    assertErrorsInResolvedUnit(result, const []);
+
+    var unit = findNode.unit;
+    checkOffset<LibraryFragment>(unit, unit.declaredFragment!, 0);
+  }
+
+  test_local_variable_fragment() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore: unused_local_variable
+  int i = 0;
+}
+''');
+    var localVariable = findNode.variableDeclaration('i = 0');
+    checkOffset<LocalVariableFragment>(localVariable,
+        localVariable.declaredFragment!, localVariable.name.offset);
+  }
+
+  test_local_variable_fragment_const() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore: unused_local_variable
+  const int i = 0;
+}
+''');
+    var localVariable = findNode.variableDeclaration('i = 0');
+    checkOffset<LocalVariableFragment>(localVariable,
+        localVariable.declaredFragment!, localVariable.name.offset);
+  }
+
+  test_localFunctionFragment_named() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  // ignore: unused_element
+  void g() {}
+}
+''');
+    var localFunction =
+        findNode.functionDeclarationStatement('g()').functionDeclaration;
+    checkOffset<LocalFunctionFragment>(localFunction,
+        localFunction.declaredFragment!, localFunction.name.offset);
+  }
+
+  test_localFunctionFragment_unnamed() async {
+    await assertNoErrorsInCode(r'''
+dynamic f() {
+  return () {};
+}
+''');
+    var localFunction = findNode.functionExpression('() {}');
+    checkOffset<LocalFunctionFragment>(
+        localFunction,
+        localFunction.declaredFragment!,
+        localFunction.parameters!.leftParenthesis.offset);
+  }
+
+  test_methodFragment() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  void foo() {}
+}
+''');
+    var methodDeclaration = findNode.methodDeclaration('foo');
+    checkOffset<MethodFragment>(methodDeclaration,
+        methodDeclaration.declaredFragment!, methodDeclaration.name.offset);
+  }
+
+  test_mixinFragment() async {
+    await assertNoErrorsInCode(r'''
+mixin M {}
+''');
+    var mixinDeclaration = findNode.mixinDeclaration('M');
+    checkOffset<MixinFragment>(mixinDeclaration,
+        mixinDeclaration.declaredFragment!, mixinDeclaration.name.offset);
+  }
+
+  test_mixinFragment_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the mixin declaration isn't at offset 0
+
+mixin {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 72, 1),
+    ]);
+    var mixinDeclaration = findNode.mixinDeclaration('mixin {}');
+    checkOffsetInRange<MixinFragment>(
+        mixinDeclaration, mixinDeclaration.declaredFragment!);
+  }
+
+  test_neverFragment() async {
+    await assertNoErrorsInCode(r'''
+Never n = throw '';
+''');
+    var namedType = findNode
+        .topLevelVariableDeclaration('Never n')
+        .variables
+        .type as NamedType;
+    expect(namedType.element2!.kind, ElementKind.NEVER);
+    // `Never` isn't defined in the source code anywhere, so its offset is 0.
+    expect(namedType.element2!.firstFragment.offset, 0);
+  }
+
+  test_prefixFragment() async {
+    await assertNoErrorsInCode(r'''
+// ignore: unused_import
+import 'dart:async' as a;
+''');
+    var importDirective = findNode.import('as a');
+    checkOffset<PrefixFragment>(
+        importDirective,
+        importDirective.libraryImport!.prefix2!,
+        importDirective.prefix!.offset);
+  }
+
+  test_prefixFragment_inMultipleImports() async {
+    await assertNoErrorsInCode(r'''
+// ignore: unused_import
+import 'dart:async' as a; // first
+// ignore: unused_import
+import 'dart:math' as a; // second
+''');
+    var firstImportDirective = findNode.import('as a; // first');
+    checkOffset<PrefixFragment>(
+        firstImportDirective,
+        firstImportDirective.libraryImport!.prefix2!,
+        firstImportDirective.prefix!.offset);
+  }
+
+  test_prefixFragment_missingName() async {
+    await assertErrorsInCode(r'''
+// ignore: unused_import
+import 'dart:async' as;
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 47, 1),
+    ]);
+    var importDirective = findNode.import('as;');
+    checkOffsetInRange<PrefixFragment>(
+        importDirective, importDirective.libraryImport!.prefix2!);
+  }
+
+  test_setterFragment_member() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  set foo(int value) {}
+}
+''');
+    var setterDeclaration = findNode.methodDeclaration('foo');
+    checkOffset<SetterFragment>(setterDeclaration,
+        setterDeclaration.declaredFragment!, setterDeclaration.name.offset);
+  }
+
+  test_setterFragment_member_implicit() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  int? x;
+}
+''');
+    var fieldDeclaration = findNode.fieldDeclaration('x').fields.variables[0];
+    checkOffset<SetterFragment>(
+        fieldDeclaration,
+        (fieldDeclaration.declaredFragment as FieldFragment)
+            .element
+            .setter2!
+            .firstFragment,
+        fieldDeclaration.name.offset);
+  }
+
+  test_setterFragment_topLevel() async {
+    await assertNoErrorsInCode(r'''
+set foo(int value) {}
+''');
+    var setterDeclaration = findNode.functionDeclaration('foo');
+    checkOffset<SetterFragment>(setterDeclaration,
+        setterDeclaration.declaredFragment!, setterDeclaration.name.offset);
+  }
+
+  test_setterFragment_topLevel_implicit() async {
+    await assertNoErrorsInCode(r'''
+int? x;
+''');
+    var topLevelVariableDeclaration =
+        findNode.topLevelVariableDeclaration('x').variables.variables[0];
+    checkOffset<SetterFragment>(
+        topLevelVariableDeclaration,
+        (topLevelVariableDeclaration.declaredFragment
+                as TopLevelVariableFragment)
+            .element
+            .setter2!
+            .firstFragment,
+        topLevelVariableDeclaration.name.offset);
+  }
+
+  test_superFormalParameterFragment() async {
+    await assertNoErrorsInCode(r'''
+class B {
+  B(int i);
+}
+
+class C extends B {
+  C(super.i);
+}
+''');
+    var parameter = findNode.superFormalParameter('super.i');
+    checkOffset<SuperFormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name.offset);
+  }
+
+  test_superFormalParameterFragment_missingName() async {
+    await assertErrorsInCode(r'''
+class B {
+  B([int? i]);
+}
+
+class C extends B {
+  C(super.);
+}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 58, 1),
+    ]);
+    var parameter = findNode.superFormalParameter('super.');
+    checkOffsetInRange<SuperFormalParameterFragment>(
+        parameter, parameter.declaredFragment!);
+  }
+
+  test_superFormalParameterFragment_withDefaultValue() async {
+    await assertNoErrorsInCode(r'''
+class B {
+  B({int? i});
+}
+
+class C extends B {
+  C({super.i = 0});
+}
+''');
+    var parameter = findNode.superFormalParameter('super.i');
+    checkOffset<SuperFormalParameterFragment>(
+        parameter, parameter.declaredFragment!, parameter.name.offset);
+  }
+
+  test_topLevelFunctionFragment() async {
+    await assertNoErrorsInCode(r'''
+void foo() {}
+''');
+    var topLevelFunctionDeclaration = findNode.functionDeclaration('foo');
+    checkOffset<TopLevelFunctionFragment>(
+        topLevelFunctionDeclaration,
+        topLevelFunctionDeclaration.declaredFragment!,
+        topLevelFunctionDeclaration.name.offset);
+  }
+
+  test_topLevelVariableFragment() async {
+    await assertNoErrorsInCode(r'''
+int? x;
+''');
+    var topLevelVariableDeclaration =
+        findNode.topLevelVariableDeclaration('x').variables.variables[0];
+    checkOffset<TopLevelVariableFragment>(
+        topLevelVariableDeclaration,
+        topLevelVariableDeclaration.declaredFragment!,
+        topLevelVariableDeclaration.name.offset);
+  }
+
+  test_topLevelVariableFragment_const() async {
+    await assertNoErrorsInCode(r'''
+const int x = 0;
+''');
+    var topLevelVariableDeclaration =
+        findNode.topLevelVariableDeclaration('x').variables.variables[0];
+    checkOffset<TopLevelVariableFragment>(
+        topLevelVariableDeclaration,
+        topLevelVariableDeclaration.declaredFragment!,
+        topLevelVariableDeclaration.name.offset);
+  }
+
+  test_typeAliasFragment_functionTypeAlias() async {
+    await assertNoErrorsInCode(r'''
+typedef void F();
+''');
+    var functionTypeAlias = findNode.functionTypeAlias('F');
+    checkOffset<TypeAliasFragment>(functionTypeAlias,
+        functionTypeAlias.declaredFragment!, functionTypeAlias.name.offset);
+  }
+
+  test_typeAliasFragment_functionTypeAlias_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the function type alias declaration isn't at offset 0
+
+typedef void();
+''', [
+      error(WarningCode.UNUSED_ELEMENT, 0, 0),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 92, 1),
+    ]);
+    var functionTypeAlias = findNode.functionTypeAlias('void()');
+    checkOffsetInRange<TypeAliasFragment>(
+        functionTypeAlias, functionTypeAlias.declaredFragment!);
+  }
+
+  test_typeAliasFragment_genericTypeAlias() async {
+    await assertNoErrorsInCode(r'''
+typedef T = int;
+''');
+    var genericTypeAlias = findNode.genericTypeAlias('T');
+    checkOffset<TypeAliasFragment>(genericTypeAlias,
+        genericTypeAlias.declaredFragment!, genericTypeAlias.name.offset);
+  }
+
+  test_typeAliasFragment_genericTypeAlias_missingName() async {
+    await assertErrorsInCode(r'''
+library; // Ensures that the generic type alias declaration isn't at offset 0
+
+typedef = int;
+''', [
+      error(WarningCode.UNUSED_ELEMENT, 0, 0),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 87, 1),
+    ]);
+    var genericTypeAlias = findNode.genericTypeAlias('= int');
+    checkOffsetInRange<TypeAliasFragment>(
+        genericTypeAlias, genericTypeAlias.declaredFragment!);
+  }
+
+  test_typeParameterFragment() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+''');
+    var typeParameter = findNode.typeParameter('T');
+    checkOffset<TypeParameterFragment>(typeParameter,
+        typeParameter.declaredFragment!, typeParameter.name.offset);
+  }
+}
diff --git a/pkg/analyzer/test/dart/element/test_all.dart b/pkg/analyzer/test/dart/element/test_all.dart
index 9f450b6..86ec8ad 100644
--- a/pkg/analyzer/test/dart/element/test_all.dart
+++ b/pkg/analyzer/test/dart/element/test_all.dart
@@ -5,12 +5,14 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'element_test.dart' as element;
+import 'fragment_offset_test.dart' as fragment_offset;
 import 'type_test.dart' as type;
 
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     element.main();
+    fragment_offset.main();
     type.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 9dcc065..7f84548 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -1046,6 +1046,9 @@
       _sink.writeIf(fragment.isDeferred, ' deferred');
       _sink.write(' as ');
       _writeFragmentName(fragment);
+      if (fragment.offset != fragment.nameOffset2) {
+        _sink.write(' (offset=${fragment.offset})');
+      }
     }
   }
 
diff --git a/pkg/analyzer/test/src/summary/elements/library_import_test.dart b/pkg/analyzer/test/src/summary/elements/library_import_test.dart
index 68396b4..914001d 100644
--- a/pkg/analyzer/test/src/summary/elements/library_import_test.dart
+++ b/pkg/analyzer/test/src/summary/elements/library_import_test.dart
@@ -858,7 +858,7 @@
     <testLibraryFragment>
       element: <testLibrary>
       libraryImports
-        dart:math as <null-name>
+        dart:math as <null-name> (offset=21)
       prefixes
         <testLibraryFragment>::@prefix2::1
           fragments: @null