The question was not which library could present an AST for all those languages, but which kind of library format can be consumed from all those languages. And ideally without FFI and writing complex wrappers. C libraries non very convenient to use from C#, JVM, JS (node.js) or sometimes it isn't even possible (e.g. for JS in the browser).
The question is important, because otherwise one would constrain editors to be written only in a language which is compatible to the library format.
Using C libraries from C# or the JVM is very convenient, even today. There’s even automated systems to generate the entire bindings for the JVM, I’ve written bindings myself for a few libraries. You can just generate the interface file for Java from the .h with JNAerator, import it, and you’re done.
It does. Because there’s also libraries to automatically spawn a separate JVM and communicate with that via an IPC system. Or even spawn other things.
But if you want a system where I have to transfer gigabytes via a JSON IPC bus every minute, sure. That’s totally not going to destroy performance in projects that are several millions of code long with major auto-generated assets.
The language server protocol is useless for larger interwoven projects. The same issue appears already with JetBrains Rider (a C# IDE where the C# parser is implemented in a separate process)
Because tiny changes can have major effects, for example, if you use templating (or Java annotation processing) and change a template that’s used everywhere.
The IDE has to always stay responsive, no matter what is happening, no matter how large the change is.
Such a change may have a huge impact on the internal state of the language server. But on protocol side it's probably minor. You should just one relevant piece of the new state on the next Goto Definition / Auto completion / etc. request. No need to stream the whole new state from the language server to the client on each update.
My current estimation is that the protocol costs are O(1) regarding project size.
The developer of the rust plugin for KDevelop said he had to rebuild half of the rust parser because the language server protocol is so completely inadequate that it can't even be used to implement half of KDevelops features.
Same with stuff like data stream analysis, how does the language server protocol let you mark a variable and see a graph of where it comes from, and how it's transformed? How do you get proper structural autocomplete?
For many features the IDE needs actual full access to the AST. The language server protocol doesn't provide that, so you have to reimplement half of the language server in your own IDE plugin. And it's far too slow.
The language server protocol is comparable in quality to Kate's language plugins, which is okay for an editor, but completely unacceptable for an IDE. You can't do proper structural refactoring either. Proper structural extraction, proper autocomplete or ast transformations, automated inline functionality across files.
For a lot of functionality you end up having to try and get the AST back from the autocomplete and cursor info that the LSP gives you to fill the IDEs internal data structures, which is ugly, painful, and slow.
I've read the article and I partly agree with the author: To get the best-possible IDE experience you will need more information than LSP provides.
However I disagree that LSP is completely unacceptable for IDEs. I work daily with VSCode and it's LSP based language support for Typescript, C# and others. The amount of IDE features that I get for Typescript is higher than what lots of real IDEs provide for their inbuilt languages. The quality of the LSP based addons seems mainly to depend on the implementation of the language servers and not on the protocol, e.g. the language server experience for TS is top-notch, the one for C# is OK-ish and the one for C++ is pretty weak.
I see no problem on integrating any-kind of auto-complete support through LSP: The IDE/Editor just sends the position inside a document which needs to be completed and the language server responds with all possible suggestions. There's absolutely no need to store an AST in the editor for that. The AST can stay in the language server for that. It's the same for references to types, refactoring commands, etc. Yes, if someone needs some non-standard "data stream analysis" the command and results for that might not yet be standardized in LSP - but they could be added if it's worth it for the users. And I guess one can also have non-standardized optional extension APIs between a language server and an editor. In the end it's the same: The editor asks the language server (which has full access to AST): Give me "a graph of where the variable comes from, and how it's transformed", and the language server responds in a well-defined way which the editor just needs to render.
And back to the article: The point of the article is not necessarily that a Rust Language Service plugin wouldn't be good enough for 90% of all users. From my point of view it's more that the author is excited about implementing language support themself in their preferred way and as perfect as possible. That's an absolutely reasonable thing. If one is interested in implementing type-interference for Rust or other complex languages themselves then I'm sure it's a great learning experience. However it will also be LOTS of work, which for a huge language as Rust might be outside of the scope which most mortal developers will be able to do in their private time. If the end result is a half-baked implementation for an IDE which is more buggy or has less features than a language-server based solution (which could be shared between multiple IDEs), then nothing has been won. The language server approach helps here in a way that instead of many 30% language implementations (or even abondoned ones) in singular IDEs work can be contracted on one LSP implementation, which might reach 70-80% feature set.
> The IDE/Editor just sends the position inside a document which needs to be completed and the language server responds with all possible suggestions. There's absolutely no need to store an AST in the editor for that. The AST can stay in the language server for that. It's the same for references to types, refactoring commands, etc. Yes, if someone needs some non-standard "data stream analysis" the command and results for that might not yet be standardized in LSP - but they could be added if it's worth it for the users. And I guess one can also have non-standardized optional extension APIs between a language server and an editor. In the end it's the same: The editor asks the language server (which has full access to AST): Give me "a graph of where the variable comes from, and how it's transformed", and the language server responds in a well-defined way which the editor just needs to render.
That would be pretty stupid, though, as every language server would duplicate a massive amount of code.