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

import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp;
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Declaration;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/computer/computer_documentation.dart';
import 'package:analysis_server/src/computer/computer_signature.dart' as server;
import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/dartdoc.dart';
import 'package:analysis_server/src/lsp/error_or.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp;
import 'package:analysis_server/src/lsp/snippets.dart';
import 'package:analysis_server/src/lsp/source_edits.dart';
import 'package:analysis_server/src/protocol_server.dart'
    as server
    hide AnalysisError;
import 'package:analysis_server/src/services/completion/dart/dart_completion_suggestion.dart';
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analysis_server/src/services/snippets/snippet.dart';
import 'package:analysis_server/src/utilities/extensions/string.dart';
import 'package:analyzer/dart/analysis/results.dart' as server;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/diagnostic/diagnostic.dart' as server;
import 'package:analyzer/error/error.dart' as server;
import 'package:analyzer/source/line_info.dart' as server;
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source_range.dart' as server;
import 'package:analyzer/src/dart/analysis/search.dart'
    as server
    show DeclarationKind;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/utilities/extensions/string.dart'
    show IntExtension;
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;

const languageSourceName = 'dart';

/// A regex used for splitting the display text in a completion so that
/// filterText only includes the symbol name and not any additional text (such
/// as parens, ` => `). Match `=>` but not `==` (which may appear in overrides).
final completionFilterTextSplitPattern = RegExp(r'=>|[\(]');

/// A regex to extract the type name from the parameter string of a setter
/// completion item.
final completionSetterTypePattern = RegExp(r'^\((\S+)\s+\S+\)$');

final diagnosticTagsForErrorCode = <String, List<lsp.DiagnosticTag>>{
  _diagnosticCode(WarningCode.DEAD_CODE): [lsp.DiagnosticTag.Unnecessary],
  _diagnosticCode(HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE): [
    lsp.DiagnosticTag.Deprecated,
  ],
  _diagnosticCode(
    HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE,
  ): [lsp.DiagnosticTag.Deprecated],
  _diagnosticCode(HintCode.DEPRECATED_MEMBER_USE): [
    lsp.DiagnosticTag.Deprecated,
  ],
  'deprecated_member_use_from_same_package': [lsp.DiagnosticTag.Deprecated],
  'deprecated_member_use_from_same_package_with_message': [
    lsp.DiagnosticTag.Deprecated,
  ],
  _diagnosticCode(HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE): [
    lsp.DiagnosticTag.Deprecated,
  ],
};

/// The value to subtract relevance from to get the correct sortText for a
/// completion item.
final sortTextMaxValue = int.parse('9' * maximumRelevance.toString().length);

/// Pattern for docComplete text on completion items that can be upgraded to
/// the "detail" field so that it can be shown more prominently by clients.
///
/// This is typically used for labels like _latest compatible_ and _latest_ in
/// the pubspec version items. These go into docComplete so that they appear
/// reasonably for non-LSP clients where there is no equivalent of the detail
/// field.
final upgradableDocCompletePattern = RegExp(r'^_([\w ]{0,20})_$');

lsp.Either2<lsp.MarkupContent, String> asMarkupContentOrString(
  Set<lsp.MarkupKind>? preferredFormats,
  String content,
) {
  return preferredFormats != null
      ? lsp.Either2<lsp.MarkupContent, String>.t1(
        _asMarkup(preferredFormats, content),
      )
      : lsp.Either2<lsp.MarkupContent, String>.t2(content);
}

({String text, lsp.InsertTextFormat format}) buildInsertText({
  required bool supportsSnippets,
  required bool commitCharactersEnabled,
  required bool completeFunctionCalls,
  required String? requiredArgumentListString,
  required List<int>? requiredArgumentListTextRanges,
  required bool hasOptionalParameters,
  required String completion,
  required int selectionOffset,
  required int selectionLength,
}) {
  var insertText = completion;
  var insertTextFormat = lsp.InsertTextFormat.PlainText;

  // SuggestionBuilder already does the equiv of completeFunctionCalls for
  // some methods (for example Flutter's setState). If the completion already
  // includes any `(` then disable our own insertion as the special-cased code
  // will likely provide better code.
  if (completion.contains('(')) {
    completeFunctionCalls = false;
  }

  // If the client supports snippets, we can support completeFunctionCalls or
  // setting a selection.
  if (supportsSnippets) {
    // completeFunctionCalls should only work if commit characters are disabled
    // otherwise the editor may insert parens that we're also inserting.
    if (!commitCharactersEnabled && completeFunctionCalls) {
      insertTextFormat = lsp.InsertTextFormat.Snippet;
      var hasRequiredParameters =
          requiredArgumentListTextRanges?.isNotEmpty ?? false;
      var functionCallSuffix =
          hasRequiredParameters && requiredArgumentListString != null
              ? buildSnippetStringWithTabStops(
                requiredArgumentListString,
                requiredArgumentListTextRanges,
              )
              // Optional params still gets a final tab stop in the parens.
              : hasOptionalParameters
              ? SnippetBuilder.finalTabStop
              // And no parameters at all we skip the tabstop in the parens.
              : '';
      insertText =
          '${SnippetBuilder.escapeSnippetPlainText(insertText)}($functionCallSuffix)';
    } else if (selectionOffset != 0 &&
        // We don't need a tab stop if the selection is the end of the string.
        selectionOffset != completion.length) {
      insertTextFormat = lsp.InsertTextFormat.Snippet;
      insertText = buildSnippetStringWithTabStops(completion, [
        selectionOffset,
        selectionLength,
      ]);
    }
  }

  return (text: insertText, format: insertTextFormat);
}

/// Creates a [lsp.WorkspaceEdit] from simple [server.SourceFileEdit]s.
///
/// [clientCapabilities] should be for the client that will handle this edit,
/// which is not necessarily the client that triggered the request that called
/// this function (for example a DTD client may call a request that triggers an
/// edit that will be sent to the editor).
///
/// If [annotateChanges] is set, change annotations will be produced and
/// marked as needing confirmation from the user (depending on the value).
///
/// Note: This code will fetch the version of each document being modified so
/// it's important to call this immediately after computing edits to ensure
/// the document is not modified before the version number is read.
lsp.WorkspaceEdit createPlainWorkspaceEdit(
  AnalysisServer analysisServer,
  LspClientCapabilities clientCapabilities,
  List<server.SourceFileEdit> edits, {
  ChangeAnnotations annotateChanges = ChangeAnnotations.none,
  String? filePath,
  LineInfo? lineInfo,
}) {
  return toWorkspaceEdit(
    annotateChanges: annotateChanges,
    clientCapabilities,
    edits.map((e) {
      // If we don't expet to create the file use the passed line info if any
      // and it matches the given file.
      // If we expect to create the file, `server.getLineInfo()` won't
      // provide a LineInfo so create one from empty contents.
      LineInfo pickedLineInfo;
      if (e.fileStamp == -1) {
        pickedLineInfo = LineInfo.fromContent('');
      } else {
        if (filePath != null && lineInfo != null && filePath == e.file) {
          pickedLineInfo = lineInfo;
        } else {
          pickedLineInfo = analysisServer.getLineInfo(e.file)!;
        }
      }
      return FileEditInformation(
        analysisServer.getVersionedDocumentIdentifier(e.file),
        pickedLineInfo,
        e.edits,
        // `fileStamp == 1` is used by the server to indicate the file needs
        // creating.
        newFile: e.fileStamp == -1,
      );
    }).toList(),
  );
}

/// Create a [WorkspaceEdit] that renames [oldPath] to [newPath].
WorkspaceEdit createRenameEdit(
  ClientUriConverter uriConverter,
  String oldPath,
  String newPath,
) {
  var changes =
      <Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>[];

  var rename = RenameFile(
    oldUri: uriConverter.toClientUri(oldPath),
    newUri: uriConverter.toClientUri(newPath),
  );

  var renameUnion =
      Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>.t3(rename);

  changes.add(renameUnion);

  var edit = WorkspaceEdit(documentChanges: changes);
  return edit;
}

