// 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_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,
  ) when isSynthetic) {
    var element = fragment.element.nonSynthetic;
    nameOffset = element.firstFragment.nameOffset;
    nameLength = element.firstFragment.name?.length;
  } else {
    nameOffset = fragment.nameOffset;
    nameLength = fragment.name?.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;
}
