Expert LSP
repository·main·Indexed 24 days ago
https://github.com/expert-lsp/expertA 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.
What's inside Expert
- 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.
Overview of Expert
mainExpert is a Language Server Protocol (LSP) implementation designed to provide language intelligence and tooling for the Expert language.Understand the Expert search index and Entry struct
mainExpert maintains a persistent search index in the project's
.expert/indexes/etsdirectory. The indexer scans.exand.exsfiles to createForge.Search.Indexer.Entryvalues, which can be queried viaEngine.Search.Store.Each
Entrycontains:type: Describes the kind of information (e.g., module, function, struct).subtype: Indicates if the entry is adefinitionor areference.
For example, a module definition
MyApp.Userand a function definitionMyApp.User.new/1are stored as separate entries. A call to that function in another file is stored as an entry with thereferencesubtype.How Expert handles project compilation
mainExpert performs two types of compilation to ensure accurate code intelligence (especially for macros and metaprogramming):
- Document compilation: Triggered via
Engine.Build.Documentfor eligible open documents (e.g., after atextDocument/didChangeifcompileOnTypeis enabled). This provides file-level diagnostics without a full build. - 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 compilein the engine node using a versionedMIX_BUILD_PATH(stored under.expert/build).
After full compilation, Expert runs
mix loadpathsand refreshes loaded module data to enable features like docstring extraction and type information lookup.- Document compilation: Triggered via
Understand expert_credo diagnostic behavior
mainThe
expert_credoplugin 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.
Understand Expert's Document and Diagnostic abstractions
mainExpert 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.Documentstructs. - Diagnostics: Represents compiler errors or warnings. Note that diagnostic objects are only valid within the scope of a specific resource.
- Documents: A single file identified by a URI containing textual content. In Expert, these are modeled as
Understand Language Server Protocol (LSP) message types in Expert
mainExpert 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.
How Expert's Manager and Engine architecture works
mainExpert 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
XPprefix) to prevent collisions with the user's project code. Communication between nodes occurs via distributed Erlang RPC using an EPMDless setup viaForge.EPMDandForge.NodePortMapperto avoid system-wide EPMD interference.Understand the Project node and its isolation
mainWhen an Elixir project is opened in Expert, the system starts a new, isolated Elixir node called the Project node. This node runs the
engineapplication 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.logfile located in the root of your project.Understand Code Mods
mainCode Mods are modules defined in the
enginesub-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 Documentin VSCode). - Prefixing unused variables with an
_.
- Formatting code (e.g., triggered by
Build Expert from source (Plain release)
mainYou can build a regular release optimized for your current system using
just.- Run the release command:
just release - Locate the executable in
apps/expert/_build/prod/rel/plain/start_expert. - Point your editor to this
start_expertbinary.
Important: If your editor does not automatically handle the communication protocol, you must pass the
--stdioflag to the Expert binary.just release- Run the release command:
Download Expert nightly builds
mainTo 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/expertOnce downloaded, configure your editor to use this binary.
gh release download nightly --pattern 'expert_linux_amd64' --repo expert-lsp/expert