usaxena95 created this revision. usaxena95 added a reviewer: hokein. Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang.
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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D67720 Files: clang-tools-extra/clangd/ClangdLSPServer.cpp clang-tools-extra/clangd/ClangdLSPServer.h clang-tools-extra/clangd/Protocol.cpp clang-tools-extra/clangd/Protocol.h clang-tools-extra/clangd/test/selection-range.test
Index: clang-tools-extra/clangd/test/selection-range.test =================================================================== --- /dev/null +++ clang-tools-extra/clangd/test/selection-range.test @@ -0,0 +1,74 @@ +# 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 int var1;\n int var2 = var1;\n}"}}} +--- +{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":2,"character":14}]}} +# CHECK: "id": 1 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parent": { +# CHECK-NEXT: "parent": { +# CHECK-NEXT: "parent": { +# CHECK-NEXT: "parent": { +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 1, +# CHECK-NEXT: "line": 3 +# 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": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 12, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 17, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 1, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 16, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 1, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 16, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 12, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +--- +{"jsonrpc":"2.0","id":3,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} Index: clang-tools-extra/clangd/Protocol.h =================================================================== --- clang-tools-extra/clangd/Protocol.h +++ clang-tools-extra/clangd/Protocol.h @@ -1222,6 +1222,24 @@ }; 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 semantic ranges for a position. + // Any range must contain all the previous ranges. ranges.front() must be the + // inner most range. ranges.back() must be the outermost range. + std::vector<Range> ranges; +}; +llvm::json::Value toJSON(const SelectionRange &); +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SelectionRange &); + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/Protocol.cpp =================================================================== --- clang-tools-extra/clangd/Protocol.cpp +++ clang-tools-extra/clangd/Protocol.cpp @@ -15,7 +15,9 @@ #include "URI.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" @@ -1073,5 +1075,27 @@ }; } +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) { + llvm::json::Object Result; + for (const auto &R : llvm::reverse(Out.ranges)) { + llvm::json::Object Head; + Head["range"] = R; + if (!Result.empty()) + Head["parent"] = std::move(Result); + Result = std::move(Head); + } + return Result; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SelectionRange &R) { + return OS << toJSON(R); +} + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/ClangdLSPServer.h =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.h +++ clang-tools-extra/clangd/ClangdLSPServer.h @@ -107,6 +107,8 @@ 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); Index: clang-tools-extra/clangd/ClangdLSPServer.cpp =================================================================== --- clang-tools-extra/clangd/ClangdLSPServer.cpp +++ clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -1125,6 +1125,29 @@ 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()); + Reply(llvm::make_error<LSPError>("failed to decode request", + 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()); + } + SelectionRange Result; + Result.ranges = std::move(*Ranges); + Reply(std::vector<SelectionRange>{Result}); + }); +} + ClangdLSPServer::ClangdLSPServer( class Transport &Transp, const FileSystemProvider &FSProvider, const clangd::CodeCompleteOptions &CCOpts, @@ -1167,6 +1190,7 @@ 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 }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits