lsp-mode Documentation

Emacs client/library for the Language Server Protocol

5,100 stars Emacs Lisp 1 file ยท ~6,462 tokens #angular#cpp#dart#emacs#eslint#golang#html#java
RAW Doc

File: README.md


title: LSP Mode - Language Server Protocol support for Emacs root_file: README.md




Language Server Protocol Support for Emacs



Why?

  • :heart: Community Driven
  • :gem: Fully featured - supports all features in Language Server Protocol v3.14.
  • :rocket: Fast - see performance section.
  • :star2: Flexible - choose between full-blown IDE with flashy UI or minimal distraction free.
  • :gear: Easy to configure - works out of the box and automatically upgrades if additional packages are present.

Overview

Client for Language Server
Protocol

(v3.14). lsp-mode aims to
provide IDE-like experience by providing optional integration with the
most popular Emacs packages like company, flycheck and projectile.

  • Non-blocking asynchronous calls
  • Real-time Diagnostics/linting via
    flycheck (recommended) or
    flymake when Emacs > 26 (requires flymake>=1.0.5)
  • Code completion - company-capf / completion-at-point (note that
    company-lsp is no
    longer supported).
  • Hovers - using lsp-ui
  • Code actions - via lsp-execute-code-action, modeline (recommended) or lsp-ui sideline.
  • Code outline - using builtin
    imenu
    or helm-imenu
  • Code navigation - using builtin
    xref,
    lsp-treemacs tree views
    or lsp-ui peek functions.
  • Code lens
  • Symbol highlights
  • Formatting
  • Project errors on modeline
  • Debugger - dap-mode
  • Breadcrumb on headerline
  • Helm integration -
    helm-lsp
  • Ivy integration - lsp-ivy
  • Consult integration - consult-lsp
  • Treemacs integration -
    lsp-treemacs
  • Semantic tokens as defined by LSP 3.17 (compatible language servers include recent development builds of clangd and rust-analyzer)
  • which-key integration
    for better discovery
  • iedit
  • dired
  • ido

Presentations/demos

See also

  • lsp-docker - provide
    docker image with preconfigured language servers with corresponding
    emacs configuration.
  • company-box -
    company frontend with icons.
  • dap-mode - Debugger
    integration for lsp-mode.
  • eglot -
    A minimal LSP implementation built in to Emacs.
  • which-key - Emacs
    package that displays available keybindings in popup
  • projectile - Project
    Interaction Library for Emacs
  • emacs-tree-sitter - Faster, fine-grained code highlighting via tree-sitter.
  • gccemacs - modified Emacs capable of compiling and running Emacs Lisp as native code.

Contributions

Contributions are very much welcome!

NOTE
Documentation for clients is generated from doc comments in the clients
themselves (see
lsp-doc.el)
and some metadata (see
lsp-clients.json)
so please submit corrections accordingly.

Support the project

The emacs-lsp organization has more than 20,000 lines of code, to keep all of this working,
we need to implement new features and help the community on a lot of issues.

You can help us keep going and improving it by supporting the project

Members

Here is a list of the current lsp-mode members and what they are
primarily working on/responsible for.

| totbwf

text
F# | **brotzeit**
    
    
    Rust | **dsyzling**
    
    
    Scala | **kurnevsky**
    
    
    Scala   Rust | **seagle0128**
    
    
    Go   Python MS |

| --- | --- | --- | --- | --- |
| sebastiansturm

text
lsp-mode core   C++ | **vibhavp**
    
    
    lsp-mode core | **yyoncho**
    
    
    lsp-mode core   Java | **ericdallo**
    
    
    Dart/Flutter   Clojure | **danielmartin**
    
    
    C++   Swift |

| kiennq

text
completions   pwsh | **nbfalcon**
    
    
    lsp-mode core   iedit | **psibi**
    
    
    Terraform   Nix | **razzmatazz**
    
    
    C#   F# | **jcs090218**
    
    
    lsp-mode core |

