Version 2.18.0-278.0.dev

Merge commit '4c263d3754cc793671eee6346ced1c63e191064a' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8979c8..9b8f7c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,10 @@
 
 - Deprecates `BidirectionalIterator`.
 
+### `dart:developer`
+
+- Deprecates `UserTag.MAX_USER_TAGS` in favor of `UserTag.maxUserTags`.
+
 ### Dart VM
 
 Implementation of `async`/`async*`/`sync*` is revamped in Dart VM,
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 39f7c88d..57df318 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -295,7 +295,7 @@
     return sb.toString();
   }
 
-  Variable variableForKey(int key) => _promotionKeyStore.variableForKey(key);
+  Variable variableForKey(int key) => _promotionKeyStore.variableForKey(key)!;
 
   Set<int> writtenInNode(Node node) => _getInfoForNode(node)._written;
 }
@@ -1833,13 +1833,11 @@
   ///
   /// A local variable is [initialized] if its declaration has an initializer.
   /// A function parameter is always initialized, so [initialized] is `true`.
-  FlowModel<Type> declare<Variable extends Object>(
-      Variable variable, int variableKey, bool initialized) {
+  FlowModel<Type> declare(int variableKey, bool initialized) {
     VariableModel<Type> newInfoForVar =
         new VariableModel.fresh(assigned: initialized);
 
-    return _updateVariableInfo(
-        new VariableReference(variable, variableKey), newInfoForVar);
+    return _updateVariableInfo(variableKey, newInfoForVar);
   }
 
   /// Gets the info for the given [promotionKey], creating it if it doesn't
@@ -1997,10 +1995,11 @@
   ///
   /// Note that the state is only changed if the previous type of [variable] was
   /// potentially nullable.
-  ExpressionInfo<Type> tryMarkNonNullable(TypeOperations<Type> typeOperations,
-      ReferenceWithType<Type> referenceWithType) {
-    VariableModel<Type> info =
-        referenceWithType.reference.getInfo(variableInfo);
+  ExpressionInfo<Type> tryMarkNonNullable(
+      TypeOperations<Type> typeOperations,
+      ReferenceWithType<Type> referenceWithType,
+      PromotionKeyStore<Object> promotionKeyStore) {
+    VariableModel<Type> info = _getInfo(referenceWithType.promotionKey);
     if (info.writeCaptured) {
       return new _TrivialExpressionInfo<Type>(this);
     }
@@ -2012,8 +2011,8 @@
     }
     assert(typeOperations.isSubtypeOf(newType, previousType));
 
-    FlowModel<Type> ifTrue = _finishTypeTest(
-        typeOperations, referenceWithType.reference, info, null, newType);
+    FlowModel<Type> ifTrue = _finishTypeTest(typeOperations, referenceWithType,
+        info, null, newType, promotionKeyStore);
 
     return new ExpressionInfo<Type>(after: this, ifTrue: ifTrue, ifFalse: this);
   }
@@ -2027,10 +2026,12 @@
   ///
   /// TODO(paulberry): if the type is non-nullable, should this method mark the
   /// variable as definitely assigned?  Does it matter?
-  FlowModel<Type> tryPromoteForTypeCast(TypeOperations<Type> typeOperations,
-      ReferenceWithType<Type> referenceWithType, Type type) {
-    VariableModel<Type> info =
-        referenceWithType.reference.getInfo(variableInfo);
+  FlowModel<Type> tryPromoteForTypeCast(
+      TypeOperations<Type> typeOperations,
+      ReferenceWithType<Type> referenceWithType,
+      Type type,
+      PromotionKeyStore<Object> promotionKeyStore) {
+    VariableModel<Type> info = _getInfo(referenceWithType.promotionKey);
     if (info.writeCaptured) {
       return this;
     }
@@ -2043,8 +2044,8 @@
 
     assert(typeOperations.isSubtypeOf(newType, previousType),
         "Expected $newType to be a subtype of $previousType.");
-    return _finishTypeTest(
-        typeOperations, referenceWithType.reference, info, type, newType);
+    return _finishTypeTest(typeOperations, referenceWithType, info, type,
+        newType, promotionKeyStore);
   }
 
   /// Returns an [ExpressionInfo] indicating the result of checking whether the
@@ -2059,9 +2060,9 @@
   ExpressionInfo<Type> tryPromoteForTypeCheck(
       TypeOperations<Type> typeOperations,
       ReferenceWithType<Type> referenceWithType,
-      Type type) {
-    VariableModel<Type> info =
-        referenceWithType.reference.getInfo(variableInfo);
+      Type type,
+      PromotionKeyStore<Object> promotionKeyStore) {
+    VariableModel<Type> info = _getInfo(referenceWithType.promotionKey);
     if (info.writeCaptured) {
       return new _TrivialExpressionInfo<Type>(this);
     }
@@ -2073,8 +2074,8 @@
         !typeOperations.isSameType(typeIfSuccess, previousType)) {
       assert(typeOperations.isSubtypeOf(typeIfSuccess, previousType),
           "Expected $typeIfSuccess to be a subtype of $previousType.");
-      ifTrue = _finishTypeTest(typeOperations, referenceWithType.reference,
-          info, type, typeIfSuccess);
+      ifTrue = _finishTypeTest(typeOperations, referenceWithType, info, type,
+          typeIfSuccess, promotionKeyStore);
     }
 
     Type factoredType = typeOperations.factor(previousType, type);
@@ -2089,8 +2090,8 @@
     } else {
       typeIfFalse = factoredType;
     }
-    FlowModel<Type> ifFalse = _finishTypeTest(
-        typeOperations, referenceWithType.reference, info, type, typeIfFalse);
+    FlowModel<Type> ifFalse = _finishTypeTest(typeOperations, referenceWithType,
+        info, type, typeIfFalse, promotionKeyStore);
 
     return new ExpressionInfo<Type>(
         after: this, ifTrue: ifTrue, ifFalse: ifFalse);
@@ -2135,8 +2136,7 @@
         promoteToTypeOfInterest: promoteToTypeOfInterest);
     if (identical(newInfoForVar, infoForVar)) return this;
 
-    return _updateVariableInfo(
-        new VariableReference(variable, variableKey), newInfoForVar);
+    return _updateVariableInfo(variableKey, newInfoForVar);
   }
 
   /// Common algorithm for [tryMarkNonNullable], [tryPromoteForTypeCast],
