// 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:io';
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/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/snippets/dart/snippet_manager.dart';
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/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/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));
}

/// 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),
                // If we expect to create the file, server.getLineInfo() won't
                // provide a LineInfo so create one from empty contents.
                e.fileStamp == -1
                    ? LineInfo.fromContent('')
                    : 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].
///
/// Can return experimental [server.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(
  lsp.LspAnalysisServer server,
  server.SourceChange change, {
  // 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,
}) {
  // 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 ||
      !server.clientCapabilities!.experimentalSnippetTextEdit ||
      !server.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(server, change.edits);
  }

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

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

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

  // Convert to the union that documentChanges is.
  final documentChanges = Either2<
      List<lsp.TextDocumentEdit>,
      List<
          Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
              lsp.DeleteFile>>>.t2([textDocumentEditsAsUnion]);

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

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;

  // By default, label is the same as the completion text, but may be added to
  // later (parens/snippets).
  final completion = getDeclarationName(declaration);
  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,
    requiredArgumentListString: declaration.defaultArgumentListString,
    requiredArgumentListTextRanges: declaration.defaultArgumentListTextRanges,
    hasOptionalParameters: declaration.parameterNames?.isNotEmpty ?? false,
    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;
  for (var t in declaration.relevanceTags) {
    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.DartSuggestionSetCompletionItemResolutionInfo(
        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);
}

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

String getDeclarationName(Declaration declaration) {
  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;
  }
  return completion;
}

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;

/// 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) {
  final startLine = location.startLine;
  final startColumn = location.startColumn;
  final endLine = location.endLine ?? -1;
  final 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.
  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 {
    final filePath = uri.toFilePath();
    // On Windows, paths that start with \ and not a drive letter are not
    // supported but will return `true` from `path.isAbsolute` so check for them
    // specifically.
    if (Platform.isWindows && filePath.startsWith(r'\')) {
      return ErrorOr<String>.error(ResponseError(
        code: lsp.ServerErrorCodes.InvalidFilePath,
        message: 'URI was not an absolute file path (missing drive letter)',
        data: uri.toString(),
      ));
    }
    return ErrorOr<String>.success(filePath);
  } 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}';
  }

  final 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)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(),
        // 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) {
  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),
  );
}

/// 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,
}) {
  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,
    ),
  );
}

/// Creates a SnippetTextEdit for an edit with a selection placeholder.
///
/// [selectionOffset] 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,
) {
  assert(capabilities.completionSnippets);

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

  // We must only get one change for this file to be able to apply snippets.
  final thisFilesChange = changes.edits.singleWhere((e) => e.file == file);
  final 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) {
    final workspaceEdit = createPlainWorkspaceEdit(server, otherFilesChanges);
    command = Command(
        title: 'Add import',
        command: Commands.sendWorkspaceEdit,
        arguments: [workspaceEdit]);
  }

  /// Convert the changes to TextEdits using snippet tokens for linked edit
  /// groups.
  final mainFileEdits = toSnippetTextEdits(
    file,
    thisFilesChange,
    changes.linkedEditGroups,
    lineInfo,
    selectionOffset:
        changes.selection?.file == file ? changes.selection?.offset : 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).
  final mainEdit = mainFileEdits
      .firstWhere((edit) => edit.range.start.line == position.line);
  final nonMainEdits = mainFileEdits.where((edit) => edit != mainEdit).toList();

  return lsp.CompletionItem(
    label: snippet.label,
    filterText: snippet.prefix,
    kind: lsp.CompletionItemKind.Snippet,
    command: command,
    documentation: documentation != null
        ? asStringOrMarkupContent(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,
    textEdit: Either2<TextEdit, InsertReplaceEdit>.t1(mainEdit),
    additionalTextEdits: nonMainEdits,
  );
}

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, {
  Range? replacementRange,
  Range? insertionRange,
  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,
    requiredArgumentListString: suggestion.defaultArgumentListString,
    requiredArgumentListTextRanges: suggestion.defaultArgumentListTextRanges,
    hasOptionalParameters: suggestion.parameterNames?.isNotEmpty ?? false,
    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: (insertionRange == null || replacementRange == null)
        ? null
        : supportsInsertReplace && insertionRange != replacementRange
            ? Either2<TextEdit, InsertReplaceEdit>.t2(
                InsertReplaceEdit(
                  insert: insertionRange,
                  replace: replacementRange,
                  newText: insertText,
                ),
              )
            : Either2<TextEdit, InsertReplaceEdit>.t1(
                TextEdit(
                  range: replacementRange,
                  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
        ?.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) {
  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, {
  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) {
  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?.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) {
  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
  );
}

List<lsp.SnippetTextEdit> toSnippetTextEdits(
  String filePath,
  server.SourceFileEdit change,
  List<server.LinkedEditGroup> editGroups,
  LineInfo lineInfo, {
  required int? selectionOffset,
}) {
  final 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 (final edit in change.edits.reversed) {
    snippetEdits.add(snippetTextEditFromEditGroups(
      filePath,
      lineInfo,
      edit,
      editGroups: editGroups,
      editOffset: edit.offset + offsetDelta,
      selectionOffset: selectionOffset,
    ));

    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.
  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(
      snippetTextEditWithSelection(lineInfo, edit,
          selectionOffsetRelative: selectionOffsetRelative,
          selectionLength: 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? 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 (!includeCommitCharacters &&
        completeFunctionCalls &&
        isCallable &&
        isInvocation) {
      insertTextFormat = lsp.InsertTextFormat.Snippet;
      final hasRequiredParameters =
          requiredArgumentListTextRanges?.isNotEmpty ?? false;
      final 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 Pair(insertText, insertTextFormat);
}

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