summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/Protocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/Protocol.cpp')
-rw-r--r--clang-tools-extra/clangd/Protocol.cpp412
1 files changed, 412 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
new file mode 100644
index 00000000000..f87f6d0912c
--- /dev/null
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -0,0 +1,412 @@
+//===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the serialization code for the LSP structs.
+// FIXME: This is extremely repetetive and ugly. Is there a better way?
+//
+//===----------------------------------------------------------------------===//
+
+#include "Protocol.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang::clangd;
+
+llvm::Optional<TextDocumentIdentifier>
+TextDocumentIdentifier::parse(llvm::yaml::MappingNode *Params) {
+ TextDocumentIdentifier Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "uri") {
+ Result.uri = Value->getValue(Storage);
+ } else if (KeyValue == "version") {
+ // FIXME: parse version, but only for VersionedTextDocumentIdentifiers.
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<Position> Position::parse(llvm::yaml::MappingNode *Params) {
+ Position Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "line") {
+ long long Val;
+ if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
+ return llvm::None;
+ Result.line = Val;
+ } else if (KeyValue == "character") {
+ long long Val;
+ if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
+ return llvm::None;
+ Result.character = Val;
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+std::string Position::unparse(const Position &P) {
+ std::string Result;
+ llvm::raw_string_ostream(Result)
+ << llvm::format(R"({"line": %d, "character": %d})", P.line, P.character);
+ return Result;
+}
+
+llvm::Optional<Range> Range::parse(llvm::yaml::MappingNode *Params) {
+ Range Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "start") {
+ auto Parsed = Position::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.start = std::move(*Parsed);
+ } else if (KeyValue == "end") {
+ auto Parsed = Position::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.end = std::move(*Parsed);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+std::string Range::unparse(const Range &P) {
+ std::string Result;
+ llvm::raw_string_ostream(Result) << llvm::format(
+ R"({"start": %s, "end": %s})", Position::unparse(P.start).c_str(),
+ Position::unparse(P.end).c_str());
+ return Result;
+}
+
+llvm::Optional<TextDocumentItem>
+TextDocumentItem::parse(llvm::yaml::MappingNode *Params) {
+ TextDocumentItem Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "uri") {
+ Result.uri = Value->getValue(Storage);
+ } else if (KeyValue == "languageId") {
+ Result.languageId = Value->getValue(Storage);
+ } else if (KeyValue == "version") {
+ long long Val;
+ if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
+ return llvm::None;
+ Result.version = Val;
+ } else if (KeyValue == "text") {
+ Result.text = Value->getValue(Storage);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<TextEdit> TextEdit::parse(llvm::yaml::MappingNode *Params) {
+ TextEdit Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value = NextKeyValue.getValue();
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "range") {
+ auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
+ if (!Map)
+ return llvm::None;
+ auto Parsed = Range::parse(Map);
+ if (!Parsed)
+ return llvm::None;
+ Result.range = std::move(*Parsed);
+ } else if (KeyValue == "newText") {
+ auto *Node = dyn_cast<llvm::yaml::ScalarNode>(Value);
+ if (!Node)
+ return llvm::None;
+ Result.newText = Node->getValue(Storage);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+std::string TextEdit::unparse(const TextEdit &P) {
+ std::string Result;
+ llvm::raw_string_ostream(Result) << llvm::format(
+ R"({"range": %s, "newText": "%s"})", Range::unparse(P.range).c_str(),
+ llvm::yaml::escape(P.newText).c_str());
+ return Result;
+}
+
+llvm::Optional<DidOpenTextDocumentParams>
+DidOpenTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+ DidOpenTextDocumentParams Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "textDocument") {
+ auto Parsed = TextDocumentItem::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.textDocument = std::move(*Parsed);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<DidChangeTextDocumentParams>
+DidChangeTextDocumentParams::parse(llvm::yaml::MappingNode *Params) {
+ DidChangeTextDocumentParams Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value = NextKeyValue.getValue();
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "textDocument") {
+ auto *Map = dyn_cast<llvm::yaml::MappingNode>(Value);
+ if (!Map)
+ return llvm::None;
+ auto Parsed = TextDocumentIdentifier::parse(Map);
+ if (!Parsed)
+ return llvm::None;
+ Result.textDocument = std::move(*Parsed);
+ } else if (KeyValue == "contentChanges") {
+ auto *Seq = dyn_cast<llvm::yaml::SequenceNode>(Value);
+ if (!Seq)
+ return llvm::None;
+ for (auto &Item : *Seq) {
+ auto *I = dyn_cast<llvm::yaml::MappingNode>(&Item);
+ if (!I)
+ return llvm::None;
+ auto Parsed = TextDocumentContentChangeEvent::parse(I);
+ if (!Parsed)
+ return llvm::None;
+ Result.contentChanges.push_back(std::move(*Parsed));
+ }
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<TextDocumentContentChangeEvent>
+TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params) {
+ TextDocumentContentChangeEvent Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "text") {
+ Result.text = Value->getValue(Storage);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<FormattingOptions>
+FormattingOptions::parse(llvm::yaml::MappingNode *Params) {
+ FormattingOptions Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::ScalarNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "tabSize") {
+ long long Val;
+ if (llvm::getAsSignedInteger(Value->getValue(Storage), 0, Val))
+ return llvm::None;
+ Result.tabSize = Val;
+ } else if (KeyValue == "insertSpaces") {
+ long long Val;
+ StringRef Str = Value->getValue(Storage);
+ if (llvm::getAsSignedInteger(Str, 0, Val)) {
+ if (Str == "true")
+ Val = 1;
+ else if (Str == "false")
+ Val = 0;
+ else
+ return llvm::None;
+ }
+ Result.insertSpaces = Val;
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+std::string FormattingOptions::unparse(const FormattingOptions &P) {
+ std::string Result;
+ llvm::raw_string_ostream(Result) << llvm::format(
+ R"({"tabSize": %d, "insertSpaces": %d})", P.tabSize, P.insertSpaces);
+ return Result;
+}
+
+llvm::Optional<DocumentRangeFormattingParams>
+DocumentRangeFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+ DocumentRangeFormattingParams Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "textDocument") {
+ auto Parsed = TextDocumentIdentifier::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.textDocument = std::move(*Parsed);
+ } else if (KeyValue == "range") {
+ auto Parsed = Range::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.range = std::move(*Parsed);
+ } else if (KeyValue == "options") {
+ auto Parsed = FormattingOptions::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.options = std::move(*Parsed);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
+
+llvm::Optional<DocumentFormattingParams>
+DocumentFormattingParams::parse(llvm::yaml::MappingNode *Params) {
+ DocumentFormattingParams Result;
+ for (auto &NextKeyValue : *Params) {
+ auto *KeyString = dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString)
+ return llvm::None;
+
+ llvm::SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ auto *Value =
+ dyn_cast_or_null<llvm::yaml::MappingNode>(NextKeyValue.getValue());
+ if (!Value)
+ return llvm::None;
+
+ llvm::SmallString<10> Storage;
+ if (KeyValue == "textDocument") {
+ auto Parsed = TextDocumentIdentifier::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.textDocument = std::move(*Parsed);
+ } else if (KeyValue == "options") {
+ auto Parsed = FormattingOptions::parse(Value);
+ if (!Parsed)
+ return llvm::None;
+ Result.options = std::move(*Parsed);
+ } else {
+ return llvm::None;
+ }
+ }
+ return Result;
+}
OpenPOWER on IntegriCloud