File: docs/blog/2020/7.0-release.md


template: comment.html

7.0 Release

I am pleased to announce lsp-mode 7.0!

Here are the most important features/news in 7.0 release

lsp-mode/the team/the ecosystem

lsp-mode team and the activity in the repo has vastly increased. lsp-mode is
no longer one man project but it is a product of Emacs LSP team and emacs
community. This has allowed us to implement some very time consuming
changes/refactoring(more about them bellow) which an year ago were unthinkable
due to the lack manpower. emacs-lsp repo has become a nice place to start
contributing to open source or learn elisp and now there are 244 contributors
in the main repo. Even more some of the current maintainers had zero elisp
knowledge before doing their first lsp-mode contributions.

We started moving out some of the server specific packages(e. g. lsp-dart
maintained by ericdallo and lsp-metals
maintained by kurnevsky, lsp-python-ms
by seagle0128, etc) in order to provide focused
support by a an expert in the language at hand. Considering where we were few months ago the
level of integrated experience provided by those packages has increased and
often it is comparable with backed by paid full time developers editors like
VScode. Here it is a gif illustrating that: lsp-dart.
LSP in its nature should be language agnostic but in order to be comparable with VScode
lsp-mode should support language server extensions as well which is much more
work than the work on protocol itself and requires a constant monitoring of the
server repo since there is no contract and the server team might change the
contract whenever they want. On the bright side lsp-mode has attracted several
server side developers or lsp-mode team members(e. g. mpanarin)
has become server side contributors and often we are ahead of changes or we directly
address issues in the server when they arise. We are still looking for
maintainer(s) for JS/TS suite(typescript-language-server, eslint, angular)
though.

Major features

3.16 spec support

We provided full support for 3.14 features one year after the version has been
released. Now, we have support for all major features of 3.16 protocol even
before it has been released (except for result streaming which apparently hasn't
been implemented by any language server).

New website

It is created ericdallo - here it is the website.
Check it out and eventually provide feedback.

Semantic highlights

This is part of 3.16 spec. It is implemented by sebastiansturm
and it can be enabled by setting lsp-enable-semantic-highlighting. We have dropped the Theia
protocol support for semantic highlighting since it is not going to make to the
official spec. ATM it is supported by Rust Analyzer, Clangd(from master
branch) and lua language server.

org-mode integration(preview)

org-mode mode is the Emacs flagman and this integration brings up the
literate programming to a new level. The integration is pretty raw but usable -
you basically can run lsp-mode language intelligence over org-mode source
block directly in the org-mode document. We have achieved that by creating
virtual buffer abstraction which allows us to fake the server that the client
has actually opened the real file.

Check gif and the docs.

I think that the ability to implement such features is why Emacs is editor in
a league of its own
. And implementing such features is one of the signs that we
are slowly moving from the phase catching up into getting ahead (or maybe I
am overly optimistic).

Language Server Protocol bindings, upcoming changes

We generated json schema from the protocol and from that schema we generated
dash destructoring, getters, setters, validators, constructors, indication for
optional/required fields, etc. which allow us to perform compile time validation
of the protocol usage. This was huge change because we had to walk through
almost all methods and replace explicit access to the elisp data structure with
protocol usage. At the same time, emacs-lsp organization has more than 20k
lines of code. This was coordinated effort and a lot of individuals contributed
to that. The benefits are that we now can switch the underlying data structure
from hashmap to plists which will yield better performance and also that the
overall quality of the codebase has increased. Example

Before:

emacs-lisp
(defun lsp--position-to-point (params)
  "Convert Position object in PARAMS to a point."
  (lsp--line-character-to-point (gethash "line" params)
                                (gethash "character" params)))

After:

emacs-lisp
(lsp-defun lsp--position-to-point ((&Position :line :character))
  "Convert `Position' object in PARAMS to a point."
  (lsp--line-character-to-point line character))

