// 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 'dart:math';

import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
    as lsp;
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
import 'package:analysis_server/src/collections.dart';
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/lsp_analysis_server.dart' as lsp;
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/search/workspace_symbols.dart' as server
    show DeclarationKind;
import 'package:analyzer/dart/analysis/results.dart' as server;
import 'package:analyzer/error/error.dart' as server;
import 'package:analyzer/source/line_info.dart' as server;
import 'package:analyzer/source/source_range.dart' as server;
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/services/available_declarations.dart';
import 'package:analyzer/src/services/available_declarations.dart' as dec;
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:analyzer_plugin/utilities/pair.dart';
import 'package:collection/collection.dart';

const languageSourceName = 'dart';

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

/// 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<String, lsp.MarkupContent> asStringOrMarkupContent(
    Set<lsp.MarkupKind>? preferredFormats, String content) {
  return preferredFormats == null
      ? lsp.Either2<String, lsp.MarkupContent>.t1(content)
      : lsp.Either2<String, lsp.MarkupContent>.t2(
          _asMarkup(preferredFormats, content));
}

/// Builds an LSP snippet string with supplied ranges as tabstops.
String buildSnippetStringWithTabStops(
  String? text,
  List<int>? offsetLengthPairs,
) {
  text ??= '';
  offsetLengthPairs ??= const [];

  // Snippets syntax is documented in the LSP spec:
  // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
  //
  // $1, $2, etc. are used for tab stops and ${1:foo} inserts a placeholder of foo.

  final output = [];
  var offset = 0;

  // When there's only a single tabstop, it should be ${0} as this is treated
  // specially as the final cursor position (if we use 1, the editor will insert
  // a 0 at the end of the string which is not what we expect).
  // When there are multiple, start with ${1} since these are placeholders the
  // user can tab through and the editor-inserted ${0} at the end is expected.
  var tabStopNumber = offsetLengthPairs.length <= 2 ? 0 : 1;

  for (var i = 0; i < offsetLengthPairs.length; i += 2) {
    final pairOffset = offsetLengthPairs[i];
    final pairLength = offsetLengthPairs[i + 1];

    // Add any text that came before this tabstop to the result.
    output.add(escapeSnippetString(text.substring(offset, pairOffset)));

    // Add this tabstop
    final tabStopText = escapeSnippetString(
        text.substring(pairOffset, pairOffset + pairLength));
    output.add('\${${tabStopNumber++}:$tabStopText}');

    offset = pairOffset + pairLength;
  }

  // Add any remaining text that was after the last tabstop.
  output.add(escapeSnippetString(text.substring(offset)));

  return output.join('');
}