/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange].
///
/// Can return experimental [lsp.SnippetTextEdit]s if the following are true:
/// - the client has indicated support for in the experimental section of their
///   client capabilities, and
/// - [allowSnippets] is true, and
/// - [change] contains only a single edit to the single file [filePath]
/// - [lineInfo] is provided (which should be for the single edited file)
///
/// Note: This code will fetch the version of each document being modified so
/// it's important to call this immediately after computing edits to ensure
/// the document is not modified before the version number is read.
lsp.WorkspaceEdit createWorkspaceEdit(
  AnalysisServer analysisServer,
  LspClientCapabilities clientCapabilities,
  server.SourceChange change, {
  ChangeAnnotations annotateChanges = ChangeAnnotations.none,
  // The caller must specify whether snippets are valid here for where they're
  // sending this edit. Right now, support is limited to CodeActions.
  bool allowSnippets = false,
  String? filePath,
  LineInfo? lineInfo,
}) {
  assert(
    annotateChanges == ChangeAnnotations.none || !allowSnippets,
    'annotateChanges is not supported with snippets',
  );
  // In order to return snippets, we must ensure we are only modifying a single
  // existing file with a single edit and that there is either a selection or a
  // linked edit group (otherwise there's no value in snippets).
  if (!allowSnippets ||
      !clientCapabilities.experimentalSnippetTextEdit ||
      !clientCapabilities.documentChanges ||
      filePath == null ||
      lineInfo == null ||
      change.edits.length != 1 ||
      change.edits.single.fileStamp == -1 || // new file
      change.edits.single.file != filePath ||
      change.edits.single.edits.length != 1 ||
      (change.selection == null && change.linkedEditGroups.isEmpty)) {
    return createPlainWorkspaceEdit(
      analysisServer,
      clientCapabilities,
      change.edits,
      annotateChanges: annotateChanges,
      filePath: filePath,
      lineInfo: lineInfo,
    );
  }

  var fileEdit = change.edits.single;
  var snippetEdits = toSnippetTextEdits(
    fileEdit.file,
    fileEdit,
    change.linkedEditGroups,
    lineInfo,
    selectionOffset: change.selection?.offset,
    selectionLength: change.selectionLength,
  );

  // Compile the edits into a TextDocumentEdit for this file.
  var textDocumentEdit = lsp.TextDocumentEdit(
    textDocument: analysisServer.getVersionedDocumentIdentifier(fileEdit.file),
    edits:
        snippetEdits
            .map(
              (e) => Either3<
                lsp.AnnotatedTextEdit,
                lsp.SnippetTextEdit,
                lsp.TextEdit
              >.t2(e),
            )
            .toList(),
  );

  // Convert to the union that documentChanges require.
  var textDocumentEditsAsUnion = Either4<
    lsp.CreateFile,
    lsp.DeleteFile,
    lsp.RenameFile,
    lsp.TextDocumentEdit
  >.t4(textDocumentEdit);

  /// Add the textDocumentEdit to a WorkspaceEdit.
  return lsp.WorkspaceEdit(documentChanges: [textDocumentEditsAsUnion]);
}

lsp.SymbolKind declarationKindToSymbolKind(
  Set<lsp.SymbolKind> supportedSymbolKinds,
  server.DeclarationKind? kind,
) {
  bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);

  List<lsp.SymbolKind> getKindPreferences() {
    switch (kind) {
      case server.DeclarationKind.CLASS:
      case server.DeclarationKind.CLASS_TYPE_ALIAS:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.CONSTRUCTOR:
        return const [lsp.SymbolKind.Constructor];
      case server.DeclarationKind.ENUM:
        return const [lsp.SymbolKind.Enum];
      case server.DeclarationKind.ENUM_CONSTANT:
        return const [lsp.SymbolKind.EnumMember, lsp.SymbolKind.Enum];
      case server.DeclarationKind.EXTENSION:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.EXTENSION_TYPE:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.FIELD:
        return const [lsp.SymbolKind.Field];
      case server.DeclarationKind.FUNCTION:
        return const [lsp.SymbolKind.Function];
      case server.DeclarationKind.FUNCTION_TYPE_ALIAS:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.GETTER:
        return const [lsp.SymbolKind.Property];
      case server.DeclarationKind.METHOD:
        return const [lsp.SymbolKind.Method];
      case server.DeclarationKind.MIXIN:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.SETTER:
        return const [lsp.SymbolKind.Property];
      case server.DeclarationKind.TYPE_ALIAS:
        return const [lsp.SymbolKind.Class];
      case server.DeclarationKind.VARIABLE:
        return const [lsp.SymbolKind.Variable];
      default:
        // Assert that we only get here if kind=null. If it's anything else
        // then we're missing a mapping from above.
        assert(kind == null, 'Unexpected declaration kind $kind');
        return const [];
    }
  }

  // LSP requires we specify *some* kind, so in the case where the above code doesn't
  // match we'll just have to send a value to avoid a crash.
  return getKindPreferences().firstWhere(
    isSupported,
    orElse: () => lsp.SymbolKind.Obj,
  );
}

lsp.CompletionItemKind? elementKindToCompletionItemKind(
  Set<lsp.CompletionItemKind> supportedCompletionKinds,
  server.ElementKind kind,
) {
  bool isSupported(lsp.CompletionItemKind kind) =>
      supportedCompletionKinds.contains(kind);

  List<lsp.CompletionItemKind> getKindPreferences() {
    switch (kind) {
      case server.ElementKind.CLASS:
      case server.ElementKind.CLASS_TYPE_ALIAS:
        return const [lsp.CompletionItemKind.Class];
      case server.ElementKind.COMPILATION_UNIT:
        return const [
          lsp.CompletionItemKind.File,
          lsp.CompletionItemKind.Module,
        ];
      case server.ElementKind.CONSTRUCTOR:
      case server.ElementKind.CONSTRUCTOR_INVOCATION:
        return const [lsp.CompletionItemKind.Constructor];
      case server.ElementKind.ENUM:
        return const [lsp.CompletionItemKind.Enum];
      case server.ElementKind.ENUM_CONSTANT:
        return const [
          lsp.CompletionItemKind.EnumMember,
          lsp.CompletionItemKind.Enum,
        ];
      case server.ElementKind.FIELD:
        return const [lsp.CompletionItemKind.Field];
      case server.ElementKind.FILE:
        return const [lsp.CompletionItemKind.File];
      case server.ElementKind.FUNCTION:
        return const [lsp.CompletionItemKind.Function];
      case server.ElementKind.FUNCTION_TYPE_ALIAS:
        return const [lsp.CompletionItemKind.Class];
      case server.ElementKind.GETTER:
        return const [lsp.CompletionItemKind.Property];
      case server.ElementKind.LABEL:
        // There isn't really a good CompletionItemKind for labels so we'll
        // just use the Text option.
        return const [lsp.CompletionItemKind.Text];
      case server.ElementKind.LIBRARY:
        return const [lsp.CompletionItemKind.Module];
      case server.ElementKind.LOCAL_VARIABLE:
        return const [lsp.CompletionItemKind.Variable];
      case server.ElementKind.METHOD:
        return const [lsp.CompletionItemKind.Method];
      case server.ElementKind.MIXIN:
        return const [lsp.CompletionItemKind.Class];
      case server.ElementKind.PARAMETER:
      case server.ElementKind.PREFIX:
        return const [lsp.CompletionItemKind.Variable];
      case server.ElementKind.SETTER:
        return const [lsp.CompletionItemKind.Property];
      case server.ElementKind.TOP_LEVEL_VARIABLE:
        return const [lsp.CompletionItemKind.Variable];
      case server.ElementKind.TYPE_PARAMETER:
        return const [
          lsp.CompletionItemKind.TypeParameter,
          lsp.CompletionItemKind.Variable,
        ];
      case server.ElementKind.UNIT_TEST_GROUP:
      case server.ElementKind.UNIT_TEST_TEST:
        return const [lsp.CompletionItemKind.Method];
      default:
        return const [];
    }
  }

  return getKindPreferences().firstWhereOrNull(isSupported);
}

