This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Wire up ASTUnit and publish diagnostics with it.
ClosedPublic

Authored by bkramer on Feb 13 2017, 2:29 AM.

Diff Detail

Repository
rL LLVM

Event Timeline

bkramer created this revision.Feb 13 2017, 2:29 AM
cierpuchaw added inline comments.
clangd/DocumentStore.h
42 ↗(On Diff #88171)

Shouldn't this be called under a lock_guard?

cierpuchaw added inline comments.Feb 13 2017, 7:30 AM
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.

ioeric added a subscriber: ioeric.Feb 13 2017, 8:10 AM
ioeric added inline comments.
clangd/ASTManager.cpp
21 ↗(On Diff #88171)

Any reason not to wrap code in namespaces instead?

krasimir added inline comments.Feb 13 2017, 8:34 AM
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?

arphaman added inline comments.
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.

krasimir added inline comments.Feb 14 2017, 3:40 AM
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.

klimek added inline comments.Feb 14 2017, 7:04 AM
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.
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; });
116 ↗(On Diff #88171)

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)

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 :)

bkramer updated this revision to Diff 88515.Feb 15 2017, 5:42 AM
bkramer marked 16 inline comments as done.
  • 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.

cierpuchaw added inline comments.Feb 15 2017, 5:55 AM
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 '{'.

bkramer updated this revision to Diff 88522.Feb 15 2017, 6:37 AM
  • Do not lock while running DocumentStore callbacks
  • Replace fake queue with a real queue (but it still has at most one element.
klimek added inline comments.Feb 15 2017, 6:48 AM
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 :)

bkramer updated this revision to Diff 88523.Feb 15 2017, 6:54 AM
  • Inline the request struct again.
klimek accepted this revision.Feb 15 2017, 7:00 AM

lg

clangd/ASTManager.cpp
138–139 ↗(On Diff #88523)

deque has resize *ducks and runs*

This revision is now accepted and ready to land.Feb 15 2017, 7:00 AM
krasimir accepted this revision.Feb 15 2017, 7:02 AM
This revision was automatically updated to reflect the committed changes.