@@ -2151,12 +2151,12 @@
   ///   no redundant or side-promotions)
   /// - The variable should not be write-captured.
   FlowModel<Type> _finishTypeTest(
-    TypeOperations<Type> typeOperations,
-    Reference<Type> reference,
-    VariableModel<Type> info,
-    Type? testedType,
-    Type? promotedType,
-  ) {
+      TypeOperations<Type> typeOperations,
+      ReferenceWithType<Type> reference,
+      VariableModel<Type> info,
+      Type? testedType,
+      Type? promotedType,
+      PromotionKeyStore<Object> promotionKeyStore) {
     List<Type> newTested = info.tested;
     if (testedType != null) {
       newTested = VariableModel._addTypeToUniqueList(
@@ -2168,7 +2168,7 @@
     if (promotedType != null) {
       newPromotedTypes =
           VariableModel._addToPromotedTypes(info.promotedTypes, promotedType);
-      if (reference is VariableReference<Object, Object> &&
+      if (reference.isPromotable(promotionKeyStore) &&
           typeOperations.isNever(promotedType)) {
         newReachable = reachable.setUnreachable();
       }
@@ -2179,7 +2179,7 @@
             newReachable == reachable
         ? this
         : _updateVariableInfo(
-            reference,
+            reference.promotionKey,
             new VariableModel<Type>(
                 promotedTypes: newPromotedTypes,
                 tested: newTested,
@@ -2190,15 +2190,20 @@
             reachable: newReachable);
   }
 
+  /// Gets the info for [promotionKey] reference, creating it if it doesn't
+  /// exist.
+  VariableModel<Type> _getInfo(int promotionKey) =>
+      variableInfo[promotionKey] ?? new VariableModel<Type>.fresh();
+
   /// Returns a new [FlowModel] where the information for [reference] is
   /// replaced with [model].
   FlowModel<Type> _updateVariableInfo(
-      Reference<Type> reference, VariableModel<Type> model,
+      int promotionKey, VariableModel<Type> model,
       {Reachability? reachable}) {
     reachable ??= this.reachable;
     Map<int, VariableModel<Type>> newVariableInfo =
         new Map<int, VariableModel<Type>>.of(variableInfo);
-    reference.storeInfo(newVariableInfo, model);
+    newVariableInfo[promotionKey] = model;
     return new FlowModel<Type>.withInfo(reachable, newVariableInfo);
   }
 
@@ -2445,7 +2450,7 @@
       _variableKeys[variable] ??= _makeNewKey(variable);
 
   @visibleForTesting
-  Variable variableForKey(int variableKey) => _keyToVariable[variableKey]!;
+  Variable? variableForKey(int variableKey) => _keyToVariable[variableKey];
 
   int _makeNewKey(Variable? variable) {
     int key = _keyToVariable.length;
@@ -2626,60 +2631,20 @@
   }
 }
 
-/// Abstract base class representing a reference to a storage location that
-/// might be of interest to flow analysis to track.  This could be a variable,
-/// `this`, or the result of a property access on some other reference.
-///
-/// Note that only variables can undergo promotion, but flow analysis may track
-/// other references in order to give useful error messages to the user about
-/// why promotion did not occur.
-@visibleForTesting
-abstract class Reference<Type extends Object> {
-  /// The reference's corresponding key, as assigned by [PromotionKeyStore].
-  final int promotionKey;
-
-  Reference(this.promotionKey);
-
-  /// Gets the info for this reference, creating it if it doesn't exist.
-  VariableModel<Type> getInfo(Map<int, VariableModel<Type>> variableInfo) =>
-      _getInfo(variableInfo) ?? new VariableModel<Type>.fresh();
-
-  /// Gets a map of non-promotion reasons associated with this reference.  This
-  /// is the map that will be returned from [FlowAnalysis.whyNotPromoted].
-  Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
-      Map<int, VariableModel<Type>> variableInfo,
-      Type staticType,
-      TypeOperations<Type> operations);
-
-  /// Creates a reference representing a get of a property called [propertyName]
-  /// on the reference represented by `this`.
-  Reference<Type> propertyGet(PromotionKeyStore promotionKeyStore,
-          String propertyName, Object? propertyMember) =>
-      new _PropertyGetReference<Type>(propertyName, propertyMember,
-          promotionKeyStore.getProperty(promotionKey, propertyName));
-
-  /// Stores info for this reference in [variableInfo].
-  void storeInfo(Map<int, VariableModel<Type>> variableInfo,
-      VariableModel<Type> variableModel) {
-    variableInfo[promotionKey] = variableModel;
-  }
-
-  /// Gets the info for this reference, or `null` if it doesn't exist.
-  VariableModel<Type>? _getInfo(Map<int, VariableModel<Type>> variableInfo) =>
-      variableInfo[promotionKey];
-}
-
 /// Container object combining a [Reference] object with its static type.
 @visibleForTesting
 class ReferenceWithType<Type extends Object> {
-  final Reference<Type> reference;
+  int promotionKey;
 
   final Type type;
 
-  ReferenceWithType(this.reference, this.type);
+  ReferenceWithType(this.promotionKey, this.type);
+
+  bool isPromotable(PromotionKeyStore<Object> promotionKeyStore) =>
+      promotionKeyStore.variableForKey(promotionKey) != null;
 
   @override
-  String toString() => 'ReferenceWithType($reference, $type)';
+  String toString() => 'ReferenceWithType($promotionKey, $type)';
 }
 
 /// Data structure representing a unique value that a variable might take on
@@ -3352,46 +3317,6 @@
   Type variableType(Variable variable);
 }
 
-/// Specialization of [Reference] representing a reference to a local variable
-/// (or function parameter).
-@visibleForTesting
-class VariableReference<Variable extends Object, Type extends Object>
-    extends Reference<Type> {
-  /// The variable being referred to.
-  final Variable variable;
-
-  VariableReference(this.variable, super.promotionKey);
-
-  @override
-  Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
-      Map<int, VariableModel<Type>> variableInfo,
-      Type staticType,
-      covariant Operations<Variable, Type> operations) {
-    VariableModel<Type>? currentVariableInfo = variableInfo[promotionKey];
-    if (currentVariableInfo == null) {
-      return () => {};
-    }
-    return () {
-      Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
-      Type currentType = currentVariableInfo.promotedTypes?.last ??
-          operations.variableType(variable);
-      NonPromotionHistory? nonPromotionHistory =
-          currentVariableInfo.nonPromotionHistory;
-      while (nonPromotionHistory != null) {
-        Type nonPromotedType = nonPromotionHistory.type;
-        if (!operations.isSubtypeOf(currentType, nonPromotedType)) {
-          result[nonPromotedType] ??= nonPromotionHistory.nonPromotionReason;
-        }
-        nonPromotionHistory = nonPromotionHistory.previous;
-      }
-      return result;
-    };
-  }
-
-  @override
-  String toString() => 'VariableReference($variable, $promotionKey)';
-}
-
 class WhyNotPromotedInfo {}
 
 /// [_FlowContext] representing an assert statement or assert initializer.
@@ -3526,8 +3451,7 @@
     Set<int> implicitlyDeclaredVars = {...anywhere._read, ...anywhere._written};
     implicitlyDeclaredVars.removeAll(anywhere._declared);
     for (int variableKey in implicitlyDeclaredVars) {
-      _current = _current.declare(
-          _promotionKeyStore.variableForKey(variableKey), variableKey, true);
+      _current = _current.declare(variableKey, true);
     }
   }
 
@@ -3539,8 +3463,8 @@
     ReferenceWithType<Type>? referenceWithType =
         _getExpressionReference(subExpression);
     if (referenceWithType == null) return;
-    _current =
-        _current.tryPromoteForTypeCast(operations, referenceWithType, type);
+    _current = _current.tryPromoteForTypeCast(
+        operations, referenceWithType, type, _promotionKeyStore);
   }
 
   @override
@@ -3613,7 +3537,7 @@
   @override
   void declare(Variable variable, bool initialized) {
     _current = _current.declare(
-        variable, _promotionKeyStore.keyForVariable(variable), initialized);
+        _promotionKeyStore.keyForVariable(variable), initialized);
   }
 
   @override
@@ -3676,14 +3600,14 @@
       // either result is possible.
     } else if (leftOperandInfo._expressionInfo is _NullInfo<Type> &&
         rhsReference != null) {
-      ExpressionInfo<Type> equalityInfo =
-          _current.tryMarkNonNullable(operations, rhsReference);
+      ExpressionInfo<Type> equalityInfo = _current.tryMarkNonNullable(
+          operations, rhsReference, _promotionKeyStore);
       _storeExpressionInfo(
           wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
     } else if (rightOperandInfo._expressionInfo is _NullInfo<Type> &&
         lhsReference != null) {
-      ExpressionInfo<Type> equalityInfo =
-          _current.tryMarkNonNullable(operations, lhsReference);
+      ExpressionInfo<Type> equalityInfo = _current.tryMarkNonNullable(
+          operations, lhsReference, _promotionKeyStore);
       _storeExpressionInfo(
           wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
     }
@@ -3821,8 +3745,8 @@
     FlowModel<Type> promoted;
     _current = _current.split();
     if (lhsReference != null) {
-      ExpressionInfo<Type> promotionInfo =
-          _current.tryMarkNonNullable(operations, lhsReference);
+      ExpressionInfo<Type> promotionInfo = _current.tryMarkNonNullable(
+          operations, lhsReference, _promotionKeyStore);
       _current = promotionInfo.ifFalse;
       promoted = promotionInfo.ifTrue;
     } else {
@@ -3893,10 +3817,10 @@
       _current = _current
           .tryPromoteForTypeCheck(
               operations,
-              new ReferenceWithType<Type>(
-                  new VariableReference<Variable, Type>(variable, variableKey),
+              new ReferenceWithType<Type>(variableKey,
                   promotedType(variable) ?? operations.variableType(variable)),
-              initializerType)
+              initializerType,
+              _promotionKeyStore)
           .ifTrue;
     }
   }
@@ -3915,7 +3839,7 @@
         _getExpressionReference(subExpression);
     if (subExpressionReference != null) {
       ExpressionInfo<Type> expressionInfo = _current.tryPromoteForTypeCheck(
-          operations, subExpressionReference, type);
+          operations, subExpressionReference, type, _promotionKeyStore);
       _storeExpressionInfo(
           isExpression, isNot ? expressionInfo.invert() : expressionInfo);
     }
@@ -4011,8 +3935,9 @@
     ReferenceWithType<Type>? operandReference =
         _getExpressionReference(operand);
     if (operandReference != null) {
-      _current =
-          _current.tryMarkNonNullable(operations, operandReference).ifTrue;
+      _current = _current
+          .tryMarkNonNullable(operations, operandReference, _promotionKeyStore)
+          .ifTrue;
     }
   }
 
@@ -4031,8 +3956,9 @@
     _stack.add(new _NullAwareAccessContext<Type>(_current));
     ReferenceWithType<Type>? targetReference = _getExpressionReference(target);
     if (targetReference != null) {
-      _current =
-          _current.tryMarkNonNullable(operations, targetReference).ifTrue;
+      _current = _current
+          .tryMarkNonNullable(operations, targetReference, _promotionKeyStore)
+          .ifTrue;
     }
   }
 
