1 //===--- SyncAPI.cpp - Sync version of ClangdServer's API --------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "index/Index.h"
17 void runAddDocument(ClangdServer
&Server
, PathRef File
,
18 llvm::StringRef Contents
, llvm::StringRef Version
,
19 WantDiagnostics WantDiags
, bool ForceRebuild
) {
20 Server
.addDocument(File
, Contents
, Version
, WantDiags
, ForceRebuild
);
21 if (!Server
.blockUntilIdleForTest())
22 llvm_unreachable("not idle after addDocument");
26 /// A helper that waits for async callbacks to fire and exposes their result in
27 /// the output variable. Intended to be used in the following way:
29 /// someAsyncFunc(Param1, Param2, /*Callback=*/capture(Result));
30 template <typename T
> struct CaptureProxy
{
31 CaptureProxy(std::optional
<T
> &Target
) : Target(&Target
) { assert(!Target
); }
33 CaptureProxy(const CaptureProxy
&) = delete;
34 CaptureProxy
&operator=(const CaptureProxy
&) = delete;
35 // We need move ctor to return a value from the 'capture' helper.
36 CaptureProxy(CaptureProxy
&&Other
) : Target(Other
.Target
) {
37 Other
.Target
= nullptr;
39 CaptureProxy
&operator=(CaptureProxy
&&) = delete;
41 operator llvm::unique_function
<void(T
)>() && {
42 assert(!Future
.valid() && "conversion to callback called multiple times");
43 Future
= Promise
.get_future();
44 return [Promise
= std::move(Promise
)](T Value
) mutable {
45 Promise
.set_value(std::make_shared
<T
>(std::move(Value
)));
52 assert(Future
.valid() && "conversion to callback was not called");
53 assert(!Target
->has_value());
54 Target
->emplace(std::move(*Future
.get()));
58 std::optional
<T
> *Target
;
59 // Using shared_ptr to workaround compilation errors with MSVC.
60 // MSVC only allows default-constructible and copyable objects as future<>
62 std::promise
<std::shared_ptr
<T
>> Promise
;
63 std::future
<std::shared_ptr
<T
>> Future
;
66 template <typename T
> CaptureProxy
<T
> capture(std::optional
<T
> &Target
) {
67 return CaptureProxy
<T
>(Target
);
71 llvm::Expected
<CodeCompleteResult
>
72 runCodeComplete(ClangdServer
&Server
, PathRef File
, Position Pos
,
73 clangd::CodeCompleteOptions Opts
) {
74 std::optional
<llvm::Expected
<CodeCompleteResult
>> Result
;
75 Server
.codeComplete(File
, Pos
, Opts
, capture(Result
));
76 return std::move(*Result
);
79 llvm::Expected
<SignatureHelp
> runSignatureHelp(ClangdServer
&Server
,
80 PathRef File
, Position Pos
,
81 MarkupKind DocumentationFormat
) {
82 std::optional
<llvm::Expected
<SignatureHelp
>> Result
;
83 Server
.signatureHelp(File
, Pos
, DocumentationFormat
, capture(Result
));
84 return std::move(*Result
);
87 llvm::Expected
<std::vector
<LocatedSymbol
>>
88 runLocateSymbolAt(ClangdServer
&Server
, PathRef File
, Position Pos
) {
89 std::optional
<llvm::Expected
<std::vector
<LocatedSymbol
>>> Result
;
90 Server
.locateSymbolAt(File
, Pos
, capture(Result
));
91 return std::move(*Result
);
94 llvm::Expected
<std::vector
<DocumentHighlight
>>
95 runFindDocumentHighlights(ClangdServer
&Server
, PathRef File
, Position Pos
) {
96 std::optional
<llvm::Expected
<std::vector
<DocumentHighlight
>>> Result
;
97 Server
.findDocumentHighlights(File
, Pos
, capture(Result
));
98 return std::move(*Result
);
101 llvm::Expected
<RenameResult
> runRename(ClangdServer
&Server
, PathRef File
,
102 Position Pos
, llvm::StringRef NewName
,
103 const RenameOptions
&RenameOpts
) {
104 std::optional
<llvm::Expected
<RenameResult
>> Result
;
105 Server
.rename(File
, Pos
, NewName
, RenameOpts
, capture(Result
));
106 return std::move(*Result
);
109 llvm::Expected
<RenameResult
>
110 runPrepareRename(ClangdServer
&Server
, PathRef File
, Position Pos
,
111 std::optional
<std::string
> NewName
,
112 const RenameOptions
&RenameOpts
) {
113 std::optional
<llvm::Expected
<RenameResult
>> Result
;
114 Server
.prepareRename(File
, Pos
, NewName
, RenameOpts
, capture(Result
));
115 return std::move(*Result
);
118 llvm::Expected
<tooling::Replacements
>
119 runFormatFile(ClangdServer
&Server
, PathRef File
, std::optional
<Range
> Rng
) {
120 std::optional
<llvm::Expected
<tooling::Replacements
>> Result
;
121 Server
.formatFile(File
, Rng
, capture(Result
));
122 return std::move(*Result
);
125 SymbolSlab
runFuzzyFind(const SymbolIndex
&Index
, llvm::StringRef Query
) {
126 FuzzyFindRequest Req
;
127 Req
.Query
= std::string(Query
);
129 return runFuzzyFind(Index
, Req
);
132 SymbolSlab
runFuzzyFind(const SymbolIndex
&Index
, const FuzzyFindRequest
&Req
) {
133 SymbolSlab::Builder Builder
;
134 Index
.fuzzyFind(Req
, [&](const Symbol
&Sym
) { Builder
.insert(Sym
); });
135 return std::move(Builder
).build();
138 RefSlab
getRefs(const SymbolIndex
&Index
, SymbolID ID
) {
141 RefSlab::Builder Slab
;
142 Index
.refs(Req
, [&](const Ref
&S
) { Slab
.insert(ID
, S
); });
143 return std::move(Slab
).build();
146 llvm::Expected
<std::vector
<SelectionRange
>>
147 runSemanticRanges(ClangdServer
&Server
, PathRef File
,
148 const std::vector
<Position
> &Pos
) {
149 std::optional
<llvm::Expected
<std::vector
<SelectionRange
>>> Result
;
150 Server
.semanticRanges(File
, Pos
, capture(Result
));
151 return std::move(*Result
);
154 llvm::Expected
<std::optional
<clangd::Path
>>
155 runSwitchHeaderSource(ClangdServer
&Server
, PathRef File
) {
156 std::optional
<llvm::Expected
<std::optional
<clangd::Path
>>> Result
;
157 Server
.switchSourceHeader(File
, capture(Result
));
158 return std::move(*Result
);
161 llvm::Error
runCustomAction(ClangdServer
&Server
, PathRef File
,
162 llvm::function_ref
<void(InputsAndAST
)> Action
) {
163 llvm::Error Result
= llvm::Error::success();
165 Server
.customAction(File
, "Custom", [&](llvm::Expected
<InputsAndAST
> AST
) {
167 Result
= AST
.takeError();
176 } // namespace clangd