Evaluation of the Language Server Protocol for Static Dependency Analysis
Researchers as well as practitioners often use static dependency graphs as a foundation for their investigations on the structure of a program. They are gathered by compiler-like static analyzers that are specific to a program language. If more than one program language is to be analyzed, different static analyzers need to be used, each having its own data structures and APIs, which increases the integration effort.
To reduce this integration effort to a minimum, a standard mechanism to obtain dependency information would be of great help. The language server protocol (LSP) is such a standardized mechanism. It was developed in the context of multi-language integrated development environments (IDE) to implement interactive features such as auto-complete or code navigation.
In this paper, we investigate whether LSP can be used to create static dependency graphs in a non-interactive way for C++, C#, Go, Java, JavaScript/TypeScript, Python, and Rust. Our use case differs from LSP’s original purpose by the magnitude of the queries for nodes and edges, potentially bringing them to its limits. We assess the scalability of the various language servers available for these languages and take a look at how various size metrics effect the different run-time phases.
We found that LSP is a real help in integrating different tools to create static dependency graphs in a uniform way. Adding a different language server for a new language requires very little effort. Yet, scalability is a real issue. The gathering of the dependency data can take hours for large projects. The expected run-time for the analyses can be predicted as a linear function of the lines of code or number of files to be processed such that one can estimate in advance when a result can be expected.