llvm/clang-tools-extra/clangd/ClangdLSPServer.cpp

//===--- ClangdLSPServer.cpp - LSP server ------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ClangdLSPServer.h"
#include "ClangdServer.h"
#include "CodeComplete.h"
#include "CompileCommands.h"
#include "Diagnostics.h"
#include "Feature.h"
#include "GlobalCompilationDatabase.h"
#include "LSPBinder.h"
#include "ModulesBuilder.h"
#include "Protocol.h"
#include "SemanticHighlighting.h"
#include "SourceCode.h"
#include "TUScheduler.h"
#include "URI.h"
#include "refactor/Tweak.h"
#include "support/Cancellation.h"
#include "support/Context.h"
#include "support/MemoryTree.h"
#include "support/Trace.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace clang {
namespace clangd {

namespace {
// Tracks end-to-end latency of high level lsp calls. Measurements are in
// seconds.
constexpr trace::Metric LSPLatency("lsp_latency", trace::Metric::Distribution,
                                   "method_name");

// LSP defines file versions as numbers that increase.
// ClangdServer treats them as opaque and therefore uses strings instead.
std::string encodeVersion(std::optional<int64_t> LSPVersion) {}
std::optional<int64_t> decodeVersion(llvm::StringRef Encoded) {}

const llvm::StringLiteral ApplyFixCommand =;
const llvm::StringLiteral ApplyTweakCommand =;
const llvm::StringLiteral ApplyRenameCommand =;

CodeAction toCodeAction(const ClangdServer::CodeActionResult::Rename &R,
                        const URIForFile &File) {}

/// Transforms a tweak into a code action that would apply it if executed.
/// EXPECTS: T.prepare() was called and returned true.
CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File,
                        Range Selection) {}

/// Convert from Fix to LSP CodeAction.
CodeAction toCodeAction(const Fix &F, const URIForFile &File,
                        const std::optional<int64_t> &Version,
                        bool SupportsDocumentChanges,
                        bool SupportChangeAnnotation) {}

void adjustSymbolKinds(llvm::MutableArrayRef<DocumentSymbol> Syms,
                       SymbolKindBitset Kinds) {}

SymbolKindBitset defaultSymbolKinds() {}

CompletionItemKindBitset defaultCompletionItemKinds() {}

// Makes sure edits in \p FE are applicable to latest file contents reported by
// editor. If not generates an error message containing information about files
// that needs to be saved.
llvm::Error validateEdits(const ClangdServer &Server, const FileEdits &FE) {}
} // namespace

// MessageHandler dispatches incoming LSP messages.
// It handles cross-cutting concerns:
//  - serializes/deserializes protocol objects to JSON
//  - logging of inbound messages
//  - cancellation handling
//  - basic call tracing
// MessageHandler ensures that initialize() is called before any other handler.
class ClangdLSPServer::MessageHandler : public Transport::MessageHandler {};
constexpr int ClangdLSPServer::MessageHandler::MaxReplayCallbacks;

// call(), notify(), and reply() wrap the Transport, adding logging and locking.
void ClangdLSPServer::callMethod(StringRef Method, llvm::json::Value Params,
                                 Callback<llvm::json::Value> CB) {}

void ClangdLSPServer::notify(llvm::StringRef Method, llvm::json::Value Params) {}

static std::vector<llvm::StringRef> semanticTokenTypes() {}

static std::vector<llvm::StringRef> semanticTokenModifiers() {}

