summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/ProtocolHandlers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/ProtocolHandlers.cpp')
-rw-r--r--clang-tools-extra/clangd/ProtocolHandlers.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/ProtocolHandlers.cpp b/clang-tools-extra/clangd/ProtocolHandlers.cpp
new file mode 100644
index 00000000000..2fe7b89490b
--- /dev/null
+++ b/clang-tools-extra/clangd/ProtocolHandlers.cpp
@@ -0,0 +1,116 @@
+//===--- ProtocolHandlers.cpp - LSP callbacks -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProtocolHandlers.h"
+#include "DocumentStore.h"
+#include "clang/Format/Format.h"
+using namespace clang;
+using namespace clangd;
+
+void TextDocumentDidOpenHandler::handleNotification(
+ llvm::yaml::MappingNode *Params) {
+ auto DOTDP = DidOpenTextDocumentParams::parse(Params);
+ if (!DOTDP) {
+ Logs << "Failed to decode DidOpenTextDocumentParams!\n";
+ return;
+ }
+ Store.addDocument(DOTDP->textDocument.uri, DOTDP->textDocument.text);
+}
+
+void TextDocumentDidChangeHandler::handleNotification(
+ llvm::yaml::MappingNode *Params) {
+ auto DCTDP = DidChangeTextDocumentParams::parse(Params);
+ if (!DCTDP || DCTDP->contentChanges.size() != 1) {
+ Logs << "Failed to decode DidChangeTextDocumentParams!\n";
+ return;
+ }
+ // We only support full syncing right now.
+ Store.addDocument(DCTDP->textDocument.uri, DCTDP->contentChanges[0].text);
+}
+
+/// Turn a [line, column] pair into an offset in Code.
+static size_t positionToOffset(StringRef Code, Position P) {
+ size_t Offset = 0;
+ for (int I = 0; I != P.line; ++I) {
+ // FIXME: \r\n
+ // FIXME: UTF-8
+ size_t F = Code.find('\n', Offset);
+ if (F == StringRef::npos)
+ return 0; // FIXME: Is this reasonable?
+ Offset = F + 1;
+ }
+ return (Offset == 0 ? 0 : (Offset - 1)) + P.character;
+}
+
+/// Turn an offset in Code into a [line, column] pair.
+static Position offsetToPosition(StringRef Code, size_t Offset) {
+ StringRef JustBefore = Code.substr(0, Offset);
+ // FIXME: \r\n
+ // FIXME: UTF-8
+ int Lines = JustBefore.count('\n');
+ int Cols = JustBefore.size() - JustBefore.rfind('\n') - 1;
+ return {Lines, Cols};
+}
+
+static std::string formatCode(StringRef Code, StringRef Filename,
+ ArrayRef<tooling::Range> Ranges, StringRef ID) {
+ // Call clang-format.
+ // FIXME: Don't ignore style.
+ format::FormatStyle Style = format::getLLVMStyle();
+ tooling::Replacements Replacements =
+ format::reformat(Style, Code, Ranges, Filename);
+
+ // Now turn the replacements into the format specified by the Language Server
+ // Protocol. Fuse them into one big JSON array.
+ std::string Edits;
+ for (auto &R : Replacements) {
+ Range ReplacementRange = {
+ offsetToPosition(Code, R.getOffset()),
+ offsetToPosition(Code, R.getOffset() + R.getLength())};
+ TextEdit TE = {ReplacementRange, R.getReplacementText()};
+ Edits += TextEdit::unparse(TE);
+ Edits += ',';
+ }
+ if (!Edits.empty())
+ Edits.pop_back();
+
+ return R"({"jsonrpc":"2.0","id":)" + ID.str() +
+ R"(,"result":[)" + Edits + R"(]})";
+}
+
+void TextDocumentRangeFormattingHandler::handleMethod(
+ llvm::yaml::MappingNode *Params, StringRef ID) {
+ auto DRFP = DocumentRangeFormattingParams::parse(Params);
+ if (!DRFP) {
+ Logs << "Failed to decode DocumentRangeFormattingParams!\n";
+ return;
+ }
+
+ StringRef Code = Store.getDocument(DRFP->textDocument.uri);
+
+ size_t Begin = positionToOffset(Code, DRFP->range.start);
+ size_t Len = positionToOffset(Code, DRFP->range.end) - Begin;
+
+ writeMessage(formatCode(Code, DRFP->textDocument.uri,
+ {clang::tooling::Range(Begin, Len)}, ID));
+}
+
+void TextDocumentFormattingHandler::handleMethod(
+ llvm::yaml::MappingNode *Params, StringRef ID) {
+ auto DFP = DocumentFormattingParams::parse(Params);
+ if (!DFP) {
+ Logs << "Failed to decode DocumentFormattingParams!\n";
+ return;
+ }
+
+ // Format everything.
+ StringRef Code = Store.getDocument(DFP->textDocument.uri);
+ writeMessage(formatCode(Code, DFP->textDocument.uri,
+ {clang::tooling::Range(0, Code.size())}, ID));
+}
OpenPOWER on IntegriCloud