lsp.SymbolKind elementKindToSymbolKind(
  Set<lsp.SymbolKind> supportedSymbolKinds,
  server.ElementKind? kind,
) {
  bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);

  List<lsp.SymbolKind> getKindPreferences() {
    switch (kind) {
      case server.ElementKind.CLASS:
      case server.ElementKind.CLASS_TYPE_ALIAS:
        return const [lsp.SymbolKind.Class];
      case server.ElementKind.COMPILATION_UNIT:
        return const [lsp.SymbolKind.File];
      case server.ElementKind.CONSTRUCTOR:
      case server.ElementKind.CONSTRUCTOR_INVOCATION:
        return const [lsp.SymbolKind.Constructor];
      case server.ElementKind.ENUM:
        return const [lsp.SymbolKind.Enum];
      case server.ElementKind.ENUM_CONSTANT:
        return const [lsp.SymbolKind.EnumMember, lsp.SymbolKind.Enum];
      case server.ElementKind.EXTENSION:
        return const [lsp.SymbolKind.Namespace];
      case server.ElementKind.EXTENSION_TYPE:
        return const [lsp.SymbolKind.Namespace];
      case server.ElementKind.FIELD:
        return const [lsp.SymbolKind.Field];
      case server.ElementKind.FILE:
        return const [lsp.SymbolKind.File];
      case server.ElementKind.FUNCTION:
      case server.ElementKind.FUNCTION_INVOCATION:
        return const [lsp.SymbolKind.Function];
      case server.ElementKind.FUNCTION_TYPE_ALIAS:
        return const [lsp.SymbolKind.Class];
      case server.ElementKind.GETTER:
        return const [lsp.SymbolKind.Property];
      case server.ElementKind.LABEL:
        // There isn't really a good SymbolKind for labels so we'll
        // just use the Null option.
        return const [lsp.SymbolKind.Null];
      case server.ElementKind.LIBRARY:
        return const [lsp.SymbolKind.Namespace];
      case server.ElementKind.LOCAL_VARIABLE:
        return const [lsp.SymbolKind.Variable];
      case server.ElementKind.METHOD:
        return const [lsp.SymbolKind.Method];
      case server.ElementKind.MIXIN:
        return const [lsp.SymbolKind.Class];
      case server.ElementKind.PARAMETER:
      case server.ElementKind.PREFIX:
        return const [lsp.SymbolKind.Variable];
      case server.ElementKind.SETTER:
        return const [lsp.SymbolKind.Property];
      case server.ElementKind.TOP_LEVEL_VARIABLE:
        return const [lsp.SymbolKind.Variable];
      case server.ElementKind.TYPE_PARAMETER:
        return const [lsp.SymbolKind.TypeParameter, lsp.SymbolKind.Variable];
      case server.ElementKind.UNIT_TEST_GROUP:
      case server.ElementKind.UNIT_TEST_TEST:
        return const [lsp.SymbolKind.Method];
      default:
        // Assert that we only get here if kind=null. If it's anything else
        // then we're missing a mapping from above.
        assert(kind == null, 'Unexpected element kind $kind');
        return const [];
    }
  }

  // LSP requires we specify *some* kind, so in the case where the above code doesn't
  // match we'll just have to send a value to avoid a crash.
  return getKindPreferences().firstWhere(
    isSupported,
    orElse: () => lsp.SymbolKind.Obj,
  );
}

lsp.Location? fragmentToLocation(
  ClientUriConverter uriConverter,
  Fragment? fragment,
) {
  if (fragment == null) {
    return null;
  }

  var libraryFragment = fragment.libraryFragment!;
  var sourcePath = libraryFragment.source.fullName;

  int? nameOffset;
  int? nameLength;
  if (fragment case PropertyAccessorFragmentImpl(
    :var isSynthetic,
    :var nonSynthetic,
  ) when isSynthetic) {
    var element = nonSynthetic;
    nameOffset = element.nameOffset.nullIfNegative;
    nameLength = element.name?.length;
  } else {
    nameOffset = fragment.nameOffset2;
    nameLength = fragment.name2?.length;
  }

  // For unnamed constructors, use the type name as the target location.
  if (nameOffset == null && fragment is ConstructorFragment) {
    nameOffset = fragment.typeNameOffset;
    nameLength = fragment.typeName?.length;
  }

  if (nameOffset == null || nameLength == null) {
    // This is some kind of synthetic fragment we can't navigate to.
    return null;
  }

  return lsp.Location(
    uri: uriConverter.toClientUri(sourcePath),
    range: toRange(libraryFragment.lineInfo, nameOffset, nameLength),
  );
}

/// Returns additional details to be shown against a completion.
CompletionDetail getCompletionDetail(
  server.CompletionSuggestion suggestion, {
  required bool supportsDeprecated,
}) {
  var element = suggestion.element;
  var parameters = element?.parameters;
  // Prefer the element return type (because it may be more specific
  // for overrides) and fall back to the parameter type or return type from the
  // suggestion (handles records).
  var returnType =
      element?.returnType ?? suggestion.parameterType ?? suggestion.returnType;

  // Extract the type from setters to be shown in the place a return type
  // would usually be shown.
  if (returnType == null &&
      element?.kind == server.ElementKind.SETTER &&
      parameters != null) {
    returnType = completionSetterTypePattern.firstMatch(parameters)?.group(1);
    parameters = null;
  }

  var truncatedParameters = switch (parameters) {
    null || '' => '',
    '()' => '()',
    _ => '(…)',
  };
  var fullSignature = switch ((parameters, returnType)) {
    (null, _) => returnType ?? '',
    (var parameters?, null) => parameters,
    (var parameters?, '') => parameters,
    (var parameters?, _) => '$parameters → $returnType',
  };
  var truncatedSignature = switch ((parameters, returnType)) {
    (null, null) => '',
    // Include a leading space when no parameters so return type isn't right
    // against the completion label.
    (null, var returnType?) => ' $returnType',
    (_, null) || (_, '') => truncatedParameters,
    (_, var returnType?) => '$truncatedParameters → $returnType',
  };

  // Use the full signature in the details popup.
  var detail = fullSignature;
  if (suggestion.isDeprecated && !supportsDeprecated) {
    // If the item is deprecated and we don't support the native deprecated flag
    // then include it in the details.
    detail = '$detail\n\n(Deprecated)'.trim();
  }

  var libraryUri = suggestion.libraryUri;
  var autoImportUri =
      (suggestion.isNotImported ?? false) && libraryUri != null
          ? Uri.parse(libraryUri)
          : null;

  return (
    detail: detail,
    truncatedParams: truncatedParameters,
    truncatedSignature: truncatedSignature,
    autoImportUri: autoImportUri,
  );
}

/// Gets a library URI formatted for display in code completion as the target
/// library that a symbol comes from.
///
/// File URIs will be made relative to [completionFilePath]. Other URIs will be
/// returned as-is.
String? getCompletionDisplayUriString({
  required ClientUriConverter uriConverter,
  required path.Context pathContext,
  required Uri? elementLibraryUri,
  required String completionFilePath,
}) {
  if (elementLibraryUri == null) {
    return null;
  }

  return elementLibraryUri.isScheme('file')
      // Compute the relative path and then put into a URI so the display
      // always uses forward slashes (as a URI) regardless of platform.
      ? uriConverter
          .toClientUri(
            pathContext.relative(
              uriConverter.fromClientUri(elementLibraryUri),
              from: pathContext.dirname(completionFilePath),
            ),
          )
          .toString()
      : elementLibraryUri.toString();
}

List<lsp.DiagnosticTag>? getDiagnosticTags(
  Set<lsp.DiagnosticTag>? supportedTags,
  plugin.AnalysisError error,
) {
  if (supportedTags == null) {
    return null;
  }

  var tags =
      diagnosticTagsForErrorCode[error.code]
          ?.where(supportedTags.contains)
          .toList();

  return tags != null && tags.isNotEmpty ? tags : null;
}

bool isDartDocument(lsp.TextDocumentIdentifier doc) => isDartUri(doc.uri);

bool isDartUri(Uri uri) => uri.path.endsWith('.dart');

/// Converts a [server.Location] to an [lsp.Range] by translating the
/// offset/length using a `LineInfo`.
///
/// This function ignores any line/column info on the
/// [server.Location] assuming it is either not available not unreliable.
lsp.Range locationOffsetLenToRange(
  server.LineInfo lineInfo,
  server.Location location,
) => toRange(lineInfo, location.offset, location.length);

/// Converts a [server.Location] to an [lsp.Range] if all line and column
/// values are available.
///
/// Returns null if any values are -1 or null.
lsp.Range? locationToRange(server.Location location) {
  var startLine = location.startLine;
  var startColumn = location.startColumn;
  var endLine = location.endLine ?? -1;
  var endColumn = location.endColumn ?? -1;
  if (startLine == -1 ||
      startColumn == -1 ||
      endLine == -1 ||
      endColumn == -1) {
    return null;
  }
  // LSP positions are 0-based but Location is 1-based.
  return Range(
    start: Position(line: startLine - 1, character: startColumn - 1),
    end: Position(line: endLine - 1, character: endColumn - 1),
  );
}

