Skip to content

Commit 79d19bd

Browse files
committed
Add SemanticRanges to Clangd server.
Summary: Adds Semantic Ranges capabilities to Clangd server. Also adds tests for running it via clangd server. This differs from the LSP spec as the spec needs this to be evaluated on multiple 'pos' and the expected output is an list of list of semantic ranges. This is majorly for multi cursor and assuming this is a rare thing, we don't want to optimize make things complicated just for this. This should be done in the LSP level by queueing one request per 'pos' in the input. LSP 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/D67650 llvm-svn: 372102
1 parent ded48e9 commit 79d19bd

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

clang-tools-extra/clangd/ClangdServer.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "Preamble.h"
1818
#include "Protocol.h"
1919
#include "SemanticHighlighting.h"
20+
#include "SemanticSelection.h"
2021
#include "SourceCode.h"
2122
#include "TUScheduler.h"
2223
#include "Trace.h"
@@ -125,8 +126,8 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
125126
// critical paths.
126127
WorkScheduler(
127128
CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
128-
std::make_unique<UpdateIndexCallbacks>(
129-
DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
129+
std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), DiagConsumer,
130+
Opts.SemanticHighlighting),
130131
Opts.UpdateDebounce, Opts.RetentionPolicy) {
131132
// Adds an index to the stack, at higher priority than existing indexes.
132133
auto AddIndex = [&](SymbolIndex *Idx) {
@@ -620,6 +621,17 @@ void ClangdServer::symbolInfo(PathRef File, Position Pos,
620621
WorkScheduler.runWithAST("SymbolInfo", File, std::move(Action));
621622
}
622623

624+
void ClangdServer::semanticRanges(PathRef File, Position Pos,
625+
Callback<std::vector<Range>> CB) {
626+
auto Action =
627+
[Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
628+
if (!InpAST)
629+
return CB(InpAST.takeError());
630+
CB(clangd::getSemanticRanges(InpAST->AST, Pos));
631+
};
632+
WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
633+
}
634+
623635
std::vector<std::pair<Path, std::size_t>>
624636
ClangdServer::getUsedBytesPerFile() const {
625637
return WorkScheduler.getUsedBytesPerFile();

clang-tools-extra/clangd/ClangdServer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ class ClangdServer {
277277
void symbolInfo(PathRef File, Position Pos,
278278
Callback<std::vector<SymbolDetails>> CB);
279279

280+
/// Get semantic ranges around a specified position in a file.
281+
void semanticRanges(PathRef File, Position Pos,
282+
Callback<std::vector<Range>> CB);
283+
280284
/// Returns estimated memory usage for each of the currently open files.
281285
/// The order of results is unspecified.
282286
/// Overall memory usage of clangd may be significantly more than reported

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "Annotations.h"
10+
#include "ClangdServer.h"
1011
#include "Matchers.h"
1112
#include "Protocol.h"
1213
#include "SemanticSelection.h"
1314
#include "SourceCode.h"
15+
#include "SyncAPI.h"
16+
#include "TestFS.h"
1417
#include "TestTU.h"
1518
#include "clang/Basic/SourceLocation.h"
1619
#include "clang/Basic/SourceManager.h"
@@ -23,6 +26,11 @@ namespace clangd {
2326
namespace {
2427
using ::testing::ElementsAreArray;
2528

29+
class IgnoreDiagnostics : public DiagnosticsConsumer {
30+
void onDiagnosticsReady(PathRef File,
31+
std::vector<Diag> Diagnostics) override {}
32+
};
33+
2634
TEST(SemanticSelection, All) {
2735
const char *Tests[] = {
2836
R"cpp( // Single statement in a function body.
@@ -138,6 +146,36 @@ TEST(SemanticSelection, All) {
138146
<< Test;
139147
}
140148
}
149+
150+
TEST(SemanticSelection, RunViaClangDServer) {
151+
MockFSProvider FS;
152+
IgnoreDiagnostics DiagConsumer;
153+
MockCompilationDatabase CDB;
154+
ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
155+
156+
auto FooH = testPath("foo.h");
157+
FS.Files[FooH] = R"cpp(
158+
int foo(int x);
159+
#define HASH(x) ((x) % 10)
160+
)cpp";
161+
162+
auto FooCpp = testPath("Foo.cpp");
163+
const char *SourceContents = R"cpp(
164+
#include "foo.h"
165+
[[void bar(int& inp) [[{
166+
// inp = HASH(foo(inp));
167+
[[inp = [[HASH([[foo([[in^p]])]])]]]];
168+
}]]]]
169+
)cpp";
170+
Annotations SourceAnnotations(SourceContents);
171+
FS.Files[FooCpp] = SourceAnnotations.code();
172+
Server.addDocument(FooCpp, SourceAnnotations.code());
173+
174+
auto Ranges = runSemanticRanges(Server, FooCpp, SourceAnnotations.point());
175+
ASSERT_TRUE(bool(Ranges))
176+
<< "getSemanticRange returned an error: " << Ranges.takeError();
177+
EXPECT_THAT(*Ranges, ElementsAreArray(SourceAnnotations.ranges()));
178+
}
141179
} // namespace
142180
} // namespace clangd
143181
} // namespace clang

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,12 @@ RefSlab getRefs(const SymbolIndex &Index, SymbolID ID) {
145145
return std::move(Slab).build();
146146
}
147147

148+
llvm::Expected<std::vector<Range>>
149+
runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos) {
150+
llvm::Optional<llvm::Expected<std::vector<Range>>> Result;
151+
Server.semanticRanges(File, Pos, capture(Result));
152+
return std::move(*Result);
153+
}
154+
148155
} // namespace clangd
149156
} // namespace clang

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ SymbolSlab runFuzzyFind(const SymbolIndex &Index, StringRef Query);
5353
SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req);
5454
RefSlab getRefs(const SymbolIndex &Index, SymbolID ID);
5555

56+
llvm::Expected<std::vector<Range>>
57+
runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos);
58+
5659
} // namespace clangd
5760
} // namespace clang
5861

0 commit comments

Comments
 (0)