// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:collection';

import 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart';
import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/protocol_server.dart'
    hide Element, ElementKind;
import 'package:analysis_server/src/protocol_server.dart'
    show CompletionSuggestion;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analysis_server/src/services/completion/dart/utilities.dart';
import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analysis_server/src/utilities/extensions/element.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/util/comment.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:meta/meta.dart';

/// This class provides suggestions based upon the visible instance members in
/// an interface type.
class MemberSuggestionBuilder {
  /// Enumerated value indicating that we have not generated any completions for
  /// a given identifier yet.
  static const int _COMPLETION_TYPE_NONE = 0;

  /// Enumerated value indicating that we have generated a completion for a
  /// getter.
  static const int _COMPLETION_TYPE_GETTER = 1;

  /// Enumerated value indicating that we have generated a completion for a
  /// setter.
  static const int _COMPLETION_TYPE_SETTER = 2;

  /// Enumerated value indicating that we have generated a completion for a
  /// field, a method, or a getter/setter pair.
  static const int _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET = 3;

  /// The request for which suggestions are being built.
  final DartCompletionRequest request;

  /// The builder used to build the suggestions.
  final SuggestionBuilder builder;

  /// Map indicating, for each possible completion identifier, whether we have
  /// already generated completions for a getter, setter, or both.  The "both"
  /// case also handles the case where have generated a completion for a method
  /// or a field.
  ///
  /// Note: the enumerated values stored in this map are intended to be bitwise
  /// compared.
  final Map<String, int> _completionTypesGenerated = HashMap<String, int>();

  MemberSuggestionBuilder(this.request, this.builder);

  /// Add a suggestion for the given [accessor].
  void addSuggestionForAccessor(
      {@required PropertyAccessorElement accessor,
      @required double inheritanceDistance}) {
    if (accessor.isAccessibleIn(request.libraryElement)) {
      var member = accessor.isSynthetic ? accessor.variable : accessor;
      if (_shouldAddSuggestion(member)) {
        builder.suggestAccessor(accessor,
            inheritanceDistance: inheritanceDistance);
      }
    }
  }

  /// Add a suggestion for the given [method].
  void addSuggestionForMethod(
      {@required MethodElement method,
      CompletionSuggestionKind kind,
      @required double inheritanceDistance}) {
    if (method.isAccessibleIn(request.libraryElement) &&
        _shouldAddSuggestion(method)) {
      builder.suggestMethod(method,
          kind: kind, inheritanceDistance: inheritanceDistance);
    }
  }

  /// Return `true` if a suggestion for the given [element] should be created.
  bool _shouldAddSuggestion(Element element) {
    // TODO(brianwilkerson) Consider moving this into SuggestionBuilder.
    var identifier = element.displayName;

    var alreadyGenerated = _completionTypesGenerated.putIfAbsent(
        identifier, () => _COMPLETION_TYPE_NONE);
    if (element is MethodElement) {
      // Anything shadows a method.
      if (alreadyGenerated != _COMPLETION_TYPE_NONE) {
        return false;
      }
      _completionTypesGenerated[identifier] =
          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
    } else if (element is PropertyAccessorElement) {
      if (element.isGetter) {
        // Getters, fields, and methods shadow a getter.
        if ((alreadyGenerated & _COMPLETION_TYPE_GETTER) != 0) {
          return false;
        }
        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_GETTER;
      } else {
        // Setters, fields, and methods shadow a setter.
        if ((alreadyGenerated & _COMPLETION_TYPE_SETTER) != 0) {
          return false;
        }
        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_SETTER;
      }
    } else if (element is FieldElement) {
      // Fields and methods shadow a field.  A getter/setter pair shadows a
      // field, but a getter or setter by itself doesn't.
      if (alreadyGenerated == _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET) {
        return false;
      }
      _completionTypesGenerated[identifier] =
          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
    } else {
      // Unexpected element type; skip it.
      assert(false);
      return false;
    }
    return true;
  }
}

/// An object used to build a list of suggestions in response to a single
/// completion request.
class SuggestionBuilder {
  /// The completion request for which suggestions are being built.
  final DartCompletionRequest request;

  /// The listener to be notified at certain points in the process of building
  /// suggestions, or `null` if no notification should occur.
  final SuggestionListener listener;

  /// A map from a completion identifier to a completion suggestion.
  final Map<String, CompletionSuggestion> _suggestionMap =
      <String, CompletionSuggestion>{};

  /// A flag indicating whether a suggestion should replace any earlier
  /// suggestions for the same completion (`true`) or whether earlier
  /// suggestions should take priority over more recent suggestions.
  // TODO(brianwilkerson) Attempt to convert the contributors so that a single
  //  approach is followed.
  bool laterReplacesEarlier = true;

  /// A flag indicating whether the [_cachedContainingMemberName] has been
  /// computed.
  bool _hasContainingMemberName = false;

  /// The name of the member containing the completion location, or `null` if
  /// either the completion location isn't within a member, the target of the
  /// completion isn't `super`, or the name of the member hasn't yet been
  /// computed. In the latter case, [_hasContainingMemberName] will be `false`.
  String _cachedContainingMemberName;

  /// Initialize a newly created suggestion builder to build suggestions for the
  /// given [request].
  SuggestionBuilder(this.request, {this.listener});

  /// Return an object that can answer questions about Flutter code.
  Flutter get flutter => Flutter.instance;

  /// Return an iterable that can be used to access the completion suggestions
  /// that have been built.
  Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values;