/// Creates a [lsp.WorkspaceEdit] from simple [server.SourceFileEdit]s.
///
/// 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(
    lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
  return toWorkspaceEdit(
      // Client capabilities are always available after initialization.
      server.clientCapabilities!,
      edits
          .map((e) => FileEditInformation(
                server.getVersionedDocumentIdentifier(e.file),
                // We should never produce edits for a file with no LineInfo.
                server.getLineInfo(e.file)!,
                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(String oldPath, String newPath) {
  final changes =
      <Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>[];

  final rename = RenameFile(
    oldUri: Uri.file(oldPath).toString(),
    newUri: Uri.file(newPath).toString(),
  );

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

  changes.add(renameUnion);

  final edit = WorkspaceEdit(
      documentChanges: Either2<
          List<TextDocumentEdit>,
          List<
              Either4<TextDocumentEdit, CreateFile, RenameFile,
                  DeleteFile>>>.t2(changes));
  return edit;
}

/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange] that can include
/// experimental [server.SnippetTextEdit]s if the client has indicated support
/// for these in the experimental section of their client capabilities.
///
/// 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(
    lsp.LspAnalysisServer server, server.SourceChange change) {
  // In order to return snippets, we must ensure we are only modifying a single
  // existing file with a single edit and that there is a linked edit group with
  // only one position and no suggestions.
  if (!server.clientCapabilities!.experimentalSnippetTextEdit ||
      change.edits.length != 1 ||
      change.edits.first.fileStamp == -1 || // new file
      change.edits.first.edits.length != 1 ||
      change.linkedEditGroups.isEmpty ||
      change.linkedEditGroups.first.positions.length != 1 ||
      change.linkedEditGroups.first.suggestions.isNotEmpty) {
    return createPlainWorkspaceEdit(server, change.edits);
  }

  // Additionally, the selection must fall within the edit offset.
  final edit = change.edits.first.edits.first;
  final selectionOffset = change.linkedEditGroups.first.positions.first.offset;
  final selectionLength = change.linkedEditGroups.first.length;

  if (selectionOffset < edit.offset ||
      selectionOffset + selectionLength > edit.offset + edit.length) {
    return createPlainWorkspaceEdit(server, change.edits);
  }

  return toWorkspaceEdit(
      server.clientCapabilities!,
      change.edits
          .map((e) => FileEditInformation(
                server.getVersionedDocumentIdentifier(e.file),
                // We should never produce edits for a file with no LineInfo.
                server.getLineInfo(e.file)!,
                e.edits,
                selectionOffsetRelative: selectionOffset - edit.offset,
                selectionLength: selectionLength,
                newFile: e.fileStamp == -1,
              ))
          .toList());
}

lsp.CompletionItemKind? declarationKindToCompletionItemKind(
  Set<lsp.CompletionItemKind> supportedCompletionKinds,
  dec.DeclarationKind kind,
) {
  bool isSupported(lsp.CompletionItemKind kind) =>
      supportedCompletionKinds.contains(kind);

  List<lsp.CompletionItemKind> getKindPreferences() {
    switch (kind) {
      case dec.DeclarationKind.CLASS:
      case dec.DeclarationKind.CLASS_TYPE_ALIAS:
      case dec.DeclarationKind.MIXIN:
        return const [lsp.CompletionItemKind.Class];
      case dec.DeclarationKind.CONSTRUCTOR:
        return const [lsp.CompletionItemKind.Constructor];
      case dec.DeclarationKind.ENUM:
        return const [lsp.CompletionItemKind.Enum];
      case dec.DeclarationKind.ENUM_CONSTANT:
        return const [
          lsp.CompletionItemKind.EnumMember,
          lsp.CompletionItemKind.Enum,
        ];
      case dec.DeclarationKind.FUNCTION:
        return const [lsp.CompletionItemKind.Function];
      case dec.DeclarationKind.FUNCTION_TYPE_ALIAS:
        return const [lsp.CompletionItemKind.Class];
      case dec.DeclarationKind.GETTER:
        return const [lsp.CompletionItemKind.Property];
      case dec.DeclarationKind.SETTER:
        return const [lsp.CompletionItemKind.Property];
      case dec.DeclarationKind.TYPE_ALIAS:
        return const [lsp.CompletionItemKind.Class];
      case dec.DeclarationKind.VARIABLE:
        return const [lsp.CompletionItemKind.Variable];
      default:
        return const [];
    }
  }

  return getKindPreferences().firstWhereOrNull(isSupported);
}

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.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.CompletionItem declarationToCompletionItem(
  LspClientCapabilities capabilities,
  String file,
  int offset,
  server.IncludedSuggestionSet includedSuggestionSet,
  Library library,
  Map<String, int> tagBoosts,
  server.LineInfo lineInfo,
  dec.Declaration declaration,
  int replacementOffset,
  int insertLength,
  int replacementLength, {
  required bool includeCommitCharacters,
  required bool completeFunctionCalls,
}) {
  final supportsSnippets = capabilities.completionSnippets;
  final parent = declaration.parent;

  String completion;
  switch (declaration.kind) {
    case DeclarationKind.ENUM_CONSTANT:
      completion = '${parent!.name}.${declaration.name}';
      break;
    case DeclarationKind.GETTER:
    case DeclarationKind.FIELD:
      completion = parent != null && parent.name.isNotEmpty
          ? '${parent.name}.${declaration.name}'
          : declaration.name;
      break;
    case DeclarationKind.CONSTRUCTOR:
      completion = parent!.name;
      if (declaration.name.isNotEmpty) {
        completion += '.${declaration.name}';
      }
      break;
    default:
      completion = declaration.name;
      break;
  }
  // By default, label is the same as the completion text, but may be added to
  // later (parens/snippets).
  var label = completion;

  // isCallable is used to suffix the label with parens so it's clear the item
  // is callable.
  final declarationKind = declaration.kind;
  final isCallable = declarationKind == DeclarationKind.CONSTRUCTOR ||
      declarationKind == DeclarationKind.FUNCTION ||
      declarationKind == DeclarationKind.METHOD;

  if (isCallable) {
    label += declaration.parameterNames?.isNotEmpty ?? false ? '(…)' : '()';
  }

  final insertTextInfo = _buildInsertText(
    supportsSnippets: supportsSnippets,
    includeCommitCharacters: includeCommitCharacters,
    completeFunctionCalls: completeFunctionCalls,
    isCallable: isCallable,
    // For SuggestionSets, we don't have a CompletionKind to check if it's
    // an invocation, but since they do not show in show/hide combinators
    // we can assume if an item is callable it's probably being used in a context
    // that can invoke it.
    isInvocation: isCallable,
    defaultArgumentListString: declaration.defaultArgumentListString,
    defaultArgumentListTextRanges: declaration.defaultArgumentListTextRanges,
    completion: completion,
    selectionOffset: 0,
    selectionLength: 0,
  );
  final insertText = insertTextInfo.first;
  final insertTextFormat = insertTextInfo.last;
  final isMultilineCompletion = insertText.contains('\n');

  final supportsDeprecatedFlag = capabilities.completionDeprecatedFlag;
  final supportsDeprecatedTag = capabilities.completionItemTags
      .contains(lsp.CompletionItemTag.Deprecated);
  final supportsAsIsInsertMode =
      capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);

  final completionKind = declarationKindToCompletionItemKind(
      capabilities.completionItemKinds, declaration.kind);

  var relevanceBoost = 0;
  declaration.relevanceTags
      .forEach((t) => relevanceBoost = max(relevanceBoost, tagBoosts[t] ?? 0));
  final itemRelevance = includedSuggestionSet.relevance + relevanceBoost;

  // 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 && declaration.isDeprecated)
        lsp.CompletionItemTag.Deprecated
    ]),
    commitCharacters:
        includeCommitCharacters ? lsp.dartCompletionCommitCharacters : null,
    detail: getDeclarationCompletionDetail(declaration, completionKind,
        supportsDeprecatedFlag || supportsDeprecatedTag),
    deprecated:
        supportsDeprecatedFlag && declaration.isDeprecated ? true : null,
    sortText: relevanceToSortText(itemRelevance),
    filterText: completion != label
        ? completion
        : null, // filterText uses label if not set
    insertText: insertText != label
        ? insertText
        : null, // insertText uses label if not set
    insertTextFormat: insertTextFormat != lsp.InsertTextFormat.PlainText
        ? insertTextFormat
        : null, // Defaults to PlainText if not supplied
    insertTextMode: supportsAsIsInsertMode && isMultilineCompletion
        ? InsertTextMode.asIs
        : null,
    // data, used for completionItem/resolve.
    data: lsp.DartCompletionItemResolutionInfo(
        file: file,
        offset: offset,
        libId: includedSuggestionSet.id,
        displayUri: includedSuggestionSet.displayUri ?? library.uri.toString(),
        rOffset: replacementOffset,
        iLength: insertLength,
        rLength: replacementLength),
  );
}

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.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.Module];
      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.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);
}