@@ -4058,13 +3984,14 @@
   @override
   void propertyGet(Expression wholeExpression, Expression target,
       String propertyName, Object? propertyMember, Type staticType) {
-    Reference<Type>? reference = _getExpressionReference(target)?.reference;
-    if (reference != null) {
+    int? targetKey = _getExpressionReference(target)?.promotionKey;
+    if (targetKey != null) {
       _storeExpressionReference(
           wholeExpression,
-          new ReferenceWithType<Type>(
-              reference.propertyGet(
-                  _promotionKeyStore, propertyName, propertyMember),
+          new _PropertyReferenceWithType<Type>(
+              propertyName,
+              propertyMember,
+              _promotionKeyStore.getProperty(targetKey, propertyName),
               staticType));
     }
   }
@@ -4116,8 +4043,7 @@
     _storeExpressionReference(
         expression,
         new ReferenceWithType<Type>(
-            new _ThisReference<Type>(_promotionKeyStore.thisPromotionKey),
-            staticType));
+            _promotionKeyStore.thisPromotionKey, staticType));
   }
 
   @override
@@ -4125,9 +4051,11 @@
       Object? propertyMember, Type staticType) {
     _storeExpressionReference(
         expression,
-        new ReferenceWithType<Type>(
-            new _ThisReference<Type>(_promotionKeyStore.thisPromotionKey)
-                .propertyGet(_promotionKeyStore, propertyName, propertyMember),
+        new _PropertyReferenceWithType<Type>(
+            propertyName,
+            propertyMember,
+            _promotionKeyStore.getProperty(
+                _promotionKeyStore.thisPromotionKey, propertyName),
             staticType));
   }
 
@@ -4160,14 +4088,12 @@
     if (exceptionVariable != null) {
       int exceptionVariableKey =
           _promotionKeyStore.keyForVariable(exceptionVariable);
-      _current =
-          _current.declare(exceptionVariable, exceptionVariableKey, true);
+      _current = _current.declare(exceptionVariableKey, true);
     }
     if (stackTraceVariable != null) {
       int stackTraceVariableKey =
           _promotionKeyStore.keyForVariable(stackTraceVariable);
-      _current =
-          _current.declare(stackTraceVariable, stackTraceVariableKey, true);
+      _current = _current.declare(stackTraceVariableKey, true);
     }
   }
 
@@ -4210,14 +4136,11 @@
   @override
   Type? variableRead(Expression expression, Variable variable) {
     int variableKey = _promotionKeyStore.keyForVariable(variable);
-    VariableReference<Variable, Type> variableReference =
-        new VariableReference<Variable, Type>(variable, variableKey);
-    VariableModel<Type> variableModel =
-        variableReference.getInfo(_current.variableInfo);
+    VariableModel<Type> variableModel = _current._getInfo(variableKey);
     Type? promotedType = variableModel.promotedTypes?.last;
     Type currentType = promotedType ?? operations.variableType(variable);
-    _storeExpressionReference(expression,
-        new ReferenceWithType<Type>(variableReference, currentType));
+    _storeExpressionReference(
+        expression, new ReferenceWithType<Type>(variableKey, currentType));
     ExpressionInfo<Type>? expressionInfo = variableModel.ssaNode?.expressionInfo
         ?.rebaseForward(operations, _current);
     if (expressionInfo != null) {
@@ -4256,8 +4179,12 @@
     if (identical(target, _expressionWithReference)) {
       ReferenceWithType<Type>? referenceWithType = _expressionReference;
       if (referenceWithType != null) {
-        return referenceWithType.reference.getNonPromotionReasons(
-            _current.variableInfo, referenceWithType.type, operations);
+        VariableModel<Type>? currentVariableInfo =
+            _current.variableInfo[referenceWithType.promotionKey];
+        if (currentVariableInfo != null) {
+          return _getNonPromotionReasons(
+              referenceWithType, currentVariableInfo);
+        }
       }
     }
     return () => {};
@@ -4266,8 +4193,15 @@
   @override
   Map<Type, NonPromotionReason> Function() whyNotPromotedImplicitThis(
       Type staticType) {
-    return new _ThisReference<Type>(_promotionKeyStore.thisPromotionKey)
-        .getNonPromotionReasons(_current.variableInfo, staticType, operations);
+    VariableModel<Type>? currentThisInfo =
+        _current.variableInfo[_promotionKeyStore.thisPromotionKey];
+    if (currentThisInfo == null) {
+      return () => {};
+    }
+    return _getNonPromotionReasons(
+        new ReferenceWithType<Type>(
+            _promotionKeyStore.thisPromotionKey, staticType),
+        currentThisInfo);
   }
 
   @override
@@ -4335,6 +4269,57 @@
     }
   }
 
+  Map<Type, NonPromotionReason> Function() _getNonPromotionReasons(
+      ReferenceWithType<Type> reference,
+      VariableModel<Type> currentVariableInfo) {
+    if (reference is _PropertyReferenceWithType<Type>) {
+      List<Type>? promotedTypes = currentVariableInfo.promotedTypes;
+      if (promotedTypes != null) {
+        return () {
+          Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
+          for (Type type in promotedTypes) {
+            result[type] = new PropertyNotPromoted(reference.propertyName,
+                reference.propertyMember, reference.type);
+          }
+          return result;
+        };
+      }
+    } else {
+      Variable? variable =
+          _promotionKeyStore.variableForKey(reference.promotionKey);
+      if (variable == null) {
+        List<Type>? promotedTypes = currentVariableInfo.promotedTypes;
+        if (promotedTypes != null) {
+          return () {
+            Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
+            for (Type type in promotedTypes) {
+              result[type] = new ThisNotPromoted();
+            }
+            return result;
+          };
+        }
+      } else {
+        return () {
+          Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
+          Type currentType = currentVariableInfo.promotedTypes?.last ??
+              operations.variableType(variable);
+          NonPromotionHistory? nonPromotionHistory =
+              currentVariableInfo.nonPromotionHistory;
+          while (nonPromotionHistory != null) {
+            Type nonPromotedType = nonPromotionHistory.type;
+            if (!operations.isSubtypeOf(currentType, nonPromotedType)) {
+              result[nonPromotedType] ??=
+                  nonPromotionHistory.nonPromotionReason;
+            }
+            nonPromotionHistory = nonPromotionHistory.previous;
+          }
+          return result;
+        };
+      }
+    }
+    return () => {};
+  }
+
   FlowModel<Type> _join(FlowModel<Type>? first, FlowModel<Type>? second) =>
       FlowModel.join(operations, first, second, _current._emptyVariableMap);
 
@@ -4991,41 +4976,24 @@
       null;
 }
 
-/// [Reference] object representing a property get applied to another reference.
-class _PropertyGetReference<Type extends Object> extends Reference<Type> {
+/// [ReferenceWithType] object representing a property get.
+class _PropertyReferenceWithType<Type extends Object>
+    extends ReferenceWithType<Type> {
   /// The name of the property.
   final String propertyName;
 
-  /// The field or property being accessed.  This matches a `propertyMember`
+  /// /// The field or property being accessed.  This matches a `propertyMember`
   /// value that was passed to either [FlowAnalysis.propertyGet] or
   /// [FlowAnalysis.thisOrSuperPropertyGet].
   final Object? propertyMember;
 
-  _PropertyGetReference(
-      this.propertyName, this.propertyMember, super.promotionKey);
-
-  @override
-  Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
-      Map<int, VariableModel<Type>> variableInfo,
-      Type staticType,
-      TypeOperations<Type> typeOperations) {
-    List<Type>? promotedTypes = _getInfo(variableInfo)?.promotedTypes;
-    if (promotedTypes != null) {
-      return () {
-        Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
-        for (Type type in promotedTypes) {
-          result[type] =
-              new PropertyNotPromoted(propertyName, propertyMember, staticType);
-        }
-        return result;
-      };
-    }
-    return () => {};
-  }
+  _PropertyReferenceWithType(
+      this.propertyName, this.propertyMember, super.promotionKey, super.type);
 
   @override
   String toString() =>
-      '_PropertyGetReference($propertyName, $propertyMember, $promotionKey)';
+      '_PropertyReferenceWithType($propertyName, $propertyMember, '
+      '$promotionKey, $type)';
 }
 
 /// [_FlowContext] representing a language construct for which flow analysis
@@ -5061,29 +5029,6 @@
       'checkpoint: $_checkpoint)';
 }
 
