Skip to content

Instantly share code, notes, and snippets.

@Nezteb
Last active May 2, 2024 04:21
Show Gist options
  • Star 35 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nezteb/dc63f1d5ad9d88907dd103da2ca000b1 to your computer and use it in GitHub Desktop.
Save Nezteb/dc63f1d5ad9d88907dd103da2ca000b1 to your computer and use it in GitHub Desktop.
Elixir Language Server Comparisons

Elixir Language Server Implementation Comparison

We'll be comparing the following:

Disclaimers:

  • I'm not an LSP expert.
  • There is no "best" Elixir language server implementation.
  • This comparison does not take performance into account.
  • Language servers might support similar features that operate differently.
  • Let me know if anything is incorrect or poorly explained.

Feature Matrix

Legend:

  • ✅: The language server supports it.
  • ⚠️: The language server supports a version of it, but with caveats.
  • ❌: The language server does not support it.
  • ❓: I don't know if the language server supports it.
  • Items that needs more detail will add additional links/notes.
Feature ElixirLS Lexical LSP Next LS Notes/Caveats
Go to definition
Find references
Find implementation
Code folding
Signature help Shows the docs for the completion item and bolds/underlines the parameter you are currently typing
Debugger
Document symbols Power bread crumbs, outline views, and you can use them to fzf to a specific symbol in the document
Workspace symbols ✅ (currently returns inconsistent symbols) Similar to document symbols, but for the whole project and might include different symbols
Workspace (monorepo) support
Workspace commands ✅ (ToPipe, FromPipe, Expand Macro, Restart LSP) ✅ (To Pipe, From Pipe) Usually invoked via a command pallette, sometimes overlap with code actions
Code actions ✅ (Underscore unused variables) ✅ (Underscore unused variables, require module) Generally operates on currently highlighted or right-clicked symbol. Could also include "ignore this error" or "import this module"
Rename symbol
Lenses ✅ (Typespec suggestions, run test overlay)
Code completion ⚠️ (some missing)
Code formatter
Documentation on hover
Compilation diagnostics ✅ (sometimes the Elixir compiler reports an error on one line but the actual cause is elsewhere, in which case Lexical figures this out for you and emits better errors) Need more details on what this is/does
Compilation on save
Compilation on type ⚠️ (enabled via config, recompiles entire project each time, not just the file being edited)
Credo integration ✅ (via plugin)
Dialyzer integration ❌ (tracking issue) ❌ (tracking issue
Ecto integration Gives you some auto-complete for assocs in schema definitions; usually provided via elixir_sense
VS Code integration
Sublime integration
Neovim integration
Vim integration
Emacs integration
Helix integration
Zed integration

Elixir-Specific Functionality

Designing a complete language server for the Elixir programming language would involve implementing many of the standard LSP features but adapted to Elixir's specific constructs and idioms. Here's what such an implementation might cover:

  • Text Synchronization:
    • Keep track of open, change, save, and close events of Elixir source files.
  • Diagnostics:
    • Integrate with Elixir's compiler to provide real-time feedback on warnings and errors.
    • Possibly integrate with other linting or static analysis tools specific to Elixir like Credo.
  • Completion:
    • Offer module, function, variable, and macro completions.
    • Provide context-aware completions for functions from the standard library, installed hex packages, and user-defined modules.
    • Recognize special Elixir constructs, such as sigils or special forms.
  • Hover:
    • Show documentation, types, or related metadata when hovering over a function, macro, module, or variable.
  • Signature Help:
    • Display function signatures, expected arguments, and documentation while typing.
  • Go to Definition:
    • Allow navigation to the definition of a function, macro, module, or variable.
    • Understand and follow aliases and imports in Elixir.
  • Find References:
    • Find all usages of a given function, module, or variable throughout the codebase.
  • Document Highlight:
    • Highlight other occurrences of the selected module, function, variable, or macro in the current file.
  • Document Symbols:
    • List all the functions, macros, and modules defined in the current document.
  • Workspace Symbols:
    • Search for modules or functions throughout the entire project or workspace.
  • Code Action:
    • Suggest fixes for common issues.
    • Offer refactorings, like extracting a function or changing function arity.
    • Integrate with Elixir's formatting tool (mix format) to suggest code format changes.
  • Code Lens:
    • Display reference counts for functions or macros.
    • Indicate test coverage or provide the option to run a particular Elixir test.
  • Document Formatting:
    • Integrate with mix format to automatically format Elixir source code.
  • Rename:
    • Safely rename functions, macros, modules, and variables while considering Elixir's scoping rules.
  • Semantic Tokens:
    • Provide syntax highlighting tokens specific to Elixir's semantics, differentiating functions, macros, module names, and more.
  • Call Hierarchy:
    • Display a tree of function calls, helping users understand the flow of complex Elixir applications.
  • Selection Range:
    • Assist with selecting Elixir-specific constructs like do blocks, case clauses, or entire function bodies.
  • Implementation, Type Definition, and Declaration:
    • While Elixir is dynamically typed, understanding protocols and behaviors can provide insights into types and implementations.
  • Document Link:
    • Link to related documentation or other source files.
  • Color Provider & Folding Range:
    • Not as crucial for Elixir, but can enhance the developer experience in specific contexts.
  • Additionally, for a language like Elixir, there are some domain-specific features that would be valuable:
    • Integration with Mix: Understand project dependencies, run tasks, or even provide diagnostics related to dependency issues.
    • Support for Ecto: Recognize Ecto schemas and queries, provide completions and diagnostics within embedded SQL, etc.
    • Understanding metaprogramming: Elixir's macro system is powerful, so having the language server understand and provide information about macros would be crucial.
    • Integration with ExUnit: Recognize test cases and offer functionality to run tests directly from the editor, display test results, etc.
    • The goal of a complete language server for Elixir would be to provide a seamless and rich development experience that understands and leverages Elixir's unique features and idioms.
@jcowgar
Copy link

jcowgar commented Nov 5, 2023

I use Lexical in Sublime daily. I simply installed LSP-elixir and change the command setting. In fact, I leave both in my config and can quickly switch if I want. To edit the configuration: Preferences > Package Settings > LSP > Servers > LSP-elixir

{
  "command": [
    // "~/Projects/other/elixir-ls/release/language_server.sh"
    "~/Projects/other/lexical/_build/prod/package/lexical/bin/start_lexical.sh"
  ]
}

Now, as you see, I have both projects checked out and will pull down latest changes when I see something of interest.

@nmk
Copy link

nmk commented Nov 11, 2023

The docs for next-ls have been reorganized it seems, the correct link to the completions page should be https://www.elixir-tools.dev/docs/next-ls/completions/.

@Nezteb
Copy link
Author

Nezteb commented Nov 13, 2023

@nmk Thanks for the note; fixed!

@mathieurousseau
Copy link

Seems lexical find_reference PR was merged to main

@Nezteb
Copy link
Author

Nezteb commented Feb 6, 2024

@mathieurousseau Fixed, thanks!

@mhanberg
Copy link

Next LS now supports two code actions (https://www.elixir-tools.dev/docs/next-ls/code-actions/) and two workspace commands (https://www.elixir-tools.dev/docs/next-ls/commands/)

@namxam
Copy link

namxam commented Apr 2, 2024

@Nezteb Lexical just merged document symbol support a few days ago: lexical-lsp/lexical@f7f7693

It adds support for the following symbols:

  • Modules
  • Functions, both private and public
  • Typespecs
  • Module Attributes
  • ExUnit describe / setup / tests

@Nezteb
Copy link
Author

Nezteb commented Apr 6, 2024

@mhanberg @namxam Table has been updated. 😄

@scohen
Copy link

scohen commented May 1, 2024

Lexical now supports

  • Workspace symbols
  • Sublime integration
  • Zed integration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment