Skip to content

Commit d7a498d

Browse files
committed
[clangd] Add support for textDocument/rangesFormatting
As part of the upcoming 3.18 spec: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#documentRangesFormattingParams Issue: clangd/clangd#1635 Differential Revision: https://reviews.llvm.org/D150852
1 parent 837cde8 commit d7a498d

File tree

10 files changed

+65
-23
lines changed

10 files changed

+65
-23
lines changed

clang-tools-extra/clangd/ClangdLSPServer.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,10 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
566566
{"save", true},
567567
}},
568568
{"documentFormattingProvider", true},
569-
{"documentRangeFormattingProvider", true},
569+
{"documentRangeFormattingProvider",
570+
llvm::json::Object{
571+
{"rangesSupport", true},
572+
}},
570573
{"documentOnTypeFormattingProvider",
571574
llvm::json::Object{
572575
{"firstTriggerCharacter", "\n"},
@@ -914,9 +917,17 @@ void ClangdLSPServer::onDocumentOnTypeFormatting(
914917
void ClangdLSPServer::onDocumentRangeFormatting(
915918
const DocumentRangeFormattingParams &Params,
916919
Callback<std::vector<TextEdit>> Reply) {
920+
onDocumentRangesFormatting(
921+
DocumentRangesFormattingParams{Params.textDocument, {Params.range}},
922+
std::move(Reply));
923+
}
924+
925+
void ClangdLSPServer::onDocumentRangesFormatting(
926+
const DocumentRangesFormattingParams &Params,
927+
Callback<std::vector<TextEdit>> Reply) {
917928
auto File = Params.textDocument.uri.file();
918929
auto Code = Server->getDraft(File);
919-
Server->formatFile(File, Params.range,
930+
Server->formatFile(File, Params.ranges,
920931
[Code = std::move(Code), Reply = std::move(Reply)](
921932
llvm::Expected<tooling::Replacements> Result) mutable {
922933
if (Result)
@@ -932,7 +943,7 @@ void ClangdLSPServer::onDocumentFormatting(
932943
auto File = Params.textDocument.uri.file();
933944
auto Code = Server->getDraft(File);
934945
Server->formatFile(File,
935-
/*Rng=*/std::nullopt,
946+
/*Rngs=*/{},
936947
[Code = std::move(Code), Reply = std::move(Reply)](
937948
llvm::Expected<tooling::Replacements> Result) mutable {
938949
if (Result)
@@ -1621,6 +1632,7 @@ void ClangdLSPServer::bindMethods(LSPBinder &Bind,
16211632
Bind.method("shutdown", this, &ClangdLSPServer::onShutdown);
16221633
Bind.method("sync", this, &ClangdLSPServer::onSync);
16231634
Bind.method("textDocument/rangeFormatting", this, &ClangdLSPServer::onDocumentRangeFormatting);
1635+
Bind.method("textDocument/rangesFormatting", this, &ClangdLSPServer::onDocumentRangesFormatting);
16241636
Bind.method("textDocument/onTypeFormatting", this, &ClangdLSPServer::onDocumentOnTypeFormatting);
16251637
Bind.method("textDocument/formatting", this, &ClangdLSPServer::onDocumentFormatting);
16261638
Bind.method("textDocument/codeAction", this, &ClangdLSPServer::onCodeAction);

clang-tools-extra/clangd/ClangdLSPServer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class ClangdLSPServer : private ClangdServer::Callbacks,
104104
Callback<std::vector<TextEdit>>);
105105
void onDocumentRangeFormatting(const DocumentRangeFormattingParams &,
106106
Callback<std::vector<TextEdit>>);
107+
void onDocumentRangesFormatting(const DocumentRangesFormattingParams &,
108+
Callback<std::vector<TextEdit>>);
107109
void onDocumentFormatting(const DocumentFormattingParams &,
108110
Callback<std::vector<TextEdit>>);
109111
// The results are serialized 'vector<DocumentSymbol>' if

clang-tools-extra/clangd/ClangdServer.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -500,29 +500,32 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
500500
std::move(Action));
501501
}
502502

503-
void ClangdServer::formatFile(PathRef File, std::optional<Range> Rng,
503+
void ClangdServer::formatFile(PathRef File, const std::vector<Range> &Rngs,
504504
Callback<tooling::Replacements> CB) {
505505
auto Code = getDraft(File);
506506
if (!Code)
507507
return CB(llvm::make_error<LSPError>("trying to format non-added document",
508508
ErrorCode::InvalidParams));
509-
tooling::Range RequestedRange;
510-
if (Rng) {
511-
llvm::Expected<size_t> Begin = positionToOffset(*Code, Rng->start);
512-
if (!Begin)
513-
return CB(Begin.takeError());
514-
llvm::Expected<size_t> End = positionToOffset(*Code, Rng->end);
515-
if (!End)
516-
return CB(End.takeError());
517-
RequestedRange = tooling::Range(*Begin, *End - *Begin);
509+
std::vector<tooling::Range> RequestedRanges;
510+
if (!Rngs.empty()) {
511+
RequestedRanges.reserve(Rngs.size());
512+
for (const auto &Rng : Rngs) {
513+
llvm::Expected<size_t> Begin = positionToOffset(*Code, Rng.start);
514+
if (!Begin)
515+
return CB(Begin.takeError());
516+
llvm::Expected<size_t> End = positionToOffset(*Code, Rng.end);
517+
if (!End)
518+
return CB(End.takeError());
519+
RequestedRanges.emplace_back(*Begin, *End - *Begin);
520+
}
518521
} else {
519-
RequestedRange = tooling::Range(0, Code->size());
522+
RequestedRanges = {tooling::Range(0, Code->size())};
520523
}
521524

522525
// Call clang-format.
523526
auto Action = [File = File.str(), Code = std::move(*Code),
524-
Ranges = std::vector<tooling::Range>{RequestedRange},
525-
CB = std::move(CB), this]() mutable {
527+
Ranges = std::move(RequestedRanges), CB = std::move(CB),
528+
this]() mutable {
526529
format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS);
527530
tooling::Replacements IncludeReplaces =
528531
format::sortIncludes(Style, Code, Ranges, File);

clang-tools-extra/clangd/ClangdServer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ class ClangdServer {
316316
bool AddContainer, Callback<ReferencesResult> CB);
317317

318318
/// Run formatting for the \p File with content \p Code.
319-
/// If \p Rng is non-null, formats only that region.
320-
void formatFile(PathRef File, std::optional<Range> Rng,
319+
/// If \p Rng is non-empty, formats only those regions.
320+
void formatFile(PathRef File, const std::vector<Range> &Rngs,
321321
Callback<tooling::Replacements> CB);
322322

323323
/// Run formatting after \p TriggerText was typed at \p Pos in \p File with

clang-tools-extra/clangd/Protocol.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,15 @@ bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R,
633633
llvm::json::Path P) {
634634
llvm::json::ObjectMapper O(Params, P);
635635
return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);
636+
;
637+
}
638+
639+
bool fromJSON(const llvm::json::Value &Params,
640+
DocumentRangesFormattingParams &R, llvm::json::Path P) {
641+
llvm::json::ObjectMapper O(Params, P);
642+
return O && O.map("textDocument", R.textDocument) &&
643+
O.map("ranges", R.ranges);
644+
;
636645
}
637646

638647
bool fromJSON(const llvm::json::Value &Params,

clang-tools-extra/clangd/Protocol.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,10 +851,23 @@ struct DocumentRangeFormattingParams {
851851

852852
/// The range to format
853853
Range range;
854+
855+
/// The list of ranges to format
856+
std::optional<std::vector<Range>> ranges;
854857
};
855858
bool fromJSON(const llvm::json::Value &, DocumentRangeFormattingParams &,
856859
llvm::json::Path);
857860

861+
struct DocumentRangesFormattingParams {
862+
/// The document to format.
863+
TextDocumentIdentifier textDocument;
864+
865+
/// The list of ranges to format
866+
std::vector<Range> ranges;
867+
};
868+
bool fromJSON(const llvm::json::Value &, DocumentRangesFormattingParams &,
869+
llvm::json::Path);
870+
858871
struct DocumentOnTypeFormattingParams {
859872
/// The document to format.
860873
TextDocumentIdentifier textDocument;

clang-tools-extra/clangd/test/initialize-params.test

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
# CHECK-NEXT: "firstTriggerCharacter": "\n",
3636
# CHECK-NEXT: "moreTriggerCharacter": []
3737
# CHECK-NEXT: },
38-
# CHECK-NEXT: "documentRangeFormattingProvider": true,
38+
# CHECK-NEXT: "documentRangeFormattingProvider": {
39+
# CHECK-NEXT: "rangesSupport": true
40+
# CHECK-NEXT: },
3941
# CHECK-NEXT: "documentSymbolProvider": true,
4042
# CHECK-NEXT: "executeCommandProvider": {
4143
# CHECK-NEXT: "commands": [

clang-tools-extra/clangd/unittests/ClangdTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ void f() {}
943943
FS.Files[Path] = Code;
944944
runAddDocument(Server, Path, Code);
945945

946-
auto Replaces = runFormatFile(Server, Path, /*Rng=*/std::nullopt);
946+
auto Replaces = runFormatFile(Server, Path, /*Rngs=*/{});
947947
EXPECT_TRUE(static_cast<bool>(Replaces));
948948
auto Changed = tooling::applyAllReplacements(Code, *Replaces);
949949
EXPECT_TRUE(static_cast<bool>(Changed));

clang-tools-extra/clangd/unittests/SyncAPI.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,
116116
}
117117

118118
llvm::Expected<tooling::Replacements>
119-
runFormatFile(ClangdServer &Server, PathRef File, std::optional<Range> Rng) {
119+
runFormatFile(ClangdServer &Server, PathRef File,
120+
const std::vector<Range> &Rngs) {
120121
std::optional<llvm::Expected<tooling::Replacements>> Result;
121-
Server.formatFile(File, Rng, capture(Result));
122+
Server.formatFile(File, Rngs, capture(Result));
122123
return std::move(*Result);
123124
}
124125

clang-tools-extra/clangd/unittests/SyncAPI.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ runPrepareRename(ClangdServer &Server, PathRef File, Position Pos,
5353
const clangd::RenameOptions &RenameOpts);
5454

5555
llvm::Expected<tooling::Replacements>
56-
runFormatFile(ClangdServer &Server, PathRef File, std::optional<Range>);
56+
runFormatFile(ClangdServer &Server, PathRef File, const std::vector<Range> &);
5757

5858
SymbolSlab runFuzzyFind(const SymbolIndex &Index, StringRef Query);
5959
SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req);

0 commit comments

Comments
 (0)