/// Escapes a string to be used in an LSP edit that uses Snippet mode.
///
/// Snippets can contain special markup like `${a:b}` so some characters need
/// escaping (according to the LSP spec, those are `$`, `}` and `\`).
String escapeSnippetString(String input) => input.replaceAllMapped(
      RegExp(r'[$}\\]'), // Replace any of $ } \
      (c) => '\\${c[0]}', // Prefix with a backslash
    );

String? getCompletionDetail(
  server.CompletionSuggestion suggestion,
  lsp.CompletionItemKind? completionKind,
  bool supportsDeprecated,
) {
  final element = suggestion.element;
  final hasElement = element != null;
  final parameters = element?.parameters;
  final returnType = element?.returnType;
  final parameterType = suggestion.parameterType;
  final hasParameters =
      hasElement && parameters != null && parameters.isNotEmpty;
  final hasReturnType =
      hasElement && returnType != null && returnType.isNotEmpty;
  final hasParameterType = parameterType != null && parameterType.isNotEmpty;

  final prefix =
      supportsDeprecated || !suggestion.isDeprecated ? '' : '(Deprecated) ';

  if (completionKind == lsp.CompletionItemKind.Property) {
    // Setters appear as methods with one arg but they also cause getters to not
    // appear in the completion list, so displaying them as setters is misleading.
    // To avoid this, always show only the return type, whether it's a getter
    // or a setter.
    return prefix +
        (element?.kind == server.ElementKind.GETTER
            ? (returnType ?? '')
            // Don't assume setters always have parameters
            // See https://github.com/dart-lang/sdk/issues/27747
            : parameters != null && parameters.isNotEmpty
                // Extract the type part from '(MyType value)`
                ? parameters.substring(1, parameters.lastIndexOf(' '))
                : '');
  } else if (hasParameters && hasReturnType) {
    return '$prefix$parameters → $returnType';
  } else if (hasReturnType) {
    return '$prefix$returnType';
  } else if (hasParameterType) {
    return '$prefix$parameterType';
  } else {
    return prefix.isNotEmpty ? prefix : null;
  }
}