/// Merges two [WorkspaceEdit]s into a single one.
///
/// Will throw if given [WorkspaceEdit]s that do not use documentChanges.
WorkspaceEdit mergeWorkspaceEdits(List<WorkspaceEdit> edits) {
  // TODO(dantup): This method (and much other code here) should be
  // significantly tidied up when nonfunction-type-aliases is available here.
  var changes =
      <Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>[];

  for (var edit in edits) {
    changes.addAll(edit.documentChanges!);
  }

  return WorkspaceEdit(documentChanges: changes);
}

lsp.Location navigationTargetToLocation(
  Uri targetFileUri,
  server.NavigationTarget target,
  server.LineInfo targetLineInfo,
) {
  return lsp.Location(
    uri: targetFileUri,
    range: toRange(targetLineInfo, target.offset, target.length),
  );
}

lsp.LocationLink? navigationTargetToLocationLink(
  server.NavigationRegion region,
  server.LineInfo regionLineInfo,
  Uri targetFileUri,
  server.NavigationTarget target,
  server.LineInfo targetLineInfo,
) {
  var nameRange = toRange(targetLineInfo, target.offset, target.length);
  var codeOffset = target.codeOffset;
  var codeLength = target.codeLength;
  var codeRange =
      codeOffset != null && codeLength != null
          ? toRange(targetLineInfo, codeOffset, codeLength)
          : nameRange;

  return lsp.LocationLink(
    originSelectionRange: toRange(regionLineInfo, region.offset, region.length),
    targetUri: targetFileUri,
    targetRange: codeRange,
    targetSelectionRange: nameRange,
  );
}

lsp.Diagnostic pluginToDiagnostic(
  ClientUriConverter uriConverter,
  server.LineInfo? Function(String) getLineInfo,
  plugin.AnalysisError error, {
  required Set<lsp.DiagnosticTag>? supportedTags,
  required bool clientSupportsCodeDescription,
}) {
  List<lsp.DiagnosticRelatedInformation>? relatedInformation;
  var contextMessages = error.contextMessages;
  if (contextMessages != null && contextMessages.isNotEmpty) {
    relatedInformation =
        contextMessages
            .map(
              (message) => pluginToDiagnosticRelatedInformation(
                uriConverter,
                getLineInfo,
                message,
              ),
            )
            .nonNulls
            .toList();
  }

  var message = error.message;
  if (error.correction != null) {
    message = '$message\n${error.correction}';
  }

  var range =
      locationToRange(error.location) ??
      locationOffsetLenToRange(
        // TODO(dantup): This null assertion is not sound and can lead to
        //   errors (for example during a large rename where files may be
        //   removed as diagnostics are being mapped). To remove this,
        //   error.location should be updated to require line/col information
        //   (which involves breaking changes).
        getLineInfo(error.location.file)!,
        error.location,
      );
  var documentationUrl = error.url;
  return lsp.Diagnostic(
    range: range,
    severity: pluginToDiagnosticSeverity(error.severity),
    code: error.code,
    source: languageSourceName,
    message: message,
    tags: getDiagnosticTags(supportedTags, error),
    relatedInformation: relatedInformation,
    // Only include codeDescription if the client explicitly supports it
    // (a minor optimization to avoid unnecessary payload/(de)serialization).
    codeDescription:
        clientSupportsCodeDescription && documentationUrl != null
            ? CodeDescription(href: Uri.parse(documentationUrl))
            : null,
  );
}

lsp.DiagnosticRelatedInformation? pluginToDiagnosticRelatedInformation(
  ClientUriConverter uriConverter,
  server.LineInfo? Function(String) getLineInfo,
  plugin.DiagnosticMessage message,
) {
  var file = message.location.file;
  var uri = uriConverter.toClientUri(file);
  var lineInfo = getLineInfo(file);
  // We shouldn't get context messages for something we can't get a LineInfo for
  // but if we did, it's better to omit the context than fail to send the errors.
  if (lineInfo == null) {
    return null;
  }
  return lsp.DiagnosticRelatedInformation(
    location: lsp.Location(
      uri: uri,
      // TODO(dantup): Switch to using line/col information from the context
      // message once confirmed that AnalyzerConverter is not using the wrong
      // LineInfo.
      range: toRange(
        lineInfo,
        message.location.offset,
        message.location.length,
      ),
    ),
    message: message.message,
  );
}

lsp.DiagnosticSeverity pluginToDiagnosticSeverity(
  plugin.AnalysisErrorSeverity severity,
) {
  return switch (severity) {
    plugin.AnalysisErrorSeverity.ERROR => lsp.DiagnosticSeverity.Error,
    plugin.AnalysisErrorSeverity.WARNING => lsp.DiagnosticSeverity.Warning,
    plugin.AnalysisErrorSeverity.INFO => lsp.DiagnosticSeverity.Information,
  };
}

/// Records a change annotation for [edit] in [uri] into the [changeAnnotations]
/// map based on the value of [annotateChanges].
ChangeAnnotation? recordEditAnnotation(
  Uri uri,
  server.SourceEdit edit, {
  required ChangeAnnotations annotateChanges,
  required Map<ChangeAnnotationIdentifier, ChangeAnnotation>? changeAnnotations,
}) {
  assert(
    (annotateChanges == ChangeAnnotations.none) == (changeAnnotations == null),
  );
  if (changeAnnotations == null) {
    return null;
  }

  // Always try to provide good descriptions when producing annotated
  // changes but use a fallback rather than failing if they're not
  // available.
  // When running with asserts, assert there is a description to
  // highlight where we're not passing them.
  assert(edit.description != null);
  var label = edit.description ?? edit.id ?? uri.pathSegments.last;
  return changeAnnotations[label] ??= ChangeAnnotation(
    label: label,
    needsConfirmation: annotateChanges == ChangeAnnotations.requireConfirmation,
  );
}

/// Converts a numeric relevance to a sortable string.
///
/// The servers relevance value is a number with highest being best. LSP uses a
/// a string sort on the `sortText` field. Subtracting the relevance from a
/// large number will produce text that will sort correctly.
///
/// Relevance can be 0, so it's important to subtract from a number like 999
/// and not 1000 or the 0 relevance items will sort at the top instead of the
/// bottom.
///
/// 1000000 -> 9999999 - 1000000 -> 8 999 999
///     555 -> 9999999 -     555 -> 9 999 444
///      10 -> 9999999 -      10 -> 9 999 989
///       1 -> 9999999 -       1 -> 9 999 998
///       0 -> 9999999 -       0 -> 9 999 999
String relevanceToSortText(int relevance) =>
    (sortTextMaxValue - relevance).toString();

/// 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
/// edits, so [editOffset] must to take into account both the offset of the edit
/// _and_ any delta from edits prior to this one in the file.
///
/// [selectionOffset] is also absolute and assumes `edit.replacement` will be
/// inserted at [editOffset].
lsp.SnippetTextEdit snippetTextEditFromEditGroups(
  String filePath,
  server.LineInfo lineInfo,
  server.SourceEdit edit, {
  required List<server.LinkedEditGroup> editGroups,
  required int editOffset,
  required int? selectionOffset,
  required int? selectionLength,
}) {
  return lsp.SnippetTextEdit(
    insertTextFormat: lsp.InsertTextFormat.Snippet,
    range: toRange(lineInfo, edit.offset, edit.length),
    newText: buildSnippetStringForEditGroups(
      edit.replacement,
      filePath: filePath,
      editGroups: editGroups,
      editOffset: editOffset,
      selectionOffset: selectionOffset,
      selectionLength: selectionLength,
    ),
  );
}

/// Creates a SnippetTextEdit for an edit with a selection placeholder.
///
/// [selectionOffsetRelative] is relative to (and therefore must be within) the
/// edit.
lsp.SnippetTextEdit snippetTextEditWithSelection(
  server.LineInfo lineInfo,
  server.SourceEdit edit, {
  required int selectionOffsetRelative,
  int? selectionLength,
}) {
  return lsp.SnippetTextEdit(
    insertTextFormat: lsp.InsertTextFormat.Snippet,
    range: toRange(lineInfo, edit.offset, edit.length),
    newText: buildSnippetStringWithTabStops(edit.replacement, [
      selectionOffsetRelative,
      selectionLength ?? 0,
    ]),
  );
}