  /// Return the name of the member containing the completion location, or
  /// `null` if the completion location isn't within a member or if the target
  /// of the completion isn't `super`.
  String get _containingMemberName {
    if (!_hasContainingMemberName) {
      _hasContainingMemberName = true;
      if (request.dotTarget is SuperExpression) {
        var containingMethod = request.target.containingNode
            .thisOrAncestorOfType<MethodDeclaration>();
        if (containingMethod != null) {
          var id = containingMethod.name;
          if (id != null) {
            _cachedContainingMemberName = id.name;
          }
        }
      }
    }
    return _cachedContainingMemberName;
  }

  /// Add a suggestion for an [accessor] declared within a class or extension.
  /// If the accessor is being invoked with a target of `super`, then the
  /// [containingMemberName] should be the name of the member containing the
  /// invocation. The [inheritanceDistance] is the value of the inheritance
  /// distance feature computed for the accessor or `-1.0` if the accessor is a
  /// static accessor.
  void suggestAccessor(PropertyAccessorElement accessor,
      {@required double inheritanceDistance}) {
    assert(accessor.enclosingElement is ClassElement ||
        accessor.enclosingElement is ExtensionElement);
    if (accessor.isSynthetic) {
      // Avoid visiting a field twice. All fields induce a getter, but only
      // non-final fields induce a setter, so we don't add a suggestion for a
      // synthetic setter.
      if (accessor.isGetter) {
        var variable = accessor.variable;
        if (variable is FieldElement) {
          suggestField(variable, inheritanceDistance: inheritanceDistance);
        }
      }
    } else {
      var type = _getPropertyAccessorType(accessor);
      int relevance;
      if (request.useNewRelevance) {
        var featureComputer = request.featureComputer;
        var contextType =
            featureComputer.contextTypeFeature(request.contextType, type);
        var elementKind = _computeElementKind(accessor);
        var hasDeprecated = featureComputer.hasDeprecatedFeature(accessor);
        var isConstant = request.inConstantContext
            ? featureComputer.isConstantFeature(accessor)
            : -1.0;
        var startsWithDollar =
            featureComputer.startsWithDollarFeature(accessor.name);
        var superMatches = featureComputer.superMatchesFeature(
            _containingMemberName, accessor.name);
        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,
            startsWithDollar: startsWithDollar,
            superMatches: superMatches);
      } else {
        relevance = accessor.hasOrInheritsDeprecated
            ? DART_RELEVANCE_LOW
            : _computeOldMemberRelevance(accessor);
        if (request.opType.includeReturnValueSuggestions) {
          relevance =
              request.opType.returnValueSuggestionsFilter(type, relevance);
        }
        if (relevance == null) {
          return;
        }
      }
      _add(_createSuggestion(accessor, relevance: relevance));
    }
  }

  /// Add a suggestion for a catch [parameter].
  void suggestCatchParameter(LocalVariableElement parameter) {
    var variableType = parameter.type;
    int relevance;
    if (request.useNewRelevance) {
      var contextType = request.featureComputer
          .contextTypeFeature(request.contextType, variableType);
      var elementKind = _computeElementKind(parameter);
      var isConstant = request.inConstantContext
          ? request.featureComputer.isConstantFeature(parameter)
          : -1.0;
      relevance = toRelevance(
          weightedAverage(
              [contextType, elementKind, isConstant], [1.0, 1.0, 1.0]),
          800);
      listener?.computedFeatures(contextType: contextType);
    } else {
      relevance = _computeOldMemberRelevance(parameter);
      relevance =
          request.opType.returnValueSuggestionsFilter(variableType, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(parameter,
        elementKind: protocol.ElementKind.PARAMETER, relevance: relevance));
  }

  /// Add a suggestion for a [classElement]. If a [kind] is provided it will
  /// be used as the kind for the suggestion. If the class can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestClass(ClassElement classElement,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    int relevance;
    if (request.useNewRelevance) {
      relevance = _computeTopLevelRelevance(classElement,
          elementType: _instantiateClassElement(classElement));
    } else if (classElement.hasOrInheritsDeprecated) {
      relevance = DART_RELEVANCE_LOW;
    } else {
      relevance = request.opType.typeNameSuggestionsFilter(
          _instantiateClassElement(classElement), DART_RELEVANCE_DEFAULT);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(classElement,
        kind: kind, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion to insert a closure matching the given function [type].
  /// If [includeTrailingComma] is `true` then the completion text will include
  /// a trailing comma, such as when the closure is part of an argument list.
  void suggestClosure(FunctionType type, {bool includeTrailingComma = false}) {
    var indent = getRequestLineIndent(request);
    var parametersString = buildClosureParameters(type);

    var blockBuffer = StringBuffer(parametersString);
    blockBuffer.writeln(' {');
    blockBuffer.write('$indent  ');
    var blockSelectionOffset = blockBuffer.length;
    blockBuffer.writeln();
    blockBuffer.write('$indent}');

    var expressionBuffer = StringBuffer(parametersString);
    expressionBuffer.write(' => ');
    var expressionSelectionOffset = expressionBuffer.length;

    if (includeTrailingComma) {
      blockBuffer.write(',');
      expressionBuffer.write(',');
    }

    CompletionSuggestion createSuggestion({
      @required String completion,
      @required String displayText,
      @required int selectionOffset,
    }) {
      return CompletionSuggestion(
        CompletionSuggestionKind.INVOCATION,
        request.useNewRelevance ? Relevance.closure : DART_RELEVANCE_HIGH,
        completion,
        selectionOffset,
        0,
        false,
        false,
        displayText: displayText,
      );
    }

    _add(createSuggestion(
      completion: blockBuffer.toString(),
      displayText: '$parametersString {}',
      selectionOffset: blockSelectionOffset,
    ));
    _add(createSuggestion(
      completion: expressionBuffer.toString(),
      displayText: '$parametersString =>',
      selectionOffset: expressionSelectionOffset,
    ));
  }

  /// Add a suggestion for a [constructor]. If a [kind] is provided it will be
  /// used as the kind for the suggestion. The flag [hasClassName] should be
  /// `true` if the completion is occurring after the name of the class and a
  /// period, and hence should not include the name of the class. If the class
  /// can only be referenced using a prefix, and the class name is to be
  /// included in the completion, then the [prefix] should be provided.
  void suggestConstructor(ConstructorElement constructor,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      bool hasClassName = false,
      String prefix}) {
    // If the class name is already in the text, then we don't support
    // prepending a prefix.
    assert(!hasClassName || prefix == null);
    var enclosingClass = constructor.enclosingElement;
    var className = enclosingClass?.name;
    if (className == null || className.isEmpty) {
      return;
    }

    var completion = constructor.displayName;
    if (!hasClassName && className != null && className.isNotEmpty) {
      if (completion == null || completion.isEmpty) {
        completion = className;
      } else {
        completion = '$className.$completion';
      }
    }
    if (completion == null || completion.isEmpty) {
      return null;
    }

    int relevance;
    var returnType = _instantiateClassElement(enclosingClass);
    if (request.useNewRelevance) {
      relevance =
          _computeTopLevelRelevance(constructor, elementType: returnType);
    } else {
      relevance = constructor.hasOrInheritsDeprecated
          ? DART_RELEVANCE_LOW
          : DART_RELEVANCE_DEFAULT;
      relevance =
          request.opType.returnValueSuggestionsFilter(returnType, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(constructor,
        completion: completion,
        kind: kind,
        prefix: prefix,
        relevance: relevance));
  }

  /// Add a suggestion for a top-level [element]. If a [kind] is provided it
  /// will be used as the kind for the suggestion.
  void suggestElement(Element element,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
    if (element is ClassElement) {
      suggestClass(element, kind: kind);
    } else if (element is ConstructorElement) {
      suggestConstructor(element, kind: kind);
    } else if (element is ExtensionElement) {
      suggestExtension(element, kind: kind);
    } else if (element is FunctionElement &&
        element.enclosingElement is CompilationUnitElement) {
      suggestTopLevelFunction(element, kind: kind);
    } else if (element is FunctionTypeAliasElement) {
      suggestFunctionTypeAlias(element, kind: kind);
    } else if (element is PropertyAccessorElement &&
        element.enclosingElement is CompilationUnitElement) {
      suggestTopLevelPropertyAccessor(element, kind: kind);
    } else {
      throw ArgumentError('Cannot suggest a ${element.runtimeType}');
    }
  }

  /// Add a suggestion for an enum [constant]. If the enum can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestEnumConstant(FieldElement constant, {String prefix}) {
    var constantName = constant.name;
    var enumElement = constant.enclosingElement;
    var enumName = enumElement.name;
    var completion = '$enumName.$constantName';

    int relevance;
    if (request.useNewRelevance) {
      relevance =
          _computeTopLevelRelevance(constant, elementType: constant.type);
    } else if (constant.hasOrInheritsDeprecated) {
      relevance = DART_RELEVANCE_LOW;
    } else {
      relevance = request.opType.returnValueSuggestionsFilter(
          _instantiateClassElement(enumElement), DART_RELEVANCE_DEFAULT);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(constant,
        completion: completion, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion for an [extension]. If a [kind] is provided it will be
  /// used as the kind for the suggestion. If the extension can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestExtension(ExtensionElement extension,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    int relevance;
    if (request.useNewRelevance) {
      relevance = _computeTopLevelRelevance(extension,
          elementType: extension.extendedType);
    } else {
      relevance = extension.hasOrInheritsDeprecated
          ? DART_RELEVANCE_LOW
          : DART_RELEVANCE_DEFAULT;
    }

    _add(_createSuggestion(extension,
        kind: kind, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion for a [field]. If the field is being referenced with a
  /// target of `super`, then the [containingMemberName] should be the name of
  /// the member containing the reference. The [inheritanceDistance] is the
  /// value of the inheritance distance feature computed for the field (or
  /// `-1.0` if the field is a static field).
  void suggestField(FieldElement field,
      {@required double inheritanceDistance}) {
    int relevance;
    if (request.useNewRelevance) {
      var featureComputer = request.featureComputer;
      var contextType =
          featureComputer.contextTypeFeature(request.contextType, field.type);
      var elementKind = _computeElementKind(field);
      var hasDeprecated = featureComputer.hasDeprecatedFeature(field);
      var isConstant = request.inConstantContext
          ? featureComputer.isConstantFeature(field)
          : -1.0;
      var startsWithDollar =
          featureComputer.startsWithDollarFeature(field.name);
      var superMatches = featureComputer.superMatchesFeature(
          _containingMemberName, field.name);
      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,
          startsWithDollar: startsWithDollar,
          superMatches: superMatches);
    } else {
      relevance = _computeOldMemberRelevance(field);
      if (request.opType.includeReturnValueSuggestions) {
        relevance =
            request.opType.returnValueSuggestionsFilter(field.type, relevance);
      }
      if (relevance == null) {
        return;
      }
    }
    _add(_createSuggestion(field, relevance: relevance));
  }

  /// Add a suggestion to reference a [field] in a field formal parameter.
  void suggestFieldFormalParameter(FieldElement field) {
    // TODO(brianwilkerson) Add a parameter (`bool includePrefix`) indicating
    //  whether to include the `this.` prefix in the completion.
    var relevance = request.useNewRelevance
        ? Relevance.fieldFormalParameter
        : DART_RELEVANCE_LOCAL_FIELD;

    _add(_createSuggestion(field, relevance: relevance));
  }

  /// Add a suggestion for the `call` method defined on functions.
  void suggestFunctionCall() {
    const callString = 'call';
    final element = protocol.Element(
        protocol.ElementKind.METHOD, callString, protocol.Element.makeFlags(),
        location: null,
        typeParameters: null,
        parameters: '()',
        returnType: 'void');
    _add(CompletionSuggestion(
      CompletionSuggestionKind.INVOCATION,
      request.useNewRelevance ? Relevance.callFunction : DART_RELEVANCE_HIGH,
      callString,
      callString.length,
      0,
      false,
      false,
      displayText: 'call()',
      element: element,
      returnType: 'void',
      parameterNames: [],
      parameterTypes: [],
      requiredParameterCount: 0,
      hasNamedParameters: false,
    ));
  }

  /// Add a suggestion for a [functionTypeAlias]. If a [kind] is provided it
  /// will be used as the kind for the suggestion. If the alias can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestFunctionTypeAlias(FunctionTypeAliasElement functionTypeAlias,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    int relevance;
    if (request.useNewRelevance) {
      relevance = _computeTopLevelRelevance(functionTypeAlias,
          defaultRelevance: 750,
          elementType: _instantiateFunctionTypeAlias(functionTypeAlias));
    } else if (functionTypeAlias.hasOrInheritsDeprecated) {
      relevance = DART_RELEVANCE_LOW;
    } else {
      relevance = functionTypeAlias.library == request.libraryElement
          ? DART_RELEVANCE_LOCAL_FUNCTION
          : DART_RELEVANCE_DEFAULT;
    }
    _add(_createSuggestion(functionTypeAlias,
        kind: kind, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion for a [keyword]. The [offset] is the offset from the
  /// beginning of the keyword where the cursor will be left.
  void suggestKeyword(String keyword, {int offset, @required int relevance}) {
    if (request.useNewRelevance) {
      // TODO(brianwilkerson) The default value should probably be a constant.
      relevance = toRelevance(
          request.featureComputer
              .keywordFeature(keyword, request.opType.completionLocation),
          800);
    }
    _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
        keyword, offset ?? keyword.length, 0, false, false));
  }

  /// Add a suggestion for a [label].
  void suggestLabel(Label label) {
    var completion = label.label?.name;
    // TODO(brianwilkerson) Figure out why we're excluding labels consisting of
    //  a single underscore.
    if (completion != null && completion.isNotEmpty && completion != '_') {
      var suggestion = CompletionSuggestion(
          CompletionSuggestionKind.IDENTIFIER,
          request.useNewRelevance ? Relevance.label : DART_RELEVANCE_DEFAULT,
          completion,
          completion.length,
          0,
          false,
          false);
      suggestion.element = createLocalElement(
          request.source, protocol.ElementKind.LABEL, label.label,
          returnType: NO_RETURN_TYPE);
      _add(suggestion);
    }
  }

  /// Add a suggestion for the `loadLibrary` [function] associated with a
  /// prefix.
  void suggestLoadLibraryFunction(FunctionElement function) {
    int relevance;
    if (request.useNewRelevance) {
      // TODO(brianwilkerson) This might want to use the context type rather
      //  than a fixed value.
      relevance = Relevance.loadLibrary;
    } else {
      relevance = function.hasOrInheritsDeprecated
          ? DART_RELEVANCE_LOW
          : DART_RELEVANCE_DEFAULT;
    }

    _add(_createSuggestion(function, relevance: relevance));
  }

  /// Add a suggestion for a local [variable].
  void suggestLocalVariable(LocalVariableElement variable) {
    var variableType = variable.type;
    int relevance;
    if (request.useNewRelevance) {
      var contextType = request.featureComputer
          .contextTypeFeature(request.contextType, variableType);
      var elementKind = _computeElementKind(variable);
      var isConstant = request.inConstantContext
          ? request.featureComputer.isConstantFeature(variable)
          : -1.0;
      var localVariableDistance = request.featureComputer
          .localVariableDistanceFeature(
              request.target.containingNode, variable);
      relevance = toRelevance(
          weightedAverage(
              [contextType, elementKind, isConstant, localVariableDistance],
              [1.0, 1.0, 1.0, 1.0]),
          800);
      listener?.computedFeatures(contextType: contextType);
    } else {
      relevance = _computeOldMemberRelevance(variable);
      relevance =
          request.opType.returnValueSuggestionsFilter(variableType, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(variable, relevance: relevance));
  }

  /// Add a suggestion for a [method]. If the method is being invoked with a
  /// target of `super`, then the [containingMemberName] should be the name of
  /// the member containing the invocation. If a [kind] is provided it will be
  /// used as the kind for the suggestion. The [inheritanceDistance] is the
  /// value of the inheritance distance feature computed for the method.
  void suggestMethod(MethodElement method,
      {CompletionSuggestionKind kind, @required double inheritanceDistance}) {
    // TODO(brianwilkerson) Refactor callers so that we're passing in the type
    //  of the target (assuming we don't already have that type available via
    //  the [request]) and compute the [inheritanceDistance] in this method.
    int relevance;
    if (request.useNewRelevance) {
      var featureComputer = request.featureComputer;
      var contextType = featureComputer.contextTypeFeature(
          request.contextType, method.returnType);
      var elementKind = _computeElementKind(method);
      var hasDeprecated = featureComputer.hasDeprecatedFeature(method);
      var isConstant = request.inConstantContext
          ? featureComputer.isConstantFeature(method)
          : -1.0;
      var startsWithDollar =
          featureComputer.startsWithDollarFeature(method.name);
      var superMatches = featureComputer.superMatchesFeature(
          _containingMemberName, method.name);
      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,
          startsWithDollar: startsWithDollar,
          superMatches: superMatches);
    } else {
      relevance = _computeOldMemberRelevance(method);
      if (request.opType.includeReturnValueSuggestions) {
        relevance = request.opType
            .returnValueSuggestionsFilter(method.returnType, relevance);
      }
      if (relevance == null) {
        return;
      }
    }

    var suggestion =
        _createSuggestion(method, kind: kind, relevance: relevance);
    if (suggestion != null) {
      if (method.name == 'setState' &&
          flutter.isExactState(method.enclosingElement)) {
        // TODO(brianwilkerson) Make this more efficient by creating the correct
        //  suggestion in the first place.
        // Find the line indentation.
        var indent = getRequestLineIndent(request);

        // Let the user know that we are going to insert a complete statement.
        suggestion.displayText = 'setState(() {});';

        // Build the completion and the selection offset.
        var buffer = StringBuffer();
        buffer.writeln('setState(() {');
        buffer.write('$indent  ');
        suggestion.selectionOffset = buffer.length;
        buffer.writeln();
        buffer.write('$indent});');
        suggestion.completion = buffer.toString();

        // There are no arguments to fill.
        suggestion.parameterNames = null;
        suggestion.parameterTypes = null;
        suggestion.requiredParameterCount = null;
        suggestion.hasNamedParameters = null;
      }
      _add(suggestion);
    }
  }

  /// Add a suggestion to use the [name] at a declaration site.
  void suggestName(String name) {
    // TODO(brianwilkerson) Explore whether there are any features of the name
    //  that can be used to provide better relevance scores.
    _add(CompletionSuggestion(
        CompletionSuggestionKind.IDENTIFIER,
        request.useNewRelevance ? 500 : DART_RELEVANCE_DEFAULT,
        name,
        name.length,
        0,
        false,
        false));
  }

  /// Add a suggestion to add a named argument corresponding to the [parameter].
  /// If [appendColon] is `true` then a colon will be added after the name. If
  /// [appendComma] is `true` then a comma will be included at the end of the
  /// completion text.
  void suggestNamedArgument(ParameterElement parameter,
      {@required bool appendColon, @required bool appendComma}) {
    var name = parameter.name;
    var type = parameter.type?.getDisplayString(
        withNullability: request.libraryElement.isNonNullableByDefault);

    var completion = name;
    if (appendColon) {
      completion += ': ';
    }
    var selectionOffset = completion.length;

    // Optionally add Flutter child widget details.
    // todo (pq): revisit this special casing; likely it can be generalized away
    var element = parameter.enclosingElement;
    if (element is ConstructorElement) {
      if (Flutter.instance.isWidget(element.enclosingElement)) {
        // Don't bother with nullability. It won't affect default list values.
        var defaultValue =
            getDefaultStringParameterValue(parameter, withNullability: false);
        // TODO(devoncarew): Should we remove the check here? We would then
        // suggest values for param types like closures.
        if (defaultValue != null && defaultValue.text == '[]') {
          var completionLength = completion.length;
          completion += defaultValue.text;
          if (defaultValue.cursorPosition != null) {
            selectionOffset = completionLength + defaultValue.cursorPosition;
          }
        }
      }
    }

    if (appendComma) {
      completion += ',';
    }

    int relevance;
    if (parameter.isRequiredNamed || parameter.hasRequired) {
      relevance = request.useNewRelevance
          ? Relevance.requiredNamedArgument
          : DART_RELEVANCE_NAMED_PARAMETER_REQUIRED;
    } else {
      relevance = request.useNewRelevance
          ? Relevance.namedArgument
          : DART_RELEVANCE_NAMED_PARAMETER;
    }

    var suggestion = CompletionSuggestion(
        CompletionSuggestionKind.NAMED_ARGUMENT,
        relevance,
        completion,
        selectionOffset,
        0,
        false,
        false,
        parameterName: name,
        parameterType: type);
    if (parameter is FieldFormalParameterElement) {
      _setDocumentation(suggestion, parameter);
      suggestion.element = convertElement(parameter);
    }
    _add(suggestion);
  }

  /// Add a suggestion to replace the [targetId] with an override of the given
  /// [element]. If [invokeSuper] is `true`, then the override will contain an
  /// invocation of an overridden member.
  Future<void> suggestOverride(SimpleIdentifier targetId,
      ExecutableElement element, bool invokeSuper) async {
    var displayTextBuffer = StringBuffer();
    var builder = ChangeBuilder(session: request.result.session);
    await builder.addDartFileEdit(request.result.path, (builder) {
      builder.addReplacement(range.node(targetId), (builder) {
        builder.writeOverride(
          element,
          displayTextBuffer: displayTextBuffer,
          invokeSuper: invokeSuper,
        );
      });
    });

    var fileEdits = builder.sourceChange.edits;
    if (fileEdits.length != 1) {
      return;
    }

    var sourceEdits = fileEdits[0].edits;
    if (sourceEdits.length != 1) {
      return;
    }

    var replacement = sourceEdits[0].replacement;
    var completion = replacement.trim();
    var overrideAnnotation = '@override';
    if (request.target.containingNode.hasOverride &&
        completion.startsWith(overrideAnnotation)) {
      completion = completion.substring(overrideAnnotation.length).trim();
    }
    if (completion.isEmpty) {
      return;
    }

    var selectionRange = builder.selectionRange;
    if (selectionRange == null) {
      return;
    }
    var offsetDelta = targetId.offset + replacement.indexOf(completion);
    var displayText =
        displayTextBuffer.isNotEmpty ? displayTextBuffer.toString() : null;
    var suggestion = CompletionSuggestion(
        CompletionSuggestionKind.OVERRIDE,
        request.useNewRelevance ? Relevance.override : DART_RELEVANCE_HIGH,
        completion,
        selectionRange.offset - offsetDelta,
        selectionRange.length,
        element.hasDeprecated,
        false,
        displayText: displayText);
    suggestion.element = protocol.convertElement(element);
    _add(suggestion);
  }

  /// Add a suggestion for a [parameter].
  void suggestParameter(ParameterElement parameter) {
    var variableType = parameter.type;
    int relevance;
    if (request.useNewRelevance) {
      // TODO(brianwilkerson) Use the distance to the declaring function as
      //  another feature.
      var contextType = request.featureComputer
          .contextTypeFeature(request.contextType, variableType);
      var elementKind = _computeElementKind(parameter);
      var isConstant = request.inConstantContext
          ? request.featureComputer.isConstantFeature(parameter)
          : -1.0;
      relevance = toRelevance(
          weightedAverage(
              [contextType, elementKind, isConstant], [1.0, 1.0, 1.0]),
          800);
      listener?.computedFeatures(contextType: contextType);
    } else {
      relevance = _computeOldMemberRelevance(parameter);
      relevance =
          request.opType.returnValueSuggestionsFilter(variableType, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(parameter, relevance: relevance));
  }

  /// Add a suggestion for a [prefix] associated with a [library].
  void suggestPrefix(LibraryElement library, String prefix) {
    int relevance;
    if (request.useNewRelevance) {
      var elementKind = _computeElementKind(library);
      // 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.
      relevance = toRelevance(elementKind, Relevance.prefix);
      listener?.computedFeatures(elementKind: elementKind);
    } else {
      relevance =
          library.hasDeprecated ? DART_RELEVANCE_LOW : DART_RELEVANCE_DEFAULT;
    }
    _add(_createSuggestion(library,
        completion: prefix,
        kind: CompletionSuggestionKind.IDENTIFIER,
        relevance: relevance));
  }

  /// Add a suggestion for a top-level [function]. If a [kind] is provided it
  /// will be used as the kind for the suggestion. If the function can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestTopLevelFunction(FunctionElement function,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    int relevance;
    if (request.useNewRelevance) {
      relevance =
          _computeTopLevelRelevance(function, elementType: function.returnType);
    } else if (function.hasOrInheritsDeprecated) {
      relevance = DART_RELEVANCE_LOW;
    } else {
      relevance = function.library == request.libraryElement
          ? DART_RELEVANCE_LOCAL_FUNCTION
          : DART_RELEVANCE_DEFAULT;
      relevance =
          request.opType.returnValueSuggestionsFilter(function.type, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(function,
        kind: kind, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion for a top-level property [accessor]. If a [kind] is
  /// provided it will be used as the kind for the suggestion. If the accessor
  /// can only be referenced using a prefix, then the [prefix] should be
  /// provided.
  void suggestTopLevelPropertyAccessor(PropertyAccessorElement accessor,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    assert(accessor.enclosingElement is CompilationUnitElement);
    if (accessor.isSynthetic) {
      // Avoid visiting a field twice. All fields induce a getter, but only
      // non-final fields induce a setter, so we don't add a suggestion for a
      // synthetic setter.
      if (accessor.isGetter) {
        var variable = accessor.variable;
        if (variable is TopLevelVariableElement) {
          suggestTopLevelVariable(variable, kind: kind);
        }
      }
    } else {
      var type = _getPropertyAccessorType(accessor);
      int relevance;
      if (request.useNewRelevance) {
        var featureComputer = request.featureComputer;
        var contextType =
            featureComputer.contextTypeFeature(request.contextType, type);
        var elementKind = _computeElementKind(accessor);
        var hasDeprecated = featureComputer.hasDeprecatedFeature(accessor);
        var isConstant = request.inConstantContext
            ? featureComputer.isConstantFeature(accessor)
            : -1.0;
        var startsWithDollar =
            featureComputer.startsWithDollarFeature(accessor.name);
        relevance = _computeMemberRelevance(
            contextType: contextType,
            elementKind: elementKind,
            hasDeprecated: hasDeprecated,
            inheritanceDistance: -1.0,
            isConstant: isConstant,
            startsWithDollar: startsWithDollar,
            superMatches: -1.0);
        listener?.computedFeatures(
            contextType: contextType,
            elementKind: elementKind,
            hasDeprecated: hasDeprecated,
            startsWithDollar: startsWithDollar);
      } else {
        relevance = accessor.hasOrInheritsDeprecated
            ? DART_RELEVANCE_LOW
            : _computeOldMemberRelevance(accessor);
        if (request.opType.includeReturnValueSuggestions) {
          relevance =
              request.opType.returnValueSuggestionsFilter(type, relevance);
        }
        if (relevance == null) {
          return;
        }
      }
      _add(_createSuggestion(accessor, prefix: prefix, relevance: relevance));
    }
  }

  /// Add a suggestion for a top-level [variable]. If a [kind] is provided it
  /// will be used as the kind for the suggestion. If the variable can only be
  /// referenced using a prefix, then the [prefix] should be provided.
  void suggestTopLevelVariable(TopLevelVariableElement variable,
      {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
      String prefix}) {
    assert(variable.enclosingElement is CompilationUnitElement);
    int relevance;
    if (request.useNewRelevance) {
      relevance =
          _computeTopLevelRelevance(variable, elementType: variable.type);
    } else {
      var type = variable.type;
      relevance = variable.hasOrInheritsDeprecated
          ? DART_RELEVANCE_LOW
          : _computeOldMemberRelevance(variable);
      relevance = request.opType.returnValueSuggestionsFilter(type, relevance);
      if (relevance == null) {
        return;
      }
    }

    _add(_createSuggestion(variable,
        kind: kind, prefix: prefix, relevance: relevance));
  }

  /// Add a suggestion for a type [parameter].
  void suggestTypeParameter(TypeParameterElement parameter) {
    int relevance;
    if (request.useNewRelevance) {
      var elementKind = _computeElementKind(parameter);
      var isConstant = request.inConstantContext
          ? request.featureComputer.isConstantFeature(parameter)
          : -1.0;
      relevance = toRelevance(
          weightedAverage([elementKind, isConstant], [1.0, 1.0]),
          Relevance.typeParameter);
      listener?.computedFeatures(elementKind: elementKind);
    } else {
      relevance = _computeOldMemberRelevance(parameter);
    }

    _add(_createSuggestion(parameter,
        kind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance));
  }

  /// Add a suggestion to use the [uri] in an import, export, or part directive.
  void suggestUri(String uri) {
    int relevance;
    if (request.useNewRelevance) {
      relevance =
          uri == 'dart:core' ? Relevance.importDartCore : Relevance.import;
    } else {
      relevance =
          uri == 'dart:core' ? DART_RELEVANCE_LOW : DART_RELEVANCE_DEFAULT;
    }
    _add(CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
        uri.length, 0, false, false));
  }

  /// Add the given [suggestion] if it isn't `null` and if it isn't shadowed by
  /// a previously added suggestion.
  void _add(protocol.CompletionSuggestion suggestion) {
    if (suggestion != null) {
      var key = suggestion.completion;
      if (suggestion.element?.kind == protocol.ElementKind.CONSTRUCTOR) {
        key = '$key()';
      }
      listener?.builtSuggestion(suggestion);
      if (laterReplacesEarlier) {
        _suggestionMap[key] = suggestion;
      } else {
        _suggestionMap.putIfAbsent(key, () => suggestion);
      }
    }
  }

  /// Compute the value of the _element kind_ feature for the given [element] in
  /// the completion context.
  double _computeElementKind(Element element) {
    var location = request.opType.completionLocation;
    var elementKind =
        request.featureComputer.elementKindFeature(element, location);
    if (elementKind < 0.0) {
      if (location == null) {
        listener?.missingCompletionLocationAt(
            request.target.containingNode, request.target.entity);
      } else {
        listener?.missingElementKindTableFor(location);
      }
    }
    return elementKind;
  }

  /// Compute a relevance value from the given feature scores:
  /// - [contextType] is higher if the type of the element matches the context
  ///   type,
  /// - [hasDeprecated] is higher if the element is not deprecated,
  /// - [inheritanceDistance] is higher if the element is defined closer to the
  ///   target type,
  /// - [startsWithDollar] is higher if the element's name doe _not_ start with
  ///   a dollar sign, and
  /// - [superMatches] is higher if the element is being invoked through `super`
  ///   and the element's name matches the name of the enclosing method.
  int _computeMemberRelevance(
      {@required double contextType,
      @required double elementKind,
      @required double hasDeprecated,
      @required double inheritanceDistance,
      @required double isConstant,
      @required double startsWithDollar,
      @required double superMatches}) {
    var score = weightedAverage([
      contextType,
      elementKind,
      hasDeprecated,
      inheritanceDistance,
      isConstant,
      startsWithDollar,
      superMatches
    ], [
      1.00, // contextType
      0.75, // elementKind
      0.50, // hasDeprecated
      1.00, // inheritanceDistance
      1.00, // isConstant
      0.50, // startsWithDollar
      1.00, // superMatches
    ]);
    return toRelevance(score, Relevance.member);
  }

  /// Compute the old relevance score for a member.
  int _computeOldMemberRelevance(Element member) {
    if (member.hasOrInheritsDeprecated) {
      return DART_RELEVANCE_LOW;
    } else if (member.name == _containingMemberName) {
      // Boost the relevance of a super expression calling a method of the
      // same name as the containing method.
      return DART_RELEVANCE_HIGH;
    }
    var identifier = member.displayName;
    if (identifier != null && identifier.startsWith(r'$')) {
      // Decrease relevance of suggestions starting with $
      // https://github.com/dart-lang/sdk/issues/27303
      return DART_RELEVANCE_LOW;
    }
    if (member is LocalVariableElement) {
      return DART_RELEVANCE_LOCAL_VARIABLE;
    }
    if (!member.name.startsWith('_') &&
        member.library == request.libraryElement) {
      // Locally declared elements sometimes have a special relevance.
      if (member is PropertyAccessorElement) {
        return DART_RELEVANCE_LOCAL_ACCESSOR;
      } else if (member is FieldElement) {
        return DART_RELEVANCE_LOCAL_FIELD;
      } else if (member is FunctionElement) {
        return DART_RELEVANCE_LOCAL_FUNCTION;
      } else if (member is MethodElement) {
        return DART_RELEVANCE_LOCAL_METHOD;
      } else if (member is ParameterElement) {
        return DART_RELEVANCE_PARAMETER;
      } else if (member is TopLevelVariableElement) {
        return DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE;
      } else if (member is TypeParameterElement) {
        return DART_RELEVANCE_TYPE_PARAMETER;
      }
    }
    return DART_RELEVANCE_DEFAULT;
  }

  /// Return the relevance score for a top-level [element].
  int _computeTopLevelRelevance(Element element,
      {int defaultRelevance = 800, @required DartType elementType}) {
    // TODO(brianwilkerson) The old relevance computation used a signal based
    //  on whether the element being suggested was from the same library in
    //  which completion is being performed. Explore whether that's a useful
    //  signal.
    var featureComputer = request.featureComputer;
    var contextType =
        featureComputer.contextTypeFeature(request.contextType, elementType);
    var elementKind = _computeElementKind(element);
    var hasDeprecated = featureComputer.hasDeprecatedFeature(element);
    var isConstant = request.inConstantContext
        ? featureComputer.isConstantFeature(element)
        : -1.0;
    var relevance = toRelevance(
        weightedAverage([contextType, elementKind, hasDeprecated, isConstant],
            [1.0, 0.75, 0.2, 1.0]),
        defaultRelevance);
    listener?.computedFeatures(
        contextType: contextType,
        elementKind: elementKind,
        hasDeprecated: hasDeprecated);
    return relevance;
  }

  /// Return a suggestion based on the [element], or `null` if a suggestion is
  /// not appropriate for the element. If the completion should be something
  /// different than the name of the element, then the [completion] should be
  /// supplied. If an [elementKind] is provided, then it will be used rather
  /// than the kind normally used for the element. If a [prefix] is provided,
  /// then the element name (or completion) will be prefixed. The [relevance] is
  /// the relevance of the suggestion.
  CompletionSuggestion _createSuggestion(Element element,
      {String completion,
      protocol.ElementKind elementKind,
      CompletionSuggestionKind kind,
      String prefix,
      @required int relevance}) {
    if (element is ExecutableElement && element.isOperator) {
      // Do not include operators in suggestions
      return null;
    }
    completion ??= element.displayName;
    if (completion == null || completion.isEmpty) {
      return null;
    }
    if (prefix != null && prefix.isNotEmpty) {
      completion = '$prefix.$completion';
    }
    kind ??= CompletionSuggestionKind.INVOCATION;
    var suggestion = CompletionSuggestion(kind, relevance, completion,
        completion.length, 0, element.hasOrInheritsDeprecated, false);

    _setDocumentation(suggestion, element);

    suggestion.element = protocol.convertElement(element);
    if (elementKind != null) {
      suggestion.element.kind = elementKind;
    }
    var enclosingElement = element.enclosingElement;
    if (enclosingElement is ClassElement) {
      suggestion.declaringType = enclosingElement.displayName;
    }
    suggestion.returnType = getReturnTypeString(element);
    if (element is ExecutableElement && element is! PropertyAccessorElement) {
      suggestion.parameterNames = element.parameters
          .map((ParameterElement parameter) => parameter.name)
          .toList();
      suggestion.parameterTypes =
          element.parameters.map((ParameterElement parameter) {
        var paramType = parameter.type;
        // Gracefully degrade if type not resolved yet
        return paramType != null
            ? paramType.getDisplayString(
                withNullability: request.libraryElement.isNonNullableByDefault)
            : 'var';
      }).toList();

      var requiredParameters = element.parameters
          .where((ParameterElement param) => param.isRequiredPositional);
      suggestion.requiredParameterCount = requiredParameters.length;

      var namedParameters =
          element.parameters.where((ParameterElement param) => param.isNamed);
      suggestion.hasNamedParameters = namedParameters.isNotEmpty;

      addDefaultArgDetails(
          suggestion, element, requiredParameters, namedParameters);
    }
    return suggestion;
  }

  /// Return the type associated with the [accessor], maybe `null` if an
  /// invalid setter with no parameters at all.
  DartType _getPropertyAccessorType(PropertyAccessorElement accessor) {
    if (accessor.isGetter) {
      return accessor.returnType;
    } else {
      var parameters = accessor.parameters;
      if (parameters.isEmpty) {
        return null;
      } else {
        return parameters[0].type;
      }
    }
  }

  InterfaceType _instantiateClassElement(ClassElement element) {
    var typeParameters = element.typeParameters;
    var typeArguments = const <DartType>[];
    if (typeParameters.isNotEmpty) {
      var neverType = request.libraryElement.typeProvider.neverType;
      typeArguments = List.filled(typeParameters.length, neverType);
    }

    var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
        ? NullabilitySuffix.none
        : NullabilitySuffix.star;

    return element.instantiate(
      typeArguments: typeArguments,
      nullabilitySuffix: nullabilitySuffix,
    );
  }

  FunctionType _instantiateFunctionTypeAlias(FunctionTypeAliasElement element) {
    var typeParameters = element.typeParameters;
    var typeArguments = const <DartType>[];
    if (typeParameters.isNotEmpty) {
      var neverType = request.libraryElement.typeProvider.neverType;
      typeArguments = List.filled(typeParameters.length, neverType);
    }

    var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
        ? NullabilitySuffix.none
        : NullabilitySuffix.star;

    return element.instantiate(
      typeArguments: typeArguments,
      nullabilitySuffix: nullabilitySuffix,
    );
  }

  /// If the [element] has a documentation comment, fill the [suggestion]'s
  /// documentation fields.
  void _setDocumentation(CompletionSuggestion suggestion, Element element) {
    var doc = DartUnitHoverComputer.computeDocumentation(
        request.dartdocDirectiveInfo, element);
    if (doc != null) {
      suggestion.docComplete = doc;
      suggestion.docSummary = getDartDocSummary(doc);
    }
  }
}

abstract class SuggestionListener {
  /// Invoked when a suggestion has been built.
  void builtSuggestion(protocol.CompletionSuggestion suggestion);

  /// Invoked with the values of the features that were computed in the process
  /// of building a suggestion. This method is only invoked when using the new
  /// relevance computations. If invoked, it is invoked prior to invoking
  /// [builtSuggestion].
  void computedFeatures(
      {double contextType,
      double elementKind,
      double hasDeprecated,
      double inheritanceDistance,
      double startsWithDollar,
      double superMatches});

  /// Invoked when an element kind feature cannot be produced because there is
  /// no completion location label associated with the completion offset.
  void missingCompletionLocationAt(
      AstNode containingNode, SyntacticEntity entity);

  /// Invoked when an element kind feature cannot be produced because there is
  /// no `elementKindRelevance` table associated with the [completionLocation].
  void missingElementKindTableFor(String completionLocation);
}
