This client does not work out-of-the-box with version 9 of Clangd (LLVM). After a bit of bantering about what the LSP protocol means, I learned that the Clangd LSP server, while it follows the LSP spec, it does not follow the intent of the LSP protocol that any client can work with any server. In the spec, TextDocumentSyncKind is used to tell the client whether the server requires open requests and incremental vs. full file content updates. Clangd indicates that it is an “Incremental” server (“Documents are synced by sending the full content on open. After that only incremental updates to the document are send.”) Whether this also means that an open is required even for language feature calls, the spec isn’t so clear-cut, so anyone can interpret the spec however they want. But Clangd assumes it is required, even for language feature requests. As it goes, the server rejects all requests from client after the client/server initialization conversation, so the server never opens the files, never emits a diagnostics notification to the client, and the client never issues any open. It’s a complete stalemate.

The problem here is two-fold: (1) the spec is ambigous, and (2) Clangd assumes the worst case possible, that an open is required even for language feature requests. Unfortunately, open is essentially a locking mechanism, where the “truth” is a “write lock” on the entire contents of the file. Clearly, requiring a write lock on a file in order to use the server for language markup is ridiculous, but I can’t seem to convince anyone that there are multiple problems here. The fact is that Clangd already reads #include files on disk without locking each of those files, a fact the developers ignore.

When I made a change request to Clangd to back off on this assumption, a change that affects 0.5% of the source code, it was rejected based on being too complex. Apparently the authors insist that the client issue an open request immediately after initialization. But, the change does work.

Even with the change, the server took 60+ s to parse and perform semantic analysis of a 7-line “Hello World” program before able to process Language Feature requests. (It was a debug build, so I will check it against a release build.) Pre-indexing with the tool clangd-indexer did not improve the processing time. Surprisingly, in VSCode the server responds in a few seconds.

Based on my interactions with the folks developing Clangd and the LSP spec, it feels they’re okay working with one client–Visual Studio Code–and with a bad spec. If you aren’t aware, MS announced Visual Studio online, with a screenshot that essentially showing the Visual Studio Code UI. It looks the end of days for Visual Studio IDE, and why there needs to be an LSP implementation for Antlr.

One further sidenote: LLVM and the build procedure have completely reorganized since the source code is now on Github.com. To do a build:

1/2: Adding to #Antlrvsix an analysis tool of #Antlr grammars. This is how it works with cycle detection and useless lexer rules. There are some issues in the responsiveness of the MS LSP client for VS2019.

Adding to #Antlrvsix the refactoring to remove useless parentheses in an #Antlr grammar. This is how it works with the extra parentheses in the arrayAccess_lf_primary rule in Java9.g4 that nobody knew were there. Only yet starting to scratch the surface of grammar optimizations.

Implementing #Antlr grammar fold refactorings in #Antlrvsix. Two types: extract a selected sequence of symbols and make a rule (shown first); replace all occurrences in the grammar with a folded rule (shown second). Spacing and comments do not matter.