Version 2.13.0-130.0.dev

Merge commit '78ca98ac8ef97ca115b2b3f38734cf905917f114' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 5b2865b..25287e5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -78,32 +78,26 @@
     {double contextType = 0.0,
     double elementKind = 0.0,
     double hasDeprecated = 0.0,
-    double inheritanceDistance = 0.0,
     double isConstant = 0.0,
     double isNoSuchMethod = 0.0,
     double keyword = 0.0,
-    double localVariableDistance = 0.0,
     double startsWithDollar = 0.0,
     double superMatches = 0.0}) {
   assert(contextType.between(0.0, 1.0));
   assert(elementKind.between(0.0, 1.0));
   assert(hasDeprecated.between(-1.0, 0.0));
-  assert(inheritanceDistance.between(0.0, 1.0));
   assert(isConstant.between(0.0, 1.0));
   assert(isNoSuchMethod.between(-1.0, 0.0));
   assert(keyword.between(0.0, 1.0));
-  assert(localVariableDistance.between(0.0, 1.0));
   assert(startsWithDollar.between(-1.0, 0.0));
   assert(superMatches.between(0.0, 1.0));
   var average = _weightedAverage([
     contextType,
     elementKind,
     hasDeprecated,
-    inheritanceDistance,
     isConstant,
     isNoSuchMethod,
     keyword,
-    localVariableDistance,
     startsWithDollar,
     superMatches,
   ], FeatureComputer.featureWeights);
@@ -150,11 +144,9 @@
     1.00, // contextType
     1.00, // elementKind
     0.50, // hasDeprecated
-    1.00, // inheritanceDistance
     1.00, // isConstant
     1.00, // isNoSuchMethod
     1.00, // keyword
-    1.00, // localVariableDistance
     0.50, // startsWithDollar
     1.00, // superMatches
   ];
@@ -257,7 +249,7 @@
   /// completing at the given [completionLocation]. If a [distance] is given it
   /// will be used to provide finer-grained relevance scores.
   double elementKindFeature(Element element, String completionLocation,
-      {int distance}) {
+      {double distance}) {
     if (completionLocation == null) {
       return 0.0;
     }
@@ -270,9 +262,9 @@
       return 0.0;
     }
     if (distance == null) {
-      return range.upper;
+      return range.middle;
     }
-    return range.conditionalProbability(_distanceToPercent(distance));
+    return range.conditionalProbability(distance);
   }
 
   /// Return the value of the _has deprecated_ feature for the given [element].
@@ -455,7 +447,7 @@
     if (distance < 0) {
       return 0.0;
     }
-    return math.pow(0.98, distance);
+    return math.pow(0.9, distance);
   }
 
   /// Return the inheritance distance between the [subclass] and the
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart b/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart
index 2b4be44..d5167d9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/probability_range.dart
@@ -14,10 +14,13 @@
   /// [upper] bounds.
   const ProbabilityRange({this.lower, this.upper});
 
+  /// The middle of the range.
+  double get middle => (upper + lower) / 2;
+
   /// Given the [probability] of an occurrence of an event that is conditional
   /// on the event represented by this range, return the probability of the
   /// event independent of the event based on this range.
   double conditionalProbability(double probability) {
-    return lower + ((upper - lower) * probability);
+    return middle + ((upper - lower) * probability / 2);
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index bd6ecf6..1f20658 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -223,7 +223,8 @@
       var featureComputer = request.featureComputer;
       var contextType =
           featureComputer.contextTypeFeature(request.contextType, type);
-      var elementKind = _computeElementKind(accessor);
+      var elementKind =
+          _computeElementKind(accessor, distance: inheritanceDistance);
       var hasDeprecated = featureComputer.hasDeprecatedFeature(accessor);
       var isConstant = request.inConstantContext
           ? featureComputer.isConstantFeature(accessor)
@@ -232,22 +233,15 @@
           featureComputer.startsWithDollarFeature(accessor.name);
       var superMatches = featureComputer.superMatchesFeature(
           _containingMemberName, accessor.name);
-      var relevance = _computeMemberRelevance(
-          contextType: contextType,
-          elementKind: elementKind,
-          hasDeprecated: hasDeprecated,
-          inheritanceDistance: inheritanceDistance,
-          isConstant: isConstant,
-          startsWithDollar: startsWithDollar,
-          superMatches: superMatches);
-      listener?.computedFeatures(
-          contextType: contextType,
-          elementKind: elementKind,
-          hasDeprecated: hasDeprecated,
-          inheritanceDistance: inheritanceDistance,
-          isConstant: isConstant,
-          startsWithDollar: startsWithDollar,
-          superMatches: superMatches);
+      var relevance = _computeRelevance(
+        contextType: contextType,
+        elementKind: elementKind,
+        hasDeprecated: hasDeprecated,
+        isConstant: isConstant,
+        startsWithDollar: startsWithDollar,
+        superMatches: superMatches,
+        inheritanceDistance: inheritanceDistance,
+      );
       _add(_createSuggestion(accessor, relevance: relevance));
     }
   }
@@ -261,15 +255,11 @@
     var isConstant = request.inConstantContext
         ? request.featureComputer.isConstantFeature(parameter)
         : 0.0;
-    var score = weightedAverage(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      isConstant: isConstant,
+    );
     _add(_createSuggestion(parameter,
         elementKind: protocol.ElementKind.PARAMETER, relevance: relevance));
   }
@@ -437,7 +427,7 @@
     var featureComputer = request.featureComputer;
     var contextType =
         featureComputer.contextTypeFeature(request.contextType, field.type);
-    var elementKind = _computeElementKind(field);
+    var elementKind = _computeElementKind(field, distance: inheritanceDistance);
     var hasDeprecated = featureComputer.hasDeprecatedFeature(field);
     var isConstant = request.inConstantContext
         ? featureComputer.isConstantFeature(field)
@@ -445,22 +435,15 @@
     var startsWithDollar = featureComputer.startsWithDollarFeature(field.name);
     var superMatches =
         featureComputer.superMatchesFeature(_containingMemberName, field.name);
-    var relevance = _computeMemberRelevance(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        inheritanceDistance: inheritanceDistance,
-        isConstant: isConstant,
-        startsWithDollar: startsWithDollar,
-        superMatches: superMatches);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        inheritanceDistance: inheritanceDistance,
-        isConstant: isConstant,
-        startsWithDollar: startsWithDollar,
-        superMatches: superMatches);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      hasDeprecated: hasDeprecated,
+      isConstant: isConstant,
+      startsWithDollar: startsWithDollar,
+      superMatches: superMatches,
+      inheritanceDistance: inheritanceDistance,
+    );
     _add(_createSuggestion(field, relevance: relevance));
   }
 
@@ -511,11 +494,10 @@
         .contextTypeFeature(request.contextType, elementType);
     var keywordFeature = request.featureComputer
         .keywordFeature(keyword, request.opType.completionLocation);
-    var score =
-        weightedAverage(contextType: contextType, keyword: keywordFeature);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        contextType: contextType, keyword: keywordFeature);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      keyword: keywordFeature,
+    );
     _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
         keyword, offset ?? keyword.length, 0, false, false));
   }
@@ -552,23 +534,19 @@
     var node = entity is AstNode ? entity : target.containingNode;
     var contextType = request.featureComputer
         .contextTypeFeature(request.contextType, variableType);
-    var elementKind = _computeElementKind(variable);
+    var localVariableDistance =
+        request.featureComputer.localVariableDistanceFeature(node, variable);
+    var elementKind =
+        _computeElementKind(variable, distance: localVariableDistance);
     var isConstant = request.inConstantContext
         ? request.featureComputer.isConstantFeature(variable)
         : 0.0;
-    var localVariableDistance =
-        request.featureComputer.localVariableDistanceFeature(node, variable);
-    var score = weightedAverage(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant,
-        localVariableDistance: localVariableDistance);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant,
-        localVariableDistance: localVariableDistance);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      isConstant: isConstant,
+      localVariableDistance: localVariableDistance,
+    );
     _add(_createSuggestion(variable, relevance: relevance));
   }
 
@@ -585,7 +563,8 @@
     var featureComputer = request.featureComputer;
     var contextType = featureComputer.contextTypeFeature(
         request.contextType, method.returnType);
-    var elementKind = _computeElementKind(method);
+    var elementKind =
+        _computeElementKind(method, distance: inheritanceDistance);
     var hasDeprecated = featureComputer.hasDeprecatedFeature(method);
     var isConstant = request.inConstantContext
         ? featureComputer.isConstantFeature(method)
@@ -595,24 +574,16 @@
     var startsWithDollar = featureComputer.startsWithDollarFeature(method.name);
     var superMatches =
         featureComputer.superMatchesFeature(_containingMemberName, method.name);
-    var relevance = _computeMemberRelevance(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        inheritanceDistance: inheritanceDistance,
-        isConstant: isConstant,
-        isNoSuchMethod: isNoSuchMethod,
-        startsWithDollar: startsWithDollar,
-        superMatches: superMatches);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        inheritanceDistance: inheritanceDistance,
-        isConstant: isConstant,
-        isNoSuchMethod: isNoSuchMethod,
-        startsWithDollar: startsWithDollar,
-        superMatches: superMatches);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      hasDeprecated: hasDeprecated,
+      isConstant: isConstant,
+      isNoSuchMethod: isNoSuchMethod,
+      startsWithDollar: startsWithDollar,
+      superMatches: superMatches,
+      inheritanceDistance: inheritanceDistance,
+    );
 
     var suggestion =
         _createSuggestion(method, kind: kind, relevance: relevance);
@@ -790,15 +761,11 @@
     var isConstant = request.inConstantContext
         ? request.featureComputer.isConstantFeature(parameter)
         : 0.0;
-    var score = weightedAverage(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        isConstant: isConstant);
+    var relevance = _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      isConstant: isConstant,
+    );
     _add(_createSuggestion(parameter, relevance: relevance));
   }
 
@@ -808,9 +775,9 @@
     // TODO(brianwilkerson) If we are in a constant context it would be nice
     //  to promote prefixes for libraries that define constants, but that
     //  might be more work than it's worth.
-    var score = weightedAverage(elementKind: elementKind);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(elementKind: elementKind);
+    var relevance = _computeRelevance(
+      elementKind: elementKind,
+    );
     _add(_createSuggestion(library,
         completion: prefix,
         kind: CompletionSuggestionKind.IDENTIFIER,
@@ -857,29 +824,20 @@
           featureComputer.contextTypeFeature(request.contextType, type);
       var elementKind = _computeElementKind(accessor);
       var hasDeprecated = featureComputer.hasDeprecatedFeature(accessor);
-      var inheritanceDistance = 0.0;
       var isConstant = request.inConstantContext
           ? featureComputer.isConstantFeature(accessor)
           : 0.0;
       var startsWithDollar =
           featureComputer.startsWithDollarFeature(accessor.name);
       var superMatches = 0.0;
-      var relevance = _computeMemberRelevance(
-          contextType: contextType,
-          elementKind: elementKind,
-          hasDeprecated: hasDeprecated,
-          inheritanceDistance: inheritanceDistance,
-          isConstant: isConstant,
-          startsWithDollar: startsWithDollar,
-          superMatches: superMatches);
-      listener?.computedFeatures(
-          contextType: contextType,
-          elementKind: elementKind,
-          hasDeprecated: hasDeprecated,
-          inheritanceDistance: inheritanceDistance,
-          isConstant: isConstant,
-          startsWithDollar: startsWithDollar,
-          superMatches: superMatches);
+      var relevance = _computeRelevance(
+        contextType: contextType,
+        elementKind: elementKind,
+        hasDeprecated: hasDeprecated,
+        isConstant: isConstant,
+        startsWithDollar: startsWithDollar,
+        superMatches: superMatches,
+      );
       _add(_createSuggestion(accessor, prefix: prefix, relevance: relevance));
     }
   }
@@ -915,11 +873,10 @@
     var isConstant = request.inConstantContext
         ? request.featureComputer.isConstantFeature(parameter)
         : 0.0;
-    var score =
-        weightedAverage(elementKind: elementKind, isConstant: isConstant);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        elementKind: elementKind, isConstant: isConstant);
+    var relevance = _computeRelevance(
+      elementKind: elementKind,
+      isConstant: isConstant,
+    );
     _add(_createSuggestion(parameter,
         kind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance));
   }
@@ -951,10 +908,10 @@
 
   /// Compute the value of the _element kind_ feature for the given [element] in
   /// the completion context.