String? getDeclarationCompletionDetail(
  dec.Declaration declaration,
  lsp.CompletionItemKind? completionKind,
  bool supportsDeprecated,
) {
  final parameters = declaration.parameters;
  final hasParameters = parameters != null && parameters.isNotEmpty;
  final returnType = declaration.returnType;
  final hasReturnType = returnType != null && returnType.isNotEmpty;

  final prefix =
      supportsDeprecated || !declaration.isDeprecated ? '' : '(Deprecated) ';

  if (completionKind == lsp.CompletionItemKind.Property) {
    // Setters appear as methods with one arg but they also cause getters to not
    // appear in the completion list, so displaying them as setters is misleading.
    // To avoid this, always show only the return type, whether it's a getter
    // or a setter.
    var suffix = '';
    if (declaration.kind == dec.DeclarationKind.GETTER) {
      suffix = declaration.returnType ?? '';
    } else {
      // Don't assume setters always have parameters
      // See https://github.com/dart-lang/sdk/issues/27747
      if (parameters != null && parameters.isNotEmpty) {
        // Extract the type part from `(MyType value)`, if there is a type.
        var spaceIndex = parameters.lastIndexOf(' ');
        if (spaceIndex > 0) {
          suffix = parameters.substring(1, spaceIndex);
        }
      }
    }
    return prefix + suffix;
  } else if (hasParameters && hasReturnType) {
    return '$prefix${declaration.parameters} → ${declaration.returnType}';
  } else if (hasReturnType) {
    return '$prefix${declaration.returnType}';
  } else {
    return prefix.isNotEmpty ? prefix : null;
  }
}

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

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

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

bool isDartDocument(lsp.TextDocumentIdentifier? doc) =>
    doc?.uri.endsWith('.dart') ?? false;

/// 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.
  final changes =
      <Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>[];

  for (final edit in edits) {
    // Flatten the Either into just the Union side to get a flat list.
    final flatResourceChanges = edit.documentChanges!.map(
      (edits) => edits.map((e) =>
          Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t1(e)),
      (resources) => resources,
    );
    changes.addAll(flatResourceChanges);
  }

  return WorkspaceEdit(
      documentChanges: Either2<
          List<TextDocumentEdit>,
          List<
              Either4<TextDocumentEdit, CreateFile, RenameFile,
                  DeleteFile>>>.t2(changes));
}

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

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

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

/// Returns the file system path for a TextDocumentIdentifier.
ErrorOr<String> pathOfDoc(lsp.TextDocumentIdentifier doc) =>
    pathOfUri(Uri.tryParse(doc.uri));

/// Returns the file system path for a TextDocumentItem.
ErrorOr<String> pathOfDocItem(lsp.TextDocumentItem doc) =>
    pathOfUri(Uri.tryParse(doc.uri));

/// Returns the file system path for a file URI.
ErrorOr<String> pathOfUri(Uri? uri) {
  if (uri == null) {
    return ErrorOr<String>.error(ResponseError(
      code: lsp.ServerErrorCodes.InvalidFilePath,
      message: 'Document URI was not supplied',
    ));
  }
  final isValidFileUri = uri.isScheme('file');
  if (!isValidFileUri) {
    return ErrorOr<String>.error(ResponseError(
      code: lsp.ServerErrorCodes.InvalidFilePath,
      message: 'URI was not a valid file:// URI',
      data: uri.toString(),
    ));
  }
  try {
    return ErrorOr<String>.success(uri.toFilePath());
  } catch (e) {
    // Even if tryParse() works and file == scheme, toFilePath() can throw on
    // Windows if there are invalid characters.
    return ErrorOr<String>.error(ResponseError(
        code: lsp.ServerErrorCodes.InvalidFilePath,
        message: 'File URI did not contain a valid file path',
        data: uri.toString()));
  }
}

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

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

  var lineInfo = getLineInfo(error.location.file);
  var documentationUrl = error.url;
  return lsp.Diagnostic(
    range: toRange(lineInfo, error.location.offset, error.location.length),
    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)serialisation).
    codeDescription: clientSupportsCodeDescription && documentationUrl != null
        ? CodeDescription(href: documentationUrl)
        : null,
  );
}

lsp.DiagnosticRelatedInformation? pluginToDiagnosticRelatedInformation(
    server.LineInfo? Function(String) getLineInfo,
    plugin.DiagnosticMessage message) {
  final file = message.location.file;
  final 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.file(file).toString(),
        range: toRange(
          lineInfo,
          message.location.offset,
          message.location.length,
        ),
      ),
      message: message.message);
}

lsp.DiagnosticSeverity pluginToDiagnosticSeverity(
    plugin.AnalysisErrorSeverity severity) {
  switch (severity) {
    case plugin.AnalysisErrorSeverity.ERROR:
      return lsp.DiagnosticSeverity.Error;
    case plugin.AnalysisErrorSeverity.WARNING:
      return lsp.DiagnosticSeverity.Warning;
    case plugin.AnalysisErrorSeverity.INFO:
      return lsp.DiagnosticSeverity.Information;
    // Note: LSP also supports "Hint", but they won't render in things like the
    // VS Code errors list as they're apparently intended to communicate
    // non-visible diagnostics back (for example, if you wanted to grey out
    // unreachable code without producing an item in the error list).
    default:
      throw 'Unknown AnalysisErrorSeverity: $severity';
  }
}

/// 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.
///
/// 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) => (9999999 - relevance).toString();