In this example :line and :character are validated as fields of Position
structure. Also, we do some handy conversions, if the field is optional it will
end up with ? like :foo?. To reduce boiler plate code we convert camelCase
to :camel-case when we are destructoring it.

Performance optimizations(flycheck, code completion)

We have rewritten the flycheck integration - the new integration provides the
same UE as the old one but it is much more effective in reporting the errors
to flycheck and lsp checker is much closer to the traditional flycheck
checkers which are initiated/controlled from Emacs. Completion integration
code is now much simpler/faster thanks to kiennq.

What's next

  • Upcoming breaking changes
    • Dropping Emacs 25 support. This will allow us utilize Emacs multi-threading
      to improve lsp-mode responsibility
    • Switching from hashtables to plists - once this change goes in users must
      recompile all lsp-mode extensions.
    • Drop company-lsp support(not ported to use lsp-protocol.el)
  • Implementing lsp-mode configuration wizard to improve beginners experience -
    check this issue for more
    details. The overall goal is let user pick settings for all features that are
    opinionated (e. g. lsp-ui) and improve the discoverability of lsp-mode
    features/extensions/settings.
  • We will try to switch to monthly/weakly release cycles and to different person
    for writing the announcements. We might eventually encourage melpa-stable
    usage.

File: docs/manual-language-docs/lsp-gopls.md


root_file: docs/manual-language-docs/lsp-gopls.md

Go (gopls)

lsp-mode provides Go language support via the
gopls language
server. See
upstream
for gopls installation instructions.

Configuration

By default, some
gopls analyzers
are enabled and others are disabled. To override, use:

text
(setq lsp-go-analyses '((shadow . t)
                        (simplifycompositelit . :json-false)))

Troubleshooting

Working with nested go.mod files

If you encounter an error like one of these:

  • errors loading workspace: You are working in a nested module. Please open it as a separate workspace folder
  • This file is in %s, which is a nested module in the %s module. gopls currently requires one module per workspace folder. Please open %s as a separate workspace folder

Then the problem is most likely because lsp-mode has not started
gopls with the correct root directory. By default lsp-mode will pick
the root of your whole Git repository (or whatever else Projectile
turns up) for all language servers started inside the repo. However,
if you have nested go.mod files, you need to have lsp-mode start
separate instances of gopls for each nested go.mod, and use the
appropriate one for each file. You can make this work by manually
invoking M-x lsp-workspace-folders-add and adding each nested
go.mod directory as a workspace folder. Then reloading LSP with M-x lsp in an affected file (or restarting Emacs) will cause the file to
be re-associated with a gopls process running under the correct
project workspace.

See #3473 for a
bit more discussion of this particular issue.


File: docs/manual-language-docs/lsp-json-ls.md


root_file: docs/manual-language-docs/lsp-json-ls.md

Completions

json-ls (vscode-json-language-server) provides completions for well known files and files which manually specify their JSON Schema using the $schema property.

In order for json-ls to provide completions, you need to enable snippet support. To do that, make sure you have installed yasnippet and that you have enabled the yasnippet minor mode.


File: docs/manual-language-docs/lsp-latex.md


root_file: docs/manual-language-docs/lsp-latex.md

lsp-latex.el: texlab LSP-client

See lsp-latex.el homepage.


File: docs/manual-language-docs/lsp-ocaml.md


author: mattiasdrp template: comment.html root_file: docs/manual-language-docs/lsp-ocaml.md

ocaml-lsp-server

Commands

`lsp-ocaml-type-enclosing`

Gets the type of ident under the cursor. It will highlight the ident and display its type.

