Skip to content

Commit 02a1c46

Browse files
committed
[clangd] Implement LSP 3.17 positionEncoding
1 parent 7efc861 commit 02a1c46

File tree

4 files changed

+54
-8
lines changed

4 files changed

+54
-8
lines changed

clang-tools-extra/clangd/ClangdLSPServer.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,9 @@ static std::vector<llvm::StringRef> semanticTokenModifiers() {
494494
void ClangdLSPServer::onInitialize(const InitializeParams &Params,
495495
Callback<llvm::json::Value> Reply) {
496496
// Determine character encoding first as it affects constructed ClangdServer.
497-
if (Params.capabilities.offsetEncoding && !Opts.Encoding) {
497+
if (Params.capabilities.PositionEncodings && !Opts.Encoding) {
498498
Opts.Encoding = OffsetEncoding::UTF16; // fallback
499-
for (OffsetEncoding Supported : *Params.capabilities.offsetEncoding)
499+
for (OffsetEncoding Supported : *Params.capabilities.PositionEncodings)
500500
if (Supported != OffsetEncoding::UnsupportedEncoding) {
501501
Opts.Encoding = Supported;
502502
break;
@@ -686,6 +686,9 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
686686
ServerCaps["executeCommandProvider"] =
687687
llvm::json::Object{{"commands", Commands}};
688688

689+
if (Opts.Encoding && Params.capabilities.PositionEncodings)
690+
ServerCaps["positionEncoding"] = *Opts.Encoding;
691+
689692
llvm::json::Object Result{
690693
{{"serverInfo",
691694
llvm::json::Object{

clang-tools-extra/clangd/Protocol.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,10 +497,18 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
497497
if (auto Cancel = StaleRequestSupport->getBoolean("cancel"))
498498
R.CancelsStaleRequests = *Cancel;
499499
}
500+
if (auto *PositionEncodings = General->get("positionEncodings")) {
501+
R.PositionEncodings.emplace();
502+
if (!fromJSON(*PositionEncodings, *R.PositionEncodings,
503+
P.field("general").field("positionEncodings")))
504+
return false;
505+
}
500506
}
501507
if (auto *OffsetEncoding = O->get("offsetEncoding")) {
502-
R.offsetEncoding.emplace();
503-
if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
508+
R.PositionEncodings.emplace();
509+
elog("UTF-8 offsets extension is used to set PositionEncodings, which is "
510+
"deprecated. Migrate to standard positionEncodings request");
511+
if (!fromJSON(*OffsetEncoding, *R.PositionEncodings,
504512
P.field("offsetEncoding")))
505513
return false;
506514
}
@@ -536,8 +544,10 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
536544
}
537545
}
538546
if (auto *OffsetEncoding = Experimental->get("offsetEncoding")) {
539-
R.offsetEncoding.emplace();
540-
if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
547+
R.PositionEncodings.emplace();
548+
elog("UTF-8 offsets extension is used to set PositionEncodings, which is "
549+
"deprecated. Migrate to standard positionEncodings request");
550+
if (!fromJSON(*OffsetEncoding, *R.PositionEncodings,
541551
P.field("offsetEncoding")))
542552
return false;
543553
}

clang-tools-extra/clangd/Protocol.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,9 @@ struct ClientCapabilities {
528528
/// textDocument.semanticHighlightingCapabilities.semanticHighlighting
529529
bool TheiaSemanticHighlighting = false;
530530

531-
/// Supported encodings for LSP character offsets. (clangd extension).
532-
std::optional<std::vector<OffsetEncoding>> offsetEncoding;
531+
/// Supported encodings for LSP character offsets.
532+
/// general.PositionEncodings
533+
std::optional<std::vector<OffsetEncoding>> PositionEncodings;
533534

534535
/// The content format that should be used for Hover requests.
535536
/// textDocument.hover.contentEncoding
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
2+
# This test verifies that we can negotiate UTF-8 offsets via the positionEncodings capability introduced in LSP 3.17.
3+
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"general":{"positionEncodings":["utf-8","utf-16"]}},"trace":"off"}}
4+
# CHECK: "positionEncoding": "utf-8"
5+
---
6+
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"/*ö*/int x;\nint y=x;"}}}
7+
---
8+
{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":6}}}
9+
# /*ö*/int x;
10+
# 01234567890
11+
# x is character (and utf-16) range [9,10) but byte range [10,11).
12+
# CHECK: "id": 1,
13+
# CHECK-NEXT: "jsonrpc": "2.0",
14+
# CHECK-NEXT: "result": [
15+
# CHECK-NEXT: {
16+
# CHECK-NEXT: "range": {
17+
# CHECK-NEXT: "end": {
18+
# CHECK-NEXT: "character": 11,
19+
# CHECK-NEXT: "line": 0
20+
# CHECK-NEXT: },
21+
# CHECK-NEXT: "start": {
22+
# CHECK-NEXT: "character": 10,
23+
# CHECK-NEXT: "line": 0
24+
# CHECK-NEXT: }
25+
# CHECK-NEXT: },
26+
# CHECK-NEXT: "uri": "file://{{.*}}/main.cpp"
27+
# CHECK-NEXT: }
28+
# CHECK-NEXT: ]
29+
---
30+
{"jsonrpc":"2.0","id":10000,"method":"shutdown"}
31+
---
32+
{"jsonrpc":"2.0","method":"exit"}

0 commit comments

Comments
 (0)