lsp.Location? searchResultToLocation(
    server.SearchResult result, server.LineInfo? lineInfo) {
  final location = result.location;

  if (lineInfo == null) {
    return null;
  }

  return lsp.Location(
    uri: Uri.file(result.location.file).toString(),
    range: toRange(lineInfo, location.offset, location.length),
  );
}

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());

  // 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,
  int replacementOffset,
  int insertLength,
  int replacementLength, {
  required bool includeCommitCharacters,
  required bool completeFunctionCalls,
  CompletionItemResolutionInfo? resolutionData,
}) {
  // Build separate display and filter labels. Displayed labels may have additional
  // info appended (for example '(...)' on callables) that should not be included
  // in filterText.
  var label = suggestion.displayText ?? suggestion.completion;
  final filterText = label;

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

  // 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.
  final elementKind = suggestion.element?.kind;
  final isCallable = elementKind == server.ElementKind.CONSTRUCTOR ||
      elementKind == server.ElementKind.FUNCTION ||
      elementKind == server.ElementKind.METHOD;
  final isInvocation =
      suggestion.kind == server.CompletionSuggestionKind.INVOCATION;

  if (suggestion.displayText == null && isCallable) {
    label += suggestion.parameterNames?.isNotEmpty ?? false ? '(…)' : '()';
  }

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

  final element = suggestion.element;
  final completionKind = element != null
      ? elementKindToCompletionItemKind(
          capabilities.completionItemKinds, element.kind)
      : suggestionKindToCompletionItemKind(
          capabilities.completionItemKinds, suggestion.kind, label);

  final insertTextInfo = _buildInsertText(
    supportsSnippets: supportsSnippets,
    includeCommitCharacters: includeCommitCharacters,
    completeFunctionCalls: completeFunctionCalls,
    isCallable: isCallable,
    isInvocation: isInvocation,
    defaultArgumentListString: suggestion.defaultArgumentListString,
    defaultArgumentListTextRanges: suggestion.defaultArgumentListTextRanges,
    completion: suggestion.completion,
    selectionOffset: suggestion.selectionOffset,
    selectionLength: suggestion.selectionLength,
  );
  final insertText = insertTextInfo.first;
  final insertTextFormat = insertTextInfo.last;
  final isMultilineCompletion = insertText.contains('\n');

  var cleanedDoc = cleanDartdoc(suggestion.docComplete);
  var detail = getCompletionDetail(suggestion, completionKind,
      supportsCompletionDeprecatedFlag || supportsDeprecatedTag);

  // 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.
  final labelMatch = cleanedDoc != null
      ? _upgradableDocCompletePattern.firstMatch(cleanedDoc)
      : null;
  if (labelMatch != null) {
    cleanedDoc = null;
    detail = labelMatch.group(1);
  }

  // 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
    ]),
    commitCharacters:
        includeCommitCharacters ? dartCompletionCommitCharacters : null,
    data: resolutionData,
    detail: detail,
    documentation: cleanedDoc != null
        ? asStringOrMarkupContent(formats, cleanedDoc)
        : null,
    deprecated: supportsCompletionDeprecatedFlag && suggestion.isDeprecated
        ? true
        : null,
    sortText: relevanceToSortText(suggestion.relevance),
    filterText: filterText != label
        ? filterText
        : null, // filterText uses label if not set
    insertText: insertText != label
        ? insertText
        : null, // insertText uses label if not set
    insertTextFormat: insertTextFormat != lsp.InsertTextFormat.PlainText
        ? insertTextFormat
        : null, // Defaults to PlainText if not supplied
    insertTextMode: supportsAsIsInsertMode && isMultilineCompletion
        ? InsertTextMode.asIs
        : null,
    textEdit: supportsInsertReplace && insertLength != replacementLength
        ? Either2<TextEdit, InsertReplaceEdit>.t2(
            InsertReplaceEdit(
              insert: toRange(lineInfo, replacementOffset, insertLength),
              replace: toRange(lineInfo, replacementOffset, replacementLength),
              newText: insertText,
            ),
          )
        : Either2<TextEdit, InsertReplaceEdit>.t1(
            TextEdit(
              range: toRange(lineInfo, replacementOffset, replacementLength),
              newText: insertText,
            ),
          ),
  );
}

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

lsp.Element toElement(server.LineInfo lineInfo, server.Element element) {
  final 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) {
  final attributes = outline.attributes;
  final dartElement = outline.dartElement;
  final children = outline.children;

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

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

lsp.FoldingRange toFoldingRange(
    server.LineInfo lineInfo, server.FoldingRegion region) {
  final range = toRange(lineInfo, region.offset, region.length);
  return lsp.FoldingRange(
      startLine: range.start.line,
      startCharacter: range.start.character,
      endLine: range.end.line,
      endCharacter: range.end.character,
      kind: toFoldingRangeKind(region.kind));
}

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;
  }
}

List<lsp.DocumentHighlight> toHighlights(
    server.LineInfo lineInfo, server.Occurrences occurrences) {
  return occurrences.offsets
      .map((offset) => lsp.DocumentHighlight(
          range: toRange(lineInfo, offset, occurrences.length)))
      .toList();
}

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

ErrorOr<int> toOffset(
  server.LineInfo lineInfo,
  lsp.Position pos, {
  failureIsCritial = false,
}) {
  // line is zero-based so cannot equal lineCount
  if (pos.line >= lineInfo.lineCount) {
    return ErrorOr<int>.error(lsp.ResponseError(
        code: failureIsCritial
            ? 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) {
  final 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 != null
        ? children.map((c) => toOutline(lineInfo, c)).toList()
        : null,
  );
}

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) {
  final start = lineInfo.getLocation(offset);
  final end = lineInfo.getLocation(offset + length);

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

lsp.SignatureHelp toSignatureHelp(Set<lsp.MarkupKind>? preferredFormats,
    server.AnalysisGetSignatureResult 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(server.ParameterInfo p) {
    final def = p.defaultValue != null ? ' = ${p.defaultValue}' : '';
    final prefix =
        p.kind == server.ParameterKind.REQUIRED_NAMED ? 'required ' : '';
    return '$prefix${p.type} ${p.name}$def';
  }

  /// Gets the full signature label in the form
  ///     foo(String s, int i, bool a = true)
  String getSignatureLabel(server.AnalysisGetSignatureResult resp) {
    final positionalRequired = signature.parameters
        .where((p) => p.kind == server.ParameterKind.REQUIRED_POSITIONAL)
        .toList();
    final positionalOptional = signature.parameters
        .where((p) => p.kind == server.ParameterKind.OPTIONAL_POSITIONAL)
        .toList();
    final named = signature.parameters
        .where((p) =>
            p.kind == server.ParameterKind.OPTIONAL_NAMED ||
            p.kind == server.ParameterKind.REQUIRED_NAMED)
        .toList();
    final params = [];
    if (positionalRequired.isNotEmpty) {
      params.add(positionalRequired.map(getParamLabel).join(', '));
    }
    if (positionalOptional.isNotEmpty) {
      params.add('[' + positionalOptional.map(getParamLabel).join(', ') + ']');
    }
    if (named.isNotEmpty) {
      params.add('{' + named.map(getParamLabel).join(', ') + '}');
    }
    return '${resp.name}(${params.join(", ")})';
  }

  lsp.ParameterInformation toParameterInfo(server.ParameterInfo 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));
  }

  final cleanedDoc = cleanDartdoc(signature.dartdoc);

  return lsp.SignatureHelp(
    signatures: [
      lsp.SignatureInformation(
        label: getSignatureLabel(signature),
        documentation: cleanedDoc != null
            ? asStringOrMarkupContent(preferredFormats, cleanedDoc)
            : null,
        parameters: signature.parameters.map(toParameterInfo).toList(),
      ),
    ],
    activeSignature: 0, // activeSignature
    // TODO(dantup): The LSP spec says this value will default to 0 if it's
    // not supplied or outside of the value range. However, setting -1 results
    // in no parameters being selected in VS Code, whereas null/0 will select the first.
    // We'd like for none to be selected (since we don't support this yet) so
    // we send -1. I've made a request for LSP to support not selecting a parameter
    // (because you could also be on param 5 of an invalid call to a function
    // taking only 3 arguments) here:
    // https://github.com/Microsoft/language-server-protocol/issues/456#issuecomment-452318297
    activeParameter: -1, // activeParameter
  );
}

lsp.SnippetTextEdit toSnippetTextEdit(
    LspClientCapabilities capabilities,
    server.LineInfo lineInfo,
    server.SourceEdit edit,
    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]),
  );
}

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.
  final start = toOffset(lineInfo, range.start);
  final end = toOffset(lineInfo, range.end);
  if (start.isError) {
    return failure(start);
  }
  if (end.isError) {
    return failure(end);
  }

  final startOffset = start.result;
  final endOffset = end.result;

  return success(server.SourceRange(startOffset, endOffset - startOffset));
}

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