When this function is called it will create a transient keymap lsp-ocaml-type-enclosing-map that allows to do the following things:

  • Increase/decrease the number of aliases expansions. As an example, suppose we want to type h in the following expression:
    ocaml
    type t = A | B
    let h : t = A
    • The lowest verbosity will give type t
    • The next verbosity will give type t = A | B
  • Go up/down the enclosing type (bound to C-/<down> by default). As an example:
    ocaml
    module A = struct
      let h : t = A
      let f () = ()
    
      (** Test doc *)
      let g (f: 'a -> 'b) a = f a
    end
    • Typing on the last a will show 'a
    • Going up will highlight f a of type 'b
    • Going up will highlight (f: 'a -> 'b) a = f a of type ('a -> 'b) -> 'a -> 'b
    • Going up will highlight the whole module and display its entire type
  • Copy the current type (bound to C-w by default)

`lsp-ocaml-find-alternate-file`

Find the interface corresponding to an implementation or the implementation corresponding to an interface.


File: docs/manual-language-docs/lsp-org.md


root_file: docs/manual-language-docs/lsp-org.md

Literate programming using LSP and org-mode(alpha)

lsp-mode provides experimental support for running the language servers
inside of org-mode source blocks. lsp-mode is
achieving this by obtaining the information about the source block from the
source block header(language + :tangle) then translating the point to the LSP
positions back and forth so the language server thinks that Emacs has opened the
original file. For this to work, the files have to be present on the disk as
well because the server expects to find them.

Here is a sample source block:

org
#+BEGIN_SRC python :tangle "python.py"
print "Hello!"
#+END_SRC

Demo

Commands

  • lsp-org start lsp-mode in source buffer. Must be executed with cursor
    being source block.
  • lsp-virtual-buffer-disconnect turn off lsp-mode.

What works

  • lsp-mode core features (finding references, going to definitions, completion, lenses, highlighting, etc)
  • company-mode
  • flycheck
  • lsp-treemacs-symbols
  • lsp-treemacs-errors-list

Known limitations

  • Incremental updates are performed by sending the whole
    buffer each time(they simulate full updates).
  • Deleting content that spans across the source block and the content of the org
    document is not handled.
  • Opening and editing the actual file from the disk might cause undefined
    behaviour because the server expects file to be open only once.

What does not work

  • dap-mode
  • lsp-ui
  • flymake(?)

What's next

  • Finishing the virtual buffers API.
  • lsp-ui support
  • dap-mode support
  • markdown-mode integration

File: docs/manual-language-docs/lsp-rust-analyzer.md


author: yyoncho template: comment.html root_file: docs/manual-language-docs/lsp-rust-analyzer.md

Server note

NOTE: If you are using rustic-mode, you have to change rustic-lsp-server instead of lsp-rust-server, since it also supports eglot as a lightweight alternative to lsp-mode.

  • lsp-rust-server Choose LSP server (default is rust-analyzer)

  • lsp-rust-switch-server Switch priorities of lsp servers

rust-analyzer

Commands

`lsp-rust-analyzer-syntax-tree`

Display syntax tree for current buffer

`lsp-rust-analyzer-status`

Display status information for rust-analyzer

`lsp-rust-analyzer-join-lines`

Join selected lines into one, smartly fixing up whitespace and trailing commas

before:

after:

inlay-hints

lsp-inlay-hints-mode enables displaying of inlay hints

Additionally, lsp-inlay-hint-enable must be set to t in order for inlay hints to render.

NOTE: the inlay hints interact badly with the lsp-ui sideline, because it doesn't seem to consider the overlays in its width calculation, which often leads to lines wrapping around.

Macro expansion

lsp-rust-analyzer-expand-macro expand macro call at point recursively

Use your own function for displaying macro expansion by customizing lsp-rust-analyzer-macro-expansion-method

Formatted and highlighted result with the default function of rustic.

auto-import

Get a list of possible auto import candidates with lsp-execute-code-action

Snippet insertion/refactor

To support refactorings that require snippet insertion(eg. generating
derive clause etc), make sure that you have enabled yasnippet and
yas-minor-mode. If you are using use-package, you can do something
like this:

emacs-lisp
(use-package yasnippet
  :ensure t
  :hook ((lsp-mode . yas-minor-mode)))

Open Cargo.toml

lsp-rust-analyzer-open-cargo-toml opens the Cargo.toml closest to the current file. Calling it with a universal argument will open the Cargo.toml in another window.

Corresponds to the rust-analyzer LSP extension

Open external documentation

lsp-rust-analyzer-open-external-docs opens external documentation related to the current position in a browser.

Corresponds to the rust-analyzer LSP extension

lsp-rust-analyzer-related-tests find all tests related to the current position, asks for user completion and executes the selected test in a compilation buffer.

Corresponds to the rust-analyzer LSP extension

In the example below, first you see that:

  • On the left, the function check_infer is defined, on the right another
    file is opened with many test functions, some of which call check_infer.
    With the cursor on check_infer, call lsp-rust-analyzer-related-tests
    and select infer_pattern_match_slice with fuzzy matching. The test is
    executed on the right with compilation major mode

  • Move the cursor to fn ellipsize and attempt to find related tests to no
    avail. Confirm that the function is indeed untested by using swiper and
    finding one place in the file, where the function is called

Caveats

extract signature

This unmerged PR contains an example method that allows
modifying the signature that is displayed by eldoc.


File: docs/manual-language-docs/lsp-rust-rls.md


root_file: docs/manual-language-docs/lsp-rust-rls.md

RLS

Customization

This is an incomplete list of the available options

  • lsp-rust-rls-server-command change command to start RLS

  • lsp-rust-show-hover-context turn off hover tooltips

rustfmt

Code formatting with rustfmt can be configured with:

lsp-rust-rustfmt-path change default path for rustfmt executable

To enable automatic code format on save, add this to your init.el (rust-mode is assumed to be installed):

text
(add-hook 'before-save-hook (lambda () (when (eq 'rust-mode major-mode)
                                           (lsp-format-buffer))))

File: docs/manual-language-docs/lsp-sqls.md


root_file: docs/manual-language-docs/lsp-sqls.md

Sample configuration:

emacs-lisp
(add-hook 'sql-mode-hook 'lsp)
(setq lsp-sqls-workspace-config-path nil)
(setq lsp-sqls-connections
    '(((driver . "mysql") (dataSourceName . "yyoncho:local@tcp(localhost:3306)/foo"))
      ((driver . "mssql") (dataSourceName . "Server=localhost;Database=sammy;User Id=yyoncho;Password=hunter2;"))
      ((driver . "postgresql") (dataSourceName . "host=127.0.0.1 port=5432 user=yyoncho password=local dbname=sammy sslmode=disable"))))

Storing Configuration in `/.sqls/config.json`

Alternatively, you can store your configuration in the project root at /.sqls/config.json:

text
{
  "sqls": {
    "connections": [
      {
        "driver": "mysql",
        "dataSourceName": "yyoncho:local@tcp(localhost:3306)/foo"
      }, 
      โ€ฆetcโ€ฆ
    ]
  }
}

In this case, you need to set lsp-sqls-workspace-config-path to "root":

emacs-lisp
(setq lsp-sqls-workspace-config-path "root")

Storing Configuration in the Current Directory

If you want to configure it for the current directory, you can create a .sqls/config.json file:

text
.sqls/config.json
target.sql

For this setup, ensure that lsp-sqls-workspace-config-path is set to "workspace":

emacs-lisp
(setq lsp-sqls-workspace-config-path "workspace")

Switching Connections and Databases

Now, lsp should start in sql-mode buffers. You can choose a server connection using M-x lsp-execute-code-action and then selecting "Switch Connections", or directly with M-x lsp-sql-switch-connection.

To change the database, use M-x lsp-execute-code-action and select "Switch Database" (or M-x lsp-sql-switch-database).