-/// [Reference] object representing an implicit or explicit reference to `this`.
-class _ThisReference<Type extends Object> extends Reference<Type> {
-  _ThisReference(super.promotionKey);
-
-  @override
-  Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
-      Map<int, VariableModel<Type>> variableInfo,
-      Type staticType,
-      TypeOperations<Type> typeOperations) {
-    List<Type>? promotedTypes = _getInfo(variableInfo)?.promotedTypes;
-    if (promotedTypes != null) {
-      return () {
-        Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
-        for (Type type in promotedTypes) {
-          result[type] = new ThisNotPromoted();
-        }
-        return result;
-      };
-    }
-    return () => {};
-  }
-}
-
 /// Specialization of [ExpressionInfo] for the case where the information we
 /// have about the expression is trivial (meaning we know by construction that
 /// the expression's [after], [ifTrue], and [ifFalse] models are all the same).
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index d2195c0..e6ee94a 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -5923,21 +5923,21 @@
         for (Var v in capturedVariables) _promotionKeyStore.keyForVariable(v)
       ]);
 
-  FlowModel<Type> _declare(Var variable, bool initialized) => this.declare(
-      variable, _promotionKeyStore.keyForVariable(variable), initialized);
+  FlowModel<Type> _declare(Var variable, bool initialized) =>
+      this.declare(_promotionKeyStore.keyForVariable(variable), initialized);
 
   VariableModel<Type> _infoFor(Var variable) =>
       infoFor(_promotionKeyStore.keyForVariable(variable));
 
   ExpressionInfo<Type> _tryMarkNonNullable(Harness h, Var variable) =>
-      tryMarkNonNullable(h, _varRefWithType(variable));
+      tryMarkNonNullable(h, _varRefWithType(variable), _promotionKeyStore);
 
   ExpressionInfo<Type> _tryPromoteForTypeCheck(
           Harness h, Var variable, String type) =>
-      tryPromoteForTypeCheck(h, _varRefWithType(variable), Type(type));
+      tryPromoteForTypeCheck(
+          h, _varRefWithType(variable), Type(type), _promotionKeyStore);
 
-  Reference<Type> _varRef(Var variable) => new VariableReference<Var, Type>(
-      variable, _promotionKeyStore.keyForVariable(variable));
+  int _varRef(Var variable) => _promotionKeyStore.keyForVariable(variable);
 
   ReferenceWithType<Type> _varRefWithType(Var variable) =>
       new ReferenceWithType<Type>(
diff --git a/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart b/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
index 5218d75..68b6ff4 100644
--- a/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_call_hierarchy.dart
@@ -2,7 +2,6 @@
 // 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:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/search/element_references.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -12,6 +11,7 @@
 import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 
 /// A [CallHierarchyItem] and a set of ranges that call to or from it.
 class CallHierarchyCalls {
@@ -45,30 +45,46 @@
   final String file;
 
   /// The range of the name at the declaration of this item.
-  final SourceRange range;
+  final SourceRange nameRange;
 
-  // TODO(dantup): This class will need to contain two ranges (codeRange +
-  //   selectionRange) for LSP.
+  /// The range of the code for the declaration of this item.
+  final SourceRange codeRange;
 
-  CallHierarchyItem.forElement(
-    Element element, {
-    required this.range,
-  })  : displayName = element is CompilationUnitElement
+  CallHierarchyItem.forElement(Element element)
+      : displayName = element is CompilationUnitElement
             ? element.source.shortName
             : element is PropertyAccessorElement
                 ? element.isGetter
                     ? 'get ${element.displayName}'
                     : 'set ${element.displayName}'
                 : element.displayName,
+        nameRange = _nameRangeForElement(element),
+        codeRange = _codeRangeForElement(element),
         file = element.source!.fullName,
         kind = CallHierarchyKind.forElement(element);
 
-  CallHierarchyItem.forProtocolElement(
-    protocol.Element element, {
-    required this.range,
-  })  : displayName = element.name,
-        file = element.location!.file,
-        kind = CallHierarchyKind.forProtocolElement(element);
+  /// Returns the [SourceRange] of the code for [element].
+  static SourceRange _codeRangeForElement(Element element) {
+    // For synthetic items (like implicit constructors), use the nonSynthetic
+    // element for the location.
+    final elementImpl = element.nonSynthetic as ElementImpl;
+
+    // Non-synthetic elements should always have code locations.
+    return SourceRange(elementImpl.codeOffset!, elementImpl.codeLength!);
+  }
+
+  /// Returns the [SourceRange] of the name for [element].
+  static SourceRange _nameRangeForElement(Element element) {
+    // For synthetic items (like implicit constructors), use the nonSynthetic
+    // element for the location.
+    element = element.nonSynthetic;
+
+    // Compilation units will return -1 for nameOffset which is not valid, so
+    //use 0:0.
+    return element.nameOffset == -1
+        ? SourceRange(0, 0)
+        : SourceRange(element.nameOffset, element.nameLength);
+  }
 }
 
 /// Kinds of [CallHierarchyItem] that can make calls to other
@@ -95,23 +111,8 @@
     ElementKind.SETTER: property,
   };
 
-  static const _protocolElementMapping = {
-    protocol.ElementKind.CLASS: class_,
-    protocol.ElementKind.COMPILATION_UNIT: file,
-    protocol.ElementKind.CONSTRUCTOR: constructor,
-    protocol.ElementKind.EXTENSION: extension,
-    protocol.ElementKind.FUNCTION: function,
-    protocol.ElementKind.GETTER: property,
-    protocol.ElementKind.METHOD: method,
-    protocol.ElementKind.MIXIN: mixin,
-    protocol.ElementKind.SETTER: property,
-  };
-
   static CallHierarchyKind forElement(Element element) =>
       _elementMapping[element.kind] ?? unknown;
-
-  static CallHierarchyKind forProtocolElement(protocol.Element element) =>
-      _protocolElementMapping[element.kind] ?? unknown;
 }
 
 /// A computer for Call Hierarchies.
@@ -143,7 +144,7 @@
     SearchEngine searchEngine,
   ) async {
     assert(target.file == _result.path);
-    final node = _findTargetNode(target.range.offset);
+    final node = _findTargetNode(target.nameRange.offset);
     var element = _getElementOfNode(node);
     if (element == null) {
       return [];
@@ -169,12 +170,12 @@
 
     // Group results by their container, since we only want to return a single
     // entry for a body, with a set of ranges within.
-    final resultsByContainer = <protocol.Element, CallHierarchyCalls>{};
+    final resultsByContainer = <Element, CallHierarchyCalls>{};
     // We may need to fetch parsed results for the other files, reuse them
     // across calls.
     final parsedUnits = <String, SomeParsedUnitResult?>{};
     for (final reference in references) {
-      final container = _getContainer(reference.path);
+      final container = _getContainer(reference.element);
       if (container == null) {
         continue;
       }
@@ -182,14 +183,11 @@
       // Create an item for a container the first time we see it.
       final containerCalls = resultsByContainer.putIfAbsent(
         container,
-        () => CallHierarchyCalls(CallHierarchyItem.forProtocolElement(
-          container,
-          range: _rangeForProtocolElement(container),
-        )),
+        () => CallHierarchyCalls(CallHierarchyItem.forElement(container)),
       );
 
       // Add this match to the containers results.
-      final range = _rangeForSearchResult(reference, parsedUnits);
+      final range = _rangeForSearchMatch(reference, parsedUnits);
       containerCalls.ranges.add(range);
     }
 
@@ -202,7 +200,7 @@
     CallHierarchyItem target,
   ) async {
     assert(target.file == _result.path);
-    final node = _findTargetNode(target.range.offset);
+    final node = _findTargetNode(target.nameRange.offset);
     if (node == null) {
       return [];
     }
@@ -229,10 +227,7 @@
       // Create an item for a target the first time we see it.
       final calls = resultsByTarget.putIfAbsent(
         target,
-        () => CallHierarchyCalls(CallHierarchyItem.forElement(
-          target,
-          range: _rangeForElement(target),
-        )),
+        () => CallHierarchyCalls(CallHierarchyItem.forElement(target)),
       );
 
       // Add this call to the targets results.
@@ -253,8 +248,7 @@
 
     // We only return targets that are executable elements.
     return element is ExecutableElement
-        ? CallHierarchyItem.forElement(element,
-            range: _rangeForElement(element))
+        ? CallHierarchyItem.forElement(element)
         : null;
   }
 
@@ -289,23 +283,26 @@
     return node;
   }
 
-  /// Returns the enclosing element (class, function body, compliation unit) for
-  /// the reference [element].
+  /// Returns the container for [element] that should be used in Call Hierarchy.
+  ///
+  /// Returns `null` if none of [elements] are valid containers.
   ///
   /// This is used to construct (and group calls by) a [CallHierarchyItem] that
   /// contains calls.
-  protocol.Element? _getContainer(List<protocol.Element> elements) {
-    return elements.firstWhere((parent) =>
-        parent.kind == protocol.ElementKind.CLASS ||
-        parent.kind == protocol.ElementKind.COMPILATION_UNIT ||
-        parent.kind == protocol.ElementKind.CONSTRUCTOR ||
-        parent.kind == protocol.ElementKind.ENUM ||
-        parent.kind == protocol.ElementKind.EXTENSION ||
-        parent.kind == protocol.ElementKind.FUNCTION ||
-        parent.kind == protocol.ElementKind.GETTER ||
-        parent.kind == protocol.ElementKind.METHOD ||
-        parent.kind == protocol.ElementKind.MIXIN ||
-        parent.kind == protocol.ElementKind.SETTER);
+  Element? _getContainer(Element element) {
+    const containerKinds = {
+      ElementKind.CLASS,
+      ElementKind.COMPILATION_UNIT,
+      ElementKind.CONSTRUCTOR,
+      ElementKind.ENUM,
+      ElementKind.EXTENSION,
+      ElementKind.FUNCTION,
+      ElementKind.GETTER,
+      ElementKind.METHOD,
+      ElementKind.SETTER,
+    };
+    return element.thisOrAncestorMatching(
+        (ancestor) => containerKinds.contains(ancestor.kind));
   }
 
   /// Return the [Element] of the given [node], or `null` if [node] is `null`,
@@ -338,17 +335,6 @@
     return element;
   }
 
-  /// Returns the [SourceRange] to use for [element].
-  ///
-  /// The returned range covers only the name of the target and does not include
-  /// any parameter list.
-  SourceRange _rangeForElement(Element element) {
-    // For synthetic items (like implicit constructors), use the nonSynthetic
-    // element for the location.
-    element = element.nonSynthetic;
-    return SourceRange(element.nameOffset, element.nameLength);
-  }
-
   /// Returns the [SourceRange] to use for [node].
   ///
   /// The returned range covers only the name of the target and does not include
@@ -373,14 +359,6 @@
     return SourceRange(node.offset, node.length);
   }
 
-  /// Returns the [SourceRange] to use for [element].
-  ///
-  /// The returned range covers only the name of the target and does not include
-  /// any parameter list.
-  SourceRange _rangeForProtocolElement(protocol.Element element) {
-    return SourceRange(element.location!.offset, element.location!.length);
-  }
-
   /// Returns the [SourceRange] for [match].
   ///
   /// Usually this is the range returned from the search index, but sometimes it
@@ -388,13 +366,13 @@
   /// for this call. For example, an unnamed constructor may be given a range
   /// covering the type name (whereas the index has a zero-width range after the
   /// type name).
