Expert LSP

repository·main·Indexed 24 days ago

https://github.com/expert-lsp/expert

A Language Server Protocol (LSP) implementation providing real-time feedback, diagnostics, and language intelligence for Elixir. It includes an Engine for runtime support and the expert_credo plugin for integrating Credo linting into the developer workflow.

Tokens
8.2K
Snippets
10
Records
77
Agent score
83%

What's inside Expert

  1. Overview of the Expert Engine

    main
    The Engine is a specialized application designed to be injected into a project's virtual machine. Its primary purpose is to provide the underlying support and runtime capabilities required for the language server to function within that project.
  2. Understand the Expert search index and Entry struct

    main

    Expert maintains a persistent search index in the project's .expert/indexes/ets directory. The indexer scans .ex and .exs files to create Forge.Search.Indexer.Entry values, which can be queried via Engine.Search.Store.

    Each Entry contains:

    • type: Describes the kind of information (e.g., module, function, struct).
    • subtype: Indicates if the entry is a definition or a reference.

    For example, a module definition MyApp.User and a function definition MyApp.User.new/1 are stored as separate entries. A call to that function in another file is stored as an entry with the reference subtype.

  3. How Expert handles project compilation

    main

    Expert performs two types of compilation to ensure accurate code intelligence (especially for macros and metaprogramming):

    1. Document compilation: Triggered via Engine.Build.Document for eligible open documents (e.g., after a textDocument/didChange if compileOnType is enabled). This provides file-level diagnostics without a full build.
    2. Full project compilation: Triggered when an engine starts, a project build is explicitly requested, or a file in a Mix project is saved. This runs mix compile in the engine node using a versioned MIX_BUILD_PATH (stored under .expert/build).

    After full compilation, Expert runs mix loadpaths and refreshes loaded module data to enable features like docstring extraction and type information lookup.

  4. Understand expert_credo diagnostic behavior

    main

    The expert_credo plugin runs Credo checks in real-time as you type.

    Important Note on File Ignored Settings: Because Expert sends the file's contents to Credo via standard output (rather than reading the file from disk), Credo loses the context of the filename. Consequently, Credo cannot determine if a file is currently ignored by your project settings. You may see Credo errors in ignored files while typing; these errors will automatically disappear once you save the file to disk.

  5. Understand Expert's Document and Diagnostic abstractions

    main

    Expert uses specific abstractions to model LSP concepts:

    • Documents: A single file identified by a URI containing textual content. In Expert, these are modeled as Expert.Document structs.
    • Diagnostics: Represents compiler errors or warnings. Note that diagnostic objects are only valid within the scope of a specific resource.
  6. Understand Language Server Protocol (LSP) message types in Expert

    main

    Expert implements the Language Server Protocol (LSP) using GenLSP. All messages exchanged between the client and the server are formatted as JSON-RPC 2.0.

    LSP messages fall into three top-level categories:

    • Requests: Sent from client to server (or vice versa) that must be answered with a Response.
    • Responses: The mandatory answer to a Request.
    • Notifications: Bi-directional messages that act like events and do not receive responses.

    Common actionable messages include Completion Requests, Goto Definition Requests, and WillSaveTextDocument Notifications.

  7. How Expert's Manager and Engine architecture works

    main

    Expert uses a split-node architecture to provide accurate Elixir code intelligence while maintaining isolation from the project being analyzed:

    • Manager node: Runs the language server, manages LSP transport (stdio or TCP), tracks editor state, and routes requests.
    • Engine node: Runs ElixirSense, indexes the project, compiles project code, and executes code-intelligence work within the project's specific context.

    This separation allows Expert to build the engine using the project's specific Elixir and Erlang/OTP versions and to namespace Expert's own modules (using an XP prefix) to prevent collisions with the user's project code. Communication between nodes occurs via distributed Erlang RPC using an EPMDless setup via Forge.EPMD and Forge.NodePortMapper to avoid system-wide EPMD interference.

  8. Understand the Project node and its isolation

    main

    When an Elixir project is opened in Expert, the system starts a new, isolated Elixir node called the Project node. This node runs the engine application and is separate from the main Expert node.

    Responsibilities of the Project node:

    • Compiling the project's code.
    • Gathering code intelligence information using ElixirSense.
    • Providing an API for the language server to interact with the project.

    Logs: You can find the logs for the Project node in the .expert/project.log file located in the root of your project.

  9. Understand Code Mods

    main

    Code Mods are modules defined in the engine sub-app that are executed within the project's virtual machine. They are designed to transform existing code.

    Workflow: A Code Mod takes a document, modifies it, and returns diffs.

    Examples:

    • Formatting code (e.g., triggered by Format Document in VSCode).
    • Prefixing unused variables with an _.
  10. Build Expert from source (Plain release)

    main

    You can build a regular release optimized for your current system using just.

    1. Run the release command:
      just release
    2. Locate the executable in apps/expert/_build/prod/rel/plain/start_expert.
    3. Point your editor to this start_expert binary.

    Important: If your editor does not automatically handle the communication protocol, you must pass the --stdio flag to the Expert binary.

    just release
  11. Download Expert nightly builds

    main

    To test the latest features, you can download a nightly build using the GitHub CLI (gh). Use the following command to download the latest Linux amd64 nightly build:

    gh release download nightly --pattern 'expert_linux_amd64' --repo expert-lsp/expert

    Once downloaded, configure your editor to use this binary.

    gh release download nightly --pattern 'expert_linux_amd64' --repo expert-lsp/expert