lsp.CompletionItem snippetToCompletionItem(
  lsp.LspAnalysisServer server,
  LspClientCapabilities capabilities,
  String file,
  LineInfo lineInfo,
  Position position,
  Snippet snippet,
  CompletionItemDefaults? defaults,
) {
  assert(capabilities.completionSnippets);

  var formats = capabilities.completionDocumentationFormats;
  var documentation = snippet.documentation;
  var supportsAsIsInsertMode = capabilities.completionInsertTextModes.contains(
    InsertTextMode.asIs,
  );
  var changes = snippet.change;

  // We must only get one change for this file to be able to apply snippets.
  var thisFilesChange = changes.edits.singleWhere((e) => e.file == file);
  var otherFilesChanges = changes.edits.where((e) => e.file != file).toList();

  // If this completion involves editing other files, we'll need to build
  // a command that the client will call to apply those edits later, because
  // LSP Completions can only provide simple edits for the current file.
  Command? command;
  if (otherFilesChanges.isNotEmpty) {
    var workspaceEdit = createPlainWorkspaceEdit(
      server,
      capabilities,
      otherFilesChanges,
    );
    command = Command(
      title: 'Add import',
      command: Commands.sendWorkspaceEdit,
      arguments: [
        {'edit': workspaceEdit},
      ],
    );
  }

  /// Convert the changes to TextEdits using snippet tokens for linked edit
  /// groups.
  var mainFileEdits = toSnippetTextEdits(
    file,
    thisFilesChange,
    changes.linkedEditGroups,
    lineInfo,
    selectionOffset:
        changes.selection?.file == file ? changes.selection?.offset : null,
    selectionLength:
        changes.selection?.file == file ? changes.selectionLength : null,
  );

  // For LSP, we need to provide the main edit and other edits separately. The
  // main edit must include the location that completion was invoked. If we find
  // more than one, take the first one since imports are usually added as later
  // edits (so when applied sequentially they will be inserted at the start of
  // the file after the other edits).
  var mainEdit = mainFileEdits.firstWhere(
    (edit) => edit.range.start.line == position.line,
  );
  var nonMainEdits = mainFileEdits.where((edit) => edit != mainEdit).toList();

  // Capture any default combined range. If there are different insert/replace
  // ranges just take `null` because snippets always use the same ranges and
  // if defaults are different ours can't possibly be redundant.
  var defaultRange = defaults?.editRange?.map(
    (ranges) => null,
    (range) => range,
  );
  var hasDefaultEditRange = mainEdit.range == defaultRange;

  return lsp.CompletionItem(
    label: snippet.label,
    filterText: snippet.prefix.orNullIfSameAs(snippet.label),
    kind: lsp.CompletionItemKind.Snippet,
    command: command,
    documentation:
        documentation != null
            ? asMarkupContentOrString(formats, documentation)
            : null,
    // Force snippets to be sorted at the bottom of the list.
    // TODO(dantup): Consider if we can rank these better. Client-side
    //   snippets have always been forced to the bottom partly because they
    //   show up in more places than wanted.
    sortText: 'zzz${snippet.prefix}',
    insertTextFormat: lsp.InsertTextFormat.Snippet,
    insertTextMode: supportsAsIsInsertMode ? InsertTextMode.asIs : null,
    // Set textEdit or textEditText depending on whether we need to specify
    // a range or not.
    textEdit:
        hasDefaultEditRange
            ? null
            : Either2<InsertReplaceEdit, TextEdit>.t2(mainEdit),
    textEditText:
        hasDefaultEditRange
            ? mainEdit.newText.orNullIfSameAs(snippet.label)
            : null,
    additionalTextEdits: nonMainEdits.nullIfEmpty,
  );
}

/// Sorts a list of [server.SourceEdit]s for mapping to LSP types.
///
/// Server works with edits that can be applied sequentially to a [String]. This
/// means inserts at the same offset are in the reverse order. For LSP, all
/// offsets relate to the original document and inserts with the same offset
/// appear in the order they will appear in the final document.
List<server.SourceEdit> sortSourceEditsForLsp(List<server.SourceEdit> edits) {
  // Since for LSP the ordering of items without the same offset do not matter,
  // we can simply reverse the entire list.
  return edits.reversed.toList();
}

lsp.CompletionItemKind? suggestionKindToCompletionItemKind(
  Set<lsp.CompletionItemKind> supportedCompletionKinds,
  server.CompletionSuggestionKind kind,
  String label,
) {
  bool isSupported(lsp.CompletionItemKind kind) =>
      supportedCompletionKinds.contains(kind);

  List<lsp.CompletionItemKind> getKindPreferences() {
    switch (kind) {
      case server.CompletionSuggestionKind.ARGUMENT_LIST:
        return const [lsp.CompletionItemKind.Variable];
      case server.CompletionSuggestionKind.IMPORT:
        // For package/relative URIs, we can send File/Folder kinds for better icons.
        if (!label.startsWith('dart:')) {
          return label.endsWith('.dart')
              ? const [
                lsp.CompletionItemKind.File,
                lsp.CompletionItemKind.Module,
              ]
              : const [
                lsp.CompletionItemKind.Folder,
                lsp.CompletionItemKind.Module,
              ];
        }
        return const [lsp.CompletionItemKind.Module];
      case server.CompletionSuggestionKind.IDENTIFIER:
        return const [lsp.CompletionItemKind.Variable];
      case server.CompletionSuggestionKind.INVOCATION:
        return const [lsp.CompletionItemKind.Method];
      case server.CompletionSuggestionKind.KEYWORD:
        return const [lsp.CompletionItemKind.Keyword];
      case server.CompletionSuggestionKind.NAMED_ARGUMENT:
        return const [lsp.CompletionItemKind.Variable];
      case server.CompletionSuggestionKind.OPTIONAL_ARGUMENT:
        return const [lsp.CompletionItemKind.Variable];
      case server.CompletionSuggestionKind.PARAMETER:
        return const [lsp.CompletionItemKind.Value];
      case server.CompletionSuggestionKind.PACKAGE_NAME:
        return const [lsp.CompletionItemKind.Module];
      default:
        return const [];
    }
  }

  return getKindPreferences().firstWhereOrNull(isSupported);
}

lsp.ClosingLabel toClosingLabel(
  server.LineInfo lineInfo,
  server.ClosingLabel label,
) => lsp.ClosingLabel(
  range: toRange(lineInfo, label.offset, label.length),
  label: label.label,
);

/// Converts [id] to a [CodeActionKind] using [fallbackOrPrefix] as a fallback
/// or a prefix if the ID is not already a fix/refactor.
lsp.CodeActionKind toCodeActionKind(
  String? id,
  lsp.CodeActionKind fallbackOrPrefix,
) {
  if (id == null) {
    return fallbackOrPrefix;
  }
  // Dart fixes and assists start with "dart.assist." and "dart.fix." but in LSP
  // we want to use the predefined prefixes for CodeActions.
  var newId = id
      .replaceAll('dart.assist', lsp.CodeActionKind.Refactor.toString())
      .replaceAll('dart.fix', lsp.CodeActionKind.QuickFix.toString())
      .replaceAll(
        'analysisOptions.assist',
        lsp.CodeActionKind.Refactor.toString(),
      )
      .replaceAll('analysisOptions.fix', lsp.CodeActionKind.QuickFix.toString())
      .replaceAll('pubspec.assist', lsp.CodeActionKind.Refactor.toString())
      .replaceAll('pubspec.fix', lsp.CodeActionKind.QuickFix.toString());

  // If the ID does not start with either of the kinds above, prefix it as
  // it will be an unqualified ID from a plugin.
  if (!newId.startsWith(lsp.CodeActionKind.Refactor.toString()) &&
      !newId.startsWith(lsp.CodeActionKind.QuickFix.toString())) {
    newId = '$fallbackOrPrefix.$newId';
  }

  return lsp.CodeActionKind(newId);
}

