[PATCH] D29886: [clangd] Wire up ASTUnit and publish diagnostics with it.
Manuel Klimek via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 14 07:04:32 PST 2017
klimek added inline comments.
================
Comment at: clangd/ASTManager.cpp:69
+ // our one-element queue is empty.
+ if (!RequestIsPending && !Done)
+ ClangRequestCV.wait(Lock);
----------------
arphaman wrote:
> 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)`.
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.
================
Comment at: clangd/ASTManager.cpp:70
+ if (!RequestIsPending && !Done)
+ ClangRequestCV.wait(Lock);
+
----------------
arphaman wrote:
> 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.
Yep, +1, the general pattern is to put while loops around.
It might actually be simpler to write that with a queue from the start (note that this would make the request queueing side somewhat less simple):
... 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; });
================
Comment at: clangd/ASTManager.cpp:116
+ Diagnostics.pop_back(); // Drop trailing comma.
+ this->Output.writeMessage(
+ R"({"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":")" +
----------------
One question is whether we want to couple this to JSON, or have structured output that we serialize.
(I'm happy with doing this now, and refining later - doesn't seem super hard to switch)
================
Comment at: clangd/ASTManager.h:34
+
+ void onDocumentAdd(StringRef Uri, const DocumentStore &Docs) override;
+ // FIXME: Implement onDocumentRemove
----------------
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.
================
Comment at: clangd/ASTManager.h:67
+ /// Setting Done to true will make the worker thread terminate.
+ std::atomic<bool> Done;
+};
----------------
arphaman wrote:
> It looks like `Done` is always accessed in a scope where `RequestLock` is locked, so `atomic` doesn't seem needed here.
Yea, after only having read this header, it looks like we might want to pull out a Request as an abstraction.
================
Comment at: clangd/ClangDMain.cpp:32
+ auto *AST = new ASTManager(Out, Store);
+ Store.addListener(std::unique_ptr<ASTManager>(AST));
JSONRPCDispatcher Dispatcher(llvm::make_unique<Handler>(Out));
----------------
krasimir wrote:
> Why not directly `Store.addListener(llvm::make_unique<ASTManager>(Out, Store));`?
Why's the ASTManager not on the stack?
================
Comment at: clangd/DocumentStore.h:39
+ for (const auto &Listener : Listeners)
+ Listener->onDocumentAdd(Uri, *this);
+ }
----------------
krasimir wrote:
> Is only the main thread supposed to addDocument-s? Otherwise the listener notifications might need to be guarded.
It would always be the responsibility of the callee to guard.
================
Comment at: clangd/DocumentStore.h:42
/// Delete a document from the store.
- void removeDocument(StringRef Uri) { Docs.erase(Uri); }
+ void removeDocument(StringRef Uri) { Docs.erase(Uri);
+ for (const auto &Listener : Listeners)
----------------
krasimir wrote:
> cierpuchaw wrote:
> > cierpuchaw wrote:
> > > Shouldn't this be called under a lock_guard?
> > I should've reworded my comment before submitting it. By 'this' I'm referring to the 'Docs.erase()' part, not the whole function.
> >
> Even under a guard, it may potentially still be unsafe since workers may operate on erased/modified StringRef-s.
That depends on the guarantees made, and when we create copies :)
https://reviews.llvm.org/D29886
More information about the cfe-commits
mailing list