[clangd] Make functions of ClangdServer callback-based

Summary:
As a consequence, all LSP operations are now handled asynchronously,
i.e. they never block the main processing thread. However, if
-run-synchronously flag is specified, clangd still runs everything on
the main thread.

Reviewers: sammccall, ioeric, hokein

Reviewed By: sammccall, ioeric

Subscribers: klimek, jkorous-apple, cfe-commits

Differential Revision: https://reviews.llvm.org/D43227

llvm-svn: 325233
This commit is contained in:
Ilya Biryukov 2018-02-15 13:15:47 +00:00
parent 80663ee986
commit 2c5e8e820b
8 changed files with 196 additions and 142 deletions

View File

@ -180,23 +180,25 @@ void ClangdLSPServer::onCommand(ExecuteCommandParams &Params) {
}
void ClangdLSPServer::onRename(RenameParams &Params) {
auto File = Params.textDocument.uri.file;
auto Code = Server.getDocument(File);
Path File = Params.textDocument.uri.file;
llvm::Optional<std::string> Code = Server.getDocument(File);
if (!Code)
return replyError(ErrorCode::InvalidParams,
"onRename called for non-added file");
auto Replacements = Server.rename(File, Params.position, Params.newName);
if (!Replacements) {
replyError(ErrorCode::InternalError,
llvm::toString(Replacements.takeError()));
return;
}
Server.rename(
File, Params.position, Params.newName,
[File, Code,
Params](llvm::Expected<std::vector<tooling::Replacement>> Replacements) {
if (!Replacements)
return replyError(ErrorCode::InternalError,
llvm::toString(Replacements.takeError()));
std::vector<TextEdit> Edits = replacementsToEdits(*Code, *Replacements);
WorkspaceEdit WE;
WE.changes = {{Params.textDocument.uri.uri(), Edits}};
reply(WE);
std::vector<TextEdit> Edits = replacementsToEdits(*Code, *Replacements);
WorkspaceEdit WE;
WE.changes = {{Params.textDocument.uri.uri(), Edits}};
reply(WE);
});
}
void ClangdLSPServer::onDocumentDidClose(DidCloseTextDocumentParams &Params) {
@ -280,21 +282,25 @@ void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {
}
void ClangdLSPServer::onSignatureHelp(TextDocumentPositionParams &Params) {
auto SignatureHelp =
Server.signatureHelp(Params.textDocument.uri.file, Params.position);
if (!SignatureHelp)
return replyError(ErrorCode::InvalidParams,
llvm::toString(SignatureHelp.takeError()));
reply(SignatureHelp->Value);
Server.signatureHelp(Params.textDocument.uri.file, Params.position,
[](llvm::Expected<Tagged<SignatureHelp>> SignatureHelp) {
if (!SignatureHelp)
return replyError(
ErrorCode::InvalidParams,
llvm::toString(SignatureHelp.takeError()));
reply(SignatureHelp->Value);
});
}
void ClangdLSPServer::onGoToDefinition(TextDocumentPositionParams &Params) {
auto Items =
Server.findDefinitions(Params.textDocument.uri.file, Params.position);
if (!Items)
return replyError(ErrorCode::InvalidParams,
llvm::toString(Items.takeError()));
reply(json::ary(Items->Value));
Server.findDefinitions(
Params.textDocument.uri.file, Params.position,
[](llvm::Expected<Tagged<std::vector<Location>>> Items) {
if (!Items)
return replyError(ErrorCode::InvalidParams,
llvm::toString(Items.takeError()));
reply(json::ary(Items->Value));
});
}
void ClangdLSPServer::onSwitchSourceHeader(TextDocumentIdentifier &Params) {
@ -303,16 +309,14 @@ void ClangdLSPServer::onSwitchSourceHeader(TextDocumentIdentifier &Params) {
}
void ClangdLSPServer::onDocumentHighlight(TextDocumentPositionParams &Params) {
auto Highlights = Server.findDocumentHighlights(Params.textDocument.uri.file,
Params.position);
if (!Highlights) {
replyError(ErrorCode::InternalError,
llvm::toString(Highlights.takeError()));
return;
}
reply(json::ary(Highlights->Value));
Server.findDocumentHighlights(
Params.textDocument.uri.file, Params.position,
[](llvm::Expected<Tagged<std::vector<DocumentHighlight>>> Highlights) {
if (!Highlights)
return replyError(ErrorCode::InternalError,
llvm::toString(Highlights.takeError()));
reply(json::ary(Highlights->Value));
});
}
ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,

View File

@ -31,36 +31,6 @@ using namespace clang::clangd;
namespace {
// Issues an async read of AST and waits for results.
template <class Ret, class Func>
Ret blockingRunWithAST(TUScheduler &S, PathRef File, Func &&F) {
// Using shared_ptr to workaround MSVC bug. It requires future<> arguments to
// have default and copy ctor.
auto SharedPtrFunc = [&](llvm::Expected<InputsAndAST> Arg) {
return std::make_shared<Ret>(F(std::move(Arg)));
};
std::packaged_task<std::shared_ptr<Ret>(llvm::Expected<InputsAndAST>)> Task(
SharedPtrFunc);
auto Future = Task.get_future();
S.runWithAST(File, std::move(Task));
return std::move(*Future.get());
}
// Issues an async read of preamble and waits for results.
template <class Ret, class Func>
Ret blockingRunWithPreamble(TUScheduler &S, PathRef File, Func &&F) {
// Using shared_ptr to workaround MSVC bug. It requires future<> arguments to
// have default and copy ctor.
auto SharedPtrFunc = [&](llvm::Expected<InputsAndPreamble> Arg) {
return std::make_shared<Ret>(F(std::move(Arg)));
};
std::packaged_task<std::shared_ptr<Ret>(llvm::Expected<InputsAndPreamble>)>
Task(SharedPtrFunc);
auto Future = Task.get_future();
S.runWithPreamble(File, std::move(Task));
return std::move(*Future.get());
}
void ignoreError(llvm::Error Err) {
handleAllErrors(std::move(Err), [](const llvm::ErrorInfoBase &) {});
}
@ -213,10 +183,11 @@ void ClangdServer::codeComplete(
std::move(Callback)));
}
llvm::Expected<Tagged<SignatureHelp>>
ClangdServer::signatureHelp(PathRef File, Position Pos,
llvm::Optional<StringRef> OverridenContents,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
void ClangdServer::signatureHelp(
PathRef File, Position Pos,
UniqueFunction<void(llvm::Expected<Tagged<SignatureHelp>>)> Callback,
llvm::Optional<StringRef> OverridenContents,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
if (UsedFS)
*UsedFS = TaggedFS.Value;
@ -227,27 +198,30 @@ ClangdServer::signatureHelp(PathRef File, Position Pos,
} else {
VersionedDraft Latest = DraftMgr.getDraft(File);
if (!Latest.Draft)
return llvm::make_error<llvm::StringError>(
return Callback(llvm::make_error<llvm::StringError>(
"signatureHelp is called for non-added document",
llvm::errc::invalid_argument);
llvm::errc::invalid_argument));
Contents = std::move(*Latest.Draft);
}
auto Action = [=](llvm::Expected<InputsAndPreamble> IP)
-> Expected<Tagged<SignatureHelp>> {
auto PCHs = this->PCHs;
auto Action = [Contents, Pos, TaggedFS,
PCHs](Path File, decltype(Callback) Callback,
llvm::Expected<InputsAndPreamble> IP) {
if (!IP)
return IP.takeError();
return Callback(IP.takeError());
auto PreambleData = IP->Preamble;
auto &Command = IP->Inputs.CompileCommand;
return make_tagged(
Callback(make_tagged(
clangd::signatureHelp(File, Command,
PreambleData ? &PreambleData->Preamble : nullptr,
Contents, Pos, TaggedFS.Value, PCHs),
TaggedFS.Tag);
TaggedFS.Tag));
};
return blockingRunWithPreamble<Expected<Tagged<SignatureHelp>>>(WorkScheduler,
File, Action);
WorkScheduler.runWithPreamble(
File, BindWithForward(Action, File.str(), std::move(Callback)));
}
llvm::Expected<tooling::Replacements>
@ -276,12 +250,15 @@ ClangdServer::formatOnType(StringRef Code, PathRef File, Position Pos) {
return formatCode(Code, File, {tooling::Range(PreviousLBracePos, Len)});
}
Expected<std::vector<tooling::Replacement>>
ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName) {
using RetType = Expected<std::vector<tooling::Replacement>>;
auto Action = [=](Expected<InputsAndAST> InpAST) -> RetType {
void ClangdServer::rename(
PathRef File, Position Pos, llvm::StringRef NewName,
UniqueFunction<void(Expected<std::vector<tooling::Replacement>>)>
Callback) {
auto Action = [Pos](Path File, std::string NewName,
decltype(Callback) Callback,
Expected<InputsAndAST> InpAST) {
if (!InpAST)
return InpAST.takeError();
return Callback(InpAST.takeError());
auto &AST = InpAST->AST;
RefactoringResultCollector ResultCollector;
@ -289,23 +266,24 @@ ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName) {
const FileEntry *FE =
SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
if (!FE)
return llvm::make_error<llvm::StringError>(
"rename called for non-added document", llvm::errc::invalid_argument);
return Callback(llvm::make_error<llvm::StringError>(
"rename called for non-added document",
llvm::errc::invalid_argument));
SourceLocation SourceLocationBeg =
clangd::getBeginningOfIdentifier(AST, Pos, FE);
tooling::RefactoringRuleContext Context(
AST.getASTContext().getSourceManager());
Context.setASTContext(AST.getASTContext());
auto Rename = clang::tooling::RenameOccurrences::initiate(
Context, SourceRange(SourceLocationBeg), NewName.str());
Context, SourceRange(SourceLocationBeg), NewName);
if (!Rename)
return Rename.takeError();
return Callback(Rename.takeError());
Rename->invoke(ResultCollector, Context);
assert(ResultCollector.Result.hasValue());
if (!ResultCollector.Result.getValue())
return ResultCollector.Result->takeError();
return Callback(ResultCollector.Result->takeError());
std::vector<tooling::Replacement> Replacements;
for (const tooling::AtomicChange &Change : ResultCollector.Result->get()) {
@ -324,9 +302,12 @@ ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName) {
Replacements.push_back(Rep);
}
}
return Replacements;
return Callback(Replacements);
};
return blockingRunWithAST<RetType>(WorkScheduler, File, std::move(Action));
WorkScheduler.runWithAST(
File,
BindWithForward(Action, File.str(), NewName.str(), std::move(Callback)));
}
llvm::Optional<std::string> ClangdServer::getDocument(PathRef File) {
@ -336,37 +317,40 @@ llvm::Optional<std::string> ClangdServer::getDocument(PathRef File) {
return std::move(*Latest.Draft);
}
std::string ClangdServer::dumpAST(PathRef File) {
auto Action = [](llvm::Expected<InputsAndAST> InpAST) -> std::string {
void ClangdServer::dumpAST(PathRef File,
UniqueFunction<void(std::string)> Callback) {
auto Action = [](decltype(Callback) Callback,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST) {
ignoreError(InpAST.takeError());
return "<no-ast>";
return Callback("<no-ast>");
}
std::string Result;
llvm::raw_string_ostream ResultOS(Result);
clangd::dumpAST(InpAST->AST, ResultOS);
ResultOS.flush();
return Result;
Callback(Result);
};
return blockingRunWithAST<std::string>(WorkScheduler, File,
std::move(Action));
WorkScheduler.runWithAST(File, BindWithForward(Action, std::move(Callback)));
}
llvm::Expected<Tagged<std::vector<Location>>>
ClangdServer::findDefinitions(PathRef File, Position Pos) {
void ClangdServer::findDefinitions(
PathRef File, Position Pos,
UniqueFunction<void(llvm::Expected<Tagged<std::vector<Location>>>)>
Callback) {
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
using RetType = llvm::Expected<Tagged<std::vector<Location>>>;
auto Action = [=](llvm::Expected<InputsAndAST> InpAST) -> RetType {
auto Action = [Pos, TaggedFS](decltype(Callback) Callback,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return InpAST.takeError();
return Callback(InpAST.takeError());
auto Result = clangd::findDefinitions(InpAST->AST, Pos);
return make_tagged(std::move(Result), TaggedFS.Tag);
Callback(make_tagged(std::move(Result), TaggedFS.Tag));
};
return blockingRunWithAST<RetType>(WorkScheduler, File, Action);
WorkScheduler.runWithAST(File, BindWithForward(Action, std::move(Callback)));
}
llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
@ -442,24 +426,27 @@ ClangdServer::formatCode(llvm::StringRef Code, PathRef File,
}
}
llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
ClangdServer::findDocumentHighlights(PathRef File, Position Pos) {
void ClangdServer::findDocumentHighlights(
PathRef File, Position Pos,
UniqueFunction<void(llvm::Expected<Tagged<std::vector<DocumentHighlight>>>)>
Callback) {
auto FileContents = DraftMgr.getDraft(File);
if (!FileContents.Draft)
return llvm::make_error<llvm::StringError>(
return Callback(llvm::make_error<llvm::StringError>(
"findDocumentHighlights called on non-added file",
llvm::errc::invalid_argument);
llvm::errc::invalid_argument));
auto TaggedFS = FSProvider.getTaggedFileSystem(File);
using RetType = llvm::Expected<Tagged<std::vector<DocumentHighlight>>>;
auto Action = [=](llvm::Expected<InputsAndAST> InpAST) -> RetType {
auto Action = [TaggedFS, Pos](decltype(Callback) Callback,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return InpAST.takeError();
return Callback(InpAST.takeError());
auto Result = clangd::findDocumentHighlights(InpAST->AST, Pos);
return make_tagged(std::move(Result), TaggedFS.Tag);
Callback(make_tagged(std::move(Result), TaggedFS.Tag));
};
return blockingRunWithAST<RetType>(WorkScheduler, File, Action);
WorkScheduler.runWithAST(File, BindWithForward(Action, std::move(Callback)));
}
void ClangdServer::scheduleReparseAndDiags(

View File

@ -189,22 +189,28 @@ public:
/// will be used. If \p UsedFS is non-null, it will be overwritten by
/// vfs::FileSystem used for signature help. This method should only be called
/// for currently tracked files.
llvm::Expected<Tagged<SignatureHelp>>
signatureHelp(PathRef File, Position Pos,
llvm::Optional<StringRef> OverridenContents = llvm::None,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
void signatureHelp(
PathRef File, Position Pos,
UniqueFunction<void(llvm::Expected<Tagged<SignatureHelp>>)> Callback,
llvm::Optional<StringRef> OverridenContents = llvm::None,
IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
/// Get definition of symbol at a specified \p Line and \p Column in \p File.
llvm::Expected<Tagged<std::vector<Location>>> findDefinitions(PathRef File,
Position Pos);
void findDefinitions(
PathRef File, Position Pos,
UniqueFunction<void(llvm::Expected<Tagged<std::vector<Location>>>)>
Callback);
/// Helper function that returns a path to the corresponding source file when
/// given a header file and vice versa.
llvm::Optional<Path> switchSourceHeader(PathRef Path);
/// Get document highlights for a given position.
llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
findDocumentHighlights(PathRef File, Position Pos);
void findDocumentHighlights(
PathRef File, Position Pos,
UniqueFunction<
void(llvm::Expected<Tagged<std::vector<DocumentHighlight>>>)>
Callback);
/// Run formatting for \p Rng inside \p File with content \p Code.
llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
@ -221,8 +227,9 @@ public:
/// Rename all occurrences of the symbol at the \p Pos in \p File to
/// \p NewName.
Expected<std::vector<tooling::Replacement>> rename(PathRef File, Position Pos,
llvm::StringRef NewName);
void rename(PathRef File, Position Pos, llvm::StringRef NewName,
UniqueFunction<void(Expected<std::vector<tooling::Replacement>>)>
Callback);
/// Gets current document contents for \p File. Returns None if \p File is not
/// currently tracked.
@ -233,7 +240,7 @@ public:
/// Only for testing purposes.
/// Waits until all requests to worker thread are finished and dumps AST for
/// \p File. \p File must be in the list of added documents.
std::string dumpAST(PathRef File);
void dumpAST(PathRef File, UniqueFunction<void(std::string)> Callback);
/// Called when an event occurs for a watched file in the workspace.
void onFileEvent(const DidChangeWatchedFilesParams &Params);

View File

@ -96,7 +96,7 @@ std::string replacePtrsInDump(std::string const &Dump) {
}
std::string dumpASTWithoutMemoryLocs(ClangdServer &Server, PathRef File) {
auto DumpWithMemLocs = Server.dumpAST(File);
auto DumpWithMemLocs = runDumpAST(Server, File);
return replacePtrsInDump(DumpWithMemLocs);
}
@ -432,17 +432,17 @@ TEST_F(ClangdVFSTest, InvalidCompileCommand) {
// Clang can't parse command args in that case, but we shouldn't crash.
Server.addDocument(FooCpp, "int main() {}");
EXPECT_EQ(Server.dumpAST(FooCpp), "<no-ast>");
EXPECT_ERROR(Server.findDefinitions(FooCpp, Position()));
EXPECT_ERROR(Server.findDocumentHighlights(FooCpp, Position()));
EXPECT_ERROR(Server.rename(FooCpp, Position(), "new_name"));
EXPECT_EQ(runDumpAST(Server, FooCpp), "<no-ast>");
EXPECT_ERROR(runFindDefinitions(Server, FooCpp, Position()));
EXPECT_ERROR(runFindDocumentHighlights(Server, FooCpp, Position()));
EXPECT_ERROR(runRename(Server, FooCpp, Position(), "new_name"));
// FIXME: codeComplete and signatureHelp should also return errors when they
// can't parse the file.
EXPECT_THAT(
runCodeComplete(Server, FooCpp, Position(), clangd::CodeCompleteOptions())
.Value.items,
IsEmpty());
auto SigHelp = Server.signatureHelp(FooCpp, Position());
auto SigHelp = runSignatureHelp(Server, FooCpp, Position());
ASSERT_TRUE(bool(SigHelp)) << "signatureHelp returned an error";
EXPECT_THAT(SigHelp->Value.signatures, IsEmpty());
}
@ -646,7 +646,7 @@ int d;
Pos.line = LineDist(RandGen);
Pos.character = ColumnDist(RandGen);
ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos));
ASSERT_TRUE(!!runFindDefinitions(Server, FilePaths[FileIndex], Pos));
};
std::vector<std::function<void()>> AsyncRequests = {
@ -768,8 +768,8 @@ TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) {
public:
std::atomic<int> Count = {0};
NoConcurrentAccessDiagConsumer(std::promise<void> StartSecondReparse)
: StartSecondReparse(std::move(StartSecondReparse)) {}
NoConcurrentAccessDiagConsumer(std::promise<void> StartSecondReparse)
: StartSecondReparse(std::move(StartSecondReparse)) {}
void onDiagnosticsReady(PathRef,
Tagged<std::vector<DiagWithFixIts>>) override {

View File

@ -626,7 +626,7 @@ SignatureHelp signatures(StringRef Text) {
Annotations Test(Text);
Server.addDocument(File, Test.code());
EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for preamble";
auto R = Server.signatureHelp(File, Test.point());
auto R = runSignatureHelp(Server, File, Test.point());
assert(R);
return R.get().Value;
}

View File

@ -17,7 +17,9 @@ namespace {
/// T Result;
/// someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
template <typename T> struct CaptureProxy {
CaptureProxy(T &Target) : Target(&Target) {}
CaptureProxy(llvm::Optional<T> &Target) : Target(&Target) {
assert(!Target.hasValue());
}
CaptureProxy(const CaptureProxy &) = delete;
CaptureProxy &operator=(const CaptureProxy &) = delete;
@ -39,16 +41,17 @@ template <typename T> struct CaptureProxy {
if (!Target)
return;
assert(Future.valid() && "conversion to callback was not called");
*Target = Future.get();
assert(!Target->hasValue());
Target->emplace(Future.get());
}
private:
T *Target;
llvm::Optional<T> *Target;
std::promise<T> Promise;
std::future<T> Future;
};
template <typename T> CaptureProxy<T> capture(T &Target) {
template <typename T> CaptureProxy<T> capture(llvm::Optional<T> &Target) {
return CaptureProxy<T>(Target);
}
} // namespace
@ -57,9 +60,44 @@ Tagged<CompletionList>
runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
clangd::CodeCompleteOptions Opts,
llvm::Optional<StringRef> OverridenContents) {
Tagged<CompletionList> Result;
llvm::Optional<Tagged<CompletionList>> Result;
Server.codeComplete(File, Pos, Opts, capture(Result), OverridenContents);
return Result;
return std::move(*Result);
}
llvm::Expected<Tagged<SignatureHelp>>
runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos,
llvm::Optional<StringRef> OverridenContents) {
llvm::Optional<llvm::Expected<Tagged<SignatureHelp>>> Result;
Server.signatureHelp(File, Pos, capture(Result), OverridenContents);
return std::move(*Result);
}
llvm::Expected<Tagged<std::vector<Location>>>
runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos) {
llvm::Optional<llvm::Expected<Tagged<std::vector<Location>>>> Result;
Server.findDefinitions(File, Pos, capture(Result));
return std::move(*Result);
}
llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos) {
llvm::Optional<llvm::Expected<Tagged<std::vector<DocumentHighlight>>>> Result;
Server.findDocumentHighlights(File, Pos, capture(Result));
return std::move(*Result);
}
llvm::Expected<std::vector<tooling::Replacement>>
runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName) {
llvm::Optional<llvm::Expected<std::vector<tooling::Replacement>>> Result;
Server.rename(File, Pos, NewName, capture(Result));
return std::move(*Result);
}
std::string runDumpAST(ClangdServer &Server, PathRef File) {
llvm::Optional<std::string> Result;
Server.dumpAST(File, capture(Result));
return std::move(*Result);
}
} // namespace clangd

View File

@ -22,6 +22,22 @@ Tagged<CompletionList>
runCodeComplete(ClangdServer &Server, PathRef File, Position Pos,
clangd::CodeCompleteOptions Opts,
llvm::Optional<StringRef> OverridenContents = llvm::None);
llvm::Expected<Tagged<SignatureHelp>>
runSignatureHelp(ClangdServer &Server, PathRef File, Position Pos,
llvm::Optional<StringRef> OverridenContents = llvm::None);
llvm::Expected<Tagged<std::vector<Location>>>
runFindDefinitions(ClangdServer &Server, PathRef File, Position Pos);
llvm::Expected<Tagged<std::vector<DocumentHighlight>>>
runFindDocumentHighlights(ClangdServer &Server, PathRef File, Position Pos);
llvm::Expected<std::vector<tooling::Replacement>>
runRename(ClangdServer &Server, PathRef File, Position Pos, StringRef NewName);
std::string runDumpAST(ClangdServer &Server, PathRef File);
} // namespace clangd
} // namespace clang

View File

@ -10,6 +10,7 @@
#include "ClangdUnit.h"
#include "Compiler.h"
#include "Matchers.h"
#include "SyncAPI.h"
#include "TestFS.h"
#include "XRefs.h"
#include "clang/Frontend/CompilerInvocation.h"
@ -249,7 +250,8 @@ int baz = f^oo;
FS.Files[FooCpp] = "";
Server.addDocument(FooCpp, SourceAnnotations.code());
auto Locations = Server.findDefinitions(FooCpp, SourceAnnotations.point());
auto Locations =
runFindDefinitions(Server, FooCpp, SourceAnnotations.point());
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
EXPECT_THAT(Locations->Value,