lsp.CompletionItem toCompletionItem(
  LspClientCapabilities capabilities,
  server.LineInfo lineInfo,
  server.CompletionSuggestion suggestion, {
  required ClientUriConverter uriConverter,
  required path.Context pathContext,
  required String completionFilePath,
  bool hasDefaultEditRange = false,
  bool hasDefaultTextMode = false,
  required Range replacementRange,
  required Range insertionRange,
  required DocumentationPreference includeDocumentation,
  required bool commitCharactersEnabled,
  required bool completeFunctionCalls,
  CompletionItemResolutionInfo? resolutionData,
}) {
  // isCallable is used to suffix the label with parens so it's clear the item
  // is callable.
  //
  // isInvocation means the location at which it's used is an invocation (and
  // therefore it is appropriate to include the parens/parameters in the
  // inserted text).
  //
  // In the case of show combinators, the parens will still be shown to indicate
  // functions but they should not be included in the completions.
  var elementKind = suggestion.element?.kind;
  var isCallable =
      elementKind == server.ElementKind.CONSTRUCTOR ||
      elementKind == server.ElementKind.FUNCTION ||
      elementKind == server.ElementKind.METHOD;
  var isInvocation =
      suggestion.kind == server.CompletionSuggestionKind.INVOCATION;
  if (!isCallable || !isInvocation) {
    completeFunctionCalls = false;
  }

  var supportsCompletionDeprecatedFlag = capabilities.completionDeprecatedFlag;
  var supportsDeprecatedTag = capabilities.completionItemTags.contains(
    lsp.CompletionItemTag.Deprecated,
  );
  var formats = capabilities.completionDocumentationFormats;
  var supportsSnippets = capabilities.completionSnippets;
  var supportsInsertReplace = capabilities.insertReplaceCompletionRanges;
  var supportsAsIsInsertMode = capabilities.completionInsertTextModes.contains(
    InsertTextMode.asIs,
  );
  var useLabelDetails = capabilities.completionLabelDetails;

  var label = suggestion.displayText ?? suggestion.completion;
  assert(label.isNotEmpty);

  // Displayed labels may have additional info appended (for example '(...)' on
  // callables and ` => ` on getters) that should not be included in filterText,
  // so strip anything from the first paren/space.
  //
  // Only do this if label doesn't start with the pattern, because if it does
  // (for example for a closure `(a, b) {}`) we'll end up with an empty string
  // but we should instead use the whole label.

  // TODO(dantup): Consider including more of these raw fields in the original
  //  suggestion to avoid needing to manipulate them in this way here.
  var filterText =
      !label.startsWith(completionFilterTextSplitPattern)
          ? label.split(completionFilterTextSplitPattern).first.trim()
          : label;

  // If we're using label details, we also don't want the label to include any
  // additional symbols as noted above, because they will appear in the extra
  // details fields.
  if (useLabelDetails) {
    label = filterText;
  }

  // Trim any trailing comma from the (displayed) label.
  if (label.endsWith(',')) {
    label = label.substring(0, label.length - 1);
  }

  var element = suggestion.element;
  var colorPreviewHex =
      capabilities.completionItemKinds.contains(CompletionItemKind.Color) &&
              suggestion is DartCompletionSuggestion
          ? suggestion.colorHex
          : null;
  var completionKind =
      colorPreviewHex != null
          ? CompletionItemKind.Color
          : element != null
          ? elementKindToCompletionItemKind(
            capabilities.completionItemKinds,
            element.kind,
          )
          : suggestionKindToCompletionItemKind(
            capabilities.completionItemKinds,
            suggestion.kind,
            label,
          );

  var labelDetails = getCompletionDetail(
    suggestion,
    supportsDeprecated:
        supportsCompletionDeprecatedFlag || supportsDeprecatedTag,
  );

  // For legacy display, include short params on the end of labels as long as
  // the item doesn't have custom display text (which may already include
  // params).
  if (!useLabelDetails && suggestion.displayText == null) {
    label += labelDetails.truncatedParams;
  }

  var insertTextInfo = buildInsertText(
    supportsSnippets: supportsSnippets,
    commitCharactersEnabled: commitCharactersEnabled,
    completeFunctionCalls: completeFunctionCalls,
    requiredArgumentListString: suggestion.defaultArgumentListString,
    requiredArgumentListTextRanges: suggestion.defaultArgumentListTextRanges,
    hasOptionalParameters: suggestion.parameterNames?.isNotEmpty ?? false,
    completion: suggestion.completion,
    selectionOffset: suggestion.selectionOffset,
    selectionLength: suggestion.selectionLength,
  );
  var insertText = insertTextInfo.text;
  var insertTextFormat = insertTextInfo.format;
  var isMultilineCompletion = insertText.contains('\n');

  var rawDoc =
      includeDocumentation == DocumentationPreference.full
          ? suggestion.docComplete
          : includeDocumentation == DocumentationPreference.summary
          ? suggestion.docSummary
          : null;
  var cleanedDoc = cleanDartdoc(rawDoc);

  // To improve the display of some items (like pubspec version numbers),
  // short labels in the format `_foo_` in docComplete are "upgraded" to the
  // detail field.
  var labelMatch =
      cleanedDoc != null
          ? upgradableDocCompletePattern.firstMatch(cleanedDoc)
          : null;
  if (labelMatch != null) {
    cleanedDoc = null;
    labelDetails = (
      detail: labelMatch.group(1)!,
      truncatedParams: labelDetails.truncatedParams,
      truncatedSignature: labelDetails.truncatedSignature,
      autoImportUri: labelDetails.autoImportUri,
    );
  }

  // Append hex colours to the end of the docs, this will allow editors that
  // use a regex to find a color at the start/end like VS Code to show a color
  // preview.
  if (colorPreviewHex != null) {
    cleanedDoc = '${cleanedDoc ?? ''}\n\n$colorPreviewHex'.trim();
  }

  // Because we potentially send thousands of these items, we should minimise
  // the generated JSON as much as possible - for example using nulls in place
  // of empty lists/false where possible.
  return lsp.CompletionItem(
    label: label,
    kind: completionKind,
    tags: nullIfEmpty([
      if (supportsDeprecatedTag && suggestion.isDeprecated)
        lsp.CompletionItemTag.Deprecated,
    ]),
    data: resolutionData,
    detail: labelDetails.detail.nullIfEmpty,
    labelDetails:
        useLabelDetails
            ? CompletionItemLabelDetails(
              detail: labelDetails.truncatedSignature.nullIfEmpty,
              description: getCompletionDisplayUriString(
                uriConverter: uriConverter,
                pathContext: pathContext,
                elementLibraryUri: labelDetails.autoImportUri,
                completionFilePath: completionFilePath,
              ),
            ).nullIfEmpty
            : null,
    documentation:
        cleanedDoc != null
            ? asMarkupContentOrString(formats, cleanedDoc)
            : null,
    deprecated:
        supportsCompletionDeprecatedFlag && suggestion.isDeprecated
            ? true
            : null,
    sortText: relevanceToSortText(suggestion.relevance),
    filterText: filterText.orNullIfSameAs(
      label,
    ), // filterText uses label if not set
    insertTextFormat:
        insertTextFormat != lsp.InsertTextFormat.PlainText
            ? insertTextFormat
            : null, // Defaults to PlainText if not supplied
    insertTextMode:
        !hasDefaultTextMode && supportsAsIsInsertMode && isMultilineCompletion
            ? InsertTextMode.asIs
            : null,
    // When using defaults for edit range, don't use textEdit.
    textEdit:
        hasDefaultEditRange
            ? null
            : supportsInsertReplace && insertionRange != replacementRange
            ? Either2<InsertReplaceEdit, TextEdit>.t1(
              InsertReplaceEdit(
                insert: insertionRange,
                replace: replacementRange,
                newText: insertText,
              ),
            )
            : Either2<InsertReplaceEdit, TextEdit>.t2(
              TextEdit(range: replacementRange, newText: insertText),
            ),
    // When using defaults for edit range, use textEditText.
    textEditText: hasDefaultEditRange ? insertText.orNullIfSameAs(label) : null,
  );
}

lsp.Diagnostic toDiagnostic(
  ClientUriConverter uriConverter,
  server.ResolvedUnitResult result,
  server.Diagnostic diagnostic, {
  required Set<lsp.DiagnosticTag> supportedTags,
  required bool clientSupportsCodeDescription,
}) {
  return pluginToDiagnostic(
    uriConverter,
    (_) => result.lineInfo,
    server.newAnalysisError_fromEngine(result, diagnostic),
    supportedTags: supportedTags,
    clientSupportsCodeDescription: clientSupportsCodeDescription,
  );
}

lsp.Element toElement(server.LineInfo lineInfo, server.Element element) {
  var location = element.location;
  return lsp.Element(
    range:
        location != null
            ? toRange(lineInfo, location.offset, location.length)
            : null,
    name: toElementName(element),
    kind: element.kind.name,
    parameters: element.parameters,
    typeParameters: element.typeParameters,
    returnType: element.returnType,
  );
}

String toElementName(server.Element element) {
  return element.name.isNotEmpty
      ? element.name
      : (element.kind == server.ElementKind.EXTENSION
          ? '<unnamed extension>'
          : '<unnamed>');
}