-  double _computeElementKind(Element element) {
+  double _computeElementKind(Element element, {double distance}) {
     var location = request.opType.completionLocation;
-    var elementKind =
-        request.featureComputer.elementKindFeature(element, location);
+    var elementKind = request.featureComputer
+        .elementKindFeature(element, location, distance: distance);
     if (elementKind < 0.0) {
       if (location == null) {
         listener?.missingCompletionLocationAt(
@@ -966,26 +923,44 @@
     return elementKind;
   }
 
-  /// Compute a relevance value from the given feature scores.
-  int _computeMemberRelevance(
-      {@required double contextType,
-      @required double elementKind,
-      @required double hasDeprecated,
-      @required double inheritanceDistance,
-      @required double isConstant,
+  /// Compute the relevance based on the given feature values and pass those
+  /// feature values to the listener if there is one.
+  int _computeRelevance(
+      {double contextType = 0.0,
+      double elementKind = 0.0,
+      double hasDeprecated = 0.0,
+      double isConstant = 0.0,
       double isNoSuchMethod = 0.0,
-      @required double startsWithDollar,
-      @required double superMatches}) {
+      double keyword = 0.0,
+      double startsWithDollar = 0.0,
+      double superMatches = 0.0,
+      // Dependent features
+      double inheritanceDistance = 0.0,
+      double localVariableDistance = 0.0}) {
     var score = weightedAverage(
         contextType: contextType,
         elementKind: elementKind,
         hasDeprecated: hasDeprecated,
-        inheritanceDistance: inheritanceDistance,
         isConstant: isConstant,
         isNoSuchMethod: isNoSuchMethod,
+        keyword: keyword,
         startsWithDollar: startsWithDollar,
         superMatches: superMatches);
-    return toRelevance(score);
+    var relevance = toRelevance(score);
+    listener?.computedFeatures(
+      contextType: contextType,
+      elementKind: elementKind,
+      hasDeprecated: hasDeprecated,
+      isConstant: isConstant,
+      isNoSuchMethod: isNoSuchMethod,
+      keyword: keyword,
+      startsWithDollar: startsWithDollar,
+      superMatches: superMatches,
+      // Dependent features
+      inheritanceDistance: inheritanceDistance,
+      localVariableDistance: localVariableDistance,
+    );
+    return relevance;
   }
 
   /// Return the relevance score for a top-level [element].
@@ -1003,18 +978,12 @@
     var isConstant = request.inConstantContext
         ? featureComputer.isConstantFeature(element)
         : 0.0;
-    var score = weightedAverage(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        isConstant: isConstant);
-    var relevance = toRelevance(score);
-    listener?.computedFeatures(
-        contextType: contextType,
-        elementKind: elementKind,
-        hasDeprecated: hasDeprecated,
-        isConstant: isConstant);
-    return relevance;
+    return _computeRelevance(
+      contextType: contextType,
+      elementKind: elementKind,
+      hasDeprecated: hasDeprecated,
+      isConstant: isConstant,
+    );
   }
 
   /// Return a suggestion based on the [element], or `null` if a suggestion is
@@ -1158,13 +1127,14 @@
       {double contextType,
       double elementKind,
       double hasDeprecated,
-      double inheritanceDistance,
       double isConstant,
       double isNoSuchMethod,
       double keyword,
-      double localVariableDistance,
       double startsWithDollar,
-      double superMatches});
+      double superMatches,
+      // Dependent features
+      double inheritanceDistance,
+      double localVariableDistance});
 
   /// Invoked when an element kind feature cannot be produced because there is
   /// no completion location label associated with the completion offset.
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 4b13c5a8..850ffd7 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1349,13 +1349,13 @@
           'contextType',
           'elementKind',
           'hasDeprecated',
-          'inheritanceDistance',
           'isConstant',
           'isNoSuchMethod',
           'keyword',
-          'localVariableDistance',
           'startsWithDollar',
-          'superMatches'
+          'superMatches',
+          'inheritanceDistance',
+          'localVariableDistance',
         ]
       ];
       for (var i = 0; i < topSuggestionCount; i++) {
@@ -1738,24 +1738,26 @@
       {double contextType = 0.0,
       double elementKind = 0.0,
       double hasDeprecated = 0.0,
-      double inheritanceDistance = 0.0,
       double isConstant = 0.0,
       double isNoSuchMethod = 0.0,
       double keyword = 0.0,
-      double localVariableDistance = 0.0,
       double startsWithDollar = 0.0,
-      double superMatches = 0.0}) {
+      double superMatches = 0.0,
+      // Dependent features
+      double inheritanceDistance = 0.0,
+      double localVariableDistance = 0.0}) {
     cachedFeatures = [
       contextType,
       elementKind,
       hasDeprecated,
-      inheritanceDistance,
       isConstant,
       isNoSuchMethod,
       keyword,
-      localVariableDistance,
       startsWithDollar,
-      superMatches
+      superMatches,
+      // Dependent features
+      inheritanceDistance,
+      localVariableDistance,
     ];
   }
 
diff --git a/tools/VERSION b/tools/VERSION
index 3a0631f..b6cf424 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 129
+PRERELEASE 130
 PRERELEASE_PATCH 0
\ No newline at end of file