void ClangdLSPServer::onInitialize(const InitializeParams &Params,
                                   Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onInitialized(const InitializedParams &Params) {}

void ClangdLSPServer::onShutdown(const NoParams &,
                                 Callback<std::nullptr_t> Reply) {}

// sync is a clangd extension: it blocks until all background work completes.
// It blocks the calling thread, so no messages are processed until it returns!
void ClangdLSPServer::onSync(const NoParams &, Callback<std::nullptr_t> Reply) {}

void ClangdLSPServer::onDocumentDidOpen(
    const DidOpenTextDocumentParams &Params) {}

void ClangdLSPServer::onDocumentDidChange(
    const DidChangeTextDocumentParams &Params) {}

void ClangdLSPServer::onDocumentDidSave(
    const DidSaveTextDocumentParams &Params) {}

void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {}

void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params,
                                Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onCommandApplyEdit(const WorkspaceEdit &WE,
                                         Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onCommandApplyTweak(const TweakArgs &Args,
                                          Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onCommandApplyRename(const RenameParams &R,
                                           Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::applyEdit(WorkspaceEdit WE, llvm::json::Value Success,
                                Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onWorkspaceSymbol(
    const WorkspaceSymbolParams &Params,
    Callback<std::vector<SymbolInformation>> Reply) {}

void ClangdLSPServer::onPrepareRename(const TextDocumentPositionParams &Params,
                                      Callback<PrepareRenameResult> Reply) {}

void ClangdLSPServer::onRename(const RenameParams &Params,
                               Callback<WorkspaceEdit> Reply) {}

void ClangdLSPServer::onDocumentDidClose(
    const DidCloseTextDocumentParams &Params) {}

void ClangdLSPServer::onDocumentOnTypeFormatting(
    const DocumentOnTypeFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {}

void ClangdLSPServer::onDocumentRangeFormatting(
    const DocumentRangeFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {}

void ClangdLSPServer::onDocumentFormatting(
    const DocumentFormattingParams &Params,
    Callback<std::vector<TextEdit>> Reply) {}

/// The functions constructs a flattened view of the DocumentSymbol hierarchy.
/// Used by the clients that do not support the hierarchical view.
static std::vector<SymbolInformation>
flattenSymbolHierarchy(llvm::ArrayRef<DocumentSymbol> Symbols,
                       const URIForFile &FileURI) {}

void ClangdLSPServer::onDocumentSymbol(const DocumentSymbolParams &Params,
                                       Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onFoldingRange(
    const FoldingRangeParams &Params,
    Callback<std::vector<FoldingRange>> Reply) {}

static std::optional<Command> asCommand(const CodeAction &Action) {}

void ClangdLSPServer::onCodeAction(const CodeActionParams &Params,
                                   Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onCompletion(const CompletionParams &Params,
                                   Callback<CompletionList> Reply) {}

void ClangdLSPServer::onSignatureHelp(const TextDocumentPositionParams &Params,
                                      Callback<SignatureHelp> Reply) {}

// Go to definition has a toggle function: if def and decl are distinct, then
// the first press gives you the def, the second gives you the matching def.
// getToggle() returns the counterpart location that under the cursor.
//
// We return the toggled location alone (ignoring other symbols) to encourage
// editors to "bounce" quickly between locations, without showing a menu.
static Location *getToggle(const TextDocumentPositionParams &Point,
                           LocatedSymbol &Sym) {}

void ClangdLSPServer::onGoToDefinition(const TextDocumentPositionParams &Params,
                                       Callback<std::vector<Location>> Reply) {}

void ClangdLSPServer::onGoToDeclaration(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<Location>> Reply) {}

void ClangdLSPServer::onSwitchSourceHeader(
    const TextDocumentIdentifier &Params,
    Callback<std::optional<URIForFile>> Reply) {}

void ClangdLSPServer::onDocumentHighlight(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<DocumentHighlight>> Reply) {}

void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params,
                              Callback<std::optional<Hover>> Reply) {}

// Our extension has a different representation on the wire than the standard.
// https://clangd.llvm.org/extensions#type-hierarchy
llvm::json::Value serializeTHIForExtension(TypeHierarchyItem THI) {}

void ClangdLSPServer::onTypeHierarchy(const TypeHierarchyPrepareParams &Params,
                                      Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onResolveTypeHierarchy(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onPrepareTypeHierarchy(
    const TypeHierarchyPrepareParams &Params,
    Callback<std::vector<TypeHierarchyItem>> Reply) {}

void ClangdLSPServer::onSuperTypes(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<std::optional<std::vector<TypeHierarchyItem>>> Reply) {}

void ClangdLSPServer::onSubTypes(
    const ResolveTypeHierarchyItemParams &Params,
    Callback<std::vector<TypeHierarchyItem>> Reply) {}

void ClangdLSPServer::onPrepareCallHierarchy(
    const CallHierarchyPrepareParams &Params,
    Callback<std::vector<CallHierarchyItem>> Reply) {}

void ClangdLSPServer::onCallHierarchyIncomingCalls(
    const CallHierarchyIncomingCallsParams &Params,
    Callback<std::vector<CallHierarchyIncomingCall>> Reply) {}

void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params,
                                         Callback<llvm::json::Value> Reply) {}

void ClangdLSPServer::onInlayHint(const InlayHintsParams &Params,
                                  Callback<std::vector<InlayHint>> Reply) {}

void ClangdLSPServer::applyConfiguration(
    const ConfigurationSettings &Settings) {}

void ClangdLSPServer::maybeExportMemoryProfile() {}

void ClangdLSPServer::maybeCleanupMemory() {}

// FIXME: This function needs to be properly tested.
void ClangdLSPServer::onChangeConfiguration(
    const DidChangeConfigurationParams &Params) {}

void ClangdLSPServer::onReference(
    const ReferenceParams &Params,
    Callback<std::vector<ReferenceLocation>> Reply) {}

void ClangdLSPServer::onGoToType(const TextDocumentPositionParams &Params,
                                 Callback<std::vector<Location>> Reply) {}

void ClangdLSPServer::onGoToImplementation(
    const TextDocumentPositionParams &Params,
    Callback<std::vector<Location>> Reply) {}

void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
                                   Callback<std::vector<SymbolDetails>> Reply) {}

void ClangdLSPServer::onSelectionRange(
    const SelectionRangeParams &Params,
    Callback<std::vector<SelectionRange>> Reply) {}

void ClangdLSPServer::onDocumentLink(
    const DocumentLinkParams &Params,
    Callback<std::vector<DocumentLink>> Reply) {}

// Increment a numeric string: "" -> 1 -> 2 -> ... -> 9 -> 10 -> 11 ...
static void increment(std::string &S) {}

void ClangdLSPServer::onSemanticTokens(const SemanticTokensParams &Params,
                                       Callback<SemanticTokens> CB) {}

void ClangdLSPServer::onSemanticTokensDelta(
    const SemanticTokensDeltaParams &Params,
    Callback<SemanticTokensOrDelta> CB) {}

void ClangdLSPServer::onMemoryUsage(const NoParams &,
                                    Callback<MemoryTree> Reply) {}

void ClangdLSPServer::onAST(const ASTParams &Params,
                            Callback<std::optional<ASTNode>> CB) {}

ClangdLSPServer::ClangdLSPServer(Transport &Transp, const ThreadsafeFS &TFS,
                                 const ClangdLSPServer::Options &Opts)
    :{}

void ClangdLSPServer::bindMethods(LSPBinder &Bind,
                                  const ClientCapabilities &Caps) {}

ClangdLSPServer::~ClangdLSPServer() {}

bool ClangdLSPServer::run() {}

void ClangdLSPServer::profile(MemoryTree &MT) const {}

std::optional<ClangdServer::DiagRef>
ClangdLSPServer::getDiagRef(StringRef File, const clangd::Diagnostic &D) {}

// A completion request is sent when the user types '>' or ':', but we only
// want to trigger on '->' and '::'. We check the preceding text to make
// sure it matches what we expected.
// Running the lexer here would be more robust (e.g. we can detect comments
// and avoid triggering completion there), but we choose to err on the side
// of simplicity here.
bool ClangdLSPServer::shouldRunCompletion(
    const CompletionParams &Params) const {}

void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version,
                                         llvm::ArrayRef<Diag> Diagnostics) {}

void ClangdLSPServer::onInactiveRegionsReady(
    PathRef File, std::vector<Range> InactiveRegions) {}

void ClangdLSPServer::onBackgroundIndexProgress(
    const BackgroundQueue::Stats &Stats) {}

void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) {}

void ClangdLSPServer::onSemanticsMaybeChanged(PathRef File) {}

} // namespace clangd
} // namespace clang