summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUtkarsh Saxena <usx@google.com>2019-09-24 13:38:33 +0000
committerUtkarsh Saxena <usx@google.com>2019-09-24 13:38:33 +0000
commit55925da4c98b3ddac0f28ccc322e8ee52553e022 (patch)
tree5bd9e806a55853ac2b3b1b89b8e68e1fae250ecc
parent3a415c20ad72f061c38282a49349c6ea31105ff2 (diff)
downloadbcm5719-llvm-55925da4c98b3ddac0f28ccc322e8ee52553e022.tar.gz
bcm5719-llvm-55925da4c98b3ddac0f28ccc322e8ee52553e022.zip
[clangd] Add semantic selection to ClangdLSPServer.
Summary: This adds semantic selection to the LSP Server. Adds support for serialization of input request and the output reply. Also adds regression tests for the feature. Currently we do not support multi cursor.The LSP Server only accepts single position in the request as opposed to many position in the spec. Spec: https://github.com/microsoft/language-server-protocol/blob/dbaeumer/3.15/specification.md#textDocument_selectionRange Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67720 llvm-svn: 372753
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp45
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.h2
-rw-r--r--clang-tools-extra/clangd/Protocol.cpp13
-rw-r--r--clang-tools-extra/clangd/Protocol.h23
-rw-r--r--clang-tools-extra/clangd/test/initialize-params.test1
-rw-r--r--clang-tools-extra/clangd/test/selection-range.test39
6 files changed, 123 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 0930c80da06..fd5b3444f34 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -22,14 +22,18 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/ScopedPrinter.h"
#include <cstddef>
+#include <memory>
#include <string>
+#include <vector>
namespace clang {
namespace clangd {
@@ -127,6 +131,21 @@ llvm::Error validateEdits(const DraftStore &DraftMgr, const Tweak::Effect &E) {
llvm::to_string(InvalidFileCount - 1) + " others)");
}
+// Converts a list of Ranges to a LinkedList of SelectionRange.
+SelectionRange render(const std::vector<Range> &Ranges) {
+ if (Ranges.empty())
+ return {};
+ SelectionRange Result;
+ Result.range = Ranges[0];
+ auto *Next = &Result.parent;
+ for (const auto &R : llvm::make_range(Ranges.begin() + 1, Ranges.end())) {
+ *Next = std::make_unique<SelectionRange>();
+ Next->get()->range = R;
+ Next = &Next->get()->parent;
+ }
+ return Result;
+}
+
} // namespace
// MessageHandler dispatches incoming LSP messages.
@@ -536,6 +555,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
{"documentHighlightProvider", true},
{"hoverProvider", true},
{"renameProvider", std::move(RenameProvider)},
+ {"selectionRangeProvider", true},
{"documentSymbolProvider", true},
{"workspaceSymbolProvider", true},
{"referencesProvider", true},
@@ -1125,6 +1145,30 @@ void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
std::move(Reply));
}
+void ClangdLSPServer::onSelectionRange(
+ const SelectionRangeParams &Params,
+ Callback<std::vector<SelectionRange>> Reply) {
+ if (Params.positions.size() != 1) {
+ elog("{0} positions provided to SelectionRange. Supports exactly one "
+ "position.",
+ Params.positions.size());
+ return Reply(llvm::make_error<LSPError>(
+ "SelectionRange supports exactly one position",
+ ErrorCode::InvalidRequest));
+ }
+ Server->semanticRanges(
+ Params.textDocument.uri.file(), Params.positions[0],
+ [Reply = std::move(Reply)](
+ llvm::Expected<std::vector<Range>> Ranges) mutable {
+ if (!Ranges) {
+ return Reply(Ranges.takeError());
+ }
+ std::vector<SelectionRange> Result;
+ Result.emplace_back(render(std::move(*Ranges)));
+ return Reply(std::move(Result));
+ });
+}
+
ClangdLSPServer::ClangdLSPServer(
class Transport &Transp, const FileSystemProvider &FSProvider,
const clangd::CodeCompleteOptions &CCOpts,
@@ -1167,6 +1211,7 @@ ClangdLSPServer::ClangdLSPServer(
MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo);
MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy);
MsgHandler->bind("typeHierarchy/resolve", &ClangdLSPServer::onResolveTypeHierarchy);
+ MsgHandler->bind("textDocument/selectionRange", &ClangdLSPServer::onSelectionRange);
// clang-format on
}
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index 4e7e042bb9a..3f9f1cc9c90 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -107,6 +107,8 @@ private:
void onChangeConfiguration(const DidChangeConfigurationParams &);
void onSymbolInfo(const TextDocumentPositionParams &,
Callback<std::vector<SymbolDetails>>);
+ void onSelectionRange(const SelectionRangeParams &,
+ Callback<std::vector<SelectionRange>>);
std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index fb1481da5b5..9b0fbc5b2f3 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -1073,5 +1073,18 @@ llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting) {
};
}
+bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
+ llvm::json::ObjectMapper O(Params);
+ return O && O.map("textDocument", P.textDocument) &&
+ O.map("positions", P.positions);
+}
+
+llvm::json::Value toJSON(const SelectionRange &Out) {
+ if (Out.parent) {
+ return llvm::json::Object{{"range", Out.range},
+ {"parent", toJSON(*Out.parent)}};
+ }
+ return llvm::json::Object{{"range", Out.range}};
+}
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index d244febfce4..6540365dccd 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -30,6 +30,7 @@
#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"
#include <bitset>
+#include <memory>
#include <string>
#include <vector>
@@ -1222,6 +1223,28 @@ struct SemanticHighlightingParams {
};
llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
+struct SelectionRangeParams {
+ /// The text document.
+ TextDocumentIdentifier textDocument;
+
+ /// The positions inside the text document.
+ std::vector<Position> positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+ /**
+ * The range of this selection range.
+ */
+ Range range;
+ /**
+ * The parent selection range containing this range. Therefore `parent.range`
+ * must contain `this.range`.
+ */
+ std::unique_ptr<SelectionRange> parent;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test
index 10a354b27ce..8a853b7c622 100644
--- a/clang-tools-extra/clangd/test/initialize-params.test
+++ b/clang-tools-extra/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
# CHECK-NEXT: "hoverProvider": true,
# CHECK-NEXT: "referencesProvider": true,
# CHECK-NEXT: "renameProvider": true,
+# CHECK-NEXT: "selectionRangeProvider": true,
# CHECK-NEXT: "signatureHelpProvider": {
# CHECK-NEXT: "triggerCharacters": [
# CHECK-NEXT: "(",
diff --git a/clang-tools-extra/clangd/test/selection-range.test b/clang-tools-extra/clangd/test/selection-range.test
new file mode 100644
index 00000000000..e7ff14a678f
--- /dev/null
+++ b/clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+# CHECK: "id": 1
+# CHECK-NEXT: "jsonrpc": "2.0",
+# CHECK-NEXT: "result": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "parent": {
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 1,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 0,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 1,
+# CHECK-NEXT: "line": 1
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 12,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
OpenPOWER on IntegriCloud