[Python] How to implement an LSP-based static code analyzer with multi-language support...

Discussão em 'Python' iniciado por Stack, Maio 3, 2025.

  1. Stack

    Stack Membro Participativo

    I'm working on a research-driven SaaS tool that analyzes legacy codebases, extracts their architecture, and stores the result in a graph database (Neo4j) for further use with LLMs (e.g., for UML diagram generation or documentation).


    What I'm trying to build:


    • A static analysis module based on LSP (Language Server Protocol).


    • It must support multiple languages — most importantly: C, C++, Python, Fortran, Pascal, COBOL, Perl.


    • The result of the analysis must be unified (e.g., a consistent JSON schema), so I can store it as nodes and edges in Neo4j:
      • Nodes: Function, Class, Module, etc.
      • Edges: CALLS, BELONGS_TO, etc.

    Constraints:

    • The module must be invokable from a Python/FastAPI backend, not via an editor.
    • The codebases can be very large (millions of lines), so performance and scalability matter.
    • LLMs can't ingest entire repositories — so I need to store the whole graph and query small subgraphs dynamically.

    What I’ve tried:


    • Looked into Joern — powerful but heavy and DSL-specific.


    • Tried Fraunhofer CPG — great for C/C++, but JVM-based and not easy to extend to other languages.


    • Found LSP servers for various languages:
      • pyright / pylsp for Python
      • clangd for C/C++
      • fortls for Fortran
      • pasls, cobol-lsp, perl-ls, vb-ls — but limited docs and ecosystem

    Where I'm stuck:

    1. How to programmatically invoke LSP servers (not via VS Code or CLI)?
    2. Are there Python libraries for managing LSP clients (like pygls, lsp-devtools, langchain-lsp, etc.)?
    3. What's the best way to standardize entity extraction across multiple languages?
    4. Are there existing tools/pipelines that go from LSP → JSON → Neo4j, or do I need to write that glue layer?

    My ideal output format looks like this:

    {
    "entities": [
    { "key": "src/foo.c::main", "kind": "Function", "name": "main", "file": "foo.c" }
    ],
    "edges": [
    ["src/foo.c::main", "src/utils.c::init", "CALLS"]
    ]
    }


    This would let me convert arbitrary code into a graph and drive queries to LLMs based on structural relevance.

    I would deeply appreciate:

    • Any pointers on running LSPs headlessly
    • Best practices on parsing LSP output into a unified model
    • Working examples of similar multi-language graph analysis tools
    • Libraries or adapters that simplify building such a pipeline

    Continue reading...

Compartilhe esta Página