[PATCH] D43068: [clangd] Remove codeComplete that returns std::future<>

Ilya Biryukov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 12 03:40:35 PST 2018


ilya-biryukov added inline comments.


================
Comment at: unittests/clangd/SyncAPI.h:1
+//===--- SyncAPI.h - Sync version of ClangdServer's API ----------*- C++-*-===//
+//
----------------
sammccall wrote:
> 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:
> 
> ```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)
As discussed offline, I've opted for both:
  - implementing the helper to allow reusing the future/promise code
  - providing a function that actually returns the value synchronously.

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.


Repository:
  rL LLVM

https://reviews.llvm.org/D43068





More information about the llvm-commits mailing list