diff options
Diffstat (limited to 'clang-tools-extra/clangd/ClangDMain.cpp')
| -rw-r--r-- | clang-tools-extra/clangd/ClangDMain.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/ClangDMain.cpp b/clang-tools-extra/clangd/ClangDMain.cpp new file mode 100644 index 00000000000..e851ea77d51 --- /dev/null +++ b/clang-tools-extra/clangd/ClangDMain.cpp @@ -0,0 +1,86 @@ +//===--- ClangDMain.cpp - clangd server loop ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DocumentStore.h" +#include "JSONRPCDispatcher.h" +#include "ProtocolHandlers.h" +#include "llvm/Support/FileSystem.h" +#include <iostream> +#include <string> +using namespace clang::clangd; + +int main(int argc, char *argv[]) { + llvm::raw_ostream &Outs = llvm::outs(); + llvm::raw_ostream &Logs = llvm::errs(); + + // Set up a document store and intialize all the method handlers for JSONRPC + // dispatching. + DocumentStore Store; + JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Outs, Logs)); + Dispatcher.registerHandler("initialize", + llvm::make_unique<InitializeHandler>(Outs, Logs)); + Dispatcher.registerHandler("shutdown", + llvm::make_unique<ShutdownHandler>(Outs, Logs)); + Dispatcher.registerHandler( + "textDocument/didOpen", + llvm::make_unique<TextDocumentDidOpenHandler>(Outs, Logs, Store)); + // FIXME: Implement textDocument/didClose. + Dispatcher.registerHandler( + "textDocument/didChange", + llvm::make_unique<TextDocumentDidChangeHandler>(Outs, Logs, Store)); + Dispatcher.registerHandler( + "textDocument/rangeFormatting", + llvm::make_unique<TextDocumentRangeFormattingHandler>(Outs, Logs, Store)); + Dispatcher.registerHandler( + "textDocument/formatting", + llvm::make_unique<TextDocumentFormattingHandler>(Outs, Logs, Store)); + + while (std::cin.good()) { + // A Language Server Protocol message starts with a HTTP header, delimited + // by \r\n. + std::string Line; + std::getline(std::cin, Line); + + // Skip empty lines. + llvm::StringRef LineRef(Line); + if (LineRef.trim().empty()) + continue; + + unsigned long long Len = 0; + // FIXME: Content-Type is a specified header, but does nothing. + // Content-Length is a mandatory header. It specifies the length of the + // following JSON. + if (LineRef.consume_front("Content-Length: ")) + llvm::getAsUnsignedInteger(LineRef.trim(), 0, Len); + + // Check if the next line only contains \r\n. If not this is another header, + // which we ignore. + char NewlineBuf[2]; + std::cin.read(NewlineBuf, 2); + if (std::memcmp(NewlineBuf, "\r\n", 2) != 0) + continue; + + // Now read the JSON. Insert a trailing null byte as required by the YAML + // parser. + std::vector<char> JSON(Len + 1); + std::cin.read(JSON.data(), Len); + + if (Len > 0) { + // Log the message. + Logs << "<-- "; + Logs.write(JSON.data(), JSON.size()); + Logs << '\n'; + Logs.flush(); + + // Finally, execute the action for this JSON message. + if (!Dispatcher.call(llvm::StringRef(JSON.data(), JSON.size() - 1))) + Logs << "JSON dispatch failed!\n"; + } + } +} |