lsp.TextDocumentEdit toTextDocumentEdit(
    LspClientCapabilities capabilities, FileEditInformation edit) {
  return lsp.TextDocumentEdit(
      textDocument: edit.doc,
      edits: edit.edits
          .map((e) => toTextDocumentEditEdit(capabilities, edit.lineInfo, e,
              selectionOffsetRelative: edit.selectionOffsetRelative,
              selectionLength: edit.selectionLength))
          .toList());
}

Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>
    toTextDocumentEditEdit(
  LspClientCapabilities capabilities,
  server.LineInfo lineInfo,
  server.SourceEdit edit, {
  int? selectionOffsetRelative,
  int? selectionLength,
}) {
  if (!capabilities.experimentalSnippetTextEdit ||
      selectionOffsetRelative == null) {
    return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t3(
        toTextEdit(lineInfo, edit));
  }
  return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t1(
      toSnippetTextEdit(capabilities, lineInfo, edit, selectionOffsetRelative,
          selectionLength));
}

lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
  return lsp.TextEdit(
    range: toRange(lineInfo, edit.offset, edit.length),
    newText: edit.replacement,
  );
}

lsp.WorkspaceEdit toWorkspaceEdit(
  LspClientCapabilities capabilities,
  List<FileEditInformation> edits,
) {
  final supportsDocumentChanges = capabilities.documentChanges;
  if (supportsDocumentChanges) {
    final supportsCreate = capabilities.createResourceOperations;
    final changes = <
        Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
            lsp.DeleteFile>>[];

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

      final textDocEdit = toTextDocumentEdit(capabilities, edit);
      final textDocEditUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
          lsp.RenameFile, lsp.DeleteFile>.t1(textDocEdit);
      changes.add(textDocEditUnion);
    }

    return lsp.WorkspaceEdit(
        documentChanges: Either2<
            List<lsp.TextDocumentEdit>,
            List<
                Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
                    lsp.DeleteFile>>>.t2(changes));
  } else {
    return lsp.WorkspaceEdit(changes: toWorkspaceEditChanges(edits));
  }
}

Map<String, List<lsp.TextEdit>> toWorkspaceEditChanges(
    List<FileEditInformation> edits) {
  MapEntry<String, List<lsp.TextEdit>> createEdit(FileEditInformation file) {
    final edits =
        file.edits.map((edit) => toTextEdit(file.lineInfo, edit)).toList();
    return MapEntry(file.doc.uri, edits);
  }

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

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

  final supportsMarkdown = preferredFormats.contains(lsp.MarkupKind.Markdown);
  final 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.
  final format = supportsPlain && !supportsMarkdown
      ? lsp.MarkupKind.PlainText
      : lsp.MarkupKind.Markdown;

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

Pair<String, lsp.InsertTextFormat> _buildInsertText({
  required bool supportsSnippets,
  required bool includeCommitCharacters,
  required bool completeFunctionCalls,
  required bool isCallable,
  required bool isInvocation,
  required String? defaultArgumentListString,
  required List<int>? defaultArgumentListTextRanges,
  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 (!includeCommitCharacters &&
        completeFunctionCalls &&
        isCallable &&
        isInvocation) {
      insertTextFormat = lsp.InsertTextFormat.Snippet;
      final hasRequiredParameters =
          (defaultArgumentListTextRanges?.length ?? 0) > 0;
      final functionCallSuffix = hasRequiredParameters
          ? buildSnippetStringWithTabStops(
              defaultArgumentListString,
              defaultArgumentListTextRanges,
            )
          : '\${0:}'; // No required params still gets a tabstop in the parens.
      insertText = '${escapeSnippetString(insertText)}($functionCallSuffix)';
    } else if (selectionOffset != 0 &&
        // We don't need a tabstop if the selection is the end of the string.
        selectionOffset != completion.length) {
      insertTextFormat = lsp.InsertTextFormat.Snippet;
      insertText = buildSnippetStringWithTabStops(
        completion,
        [selectionOffset, selectionLength],
      );
    }
  }

  return Pair(insertText, insertTextFormat);
}

String _errorCode(server.ErrorCode code) => code.name.toLowerCase();