lsp.FlutterOutline toFlutterOutline(
  server.LineInfo lineInfo,
  server.FlutterOutline outline,
) {
  var attributes = outline.attributes;
  var dartElement = outline.dartElement;
  var children = outline.children;

  return lsp.FlutterOutline(
    kind: outline.kind.name,
    label: outline.label,
    className: outline.className,
    variableName: outline.variableName,
    attributes:
        attributes
            ?.map((attribute) => toFlutterOutlineAttribute(lineInfo, attribute))
            .toList(),
    dartElement: dartElement != null ? toElement(lineInfo, dartElement) : null,
    range: toRange(lineInfo, outline.offset, outline.length),
    codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
    children: children?.map((c) => toFlutterOutline(lineInfo, c)).toList(),
  );
}

lsp.FlutterOutlineAttribute toFlutterOutlineAttribute(
  server.LineInfo lineInfo,
  server.FlutterOutlineAttribute attribute,
) {
  var valueLocation = attribute.valueLocation;
  return lsp.FlutterOutlineAttribute(
    name: attribute.name,
    label: attribute.label,
    valueRange:
        valueLocation != null
            ? toRange(lineInfo, valueLocation.offset, valueLocation.length)
            : null,
  );
}

lsp.FoldingRangeKind? toFoldingRangeKind(server.FoldingKind kind) {
  switch (kind) {
    case server.FoldingKind.COMMENT:
    case server.FoldingKind.DOCUMENTATION_COMMENT:
    case server.FoldingKind.FILE_HEADER:
      return lsp.FoldingRangeKind.Comment;
    case server.FoldingKind.DIRECTIVES:
      return lsp.FoldingRangeKind.Imports;
    default:
      // null (actually undefined in LSP, the toJson() takes care of that) is
      // valid, and actually the value used for the majority of folds
      // (class/functions/etc.).
      return null;
  }
}

lsp.Location toLocation(
  ClientUriConverter uriConverter,
  server.Location location,
  server.LineInfo lineInfo,
) => lsp.Location(
  uri: uriConverter.toClientUri(location.file),
  range: toRange(lineInfo, location.offset, location.length),
);

ErrorOr<int> toOffset(
  server.LineInfo lineInfo,
  lsp.Position pos, {
  bool failureIsCritical = false,
}) {
  // line is zero-based so cannot equal lineCount
  if (pos.line >= lineInfo.lineCount) {
    return ErrorOr<int>.error(
      lsp.ResponseError(
        code:
            failureIsCritical
                ? lsp.ServerErrorCodes.ClientServerInconsistentState
                : lsp.ServerErrorCodes.InvalidFileLineCol,
        message: 'Invalid line number',
        data: pos.line.toString(),
      ),
    );
  }
  // TODO(dantup): Is there any way to validate the character? We could ensure
  // it's less than the offset of the next line, but that would only work for
  // all lines except the last one.
  return ErrorOr<int>.success(
    lineInfo.getOffsetOfLine(pos.line) + pos.character,
  );
}

lsp.Outline toOutline(server.LineInfo lineInfo, server.Outline outline) {
  var children = outline.children;
  return lsp.Outline(
    element: toElement(lineInfo, outline.element),
    range: toRange(lineInfo, outline.offset, outline.length),
    codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
    children: children?.map((c) => toOutline(lineInfo, c)).toList(),
  );
}

lsp.Position toPosition(server.CharacterLocation location) {
  // LSP is zero-based, but analysis server is 1-based.
  return lsp.Position(
    line: location.lineNumber - 1,
    character: location.columnNumber - 1,
  );
}

lsp.Range toRange(server.LineInfo lineInfo, int offset, int length) {
  assert(offset >= 0);
  assert(length >= 0);
  var start = lineInfo.getLocation(offset);
  var end = lineInfo.getLocation(offset + length);

  return lsp.Range(start: toPosition(start), end: toPosition(end));
}

lsp.SignatureHelp toSignatureHelp(
  Set<lsp.MarkupKind>? preferredFormats,
  server.SignatureInformation signature,
) {
  // For now, we only support returning one (though we may wish to use named
  // args. etc. to provide one for each possible "next" option when the cursor
  // is at the end ready to provide another argument).

  /// Gets the label for an individual parameter in the form
  ///     String s = 'foo'
  String getParamLabel(FormalParameterElement p) {
    var defaultCodeSuffix =
        p.defaultValueCode != null ? ' = ${p.defaultValueCode}' : '';
    var requiredPrefix = p.isRequiredNamed ? 'required ' : '';
    return '$requiredPrefix${p.type} ${p.displayName}$defaultCodeSuffix';
  }

  /// Gets the full signature label in the form
  ///     foo(String s, int i, bool a = true)
  String getSignatureLabel(server.SignatureInformation resp) {
    var positionalRequired =
        signature.parameters.where((p) => p.isRequiredPositional).toList();
    var positionalOptional =
        signature.parameters.where((p) => p.isOptionalPositional).toList();
    var named = signature.parameters.where((p) => p.isNamed).toList();
    var params = [
      if (positionalRequired.isNotEmpty)
        positionalRequired.map(getParamLabel).join(', '),
      if (positionalOptional.isNotEmpty)
        '[${positionalOptional.map(getParamLabel).join(', ')}]',
      if (named.isNotEmpty) '{${named.map(getParamLabel).join(', ')}}',
    ];
    return '${resp.name}(${params.join(", ")})';
  }

  lsp.ParameterInformation toParameterInfo(FormalParameterElement param) {
    // LSP 3.14.0 supports providing label offsets (to avoid clients having
    // to guess based on substrings). We should check the
    // signatureHelp.signatureInformation.parameterInformation.labelOffsetSupport
    // capability when deciding to send that.
    return lsp.ParameterInformation(label: getParamLabel(param));
  }

  var cleanedDoc = cleanDartdoc(signature.dartdoc);

  return lsp.SignatureHelp(
    signatures: [
      lsp.SignatureInformation(
        label: getSignatureLabel(signature),
        documentation:
            cleanedDoc != null
                ? asMarkupContentOrString(preferredFormats, cleanedDoc)
                : null,
        parameters: signature.parameters.map(toParameterInfo).toList(),
      ),
    ],
    activeSignature: 0, // activeSignature
    // We must provide a unsigned integer here but it's possible there isn't
    // a valid value (because the user might be in the 10th argument of an
    // invocation that only takes 1). The LSP spec allows us to send an
    // out-of-bounds value so send the first out-of-bound value (`.length`). The
    // spec says this may be treated as 0, however VS Code will not highlight
    // any parameter in this case (which is preferred and hopefully other
    // clients may copy).
    activeParameter:
        signature.activeParameterIndex ?? signature.parameters.length,
  );
}

List<lsp.SnippetTextEdit> toSnippetTextEdits(
  String filePath,
  server.SourceFileEdit change,
  List<server.LinkedEditGroup> editGroups,
  LineInfo lineInfo, {
  required int? selectionOffset,
  required int? selectionLength,
}) {
  var snippetEdits = <lsp.SnippetTextEdit>[];

  // Edit groups offsets are based on the document after the edits are applied.
  // This means we must compute an offset delta for each edit that takes into
  // account all edits that might be made before it in the document (which are
  // after it in the edits). To do this, reverse the list when computing the
  // offsets, but reverse them back to the original list order when returning so
  // that we do not apply them incorrectly in tests (where we will apply them
  // in-sequence).

  var offsetDelta = 0;
  for (var edit in change.edits.reversed) {
    snippetEdits.add(
      snippetTextEditFromEditGroups(
        filePath,
        lineInfo,
        edit,
        editGroups: editGroups,
        editOffset: edit.offset + offsetDelta,
        selectionOffset: selectionOffset,
        selectionLength: selectionLength,
      ),
    );

    offsetDelta += edit.replacement.length - edit.length;
  }

  return snippetEdits.reversed.toList();
}

ErrorOr<server.SourceRange> toSourceRange(
  server.LineInfo lineInfo,
  Range range,
) {
  // If there is a range, convert to offsets because that's what
  // the tokens are computed using initially.
  var start = toOffset(lineInfo, range.start);
  var end = toOffset(lineInfo, range.end);

  return (start, end).mapResultsSync(
    (start, end) => success(server.SourceRange(start, end - start)),
  );
}

ErrorOr<server.SourceRange?> toSourceRangeNullable(
  server.LineInfo lineInfo,
  Range? range,
) => range != null ? toSourceRange(lineInfo, range) : success(null);

