#include "Preamble.h"
#include "Protocol.h"
#include "SemanticHighlighting.h"
+#include "SemanticSelection.h"
#include "SourceCode.h"
#include "TUScheduler.h"
#include "Trace.h"
// critical paths.
WorkScheduler(
CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
- std::make_unique<UpdateIndexCallbacks>(
- DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
+ std::make_unique<UpdateIndexCallbacks>(DynamicIdx.get(), DiagConsumer,
+ Opts.SemanticHighlighting),
Opts.UpdateDebounce, Opts.RetentionPolicy) {
// Adds an index to the stack, at higher priority than existing indexes.
auto AddIndex = [&](SymbolIndex *Idx) {
WorkScheduler.runWithAST("SymbolInfo", File, std::move(Action));
}
+void ClangdServer::semanticRanges(PathRef File, Position Pos,
+ Callback<std::vector<Range>> CB) {
+ auto Action =
+ [Pos, CB = std::move(CB)](llvm::Expected<InputsAndAST> InpAST) mutable {
+ if (!InpAST)
+ return CB(InpAST.takeError());
+ CB(clangd::getSemanticRanges(InpAST->AST, Pos));
+ };
+ WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
+}
+
std::vector<std::pair<Path, std::size_t>>
ClangdServer::getUsedBytesPerFile() const {
return WorkScheduler.getUsedBytesPerFile();
void symbolInfo(PathRef File, Position Pos,
Callback<std::vector<SymbolDetails>> CB);
+ /// Get semantic ranges around a specified position in a file.
+ void semanticRanges(PathRef File, Position Pos,
+ Callback<std::vector<Range>> CB);
+
/// Returns estimated memory usage for each of the currently open files.
/// The order of results is unspecified.
/// Overall memory usage of clangd may be significantly more than reported
//===----------------------------------------------------------------------===//
#include "Annotations.h"
+#include "ClangdServer.h"
#include "Matchers.h"
#include "Protocol.h"
#include "SemanticSelection.h"
#include "SourceCode.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
#include "TestTU.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
namespace {
using ::testing::ElementsAreArray;
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+ void onDiagnosticsReady(PathRef File,
+ std::vector<Diag> Diagnostics) override {}
+};
+
TEST(SemanticSelection, All) {
const char *Tests[] = {
R"cpp( // Single statement in a function body.
<< Test;
}
}
+
+TEST(SemanticSelection, RunViaClangDServer) {
+ MockFSProvider FS;
+ IgnoreDiagnostics DiagConsumer;
+ MockCompilationDatabase CDB;
+ ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+ auto FooH = testPath("foo.h");
+ FS.Files[FooH] = R"cpp(
+ int foo(int x);
+ #define HASH(x) ((x) % 10)
+ )cpp";
+
+ auto FooCpp = testPath("Foo.cpp");
+ const char *SourceContents = R"cpp(
+ #include "foo.h"
+ [[void bar(int& inp) [[{
+ // inp = HASH(foo(inp));
+ [[inp = [[HASH([[foo([[in^p]])]])]]]];
+ }]]]]
+ )cpp";
+ Annotations SourceAnnotations(SourceContents);
+ FS.Files[FooCpp] = SourceAnnotations.code();
+ Server.addDocument(FooCpp, SourceAnnotations.code());
+
+ auto Ranges = runSemanticRanges(Server, FooCpp, SourceAnnotations.point());
+ ASSERT_TRUE(bool(Ranges))
+ << "getSemanticRange returned an error: " << Ranges.takeError();
+ EXPECT_THAT(*Ranges, ElementsAreArray(SourceAnnotations.ranges()));
+}
} // namespace
} // namespace clangd
} // namespace clang
return std::move(Slab).build();
}
+llvm::Expected<std::vector<Range>>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos) {
+ llvm::Optional<llvm::Expected<std::vector<Range>>> Result;
+ Server.semanticRanges(File, Pos, capture(Result));
+ return std::move(*Result);
+}
+
} // namespace clangd
} // namespace clang
SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req);
RefSlab getRefs(const SymbolIndex &Index, SymbolID ID);
+llvm::Expected<std::vector<Range>>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos);
+
} // namespace clangd
} // namespace clang