It was deprecated and callback version and is used everywhere.
Only changes to the testing code were needed.
Details
Diff Detail
- Repository
- rCTE Clang Tools Extra
- Build Status
Buildable 14752 Build 14752: arc lint + arc unit
Event Timeline
unittests/clangd/SyncAPI.h | ||
---|---|---|
8 | Any reason not to put sync APIs in ClangdServer by their async versions, so that they are easier to find? I might be missing context. But if there is a good reason, please explain in the file doc. |
unittests/clangd/SyncAPI.h | ||
---|---|---|
8 | That's a good question. I don't think we want anyone using the sync versions of the API. The tests are somewhat special, though, as they'll get really complicated if we move everything to callbacks and we don't want that. This probably deserves a comment. |
unittests/clangd/SyncAPI.h | ||
---|---|---|
8 | If these are expected to be used by tests only, I'd suggest moving the file to the test directory. |
unittests/clangd/SyncAPI.h | ||
---|---|---|
8 | I think it's in the unittest directory already, so we're covered here :-) |
unittests/clangd/SyncAPI.h | ||
---|---|---|
8 | Sorry! My bad! |
One down!
I'd like to know what you think about a generic "block the call and capture the result" mechanism rather than method-specific wrappers.
But if you're not convinced or just want to land this, I don't want to block the review.
unittests/clangd/SyncAPI.h | ||
---|---|---|
1 | Being able to call synchronously is really nice for tests. It would be nice if we had a primitive we could compose. Here's an idea that might work: Tagged<CompletionList> CompletionResults; Server.codeComplete(File, Pos, Opts, capture(CompletionResults), OverriddenContents); capture() returns a callback that writes into CompletionResults. It also magically causes the call to block! (brief pause for you to consider the API before I suggest a shameful implementation) Actually capture() returns a proxy object that converts to UniqueFunction. The proxy object itself has a destructor that blocks on the UF being invoked. The proxy will be destroyed at the end of the full-expression, i.e. the line. e.g. template <typename T> struct CaptureProxy { T &Target; std::promise<T> Promise; std::future<T> Future; CaptureProxy(T &Target) : Target(Target) {} operator UniqueFunction<void(T)>() { return BindWithForward([](T Value, std::promise<T> Promise) { Promise.set_value(std::move(Value)); }, std::move(Promise)); } ~CaptureProxy() { Target = Future.get(); } }; template <typename T> CaptureProxy<T> capture(T &Target) { return CaptureProxy<T>(Target); } This is a little bit magic, but it's just for tests :-) (One caveat - this needs the return value to be default-constructible. We could easily use Optional instead, but these are default-constructible in practice) | |
8 | Yep, can you add a file comment describing why these exist? |
- Added CaptureProxy<T> helper, use it to implement runCodeComplete.
- Documented that we deliberately don't expose the sync API in tests.
- Rebased onto the latest head.
unittests/clangd/SyncAPI.h | ||
---|---|---|
1 | As discussed offline, I've opted for both:
This approach writing a small amount of wrapper code for each of the LSP methods in ClangdServer, but it, arguably, makes the test code nicer. |
Being able to call synchronously is really nice for tests.
It's a bit unfortunate that to do this for each function we want to call synchronously (giving them a name, writing some boilerplate that repeats the args a few times).
It would be nice if we had a primitive we could compose.
Here's an idea that might work:
capture() returns a callback that writes into CompletionResults. It also magically causes the call to block!
(brief pause for you to consider the API before I suggest a shameful implementation)
Actually capture() returns a proxy object that converts to UniqueFunction. The proxy object itself has a destructor that blocks on the UF being invoked. The proxy will be destroyed at the end of the full-expression, i.e. the line. e.g.
This is a little bit magic, but it's just for tests :-)
(One caveat - this needs the return value to be default-constructible. We could easily use Optional instead, but these are default-constructible in practice)