/// Creates an [lsp.TextDocumentEdit] for [fileEdit].
///
/// If [changeAnnotations] is not `null`, change annotations will be appended
/// for each edit produced and marked as requiring user confirmation.
lsp.TextDocumentEdit toTextDocumentEdit(
  LspClientCapabilities capabilities,
  FileEditInformation fileEdit, {
  ChangeAnnotations annotateChanges = ChangeAnnotations.none,
  Map<ChangeAnnotationIdentifier, ChangeAnnotation>? changeAnnotations,
}) {
  assert(
    (annotateChanges == ChangeAnnotations.none) == (changeAnnotations == null),
  );
  return lsp.TextDocumentEdit(
    textDocument: fileEdit.doc,
    edits:
        sortSourceEditsForLsp(fileEdit.edits).map((edit) {
          var annotation = recordEditAnnotation(
            fileEdit.doc.uri,
            edit,
            annotateChanges: annotateChanges,
            changeAnnotations: changeAnnotations,
          );
          return toTextDocumentEditEdit(
            capabilities,
            fileEdit.lineInfo,
            edit,
            selectionOffsetRelative: fileEdit.selectionOffsetRelative,
            selectionLength: fileEdit.selectionLength,
            annotationIdentifier: annotation?.label,
          );
        }).toList(),
  );
}

Either3<lsp.AnnotatedTextEdit, lsp.SnippetTextEdit, lsp.TextEdit>
toTextDocumentEditEdit(
  LspClientCapabilities capabilities,
  server.LineInfo lineInfo,
  server.SourceEdit edit, {
  int? selectionOffsetRelative,
  int? selectionLength,
  lsp.ChangeAnnotationIdentifier? annotationIdentifier,
}) {
  if (annotationIdentifier != null) {
    return Either3<lsp.AnnotatedTextEdit, lsp.SnippetTextEdit, lsp.TextEdit>.t1(
      lsp.AnnotatedTextEdit(
        annotationId: annotationIdentifier,
        range: toRange(lineInfo, edit.offset, edit.length),
        newText: edit.replacement,
      ),
    );
  }
  if (!capabilities.experimentalSnippetTextEdit ||
      selectionOffsetRelative == null) {
    return Either3<lsp.AnnotatedTextEdit, lsp.SnippetTextEdit, lsp.TextEdit>.t3(
      toTextEdit(lineInfo, edit),
    );
  }
  return Either3<lsp.AnnotatedTextEdit, lsp.SnippetTextEdit, lsp.TextEdit>.t2(
    snippetTextEditWithSelection(
      lineInfo,
      edit,
      selectionOffsetRelative: selectionOffsetRelative,
      selectionLength: selectionLength,
    ),
  );
}

lsp.TextEdit toTextEdit(
  server.LineInfo lineInfo,
  server.SourceEdit edit, {
  ChangeAnnotation? annotation,
}) {
  return annotation != null
      ? lsp.AnnotatedTextEdit(
        range: toRange(lineInfo, edit.offset, edit.length),
        newText: edit.replacement,
        annotationId: annotation.label,
      )
      : lsp.TextEdit(
        range: toRange(lineInfo, edit.offset, edit.length),
        newText: edit.replacement,
      );
}

/// Creates an [lsp.WorkspaceEdit] for [edits].
///
/// [clientCapabilities] should be for the client that will handle this edit,
/// which is not necessarily the client that triggered the request that called
/// this function (for example a DTD client may call a request that triggers an
/// edit that will be sent to the editor).
///
/// If [annotateChanges] is set, change annotations will be produced and
/// marked as needing confirmation from the user (depending on the value).
lsp.WorkspaceEdit toWorkspaceEdit(
  LspClientCapabilities clientCapabilities,
  List<FileEditInformation> edits, {
  ChangeAnnotations annotateChanges = ChangeAnnotations.none,
}) {
  var supportsDocumentChanges = clientCapabilities.documentChanges;
  var changeAnnotations =
      annotateChanges != ChangeAnnotations.none
          ? <lsp.ChangeAnnotationIdentifier, ChangeAnnotation>{}
          : null;

  if (supportsDocumentChanges) {
    var supportsCreate = clientCapabilities.createResourceOperations;
    var changes =
        <
          Either4<
            lsp.CreateFile,
            lsp.DeleteFile,
            lsp.RenameFile,
            lsp.TextDocumentEdit
          >
        >[];

    // Convert each SourceEdit to either a TextDocumentEdit or a
    // CreateFile + a TextDocumentEdit depending on whether it's a new
    // file.
    for (var fileEdit in edits) {
      if (supportsCreate && fileEdit.newFile) {
        var create = lsp.CreateFile(uri: fileEdit.doc.uri);
        var createUnion = Either4<
          lsp.CreateFile,
          lsp.DeleteFile,
          lsp.RenameFile,
          lsp.TextDocumentEdit
        >.t1(create);
        changes.add(createUnion);
      }

      var textDocEdit = toTextDocumentEdit(
        clientCapabilities,
        fileEdit,
        annotateChanges: annotateChanges,
        changeAnnotations: changeAnnotations,
      );
      var textDocEditUnion = Either4<
        lsp.CreateFile,
        lsp.DeleteFile,
        lsp.RenameFile,
        lsp.TextDocumentEdit
      >.t4(textDocEdit);
      changes.add(textDocEditUnion);
    }

    return lsp.WorkspaceEdit(
      documentChanges: changes,
      changeAnnotations: changeAnnotations,
    );
  } else {
    return lsp.WorkspaceEdit(
      changes: toWorkspaceEditChanges(
        edits,
        annotateChanges: annotateChanges,
        changeAnnotations: changeAnnotations,
      ),
      changeAnnotations: changeAnnotations,
    );
  }
}

Map<Uri, List<lsp.TextEdit>> toWorkspaceEditChanges(
  List<FileEditInformation> edits, {
  ChangeAnnotations annotateChanges = ChangeAnnotations.none,
  Map<ChangeAnnotationIdentifier, ChangeAnnotation>? changeAnnotations,
}) {
  MapEntry<Uri, List<lsp.TextEdit>> createEdit(FileEditInformation file) {
    var edits =
        sortSourceEditsForLsp(file.edits).map((edit) {
          var annotation = recordEditAnnotation(
            file.doc.uri,
            edit,
            annotateChanges: annotateChanges,
            changeAnnotations: changeAnnotations,
          );
          return toTextEdit(file.lineInfo, edit, annotation: annotation);
        }).toList();
    return MapEntry(file.doc.uri, edits);
  }

  return Map<Uri, List<lsp.TextEdit>>.fromEntries(edits.map(createEdit));
}

lsp.MarkupContent _asMarkup(
  Set<lsp.MarkupKind> preferredFormats,
  String content,
) {
  if (preferredFormats.isEmpty) {
    preferredFormats.add(lsp.MarkupKind.Markdown);
  }

  var supportsMarkdown = preferredFormats.contains(lsp.MarkupKind.Markdown);
  var supportsPlain = preferredFormats.contains(lsp.MarkupKind.PlainText);
  // Since our PlainText version is actually just Markdown, only advertise it
  // as PlainText if the client explicitly supports PlainText and not Markdown.
  var format =
      supportsPlain && !supportsMarkdown
          ? lsp.MarkupKind.PlainText
          : lsp.MarkupKind.Markdown;

  return lsp.MarkupContent(kind: format, value: content);
}

String _diagnosticCode(server.DiagnosticCode code) => code.name.toLowerCase();

/// Additional details about a completion that may be formatted differently
/// depending on the client capabilities.
typedef CompletionDetail =
    ({
      /// Additional details to go in the details popup.
      ///
      /// This is usually a full signature (with full parameters) and may also
      /// include whether the item is deprecated if the client did not support the
      /// native deprecated tag.
      String detail,

      /// Truncated parameters. Similar to [truncatedSignature] but does not
      /// include return types. Used in clients that cannot format signatures
      /// differently and is appended immediately after the completion label. The
      /// return type is omitted to reduce noise because this text is not subtle.
      String truncatedParams,

      /// A signature with truncated params. Used for showing immediately after
      /// the completion label when it can be formatted differently.
      ///
      /// () → String
      String truncatedSignature,

      /// The URI that will be auto-imported if this item is selected in a
      /// user-friendly string format (for example a relative path if for a `file:/`
      /// URI).
      Uri? autoImportUri,
    });

extension CompletionLabelExtension on CompletionItemLabelDetails {
  /// Returns `null` if no fields are set, otherwise `this`.
  CompletionItemLabelDetails? get nullIfEmpty =>
      detail != null || description != null ? this : null;
}

extension _ListExtensions<T> on List<T> {
  /// Returns `null` if this list is empty, otherwise `this`.
  List<T>? get nullIfEmpty => isEmpty ? null : this;
}
