This requires an accessible compilation database. The parsing is done
asynchronously on a separate thread.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
| clangd/DocumentStore.h | ||
|---|---|---|
| 42 ↗ | (On Diff #88171) | Shouldn't this be called under a lock_guard? |
| clangd/DocumentStore.h | ||
|---|---|---|
| 42 ↗ | (On Diff #88171) | I should've reworded my comment before submitting it. By 'this' I'm referring to the 'Docs.erase()' part, not the whole function. |
| clangd/ASTManager.cpp | ||
|---|---|---|
| 21 ↗ | (On Diff #88171) | Any reason not to wrap code in namespaces instead? |
| clangd/DocumentStore.h | ||
|---|---|---|
| 42 ↗ | (On Diff #88171) | Even under a guard, it may potentially still be unsafe since workers may operate on erased/modified StringRef-s. |
| 51 ↗ | (On Diff #88171) | StringRef doesn't own the underlying data, right? What if I erase it in the meantime? |
| 63 ↗ | (On Diff #88171) | Same thing, shouldn't these be strings? |
| clangd/ASTManager.cpp | ||
|---|---|---|
| 69 ↗ | (On Diff #88171) | This is just a suggestion based on personal opinion: RequestIsPending and Done can be merged into one enum value that uses an enum like this: enum ASTManagerState {
Waiting, ReceivedRequest, Done
}Then this condition could be rewritten as if (state == Waiting). |
| 70 ↗ | (On Diff #88171) | I believe std::condition_variable may also be unblocked spuriously when wait is called without a predicate, which would lead to an empty File down below. |
| clangd/ASTManager.h | ||
| 67 ↗ | (On Diff #88171) | It looks like Done is always accessed in a scope where RequestLock is locked, so atomic doesn't seem needed here. |
| clangd/ASTManager.cpp | ||
|---|---|---|
| 148 ↗ | (On Diff #88171) | Do you have an idea about a proper error handling if Error? |
| 162 ↗ | (On Diff #88171) | Then maybe we need a big disclaimer comment at the declaration of createASTUnitForFile? |
| clangd/ClangDMain.cpp | ||
| 32 ↗ | (On Diff #88171) | Why not directly Store.addListener(llvm::make_unique<ASTManager>(Out, Store));? |
| clangd/DocumentStore.h | ||
| 39 ↗ | (On Diff #88171) | Is only the main thread supposed to addDocument-s? Otherwise the listener notifications might need to be guarded. |
| clangd/ASTManager.cpp | ||
|---|---|---|
| 69 ↗ | (On Diff #88171) | I'm not so sure. Once we have a queue (iff we ever get a queue), the "request available" is an attribute of the queue, while the "we need to exit" is an attribute of the system. |
| 70 ↗ | (On Diff #88171) | Yep, +1, the general pattern is to put while loops around. ... Lock(RequestLock);
while (Requests.empty() && !Done) {
ClangRequestCV.wait(Lock);
}
if (Done) return;
File = Request.pop_front();
ClangRequestCV.notify_all();
...
the while loop can be written somewhat simpler with the pred version:
ClangRequestCV.wait(Lock, [&] { return !Request.empty() || Done; }); |
| 116 ↗ | (On Diff #88171) | One question is whether we want to couple this to JSON, or have structured output that we serialize. |
| clangd/ASTManager.h | ||
| 34 ↗ | (On Diff #88171) | At a first glance, it's weird that we have a global document store, but get a document store for each notification. This at least needs documentation. |
| 67 ↗ | (On Diff #88171) | Yea, after only having read this header, it looks like we might want to pull out a Request as an abstraction. |
| clangd/ClangDMain.cpp | ||
| 32 ↗ | (On Diff #88171) | Why's the ASTManager not on the stack? |
| clangd/DocumentStore.h | ||
| 39 ↗ | (On Diff #88171) | It would always be the responsibility of the callee to guard. |
| 42 ↗ | (On Diff #88171) | That depends on the guarantees made, and when we create copies :) |
- Address review comments.
| clangd/ASTManager.cpp | ||
|---|---|---|
| 21 ↗ | (On Diff #88171) | I don't really have an opinion one way or the other, but this seems to be the preferred way of doing this in LLVM. |
| 70 ↗ | (On Diff #88171) | Added the lambda. The current state is pretty weird, but making it a queue just to drop random elements from that queue is even weirder :( |
| 148 ↗ | (On Diff #88171) | For now I'll send it to logs() |
| clangd/ASTManager.h | ||
| 34 ↗ | (On Diff #88171) | This is leftover from an earlier design. Removed. |
| 67 ↗ | (On Diff #88171) | Wrapped all the guarded variables in a struct. |
| clangd/ClangDMain.cpp | ||
| 32 ↗ | (On Diff #88171) | Fixed. Lifetime is no longer managed by the DocumentStore (that was a bit weird) |
| clangd/DocumentStore.h | ||
| 39 ↗ | (On Diff #88171) | Added guard for now. |
| 42 ↗ | (On Diff #88171) | Added guard. |
| 51 ↗ | (On Diff #88171) | I guess it makes sense to create copies here. Somewhat sad but safe. |
| 63 ↗ | (On Diff #88171) | Done. |
| clangd/DocumentStore.h | ||
|---|---|---|
| 42 ↗ | (On Diff #88171) | 'Docs.erase(Uri);' is still outside the critical section. It's easy to miss because of its placement directly after '{'. |
- Do not lock while running DocumentStore callbacks
- Replace fake queue with a real queue (but it still has at most one element.
| clangd/ASTManager.h | ||
|---|---|---|
| 67 ↗ | (On Diff #88171) | For me that actually makes it worse (sorry): I now read "Request.Done" and think the request is done :) |
http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/2437 is broken by this revision.