-  SourceRange _rangeForSearchResult(
-    protocol.SearchResult match,
+  SourceRange _rangeForSearchMatch(
+    SearchMatch match,
     Map<String, SomeParsedUnitResult?> parsedUnits,
   ) {
-    var offset = match.location.offset;
-    var length = match.location.length;
-    final file = match.location.file;
+    var offset = match.sourceRange.offset;
+    var length = match.sourceRange.length;
+    final file = match.file;
     final result = parsedUnits.putIfAbsent(
       file,
       () => _result.session.getParsedUnit(file),
diff --git a/pkg/analysis_server/lib/src/handler/legacy/search_find_element_references.dart b/pkg/analysis_server/lib/src/handler/legacy/search_find_element_references.dart
index a0bdfbb..d6effb9 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/search_find_element_references.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/search_find_element_references.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/plugin/protocol/protocol_dart.dart' as protocol;
 import 'package:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/handler/legacy/legacy_handler.dart';
+import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/search/element_references.dart';
 import 'package:analyzer/dart/element/element.dart';
 
@@ -48,8 +49,8 @@
     if (element != null) {
       var computer = ElementReferencesComputer(searchEngine);
       var results = await computer.compute(element, params.includePotential);
-      sendSearchResults(
-          protocol.SearchResultsParams(searchId, results.toList(), true));
+      sendSearchResults(protocol.SearchResultsParams(
+          searchId, results.map(newSearchResult_fromMatch).toList(), true));
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index 07fd4ff..2fe9d4d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -5,9 +5,10 @@
 import 'package:analysis_server/lsp_protocol/protocol.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
-import 'package:analysis_server/src/protocol_server.dart' show SearchResult;
 import 'package:analysis_server/src/protocol_server.dart' show NavigationTarget;
 import 'package:analysis_server/src/search/element_references.dart';
+import 'package:analysis_server/src/services/search/search_engine.dart'
+    show SearchMatch;
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -70,11 +71,22 @@
     }
 
     final computer = ElementReferencesComputer(server.searchEngine);
+    final session = element.session ?? unit.session;
     final results = await computer.compute(element, false);
 
-    Location? toLocation(SearchResult result) {
-      final lineInfo = server.getLineInfo(result.location.file);
-      return searchResultToLocation(result, lineInfo);
+    Location? toLocation(SearchMatch result) {
+      final file = session.getFile(result.file);
+      if (file is! FileResult) {
+        return null;
+      }
+      return Location(
+        uri: Uri.file(result.file).toString(),
+        range: toRange(
+          file.lineInfo,
+          result.sourceRange.offset,
+          result.sourceRange.length,
+        ),
+      );
     }
 
     final referenceResults =
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index a3c3c99..7e2c591 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -891,20 +891,6 @@
 ///   0 -> 9999999 -   0 -> 9 999 999
 String relevanceToSortText(int relevance) => (9999999 - relevance).toString();
 
-lsp.Location? searchResultToLocation(
-    server.SearchResult result, server.LineInfo? lineInfo) {
-  final location = result.location;
-
-  if (lineInfo == null) {
-    return null;
-  }
-
-  return lsp.Location(
-    uri: Uri.file(result.location.file).toString(),
-    range: toRange(lineInfo, location.offset, location.length),
-  );
-}
-
 /// Creates a SnippetTextEdit for a set of edits using Linked Edit Groups.
 ///
 /// Edit groups offsets are based on the entire content being modified after all
diff --git a/pkg/analysis_server/lib/src/search/element_references.dart b/pkg/analysis_server/lib/src/search/element_references.dart
index f843776..afccf67 100644
--- a/pkg/analysis_server/lib/src/search/element_references.dart
+++ b/pkg/analysis_server/lib/src/search/element_references.dart
@@ -14,10 +14,9 @@
 
   ElementReferencesComputer(this.searchEngine);
 
-  /// Computes [SearchResult]s for [element] references.
-  Future<List<SearchResult>> compute(
-      Element element, bool withPotential) async {
-    var results = <SearchResult>[];
+  /// Computes [SearchMatch]es for [element] references.
+  Future<List<SearchMatch>> compute(Element element, bool withPotential) async {
+    var results = <SearchMatch>[];
 
     // Add element references.
     results.addAll(await _findElementsReferences(element));
@@ -26,7 +25,7 @@
     if (withPotential && _isMemberElement(element)) {
       var name = element.displayName;
       var matches = await searchEngine.searchMemberReferences(name);
-      results.addAll(matches.where((match) => !match.isResolved).map(toResult));
+      results.addAll(matches.where((match) => !match.isResolved));
     }
 
     return results;
@@ -34,8 +33,8 @@
 
   /// Returns a [Future] completing with a [List] of references to [element] or
   /// to the corresponding hierarchy [Element]s.
-  Future<List<SearchResult>> _findElementsReferences(Element element) async {
-    var allResults = <SearchResult>[];
+  Future<List<SearchMatch>> _findElementsReferences(Element element) async {
+    var allResults = <SearchMatch>[];
     var refElements = await _getRefElements(element);
     for (var refElement in refElements) {
       var elementResults = await _findSingleElementReferences(refElement);
@@ -45,10 +44,9 @@
   }
 
   /// Returns a [Future] completing with a [List] of references to [element].
-  Future<List<SearchResult>> _findSingleElementReferences(
+  Future<List<SearchMatch>> _findSingleElementReferences(
       Element element) async {
-    var matches = await searchEngine.searchReferences(element);
-    return matches.map(toResult).toList();
+    return searchEngine.searchReferences(element);
   }
 
   /// Returns a [Future] completing with [Element]s to search references to.
diff --git a/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart b/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
index 6bc39cc..20e6cda 100644
--- a/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/call_hierarchy_computer_test.dart
@@ -21,24 +21,34 @@
 }
 
 /// Matches a [CallHierarchyItem] with the given name/kind/file.
-Matcher _isItem(CallHierarchyKind kind, String displayName, String file,
-        SourceRange range) =>
+Matcher _isItem(
+  CallHierarchyKind kind,
+  String displayName,
+  String file, {
+  required SourceRange nameRange,
+  required SourceRange codeRange,
+}) =>
     TypeMatcher<CallHierarchyItem>()
         .having((e) => e.kind, 'kind', kind)
         .having((e) => e.displayName, 'displayName', displayName)
         .having((e) => e.file, 'file', file)
-        .having((e) => e.range, 'range', range);
+        .having((e) => e.nameRange, 'nameRange', nameRange)
+        .having((e) => e.codeRange, 'codeRange', codeRange);
 
 /// Matches a [CallHierarchyCalls] result with the given element/ranges.
 Matcher _isResult(
   CallHierarchyKind kind,
   String displayName,
-  String file,
-  SourceRange range, {
+  String file, {
+  required SourceRange nameRange,
+  required SourceRange codeRange,
   List<SourceRange>? ranges,
 }) {
-  var matcher = TypeMatcher<CallHierarchyCalls>()
-      .having((c) => c.item, 'item', _isItem(kind, displayName, file, range));
+  var matcher = TypeMatcher<CallHierarchyCalls>().having(
+      (c) => c.item,
+      'item',
+      _isItem(kind, displayName, file,
+          nameRange: nameRange, codeRange: codeRange));
 
   if (ranges != null) {
     matcher = matcher.having((c) => c.ranges, 'ranges', ranges);
@@ -50,6 +60,10 @@
 abstract class AbstractCallHierarchyTest extends AbstractSingleUnitTest {
   final startOfFile = SourceRange(0, 0);
 
+  /// Gets the entire range for [code].
+  SourceRange entireRange(String code) =>
+      SourceRange(0, withoutMarkers(code).length);
+
   // Gets the expected range that follows the string [prefix] in [code] with a
   // length of [match.length].
   SourceRange rangeAfterPrefix(String prefix, String code, String match) =>
@@ -64,6 +78,18 @@
     return SourceRange(index, (match ?? search).length);
   }
 
+  // Gets the code range between markers in the form `/*1*/` where `1` is
+  // [number].
+  SourceRange rangeNumbered(int number, String code) {
+    code = withoutMarkers(code);
+    final marker = '/*$number*/';
+    final start = code.indexOf(marker) + marker.length;
+    final end = code.lastIndexOf(marker);
+    expect(start, greaterThanOrEqualTo(0 + marker.length));
+    expect(end, greaterThan(start));
+    return SourceRange(start, end - start);
+  }
+
   String withoutMarkers(String code) => code.replaceAll('^', '');
 }
 
@@ -111,7 +137,7 @@
   Future<void> test_constructor() async {
     final contents = '''
 class Foo {
-  Fo^o(String a) {}
+  /*1*/Fo^o(String a) {}/*1*/
 }
     ''';
 
@@ -122,7 +148,8 @@
         CallHierarchyKind.constructor,
         'Foo',
         testFile,
-        rangeAtSearch('Foo(', contents, 'Foo'),
+        nameRange: rangeAtSearch('Foo(', contents, 'Foo'),
+        codeRange: rangeNumbered(1, contents),
       ),
     );
   }
@@ -131,14 +158,14 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   final foo = Fo^o();
 }
     ''';
 
     final otherContents = '''
 class Foo {
-  Foo();
+  /*1*/Foo();/*1*/
 }
     ''';
 
@@ -149,14 +176,15 @@
           CallHierarchyKind.constructor,
           'Foo',
           otherFile,
-          rangeAtSearch('Foo(', otherContents, 'Foo'),
+          nameRange: rangeAtSearch('Foo(', otherContents, 'Foo'),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_extension_method() async {
     final contents = '''
 extension StringExtension on String {
-  void myMet^hod() {}
+  /*1*/void myMet^hod() {}/*1*/
 }
     ''';
 
@@ -166,7 +194,8 @@
           CallHierarchyKind.method,
           'myMethod',
           testFile,
-          rangeAtSearch('myMethod', contents),
+          nameRange: rangeAtSearch('myMethod', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -174,14 +203,14 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   ''.myMet^hod();
 }
     ''';
 
     final otherContents = '''
 extension StringExtension on String {
-  void myMethod() {}
+  /*1*/void myMethod() {}/*1*/
 }
     ''';
 
@@ -192,13 +221,14 @@
           CallHierarchyKind.method,
           'myMethod',
           otherFile,
-          rangeAtSearch('myMethod', otherContents),
+          nameRange: rangeAtSearch('myMethod', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_function() async {
     final contents = '''
-void myFun^ction() {}
+/*1*/void myFun^ction() {}/*1*/
     ''';
 
     await expectTarget(
@@ -207,7 +237,8 @@
           CallHierarchyKind.function,
           'myFunction',
           testFile,
-          rangeAtSearch('myFunction', contents),
+          nameRange: rangeAtSearch('myFunction', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -215,13 +246,13 @@
     final contents = '''
 import 'other.dart' as f;
 
-f() {
+void f() {
   f.myFun^ction();
 }
     ''';
 
     final otherContents = '''
-void myFunction() {}
+/*1*/void myFunction() {}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -231,14 +262,15 @@
           CallHierarchyKind.function,
           'myFunction',
           otherFile,
-          rangeAtSearch('myFunction', otherContents),
+          nameRange: rangeAtSearch('myFunction', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_getter() async {
     final contents = '''
 class Foo {
-  String get fo^o => '';
+  /*1*/String get fo^o => '';/*1*/
 }
     ''';
 
@@ -248,7 +280,8 @@
           CallHierarchyKind.property,
           'get foo',
           testFile,
-          rangeAtSearch('foo', contents),
+          nameRange: rangeAtSearch('foo', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -256,13 +289,13 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   final foo = ba^r;
 }
     ''';
 
     final otherContents = '''
-String get bar => '';
+/*1*/String get bar => '';/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -272,7 +305,8 @@
           CallHierarchyKind.property,
           'get bar',
           otherFile,
-          rangeAtSearch('bar', otherContents),
+          nameRange: rangeAtSearch('bar', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
@@ -283,13 +317,13 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   final foo = Fo^o();
 }
     ''';
 
     final otherContents = '''
-class Foo {}
+/*1*/class Foo {}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -299,14 +333,15 @@
           CallHierarchyKind.constructor,
           'Foo',
           otherFile,
-          rangeAtSearch('Foo {', otherContents, 'Foo'),
+          nameRange: rangeAtSearch('Foo {', otherContents, 'Foo'),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_method() async {
     final contents = '''
 class Foo {
-  void myMet^hod() {}
+  /*1*/void myMet^hod() {}/*1*/
 }
     ''';
 
@@ -316,7 +351,8 @@
           CallHierarchyKind.method,
           'myMethod',
           testFile,
-          rangeAtSearch('myMethod', contents),
+          nameRange: rangeAtSearch('myMethod', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -324,14 +360,14 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   Foo().myMet^hod();
 }
     ''';
 
     final otherContents = '''
 class Foo {
-  void myMethod() {}
+  /*1*/void myMethod() {}/*1*/
 }
     ''';
 
@@ -342,14 +378,15 @@
           CallHierarchyKind.method,
           'myMethod',
           otherFile,
-          rangeAtSearch('myMethod', otherContents),
+          nameRange: rangeAtSearch('myMethod', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_mixin_method() async {
     final contents = '''
 mixin Bar {
-  void myMet^hod() {}
+  /*1*/void myMet^hod() {}/*1*/
 }
     ''';
 
@@ -359,7 +396,8 @@
           CallHierarchyKind.method,
           'myMethod',
           testFile,
-          rangeAtSearch('myMethod', contents),
+          nameRange: rangeAtSearch('myMethod', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -367,14 +405,14 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   Foo().myMet^hod();
 }
     ''';
 
     final otherContents = '''
 class Bar {
-  void myMethod() {}
+  /*1*/void myMethod() {}/*1*/
 }
 
 class Foo with Bar {}
@@ -387,14 +425,15 @@
           CallHierarchyKind.method,
           'myMethod',
           otherFile,
-          rangeAtSearch('myMethod', otherContents),
+          nameRange: rangeAtSearch('myMethod', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_namedConstructor() async {
     final contents = '''
 class Foo {
-  Foo.Ba^r(String a) {}
+  /*1*/Foo.Ba^r(String a) {}/*1*/
 }
     ''';
 
@@ -404,7 +443,8 @@
           CallHierarchyKind.constructor,
           'Foo.Bar',
           testFile,
-          rangeAtSearch('Bar', contents),
+          nameRange: rangeAtSearch('Bar', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -422,14 +462,14 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   final foo = Foo.Ba^r();
 }
     ''';
 
     final otherContents = '''
 class Foo {
-  Foo.Bar();
+  /*1*/Foo.Bar();/*1*/
 }
     ''';
 
@@ -440,7 +480,8 @@
           CallHierarchyKind.constructor,
           'Foo.Bar',
           otherFile,
-          rangeAtSearch('Bar', otherContents),
+          nameRange: rangeAtSearch('Bar', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
@@ -448,7 +489,7 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   final foo = Fo^o.Bar();
 }
     ''';
@@ -466,7 +507,7 @@
   Future<void> test_setter() async {
     final contents = '''
 class Foo {
-  set fo^o(Strin value) {};
+  /*1*/set fo^o(String value) {}/*1*/
 }
     ''';
 
@@ -476,7 +517,8 @@
           CallHierarchyKind.property,
           'set foo',
           testFile,
-          rangeAtSearch('foo', contents),
+          nameRange: rangeAtSearch('foo', contents),
+          codeRange: rangeNumbered(1, contents),
         ));
   }
 
@@ -484,13 +526,13 @@
     final contents = '''
 import 'other.dart';
 
-f() {
+void f() {
   ba^r = '';
 }
     ''';
 
     final otherContents = '''
-set bar(String value) {}
+/*1*/set bar(String value) {}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -500,12 +542,13 @@
           CallHierarchyKind.property,
           'set bar',
           otherFile,
-          rangeAtSearch('bar', otherContents),
+          nameRange: rangeAtSearch('bar', otherContents),
+          codeRange: rangeNumbered(1, otherContents),
         ));
   }
 
   Future<void> test_whitespace() async {
-    await expectNoTarget(' ^  f() {}');
+    await expectNoTarget(' ^  void f() {}');
   }
 }
 
@@ -556,17 +599,17 @@
 import 'test.dart';
 
 final foo1 = Foo();
-class Bar {
+/*1*/class Bar {
   final foo2 = Foo();
-  Foo get foo3 => Foo();
-  Bar() {
+  /*2*/Foo get foo3 => Foo();/*2*/
+  /*3*/Bar() {
     final foo4 = Foo();
-  }
-  void bar() {
+  }/*3*/
+  /*4*/void bar() {
     final foo5 = Foo();
     final foo6 = Foo();
-  }
-}
+  }/*4*/
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -578,27 +621,33 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.file, 'other.dart', otherFile, startOfFile,
+        _isResult(CallHierarchyKind.file, 'other.dart', otherFile,
+            nameRange: startOfFile,
+            codeRange: entireRange(otherContents),
             ranges: [
               rangeAfter('foo1 = '),
             ]),
         _isResult(CallHierarchyKind.class_, 'Bar', otherFile,
-            rangeAtSearch('Bar {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('foo2 = '),
             ]),
-        _isResult(CallHierarchyKind.property, 'foo3', otherFile,
-            rangeAtSearch('foo3', otherContents),
+        _isResult(CallHierarchyKind.property, 'get foo3', otherFile,
+            nameRange: rangeAtSearch('foo3', otherContents),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfter('foo3 => '),
             ]),
         _isResult(CallHierarchyKind.constructor, 'Bar', otherFile,
-            rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(3, otherContents),
             ranges: [
               rangeAfter('foo4 = '),
             ]),
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(4, otherContents),
             ranges: [
               rangeAfter('foo5 = '),
               rangeAfter('foo6 = '),
@@ -617,9 +666,9 @@
     final otherContents = '''
 import 'test.dart';
 
-void f() {
+/*1*/void f() {
   ''.myMethod();
-}
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -632,7 +681,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', otherFile,
-            rangeAtSearch('f() {', otherContents, 'f'),
+            nameRange: rangeAtSearch('f() {', otherContents, 'f'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter("''."),
             ]),
@@ -650,17 +700,17 @@
 
 final foo1 = myFunction();
 
-class Bar {
+/*1*/class Bar {
   final foo2 = myFunction();
-  String get foo3 => myFunction();
-  Bar() {
+  /*2*/String get foo3 => myFunction();/*2*/
+  /*3*/Bar() {
     final foo4 = myFunction();
-  }
-  void bar() {
+  }/*3*/
+  /*4*/void bar() {
     final foo5 = myFunction();
     final foo6 = myFunction();
-  }
-}
+  }/*4*/
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -672,27 +722,33 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.file, 'other.dart', otherFile, startOfFile,
+        _isResult(CallHierarchyKind.file, 'other.dart', otherFile,
+            nameRange: startOfFile,
+            codeRange: entireRange(otherContents),
             ranges: [
               rangeAfter('foo1 = '),
             ]),
         _isResult(CallHierarchyKind.class_, 'Bar', otherFile,
-            rangeAtSearch('Bar {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('foo2 = '),
             ]),
-        _isResult(CallHierarchyKind.property, 'foo3', otherFile,
-            rangeAtSearch('foo3', otherContents),
+        _isResult(CallHierarchyKind.property, 'get foo3', otherFile,
+            nameRange: rangeAtSearch('foo3', otherContents),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfter('foo3 => '),
             ]),
         _isResult(CallHierarchyKind.constructor, 'Bar', otherFile,
-            rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(3, otherContents),
             ranges: [
               rangeAfter('foo4 = '),
             ]),
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(4, otherContents),
             ranges: [
               rangeAfter('foo5 = '),
               rangeAfter('foo6 = '),
@@ -710,17 +766,17 @@
 import 'test.dart';
 
 final foo1 = foo;
-class Bar {
+/*1*/class Bar {
   final foo2 = foo;
-  Foo get foo3 => foo;
-  Bar() {
+  /*2*/Foo get foo3 => foo;/*2*/
+  /*3*/Bar() {
     final foo4 = foo;
-  }
-  void bar() {
+  }/*3*/
+  /*4*/void bar() {
     final foo5 = foo;
     final foo6 = foo;
-  }
-}
+  }/*4*/
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -732,27 +788,33 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.file, 'other.dart', otherFile, startOfFile,
+        _isResult(CallHierarchyKind.file, 'other.dart', otherFile,
+            nameRange: startOfFile,
+            codeRange: entireRange(otherContents),
             ranges: [
               rangeAfter('foo1 = '),
             ]),
         _isResult(CallHierarchyKind.class_, 'Bar', otherFile,
-            rangeAtSearch('Bar {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('foo2 = '),
             ]),
-        _isResult(CallHierarchyKind.property, 'foo3', otherFile,
-            rangeAtSearch('foo3', otherContents),
+        _isResult(CallHierarchyKind.property, 'get foo3', otherFile,
+            nameRange: rangeAtSearch('foo3', otherContents),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfter('foo3 => '),
             ]),
         _isResult(CallHierarchyKind.constructor, 'Bar', otherFile,
-            rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(3, otherContents),
             ranges: [
               rangeAfter('foo4 = '),
             ]),
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(4, otherContents),
             ranges: [
               rangeAfter('foo5 = '),
               rangeAfter('foo6 = '),
@@ -768,9 +830,9 @@
 // ignore_for_file: unused_local_variable
 import 'other.dart';
 
-f() {
+/*1*/void f() {
   final foo1 = Fo^o();
-}
+}/*1*/
     ''';
 
     final otherContents = '''
@@ -789,11 +851,14 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', testFile,
-            rangeAtSearch('f() {', contents, 'f'),
+            nameRange: rangeAtSearch('f() {', contents, 'f'),
+            codeRange: rangeNumbered(1, contents),
             ranges: [
               rangeAfter('foo1 = ', contents),
             ]),
-        _isResult(CallHierarchyKind.file, 'other.dart', otherFile, startOfFile,
+        _isResult(CallHierarchyKind.file, 'other.dart', otherFile,
+            nameRange: startOfFile,
+            codeRange: entireRange(otherContents),
             ranges: [
               rangeAfter('foo2 = ', otherContents),
             ]),
@@ -811,10 +876,10 @@
     final otherContents = '''
 import 'test.dart';
 
-void f() {
+/*1*/void f() {
   Foo().myMethod();
   final tearoff = Foo().myMethod;
-}
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -827,7 +892,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', otherFile,
-            rangeAtSearch('f() {', otherContents, 'f'),
+            nameRange: rangeAtSearch('f() {', otherContents, 'f'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('Foo().'),
               rangeAfter('tearoff = Foo().'),
@@ -848,9 +914,9 @@
     final otherContents = '''
 import 'test.dart';
 
-void f() {
+/*1*/void f() {
   Foo().myMethod();
-}
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -863,7 +929,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', otherFile,
-            rangeAtSearch('f() {', otherContents, 'f'),
+            nameRange: rangeAtSearch('f() {', otherContents, 'f'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('Foo().'),
             ]),
@@ -881,9 +948,9 @@
     final otherContents = '''
 import 'test.dart';
 
-f() {
+/*1*/void f() {
   final foo = Foo.Bar();
-}
+}/*1*/
     ''';
 
     // Gets the expected range that follows the string [prefix].
@@ -896,7 +963,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', otherFile,
-            rangeAtSearch('f() {', otherContents, 'f'),
+            nameRange: rangeAtSearch('f() {', otherContents, 'f'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfter('foo = Foo.'),
             ]),
@@ -913,13 +981,13 @@
 import 'test.dart';
 
 class Bar {
-  Bar() {
-    /*1*/foo = '';
-  }
-  void bar() {
-    /*2*/foo = '';
-    /*3*/foo = '';
-  }
+  /*1*/Bar() {
+    /*a*/foo = '';
+  }/*1*/
+  /*2*/void bar() {
+    /*b*/foo = '';
+    /*c*/foo = '';
+  }/*2*/
 }
     ''';
 
@@ -933,15 +1001,17 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.constructor, 'Bar', otherFile,
-            rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            nameRange: rangeAtSearch('Bar() {', otherContents, 'Bar'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
-              rangeAfter('/*1*/'),
+              rangeAfter('/*a*/'),
             ]),
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
-              rangeAfter('/*2*/'),
-              rangeAfter('/*3*/'),
+              rangeAfter('/*b*/'),
+              rangeAfter('/*c*/'),
             ]),
       ]),
     );
@@ -997,11 +1067,11 @@
 
     final otherContents = '''
 class A {
-  A();
+  /*1*/A();/*1*/
 }
 
-class B {
-}
+/*2*/class B {
+}/*2*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1010,13 +1080,15 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.constructor, 'A', otherFile,
-            rangeAtSearch('A();', otherContents, 'A'),
+            nameRange: rangeAtSearch('A();', otherContents, 'A'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAtSearch('A()', contents, 'A'),
               rangeAfterPrefix('constructorTearoffA = A.', contents, 'new'),
             ]),
         _isResult(CallHierarchyKind.constructor, 'B', otherFile,
-            rangeAtSearch('B {', otherContents, 'B'),
+            nameRange: rangeAtSearch('B {', otherContents, 'B'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAtSearch('B()', contents, 'B'),
               rangeAfterPrefix('constructorTearoffB = B.', contents, 'new'),
@@ -1040,7 +1112,7 @@
 
     final otherContents = '''
 extension StringExtension on String {
-  bar() {}
+  /*1*/void bar() {}/*1*/
 }
     ''';
 
@@ -1050,7 +1122,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAtSearch('bar();', contents, 'bar'),
               rangeAtSearch('bar;', contents, 'bar'),
@@ -1065,9 +1138,9 @@
 import 'other.dart';
 
 void fo^o() {
-  void nested() {
+  /*1*/void nested() {
     f(); // not a call of 'foo'
-  }
+  }/*1*/
   f(); // 1
   final tearoff = f;
   nested();
@@ -1076,7 +1149,7 @@
     ''';
 
     final otherContents = '''
-void f() {}
+/*1*/void f() {}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1085,13 +1158,15 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.function, 'f', otherFile,
-            rangeAtSearch('f() {', otherContents, 'f'),
+            nameRange: rangeAtSearch('f() {', otherContents, 'f'),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAtSearch('f(); // 1', contents, 'f'),
               rangeAfterPrefix('tearoff = ', contents, 'f'),
             ]),
         _isResult(CallHierarchyKind.function, 'nested', testFile,
-            rangeAtSearch('nested() {', contents, 'nested'),
+            nameRange: rangeAtSearch('nested() {', contents, 'nested'),
+            codeRange: rangeNumbered(1, contents),
             ranges: [
               rangeAtSearch('nested();', contents, 'nested'),
               rangeAfterPrefix('nestedTearoff = ', contents, 'nested'),
@@ -1114,9 +1189,9 @@
     ''';
 
     final otherContents = '''
-class A {
-  String get b => '';
-}
+/*1*/class A {
+  /*2*/String get b => '';/*2*/
+}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1124,10 +1199,16 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.constructor, 'A', otherFile,
-            rangeAtSearch('A {', otherContents, 'A')),
+        _isResult(
+          CallHierarchyKind.constructor,
+          'A',
+          otherFile,
+          nameRange: rangeAtSearch('A {', otherContents, 'A'),
+          codeRange: rangeNumbered(1, otherContents),
+        ),
         _isResult(CallHierarchyKind.property, 'get b', otherFile,
-            rangeAtSearch('b => ', otherContents, 'b'),
+            nameRange: rangeAtSearch('b => ', otherContents, 'b'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfterPrefix('a.', contents, 'b'),
               rangeAfterPrefix('A().', contents, 'b'),
@@ -1144,7 +1225,7 @@
 // ignore_for_file: unused_local_variable
 import 'other.dart';
 
-f() {
+void f() {
   final foo1 = Fo^o();
 }
     ''';
@@ -1177,10 +1258,10 @@
     ''';
 
     final otherContents = '''
-class A {
+/*1*/class A {
   String field;
-  void bar() {}
-}
+  /*2*/void bar() {}/*2*/
+}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1188,10 +1269,16 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.constructor, 'A', otherFile,
-            rangeAtSearch('A {', otherContents, 'A')),
+        _isResult(
+          CallHierarchyKind.constructor,
+          'A',
+          otherFile,
+          nameRange: rangeAtSearch('A {', otherContents, 'A'),
+          codeRange: rangeNumbered(1, otherContents),
+        ),
         _isResult(CallHierarchyKind.method, 'bar', otherFile,
-            rangeAtSearch('bar() {', otherContents, 'bar'),
+            nameRange: rangeAtSearch('bar() {', otherContents, 'bar'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfterPrefix('a.', contents, 'bar'),
               rangeAfterPrefix('tearoff = a.', contents, 'bar'),
@@ -1217,10 +1304,10 @@
 
     final otherContents = '''
 mixin OtherMixin {
-  void foo() {}
+  /*2*/void foo() {}/*2*/
 }
 
-class A with OtherMixin {}
+/*1*/class A with OtherMixin {}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1228,10 +1315,16 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.constructor, 'A', otherFile,
-            rangeAtSearch('A with', otherContents, 'A')),
+        _isResult(
+          CallHierarchyKind.constructor,
+          'A',
+          otherFile,
+          nameRange: rangeAtSearch('A with', otherContents, 'A'),
+          codeRange: rangeNumbered(1, otherContents),
+        ),
         _isResult(CallHierarchyKind.method, 'foo', otherFile,
-            rangeAtSearch('foo() {', otherContents, 'foo'),
+            nameRange: rangeAtSearch('foo() {', otherContents, 'foo'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfterPrefix('a.', contents, 'foo'),
               rangeAfterPrefix('A().', contents, 'foo'),
@@ -1257,7 +1350,7 @@
     final otherContents = '''
 void f() {}
 class A {
-  A.named();
+  /*1*/A.named();/*1*/
 }
     ''';
 
@@ -1267,7 +1360,8 @@
       calls,
       unorderedEquals([
         _isResult(CallHierarchyKind.constructor, 'A.named', otherFile,
-            rangeAtSearch('named', otherContents),
+            nameRange: rangeAtSearch('named', otherContents),
+            codeRange: rangeNumbered(1, otherContents),
             ranges: [
               rangeAfterPrefix('a = A.', contents, 'named'),
               rangeAfterPrefix('constructorTearoff = A.', contents, 'named'),
@@ -1288,9 +1382,9 @@
     ''';
 
     final otherContents = '''
-class A {
-  set b(String value) {}
-}
+/*1*/class A {
+  /*2*/set b(String value) {}/*2*/
+}/*1*/
     ''';
 
     addSource(otherFile, otherContents);
@@ -1298,10 +1392,16 @@
     expect(
       calls,
       unorderedEquals([
-        _isResult(CallHierarchyKind.constructor, 'A', otherFile,
-            rangeAtSearch('A {', otherContents, 'A')),
+        _isResult(
+          CallHierarchyKind.constructor,
+          'A',
+          otherFile,
+          nameRange: rangeAtSearch('A {', otherContents, 'A'),
+          codeRange: rangeNumbered(1, otherContents),
+        ),
         _isResult(CallHierarchyKind.property, 'set b', otherFile,
-            rangeAtSearch('b(String ', otherContents, 'b'),
+            nameRange: rangeAtSearch('b(String ', otherContents, 'b'),
+            codeRange: rangeNumbered(2, otherContents),
             ranges: [
               rangeAfterPrefix('a.', contents, 'b'),
               rangeAfterPrefix('A().', contents, 'b'),
diff --git a/sdk/lib/developer/profiler.dart b/sdk/lib/developer/profiler.dart
index bf6ae6b..b134de7 100644
--- a/sdk/lib/developer/profiler.dart
+++ b/sdk/lib/developer/profiler.dart
@@ -10,9 +10,9 @@
   /// The maximum number of UserTag instances that can be created by a program.
   static const maxUserTags = 64;
 
-  @deprecated
-  // TODO: We shouldn't be using SCREAMING_CAPS for constants, so this should
-  // be removed for Dart 3.0.
+  @Deprecated("Use 'maxUserTags' instead. Will be removed in Dart 3.0.")
+  // TODO(bkonyi): We shouldn't be using SCREAMING_CAPS for constants, so this
+  // should be removed for Dart 3.0.
   static const MAX_USER_TAGS = maxUserTags;
 
   external factory UserTag(String label);
diff --git a/tools/VERSION b/tools/VERSION
index 6c8c0b4..a271db8 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 277
+PRERELEASE 278
 PRERELEASE_PATCH 0
\ No newline at end of file