config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

lsp-rust.el (75304B)


      1 ;;; lsp-rust.el --- Rust Client settings             -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2019  Ivan Yonchovski
      4 
      5 ;; Author: Ivan Yonchovski <yyoncho@gmail.com>
      6 ;; Keywords:
      7 
      8 ;; This program is free software; you can redistribute it and/or modify
      9 ;; it under the terms of the GNU General Public License as published by
     10 ;; the Free Software Foundation, either version 3 of the License, or
     11 ;; (at your option) any later version.
     12 
     13 ;; This program is distributed in the hope that it will be useful,
     14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 ;; GNU General Public License for more details.
     17 
     18 ;; You should have received a copy of the GNU General Public License
     19 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     20 
     21 ;;; Commentary:
     22 
     23 ;; lsp-rust client
     24 
     25 ;;; Code:
     26 
     27 (require 'lsp-mode)
     28 (require 'ht)
     29 (require 'dash)
     30 (require 'lsp-semantic-tokens)
     31 (require 's)
     32 
     33 (defgroup lsp-rust nil
     34   "LSP support for Rust, using Rust Language Server or rust-analyzer."
     35   :group 'lsp-mode
     36   :link '(url-link "https://github.com/rust-lang/rls")
     37   :package-version '(lsp-mode . "6.1"))
     38 
     39 (defgroup lsp-rust-rls nil
     40   "LSP support for Rust, using Rust Language Server."
     41   :group 'lsp-mode
     42   :link '(url-link "https://github.com/rust-lang/rls")
     43   :package-version '(lsp-mode . "8.0.0"))
     44 
     45 (defgroup lsp-rust-analyzer nil
     46   "LSP support for Rust, using rust-analyzer."
     47   :group 'lsp-mode
     48   :link '(url-link "https://github.com/rust-lang/rust-analyzer")
     49   :package-version '(lsp-mode . "8.0.0"))
     50 
     51 (defgroup lsp-rust-analyzer-semantic-tokens nil
     52   "LSP semantic tokens support for rust-analyzer."
     53   :group 'lsp-rust-analyzer
     54   :link '(url-link "https://github.com/rust-lang/rust-analyzer")
     55   :package-version '(lsp-mode . "9.0.0"))
     56 
     57 (defcustom lsp-rust-server 'rust-analyzer
     58   "Choose LSP server."
     59   :type '(choice (const :tag "rls" rls)
     60                  (const :tag "rust-analyzer" rust-analyzer))
     61   :group 'lsp-rust
     62   :package-version '(lsp-mode . "6.2"))
     63 
     64 ;; RLS
     65 
     66 (defcustom lsp-rust-rls-server-command '("rls")
     67   "Command to start RLS."
     68   :type '(repeat string)
     69   :group 'lsp-rust-rls
     70   :package-version '(lsp-mode . "6.1"))
     71 
     72 (defcustom lsp-rust-library-directories
     73   '("~/.cargo/registry/src" "~/.rustup/toolchains")
     74   "List of directories which will be considered to be libraries."
     75   :risky t
     76   :type '(repeat string)
     77   :group 'lsp-rust-rls
     78   :package-version '(lsp-mode . "6.1"))
     79 
     80 (defcustom lsp-rust-sysroot nil
     81   "If non-nil, use the given path as the sysroot for all rustc invocations
     82 instead of trying to detect the sysroot automatically."
     83   :type '(choice
     84           (const :tag "None" nil)
     85           (string :tag "Sysroot"))
     86   :group 'lsp-rust-rls
     87   :package-version '(lsp-mode . "6.1"))
     88 
     89 (defcustom lsp-rust-target nil
     90   "If non-nil, use the given target triple for all rustc invocations."
     91   :type '(choice
     92           (const :tag "None" nil)
     93           (string :tag "Target"))
     94   :group 'lsp-rust-rls
     95   :package-version '(lsp-mode . "6.1"))
     96 
     97 (defcustom lsp-rust-rustflags nil
     98   "Flags added to RUSTFLAGS."
     99   :type '(choice
    100           (const :tag "None" nil)
    101           (string :tag "Flags"))
    102   :group 'lsp-rust-rls
    103   :package-version '(lsp-mode . "6.1"))
    104 
    105 (defcustom lsp-rust-clear-env-rust-log t
    106   "Clear the RUST_LOG environment variable before running rustc or cargo."
    107   :type 'boolean
    108   :group 'lsp-rust-rls
    109   :package-version '(lsp-mode . "6.1"))
    110 
    111 (defcustom lsp-rust-build-lib nil
    112   "If non-nil, checks the project as if you passed the `--lib' argument to
    113 cargo.
    114 
    115 Mutually exclusive with, and preferred over, `lsp-rust-build-bin'. (Unstable)"
    116   :type 'boolean
    117   :group 'lsp-rust-rls
    118   :package-version '(lsp-mode . "6.1"))
    119 
    120 (defcustom lsp-rust-build-bin nil
    121   "If non-nil, checks the project as if you passed `-- bin <build_bin>'
    122 argument to cargo.
    123 
    124 Mutually exclusive with `lsp-rust-build-lib'. (Unstable)"
    125   :type '(choice
    126           (const :tag "None" nil)
    127           (string :tag "Binary"))
    128   :group 'lsp-rust-rls
    129   :package-version '(lsp-mode . "6.1"))
    130 
    131 (defcustom lsp-rust-cfg-test nil
    132   "If non-nil, checks the project as if you were running `cargo test' rather
    133 than cargo build.
    134 
    135 I.e., compiles (but does not run) test code."
    136   :type 'boolean
    137   :group 'lsp-rust-rls
    138   :package-version '(lsp-mode . "6.1"))
    139 
    140 (defcustom lsp-rust-unstable-features nil
    141   "Enable unstable features."
    142   :type 'boolean
    143   :group 'lsp-rust-rls
    144   :package-version '(lsp-mode . "6.1"))
    145 
    146 (defcustom lsp-rust-wait-to-build nil
    147   "Time in milliseconds between receiving a change notification
    148 and starting build. If not specified, automatically inferred by
    149 the latest build duration."
    150   :type '(choice
    151           (const :tag "Auto" nil)
    152           (number :tag "Time"))
    153   :group 'lsp-rust-rls
    154   :package-version '(lsp-mode . "6.1"))
    155 
    156 (defcustom lsp-rust-show-warnings t
    157   "Show warnings."
    158   :type 'boolean
    159   :group 'lsp-rust-rls
    160   :package-version '(lsp-mode . "6.1"))
    161 
    162 (defcustom lsp-rust-crate-blocklist  [
    163                                       "cocoa"
    164                                       "gleam"
    165                                       "glium"
    166                                       "idna"
    167                                       "libc"
    168                                       "openssl"
    169                                       "rustc_serialize"
    170                                       "serde"
    171                                       "serde_json"
    172                                       "typenum"
    173                                       "unicode_normalization"
    174                                       "unicode_segmentation"
    175                                       "winapi"
    176                                       ]
    177   "A list of Cargo crates to blocklist."
    178   :type 'lsp-string-vector
    179   :group 'lsp-rust-rls
    180   :package-version '(lsp-mode . "6.1"))
    181 
    182 (defcustom lsp-rust-build-on-save nil
    183   "Only index the project when a file is saved and not on change."
    184   :type 'boolean
    185   :group 'lsp-rust-rls
    186   :package-version '(lsp-mode . "6.1"))
    187 
    188 (defcustom lsp-rust-features []
    189   "List of features to activate.
    190 Corresponds to the `rust-analyzer` setting `rust-analyzer.cargo.features`.
    191 Set this to `\"all\"` to pass `--all-features` to cargo."
    192   :type 'lsp-string-vector
    193   :group 'lsp-rust-rls
    194   :package-version '(lsp-mode . "6.1"))
    195 
    196 (defcustom lsp-rust-all-features nil
    197   "Enable all Cargo features."
    198   :type 'boolean
    199   :group 'lsp-rust-rls
    200   :package-version '(lsp-mode . "6.1"))
    201 
    202 (defcustom lsp-rust-no-default-features nil
    203   "Do not enable default Cargo features."
    204   :type 'boolean
    205   :group 'lsp-rust-rls
    206   :package-version '(lsp-mode . "6.1"))
    207 
    208 (defcustom lsp-rust-racer-completion t
    209   "Enables code completion using racer."
    210   :type 'boolean
    211   :group 'lsp-rust-rls
    212   :package-version '(lsp-mode . "6.1"))
    213 
    214 (defcustom lsp-rust-clippy-preference "opt-in"
    215   "Controls eagerness of clippy diagnostics when available.
    216 Valid values are (case-insensitive):
    217  - \"off\": Disable clippy lints.
    218  - \"opt-in\": Clippy lints are shown when crates specify `#![warn(clippy)]'.
    219  - \"on\": Clippy lints enabled for all crates in workspace.
    220 
    221 You need to install clippy via rustup if you haven't already."
    222   :type '(choice
    223           (const "on")
    224           (const "opt-in")
    225           (const "off"))
    226   :group 'lsp-rust-rls
    227   :package-version '(lsp-mode . "6.1"))
    228 
    229 (defcustom lsp-rust-jobs nil
    230   "Number of Cargo jobs to be run in parallel."
    231   :type '(choice
    232           (const :tag "Auto" nil)
    233           (number :tag "Jobs"))
    234   :group 'lsp-rust-rls
    235   :package-version '(lsp-mode . "6.1"))
    236 
    237 (defcustom lsp-rust-all-targets t
    238   "Checks the project as if you were running cargo check --all-targets.
    239 I.e., check all targets and integration tests too."
    240   :type 'boolean
    241   :group 'lsp-rust-rls
    242   :package-version '(lsp-mode . "6.1"))
    243 
    244 (defcustom lsp-rust-target-dir nil
    245   "When specified, it places the generated analysis files at the
    246 specified target directory. By default it is placed target/rls
    247 directory."
    248   :type '(choice
    249           (const :tag "Default" nil)
    250           (string :tag "Directory"))
    251   :group 'lsp-rust-rls
    252   :package-version '(lsp-mode . "6.1"))
    253 
    254 (defcustom lsp-rust-rustfmt-path nil
    255   "When specified, RLS will use the Rustfmt pointed at the path
    256 instead of the bundled one"
    257   :type '(choice
    258           (const :tag "Bundled" nil)
    259           (string :tag "Path"))
    260   :group 'lsp-rust-rls
    261   :package-version '(lsp-mode . "6.1"))
    262 
    263 (defcustom lsp-rust-build-command nil
    264   "EXPERIMENTAL (requires `rust.unstable_features')
    265 If set, executes a given program responsible for rebuilding save-analysis to be
    266 loaded by the RLS. The program given should output a list of resulting .json
    267 files on stdout.
    268 
    269 Implies `rust.build_on_save': true."
    270   :type '(choice
    271           (const :tag "None" nil)
    272           (string :tag "Command"))
    273   :group 'lsp-rust-rls
    274   :package-version '(lsp-mode . "6.1"))
    275 
    276 (defcustom lsp-rust-full-docs nil
    277   "Instructs cargo to enable full documentation extraction during
    278 save-analysis while building the crate."
    279   :type 'boolean
    280   :group 'lsp-rust-rls
    281   :package-version '(lsp-mode . "6.1"))
    282 
    283 (defcustom lsp-rust-show-hover-context t
    284   "Show additional context in hover tooltips when available. This
    285 is often the type local variable declaration."
    286   :type 'boolean
    287   :group 'lsp-rust-rls
    288   :package-version '(lsp-mode . "6.1"))
    289 
    290 (lsp-register-custom-settings
    291  '(("rust.show_hover_context" lsp-rust-show-hover-context t)
    292    ("rust.full_docs" lsp-rust-full-docs t)
    293    ("rust.build_command" lsp-rust-build-command)
    294    ("rust.rustfmt_path" lsp-rust-rustfmt-path)
    295    ("rust.target_dir" lsp-rust-target-dir)
    296    ("rust.all_targets" lsp-rust-all-targets t)
    297    ("rust.jobs" lsp-rust-jobs)
    298    ("rust.clippy_preference" lsp-rust-clippy-preference)
    299    ("rust.racer_completion" lsp-rust-racer-completion t)
    300    ("rust.no_default_features" lsp-rust-no-default-features t)
    301    ("rust.all_features" lsp-rust-all-features t)
    302    ("rust.features" lsp-rust-features)
    303    ("rust.build_on_save" lsp-rust-build-on-save t)
    304    ("rust.crate_blocklist" lsp-rust-crate-blocklist)
    305    ("rust.show_warnings" lsp-rust-show-warnings t)
    306    ("rust.wait_to_build" lsp-rust-wait-to-build)
    307    ("rust.unstable_features" lsp-rust-unstable-features t)
    308    ("rust.cfg_test" lsp-rust-cfg-test t)
    309    ("rust.build_bin" lsp-rust-build-bin)
    310    ("rust.build_lib" lsp-rust-build-lib t)
    311    ("rust.clear_env_rust_log" lsp-rust-clear-env-rust-log t)
    312    ("rust.rustflags" lsp-rust-rustflags)
    313    ("rust.target" lsp-rust-target)
    314    ("rust.sysroot" lsp-rust-sysroot)))
    315 
    316 (defun lsp-clients--rust-window-progress (workspace params)
    317   "Progress report handling.
    318 PARAMS progress report notification data."
    319   (-let [(&v1:ProgressParams :done? :message? :title) params]
    320     (if (or done? (s-blank-str? message?))
    321         (lsp-workspace-status nil workspace)
    322       (lsp-workspace-status (format "%s - %s" title (or message? "")) workspace))))
    323 
    324 (lsp-defun lsp-rust--rls-run ((&Command :arguments? params))
    325   (-let* (((&rls:Cmd :env :binary :args :cwd) (lsp-seq-first params))
    326           (default-directory (or cwd (lsp-workspace-root) default-directory) ))
    327     (compile
    328      (format "%s %s %s"
    329              (s-join " " (ht-amap (format "%s=%s" key value) env))
    330              binary
    331              (s-join " " args)))))
    332 
    333 (lsp-register-client
    334  (make-lsp-client :new-connection (lsp-stdio-connection (lambda () lsp-rust-rls-server-command))
    335                   :activation-fn (lsp-activate-on "rust")
    336                   :priority (if (eq lsp-rust-server 'rls) 1 -1)
    337                   :initialization-options '((omitInitBuild . t)
    338                                             (cmdRun . t))
    339                   :notification-handlers (ht ("window/progress" 'lsp-clients--rust-window-progress))
    340                   :action-handlers (ht ("rls.run" 'lsp-rust--rls-run))
    341                   :library-folders-fn (lambda (_workspace) lsp-rust-library-directories)
    342                   :initialized-fn (lambda (workspace)
    343                                     (with-lsp-workspace workspace
    344                                       (lsp--set-configuration
    345                                        (lsp-configuration-section "rust"))))
    346                   :server-id 'rls))
    347 
    348 
    349 ;; rust-analyzer
    350 (defcustom lsp-rust-analyzer-server-command '("rust-analyzer")
    351   "Command to start rust-analyzer."
    352   :type '(repeat string)
    353   :group 'lsp-rust-analyzer
    354   :package-version '(lsp-mode . "6.2"))
    355 
    356 (defcustom lsp-rust-analyzer-library-directories
    357   '("~/.cargo/registry/src" "~/.rustup/toolchains")
    358   "List of directories which will be considered to be libraries."
    359   :risky t
    360   :type '(repeat string)
    361   :group 'lsp-rust-analyzer
    362   :package-version '(lsp-mode . "9.0.0"))
    363 
    364 (defcustom lsp-rust-analyzer-server-format-inlay-hints t
    365   "Whether to ask rust-analyzer to format inlay hints itself.  If
    366 active, the various inlay format settings are not used."
    367   :type 'boolean
    368   :group 'lsp-rust-analyzer
    369   :package-version '(lsp-mode . "9.0.0"))
    370 
    371 (defcustom lsp-rust-analyzer-hide-closure-initialization nil
    372   "Whether to hide inlay type hints for `let` statements that initialize
    373 to a closure. Only applies to closures with blocks, same as
    374 `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`."
    375   :type 'boolean
    376   :group 'lsp-rust-analyzer
    377   :package-version '(lsp-mode . "9.0.0"))
    378 
    379 (defcustom lsp-rust-analyzer-highlight-breakpoints t
    380   "Enables highlighting of related references while the cursor is on
    381 `break`, `loop`, `while`, or `for` keywords."
    382   :type 'boolean
    383   :group 'lsp-rust-analyzer
    384   :package-version '(lsp-mode . "9.0.0"))
    385 
    386 (defcustom lsp-rust-analyzer-highlight-closure-captures t
    387   "Enables highlighting of all captures of a closure while the
    388 cursor is on the `|` or move keyword of a closure."
    389   :type 'boolean
    390   :group 'lsp-rust-analyzer
    391   :package-version '(lsp-mode . "9.0.0"))
    392 
    393 (defcustom lsp-rust-analyzer-highlight-exit-points t
    394   "Enables highlighting of all exit points while the cursor is on
    395 any `return`, `?`, `fn`, or return type arrow (`->`)."
    396   :type 'boolean
    397   :group 'lsp-rust-analyzer
    398   :package-version '(lsp-mode . "9.0.0"))
    399 
    400 (defcustom lsp-rust-analyzer-highlight-references t
    401   "Enables highlighting of related references while the cursor is on
    402 any identifier."
    403   :type 'boolean
    404   :group 'lsp-rust-analyzer
    405   :package-version '(lsp-mode . "9.0.0"))
    406 
    407 (defcustom lsp-rust-analyzer-highlight-yield-points t
    408   "Enables highlighting of all break points for a loop or block
    409 context while the cursor is on any `async` or `await` keywords."
    410   :type 'boolean
    411   :group 'lsp-rust-analyzer
    412   :package-version '(lsp-mode . "9.0.0"))
    413 
    414 (defcustom lsp-rust-analyzer-closure-return-type-hints "never"
    415   "Whether to show inlay type hints for return types of closures."
    416   :type '(choice
    417           (const "never")
    418           (const "always")
    419           (const "with_block"))
    420   :group 'lsp-rust-analyzer
    421   :package-version '(lsp-mode . "9.0.0"))
    422 
    423 (defcustom lsp-rust-analyzer-discriminants-hints "never"
    424   "Whether to show enum variant discriminant hints."
    425   :type '(choice
    426           (const "never")
    427           (const "always")
    428           (const "fieldless"))
    429   :group 'lsp-rust-analyzer
    430   :package-version '(lsp-mode . "9.0.0"))
    431 
    432 (defcustom lsp-rust-analyzer-expression-adjustment-hints "never"
    433   "Whether to show inlay hints for type adjustments.."
    434   :type '(choice
    435           (const "never")
    436           (const "always")
    437           (const "reborrow"))
    438   :group 'lsp-rust-analyzer
    439   :package-version '(lsp-mode . "9.0.0"))
    440 
    441 (defcustom lsp-rust-analyzer-expression-adjustment-hints-mode "prefix"
    442   "Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc)."
    443   :type '(choice
    444           (const "prefix")
    445           (const "postfix")
    446           (const "prefer_prefix")
    447           (const "prefer_postfix"))
    448   :group 'lsp-rust-analyzer
    449   :package-version '(lsp-mode . "9.0.0"))
    450 
    451 (defcustom lsp-rust-analyzer-expression-adjustment-hide-unsafe nil
    452   "Whether to hide inlay hints for type adjustments outside of
    453 `unsafe` blocks."
    454   :type 'boolean
    455   :group 'lsp-rust-analyzer
    456   :package-version '(lsp-mode . "9.0.0"))
    457 
    458 (defcustom lsp-rust-analyzer-implicit-drops nil
    459   "Whether to show implicit drop hints."
    460   :type 'boolean
    461   :group 'lsp-rust-analyzer
    462   :package-version '(lsp-mode . "9.0.0"))
    463 
    464 
    465 (defcustom lsp-rust-analyzer-closure-capture-hints nil
    466   "Whether to show inlay hints for closure captures."
    467   :type 'boolean
    468   :group 'lsp-rust-analyzer
    469   :package-version '(lsp-mode . "9.0.0"))
    470 
    471 (defcustom lsp-rust-analyzer-closure-style "impl_fn"
    472   "Closure notation in type and chaining inlay hints."
    473   :type 'string
    474   :group 'lsp-rust-analyzer
    475   :package-version '(lsp-mode . "9.0.0"))
    476 
    477 (defcustom lsp-rust-analyzer-hide-named-constructor nil
    478   "Whether to hide inlay type hints for constructors."
    479   :type 'boolean
    480   :group 'lsp-rust-analyzer
    481   :package-version '(lsp-mode . "9.0.0"))
    482 
    483 (defcustom lsp-rust-analyzer-max-inlay-hint-length nil
    484   "Max inlay hint length."
    485   :type 'integer
    486   :group 'lsp-rust-analyzer
    487   :package-version '(lsp-mode . "6.2.2"))
    488 
    489 (defcustom lsp-rust-analyzer-display-chaining-hints nil
    490   "Whether to show inlay type hints for method chains.  These
    491 hints will be formatted with the type hint formatting options, if
    492 the mode is not configured to ask the server to format them."
    493   :type 'boolean
    494   :group 'lsp-rust-analyzer
    495   :package-version '(lsp-mode . "6.2.2"))
    496 
    497 (defcustom lsp-rust-analyzer-display-lifetime-elision-hints-enable "never"
    498   "Whether to show elided lifetime inlay hints."
    499   :type '(choice
    500           (const "never")
    501           (const "always")
    502           (const "skip_trivial"))
    503   :group 'lsp-rust-analyzer
    504   :package-version '(lsp-mode . "9.0.0"))
    505 
    506 (defcustom lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil
    507   "When showing elided lifetime inlay hints, whether to use
    508 parameter names or numeric placeholder names for the lifetimes."
    509   :type 'boolean
    510   :group 'lsp-rust-analyzer
    511   :package-version '(lsp-mode . "9.0.0"))
    512 
    513 (defcustom lsp-rust-analyzer-display-closure-return-type-hints nil
    514   "Whether to show closure return type inlay hints for closures
    515 with block bodies."
    516   :type 'boolean
    517   :group 'lsp-rust-analyzer
    518   :package-version '(lsp-mode . "9.0.0"))
    519 
    520 (defcustom lsp-rust-analyzer-display-parameter-hints nil
    521   "Whether to show function parameter name inlay hints at the call site."
    522   :type 'boolean
    523   :group 'lsp-rust-analyzer
    524   :package-version '(lsp-mode . "6.2.2"))
    525 
    526 (defcustom lsp-rust-analyzer-display-reborrow-hints "never"
    527   "Whether to show inlay type hints for compiler inserted reborrows."
    528   :type '(choice
    529           (const "always")
    530           (const "never")
    531           (const "mutable"))
    532   :group 'lsp-rust-analyzer
    533   :package-version '(lsp-mode . "9.0.0"))
    534 
    535 (defcustom lsp-rust-analyzer-binding-mode-hints nil
    536   "Whether to show inlay type hints for binding modes."
    537   :type 'boolean
    538   :group 'lsp-rust-analyzer
    539   :package-version '(lsp-mode . "9.0.0"))
    540 
    541 (defcustom lsp-rust-analyzer-closing-brace-hints t
    542   "Whether to show inlay hints after a closing `}` to indicate what item it
    543 belongs to."
    544   :type 'boolean
    545   :group 'lsp-rust-analyzer
    546   :package-version '(lsp-mode . "9.0.0"))
    547 
    548 (defcustom lsp-rust-analyzer-closing-brace-hints-min-lines 25
    549   "Minimum number of lines required before the `}` until the hint is shown
    550 \(set to 0 or 1 to always show them)."
    551   :type 'integer
    552   :group 'lsp-rust-analyzer
    553   :package-version '(lsp-mode . "9.0.0"))
    554 
    555 (defcustom lsp-rust-analyzer-lru-capacity nil
    556   "Number of syntax trees rust-analyzer keeps in memory."
    557   :type 'integer
    558   :group 'lsp-rust-analyzer
    559   :package-version '(lsp-mode . "6.2.2"))
    560 
    561 (defcustom lsp-rust-analyzer-cargo-target nil
    562   "Compilation target (target triple)."
    563   :type '(choice
    564           (string :tag "Target")
    565           (const :tag "None" nil))
    566   :group 'lsp-rust-analyzer
    567   :package-version '(lsp-mode . "8.0.0"))
    568 
    569 (defcustom lsp-rust-analyzer-cargo-watch-enable t
    570   "Enable Cargo watch."
    571   :type 'boolean
    572   :group 'lsp-rust-analyzer
    573   :package-version '(lsp-mode . "6.2.2"))
    574 
    575 (defcustom lsp-rust-analyzer-cargo-watch-command "check"
    576   "Cargo watch command."
    577   :type 'string
    578   :group 'lsp-rust-analyzer
    579   :package-version '(lsp-mode . "6.2.2"))
    580 
    581 (defcustom lsp-rust-analyzer-cargo-watch-args []
    582   "Extra arguments for `cargo check`."
    583   :type 'lsp-string-vector
    584   :group 'lsp-rust-analyzer
    585   :package-version '(lsp-mode . "6.2.2"))
    586 
    587 (defcustom lsp-rust-analyzer-cargo-override-command []
    588   "Advanced option, fully override the command rust-analyzer uses for checking.
    589 The command should include `--message=format=json` or similar option."
    590   :type 'lsp-string-vector
    591   :group 'lsp-rust-analyzer
    592   :package-version '(lsp-mode . "6.2.2"))
    593 
    594 (defcustom lsp-rust-analyzer-check-all-targets t
    595   "Enables --all-targets for `cargo check`."
    596   :type 'boolean
    597   :group 'lsp-rust-analyzer
    598   :package-version '(lsp-mode . "8.0.2"))
    599 
    600 (defcustom lsp-rust-analyzer-checkonsave-features nil
    601   "List of features to activate.
    602 Corresponds to the `rust-analyzer` setting `rust-analyzer.check.features`.
    603 When set to `nil` (default), the value of `lsp-rust-features' is inherited.
    604 Set this to `\"all\"` to pass `--all-features` to cargo.
    605 Note: setting this to `nil` means \"unset\", whereas setting this
    606 to `[]` (empty vector) means \"set to empty list of features\",
    607 which overrides any value that would otherwise be inherited from
    608 `lsp-rust-features'."
    609   :type 'lsp-string-vector
    610   :group 'lsp-rust-rust-analyzer
    611   :package-version '(lsp-mode . "8.0.2"))
    612 
    613 (defcustom lsp-rust-analyzer-cargo-unset-test []
    614   "force rust-analyzer to unset `#[cfg(test)]` for the specified crates."
    615   :type 'lsp-string-vector
    616   :group 'lsp-rust-analyzer
    617   :package-version '(lsp-mode . "9.0.0"))
    618 
    619 (defcustom lsp-rust-analyzer-use-client-watching t
    620   "Use client watching"
    621   :type 'boolean
    622   :group 'lsp-rust-analyzer
    623   :package-version '(lsp-mode . "6.2.2"))
    624 
    625 (defcustom lsp-rust-analyzer-exclude-globs []
    626   "Exclude globs"
    627   :type 'lsp-string-vector
    628   :group 'lsp-rust-analyzer
    629   :package-version '(lsp-mode . "6.2.2"))
    630 
    631 (defcustom lsp-rust-analyzer-exclude-dirs []
    632   "These directories will be ignored by rust-analyzer."
    633   :type 'lsp-string-vector
    634   :group 'lsp-rust-analyzer
    635   :package-version '(lsp-mode . "8.0.0"))
    636 
    637 (defcustom lsp-rust-analyzer-macro-expansion-method 'lsp-rust-analyzer-macro-expansion-default
    638   "Use a different function if you want formatted macro expansion results and
    639 syntax highlighting."
    640   :type 'function
    641   :group 'lsp-rust-analyzer
    642   :package-version '(lsp-mode . "6.2.2"))
    643 
    644 (defcustom lsp-rust-analyzer-diagnostics-enable t
    645   "Whether to show native rust-analyzer diagnostics."
    646   :type 'boolean
    647   :group 'lsp-rust-analyzer
    648   :package-version '(lsp-mode . "6.3.2"))
    649 
    650 (defcustom lsp-rust-analyzer-diagnostics-enable-experimental nil
    651   "Whether to show native rust-analyzer diagnostics that are still experimental
    652 \(might have more false positives than usual)."
    653   :type 'boolean
    654   :group 'lsp-rust-analyzer
    655   :package-version '(lsp-mode . "8.0.0"))
    656 
    657 (defcustom lsp-rust-analyzer-diagnostics-disabled []
    658   "List of native rust-analyzer diagnostics to disable."
    659   :type 'lsp-string-vector
    660   :group 'lsp-rust-analyzer
    661   :package-version '(lsp-mode . "8.0.0"))
    662 
    663 (defcustom lsp-rust-analyzer-diagnostics-warnings-as-hint []
    664   "List of warnings that should be displayed with hint severity."
    665   :type 'lsp-string-vector
    666   :group 'lsp-rust-analyzer
    667   :package-version '(lsp-mode . "8.0.0"))
    668 
    669 (defcustom lsp-rust-analyzer-diagnostics-warnings-as-info []
    670   "List of warnings that should be displayed with info severity."
    671   :type 'lsp-string-vector
    672   :group 'lsp-rust-analyzer
    673   :package-version '(lsp-mode . "8.0.0"))
    674 
    675 (define-obsolete-variable-alias
    676   'lsp-rust-analyzer-cargo-load-out-dirs-from-check
    677   'lsp-rust-analyzer-cargo-run-build-scripts
    678   "8.0.0")
    679 
    680 (defcustom lsp-rust-analyzer-cargo-run-build-scripts t
    681   "Whether to run build scripts (`build.rs`) for more precise code analysis."
    682   :type 'boolean
    683   :group 'lsp-rust-analyzer
    684   :package-version '(lsp-mode . "8.0.0"))
    685 
    686 (defcustom lsp-rust-analyzer-rustfmt-extra-args []
    687   "Additional arguments to rustfmt."
    688   :type 'lsp-string-vector
    689   :group 'lsp-rust-analyzer
    690   :package-version '(lsp-mode . "6.3.2"))
    691 
    692 (defcustom lsp-rust-analyzer-rustfmt-override-command []
    693   "Advanced option, fully override the command rust-analyzer uses
    694 for formatting."
    695   :type 'lsp-string-vector
    696   :group 'lsp-rust-analyzer
    697   :package-version '(lsp-mode . "6.3.2"))
    698 
    699 (defcustom lsp-rust-analyzer-rustfmt-rangeformatting-enable nil
    700   "Enables the use of rustfmt's unstable range formatting command for the
    701 `textDocument/rangeFormatting` request. The rustfmt option is unstable and only
    702 available on a nightly build."
    703   :type 'boolean
    704   :group 'lsp-rust-analyzer
    705   :package-version '(lsp-mode . "9.0.0"))
    706 
    707 (defcustom lsp-rust-analyzer-completion-add-call-parenthesis t
    708   "Whether to add parenthesis when completing functions."
    709   :type 'boolean
    710   :group 'lsp-rust-analyzer
    711   :package-version '(lsp-mode . "6.3.2"))
    712 
    713 (defcustom lsp-rust-analyzer-completion-add-call-argument-snippets t
    714   "Whether to add argument snippets when completing functions."
    715   :type 'boolean
    716   :group 'lsp-rust-analyzer
    717   :package-version '(lsp-mode . "6.3.2"))
    718 
    719 (defcustom lsp-rust-analyzer-completion-postfix-enable t
    720   "Whether to show postfix snippets like `dbg`, `if`, `not`, etc."
    721   :type 'boolean
    722   :group 'lsp-rust-analyzer
    723   :package-version '(lsp-mode . "6.3.2"))
    724 
    725 (defcustom lsp-rust-analyzer-call-info-full t
    726   "Whether to show function name and docs in parameter hints."
    727   :type 'boolean
    728   :group 'lsp-rust-analyzer
    729   :package-version '(lsp-mode . "6.3.2"))
    730 
    731 (defcustom lsp-rust-analyzer-proc-macro-enable t
    732   "Enable Proc macro support.
    733 Implies `lsp-rust-analyzer-cargo-run-build-scripts'"
    734   :type 'boolean
    735   :group 'lsp-rust-analyzer
    736   :package-version '(lsp-mode . "6.3.2"))
    737 
    738 (defcustom lsp-rust-analyzer-import-prefix "plain"
    739   "The path structure for newly inserted paths to use.
    740 Valid values are:
    741  - \"plain\": Insert import paths relative to the current module, using up to
    742 one `super' prefix if the parent module contains the requested item.
    743  - \"by_self\": Prefix all import paths with `self' if they don't begin with
    744 `self', `super', `crate' or a crate name.
    745  - \"by_crate\": Force import paths to be absolute by always starting
    746 them with `crate' or the crate name they refer to."
    747   :type '(choice
    748           (const "plain")
    749           (const "by_self")
    750           (const "by_crate"))
    751   :group 'lsp-rust-analyzer
    752   :package-version '(lsp-mode . "8.0.0"))
    753 
    754 (defcustom lsp-rust-analyzer-import-granularity "crate"
    755   "How imports should be grouped into use statements."
    756   :type '(choice
    757           (const "crate" :doc "Merge imports from the same crate into a single use statement. This kind of nesting is only supported in Rust versions later than 1.24.")
    758           (const "module" :doc "Merge imports from the same module into a single use statement.")
    759           (const "item" :doc "Don’t merge imports at all, creating one import per item.")
    760           (const "preserve" :doc "Do not change the granularity of any imports. For auto-import this has the same effect as `\"item\"'"))
    761   :group 'lsp-rust-analyzer
    762   :package-version '(lsp-mode . "8.0.0"))
    763 
    764 (defcustom lsp-rust-analyzer-cargo-auto-reload t
    765   "Automatically refresh project info via `cargo metadata' on `Cargo.toml' changes."
    766   :type 'boolean
    767   :group 'lsp-rust-analyzer
    768   :package-version '(lsp-mode . "8.0.0"))
    769 
    770 (defcustom lsp-rust-analyzer-use-rustc-wrapper-for-build-scripts t
    771   "Use `RUSTC_WRAPPER=rust-analyzer' when running build scripts to avoid
    772 compiling unnecessary things."
    773   :type 'boolean
    774   :group 'lsp-rust-analyzer
    775   :package-version '(lsp-mode . "8.0.0"))
    776 
    777 (defcustom lsp-rust-analyzer-completion-auto-import-enable t
    778   "Toggles the additional completions that automatically add imports when
    779 completed. `lsp-completion-enable-additional-text-edit' must be non-nil
    780  for this feature to be fully enabled."
    781   :type 'boolean
    782   :group 'lsp-rust-analyzer
    783   :package-version '(lsp-mode . "8.0.0"))
    784 
    785 (defcustom lsp-rust-analyzer-completion-auto-self-enable t
    786   "Toggles the additional completions that automatically show method calls
    787 and field accesses with self prefixed to them when inside a method."
    788   :type 'boolean
    789   :group 'lsp-rust-analyzer
    790   :package-version '(lsp-mode . "8.0.0"))
    791 
    792 (defcustom lsp-rust-analyzer-import-enforce-granularity nil
    793   "Whether to enforce the import granularity setting for all files.
    794  If set to nil rust-analyzer will try to keep import styles consistent per file."
    795   :type 'boolean
    796   :group 'lsp-rust-analyzer
    797   :package-version '(lsp-mode . "8.0.0"))
    798 
    799 (defcustom lsp-rust-analyzer-imports-merge-glob t
    800   "Whether to allow import insertion to merge new imports into single path
    801 glob imports like `use std::fmt::*;`."
    802   :type 'boolean
    803   :group 'lsp-rust-analyzer
    804   :package-version '(lsp-mode . "9.0.0"))
    805 
    806 (defcustom lsp-rust-analyzer-import-group t
    807   "Group inserted imports by the following order:
    808 https://rust-analyzer.github.io/manual.html#auto-import.
    809  Groups are separated by newlines."
    810   :type 'boolean
    811   :group 'lsp-rust-analyzer
    812   :package-version '(lsp-mode . "8.0.0"))
    813 
    814 (defcustom lsp-rust-analyzer-highlighting-strings t
    815   "Use semantic tokens for strings."
    816   :type 'boolean
    817   :group 'lsp-rust-analyzer
    818   :package-version '(lsp-mode . "8.0.0"))
    819 
    820 (defcustom lsp-rust-analyzer-rustc-source nil
    821   "Path to the Cargo.toml of the rust compiler workspace."
    822   :type '(choice
    823           (file :tag "Path")
    824           (const :tag "None" nil))
    825   :group 'lsp-rust-analyzer
    826   :package-version '(lsp-mode . "8.0.0"))
    827 
    828 (defcustom lsp-rust-analyzer-linked-projects []
    829   "Disable project auto-discovery in favor of explicitly specified set of
    830 projects. Elements must be paths pointing to `Cargo.toml`, `rust-project.json`,
    831 or JSON objects in `rust-project.json` format."
    832   :type 'lsp-string-vector
    833   :group 'lsp-rust-analyzer
    834   :package-version '(lsp-mode . "9.0.0"))
    835 
    836 (defcustom lsp-rust-analyzer-experimental-proc-attr-macros t
    837   "Whether to enable experimental support for expanding proc macro attributes."
    838   :type 'boolean
    839   :group 'lsp-rust-analyzer
    840   :package-version '(lsp-mode . "8.0.0"))
    841 
    842 (defcustom lsp-rust-analyzer-cargo-extra-args []
    843   "Extra arguments that are passed to every cargo invocation."
    844   :type 'lsp-string-vector
    845   :group 'lsp-rust-analyzer
    846   :package-version '(lsp-mode . "9.0.0"))
    847 
    848 (defcustom lsp-rust-analyzer-cargo-extra-env []
    849   "Extra environment variables that will be set when running cargo, rustc or
    850 other commands within the workspace.  Useful for setting RUSTFLAGS."
    851   :type 'lsp-string-vector
    852   :group 'lsp-rust-analyzer
    853   :package-version '(lsp-mode . "9.0.0"))
    854 
    855 (defconst lsp-rust-notification-handlers
    856   '(("rust-analyzer/publishDecorations" . (lambda (_w _p)))))
    857 
    858 (defconst lsp-rust-action-handlers
    859   '())
    860 
    861 (define-derived-mode lsp-rust-analyzer-syntax-tree-mode special-mode "Rust-Analyzer-Syntax-Tree"
    862   "Mode for the rust-analyzer syntax tree buffer.")
    863 
    864 (defun lsp-rust-analyzer-syntax-tree ()
    865   "Display syntax tree for current buffer."
    866   (interactive)
    867   (-let* ((root (lsp-workspace-root default-directory))
    868           (params (lsp-make-rust-analyzer-syntax-tree-params
    869                    :text-document (lsp--text-document-identifier)
    870                    :range? (if (use-region-p)
    871                                (lsp--region-to-range (region-beginning) (region-end))
    872                              (lsp--region-to-range (point-min) (point-max)))))
    873           (results (lsp-send-request (lsp-make-request
    874                                       "rust-analyzer/syntaxTree"
    875                                       params))))
    876     (let ((buf (get-buffer-create (format "*rust-analyzer syntax tree %s*" root)))
    877           (inhibit-read-only t))
    878       (with-current-buffer buf
    879         (lsp-rust-analyzer-syntax-tree-mode)
    880         (erase-buffer)
    881         (insert results)
    882         (goto-char (point-min)))
    883       (pop-to-buffer buf))))
    884 
    885 (define-derived-mode lsp-rust-analyzer-status-mode special-mode "Rust-Analyzer-Status"
    886   "Mode for the rust-analyzer status buffer.")
    887 
    888 (defun lsp-rust-analyzer-status ()
    889   "Displays status information for rust-analyzer."
    890   (interactive)
    891   (-let* ((root (lsp-workspace-root default-directory))
    892           (params (lsp-make-rust-analyzer-analyzer-status-params
    893                    :text-document (lsp--text-document-identifier)))
    894           (results (lsp-send-request (lsp-make-request
    895                                       "rust-analyzer/analyzerStatus"
    896                                       params))))
    897     (let ((buf (get-buffer-create (format "*rust-analyzer status %s*" root)))
    898           (inhibit-read-only t))
    899       (with-current-buffer buf
    900         (lsp-rust-analyzer-status-mode)
    901         (erase-buffer)
    902         (insert results)
    903         (pop-to-buffer buf)))))
    904 
    905 (defun lsp-rust-analyzer-view-item-tree ()
    906   "Show item tree of rust file."
    907   (interactive)
    908   (-let* ((params (lsp-make-rust-analyzer-view-item-tree
    909                    :text-document (lsp--text-document-identifier)))
    910           (results (lsp-send-request (lsp-make-request
    911                                       "rust-analyzer/viewItemTree"
    912                                       params))))
    913     (let ((buf (get-buffer-create "*rust-analyzer item tree*"))
    914           (inhibit-read-only t))
    915       (with-current-buffer buf
    916         (special-mode)
    917         (erase-buffer)
    918         (insert (lsp--render-string results "rust"))
    919         (pop-to-buffer buf)))))
    920 
    921 (defun lsp-rust-analyzer-view-hir ()
    922   "View Hir of function at point."
    923   (interactive)
    924   (-let* ((params (lsp-make-rust-analyzer-expand-macro-params
    925                    :text-document (lsp--text-document-identifier)
    926                    :position (lsp--cur-position)))
    927           (results (lsp-send-request (lsp-make-request
    928                                       "rust-analyzer/viewHir"
    929                                       params))))
    930     (let ((buf (get-buffer-create "*rust-analyzer hir*"))
    931           (inhibit-read-only t))
    932       (with-current-buffer buf
    933         (special-mode)
    934         (erase-buffer)
    935         (insert results)
    936         (pop-to-buffer buf)))))
    937 
    938 (defun lsp-rust-analyzer-join-lines ()
    939   "Join selected lines into one, smartly fixing up whitespace and trailing commas."
    940   (interactive)
    941   (let* ((params (lsp-make-rust-analyzer-join-lines-params
    942                   :text-document (lsp--text-document-identifier)
    943                   :ranges (vector (if (use-region-p)
    944                                       (lsp--region-to-range (region-beginning) (region-end))
    945                                     (lsp--region-to-range (point) (point))))))
    946          (result (lsp-send-request (lsp-make-request "experimental/joinLines" params))))
    947     (lsp--apply-text-edits result 'code-action)))
    948 
    949 (defun lsp-rust-analyzer-reload-workspace ()
    950   "Reload workspace, picking up changes from Cargo.toml"
    951   (interactive)
    952   (lsp--cur-workspace-check)
    953   (lsp-send-request (lsp-make-request "rust-analyzer/reloadWorkspace")))
    954 
    955 (defcustom lsp-rust-analyzer-download-url
    956   (let* ((x86 (string-prefix-p "x86_64" system-configuration))
    957          (arch (if x86 "x86_64" "aarch64")))
    958     (format "https://github.com/rust-lang/rust-analyzer/releases/latest/download/%s"
    959             (pcase system-type
    960               ('gnu/linux (format "rust-analyzer-%s-unknown-linux-gnu.gz" arch))
    961               ('darwin (format "rust-analyzer-%s-apple-darwin.gz" arch))
    962               ('windows-nt (format "rust-analyzer-%s-pc-windows-msvc.zip" arch)))))
    963   "Automatic download url for Rust Analyzer"
    964   :type 'string
    965   :group 'lsp-rust-analyzer
    966   :package-version '(lsp-mode . "8.0.0"))
    967 
    968 (defcustom lsp-rust-analyzer-store-path (f-join lsp-server-install-dir "rust"
    969                                                 (pcase system-type
    970                                                   ('windows-nt "rust-analyzer.exe")
    971                                                   (_ "rust-analyzer")))
    972   "The path to the file in which `rust-analyzer' will be stored."
    973   :type 'file
    974   :group 'lsp-rust-analyzer
    975   :package-version '(lsp-mode . "8.0.0"))
    976 
    977 (lsp-dependency
    978  'rust-analyzer
    979  `(:download :url lsp-rust-analyzer-download-url
    980              :decompress ,(pcase system-type ('windows-nt :zip) (_ :gzip))
    981              :store-path lsp-rust-analyzer-store-path
    982              :set-executable? t)
    983  `(:system ,(file-name-nondirectory lsp-rust-analyzer-store-path)))
    984 
    985 (lsp-defun lsp-rust--analyzer-run-single ((&Command :arguments?))
    986   (lsp-rust-analyzer-run (lsp-seq-first arguments?)))
    987 
    988 (lsp-defun lsp-rust--analyzer-show-references
    989   ((&Command :title :arguments? [_uri _filepos references]))
    990   (lsp-show-xrefs (lsp--locations-to-xref-items references) nil
    991                   (s-contains-p "reference" title)))
    992 
    993 (declare-function dap-debug "ext:dap-mode" (template) t)
    994 
    995 (lsp-defun lsp-rust--analyzer-debug-lens ((&Command :arguments? [args]))
    996   (lsp-rust-analyzer-debug args))
    997 
    998 ;; Semantic tokens
    999 
   1000 ;; Modifier faces
   1001 (defface lsp-rust-analyzer-documentation-modifier-face
   1002   '((t nil))
   1003   "The face modification to use for documentation items."
   1004   :group 'lsp-rust-analyzer-semantic-tokens)
   1005 
   1006 (defface lsp-rust-analyzer-declaration-modifier-face
   1007   '((t nil))
   1008   "The face modification to use for declaration items."
   1009   :group 'lsp-rust-analyzer-semantic-tokens)
   1010 
   1011 (defface lsp-rust-analyzer-definition-modifier-face
   1012   '((t nil))
   1013   "The face modification to use for definition items."
   1014   :group 'lsp-rust-analyzer-semantic-tokens)
   1015 
   1016 (defface lsp-rust-analyzer-static-modifier-face
   1017   '((t nil))
   1018   "The face modification to use for static items."
   1019   :group 'lsp-rust-analyzer-semantic-tokens)
   1020 
   1021 (defface lsp-rust-analyzer-abstract-modifier-face
   1022   '((t nil))
   1023   "The face modification to use for abstract items."
   1024   :group 'lsp-rust-analyzer-semantic-tokens)
   1025 
   1026 (defface lsp-rust-analyzer-deprecated-modifier-face
   1027   '((t nil))
   1028   "The face modification to use for deprecated items."
   1029   :group 'lsp-rust-analyzer-semantic-tokens)
   1030 
   1031 (defface lsp-rust-analyzer-readonly-modifier-face
   1032   '((t nil))
   1033   "The face modification to use for readonly items."
   1034   :group 'lsp-rust-analyzer-semantic-tokens)
   1035 
   1036 (defface lsp-rust-analyzer-default-library-modifier-face
   1037   '((t nil))
   1038   "The face modification to use for default-library items."
   1039   :group 'lsp-rust-analyzer-semantic-tokens)
   1040 
   1041 (defface lsp-rust-analyzer-async-modifier-face
   1042   '((t nil))
   1043   "The face modification to use for async items."
   1044   :group 'lsp-rust-analyzer-semantic-tokens)
   1045 
   1046 (defface lsp-rust-analyzer-attribute-modifier-face
   1047   '((t nil))
   1048   "The face modification to use for attribute items."
   1049   :group 'lsp-rust-analyzer-semantic-tokens)
   1050 
   1051 (defface lsp-rust-analyzer-callable-modifier-face
   1052   '((t nil))
   1053   "The face modification to use for callable items."
   1054   :group 'lsp-rust-analyzer-semantic-tokens)
   1055 
   1056 (defface lsp-rust-analyzer-constant-modifier-face
   1057   '((t nil))
   1058   "The face modification to use for constant items."
   1059   :group 'lsp-rust-analyzer-semantic-tokens)
   1060 
   1061 (defface lsp-rust-analyzer-consuming-modifier-face
   1062   '((t nil))
   1063   "The face modification to use for consuming items."
   1064   :group 'lsp-rust-analyzer-semantic-tokens)
   1065 
   1066 (defface lsp-rust-analyzer-control-flow-modifier-face
   1067   '((t nil))
   1068   "The face modification to use for control-flow items."
   1069   :group 'lsp-rust-analyzer-semantic-tokens)
   1070 
   1071 (defface lsp-rust-analyzer-crate-root-modifier-face
   1072   '((t nil))
   1073   "The face modification to use for crate-root items."
   1074   :group 'lsp-rust-analyzer-semantic-tokens)
   1075 
   1076 (defface lsp-rust-analyzer-injected-modifier-face
   1077   '((t nil))
   1078   "The face modification to use for injected items."
   1079   :group 'lsp-rust-analyzer-semantic-tokens)
   1080 
   1081 (defface lsp-rust-analyzer-intra-doc-link-modifier-face
   1082   '((t nil))
   1083   "The face modification to use for intra-doc-link items."
   1084   :group 'lsp-rust-analyzer-semantic-tokens)
   1085 
   1086 (defface lsp-rust-analyzer-library-modifier-face
   1087   '((t nil))
   1088   "The face modification to use for library items."
   1089   :group 'lsp-rust-analyzer-semantic-tokens)
   1090 
   1091 (defface lsp-rust-analyzer-mutable-modifier-face
   1092   '((t :underline t))
   1093   "The face modification to use for mutable items."
   1094   :group 'lsp-rust-analyzer-semantic-tokens)
   1095 
   1096 (defface lsp-rust-analyzer-public-modifier-face
   1097   '((t nil))
   1098   "The face modification to use for public items."
   1099   :group 'lsp-rust-analyzer-semantic-tokens)
   1100 
   1101 (defface lsp-rust-analyzer-reference-modifier-face
   1102   '((t :bold t))
   1103   "The face modification to use for reference items."
   1104   :group 'lsp-rust-analyzer-semantic-tokens)
   1105 
   1106 (defface lsp-rust-analyzer-trait-modifier-face
   1107   '((t nil))
   1108   "The face modification to use for trait items."
   1109   :group 'lsp-rust-analyzer-semantic-tokens)
   1110 
   1111 (defface lsp-rust-analyzer-unsafe-modifier-face
   1112   '((t nil))
   1113   "The face modification to use for unsafe items."
   1114   :group 'lsp-rust-analyzer-semantic-tokens)
   1115 
   1116 
   1117 ;; ---------------------------------------------------------------------
   1118 ;; Semantic token modifier face customization
   1119 
   1120 (defcustom lsp-rust-analyzer-documentation-modifier 'lsp-rust-analyzer-documentation-modifier-face
   1121   "Face for semantic token modifier for `documentation' attribute."
   1122   :type 'face
   1123   :group 'lsp-rust-analyzer-semantic-tokens
   1124   :package-version '(lsp-mode . "9.0.0"))
   1125 
   1126 (defcustom lsp-rust-analyzer-declaration-modifier 'lsp-rust-analyzer-declaration-modifier-face
   1127   "Face for semantic token modifier for `declaration' attribute."
   1128   :type 'face
   1129   :group 'lsp-rust-analyzer-semantic-tokens
   1130   :package-version '(lsp-mode . "9.0.0"))
   1131 
   1132 (defcustom lsp-rust-analyzer-definition-modifier 'lsp-rust-analyzer-definition-modifier-face
   1133   "Face for semantic token modifier for `definition' attribute."
   1134   :type 'face
   1135   :group 'lsp-rust-analyzer-semantic-tokens
   1136   :package-version '(lsp-mode . "9.0.0"))
   1137 
   1138 (defcustom lsp-rust-analyzer-static-modifier 'lsp-rust-analyzer-static-modifier-face
   1139   "Face for semantic token modifier for `static' attribute."
   1140   :type 'face
   1141   :group 'lsp-rust-analyzer-semantic-tokens
   1142   :package-version '(lsp-mode . "9.0.0"))
   1143 
   1144 (defcustom lsp-rust-analyzer-abstract-modifier 'lsp-rust-analyzer-abstract-modifier-face
   1145   "Face for semantic token modifier for `abstract' attribute."
   1146   :type 'face
   1147   :group 'lsp-rust-analyzer-semantic-tokens
   1148   :package-version '(lsp-mode . "9.0.0"))
   1149 
   1150 (defcustom lsp-rust-analyzer-deprecated-modifier 'lsp-rust-analyzer-deprecated-modifier-face
   1151   "Face for semantic token modifier for `deprecated' attribute."
   1152   :type 'face
   1153   :group 'lsp-rust-analyzer-semantic-tokens
   1154   :package-version '(lsp-mode . "9.0.0"))
   1155 
   1156 (defcustom lsp-rust-analyzer-readonly-modifier 'lsp-rust-analyzer-readonly-modifier-face
   1157   "Face for semantic token modifier for `readonly' attribute."
   1158   :type 'face
   1159   :group 'lsp-rust-analyzer-semantic-tokens
   1160   :package-version '(lsp-mode . "9.0.0"))
   1161 
   1162 (defcustom lsp-rust-analyzer-default-library-modifier 'lsp-rust-analyzer-default-library-modifier-face
   1163   "Face for semantic token modifier for `default' attribute."
   1164   :type 'face
   1165   :group 'lsp-rust-analyzer-semantic-tokens
   1166   :package-version '(lsp-mode . "9.0.0"))
   1167 
   1168 (defcustom lsp-rust-analyzer-async-modifier 'lsp-rust-analyzer-async-modifier-face
   1169   "Face for semantic token modifier for `async' attribute."
   1170   :type 'face
   1171   :group 'lsp-rust-analyzer-semantic-tokens
   1172   :package-version '(lsp-mode . "9.0.0"))
   1173 
   1174 (defcustom lsp-rust-analyzer-attribute-modifier 'lsp-rust-analyzer-attribute-modifier-face
   1175   "Face for semantic token modifier for `attribute' attribute."
   1176   :type 'face
   1177   :group 'lsp-rust-analyzer-semantic-tokens
   1178   :package-version '(lsp-mode . "9.0.0"))
   1179 
   1180 (defcustom lsp-rust-analyzer-callable-modifier 'lsp-rust-analyzer-callable-modifier-face
   1181   "Face for semantic token modifier for `callable' attribute."
   1182   :type 'face
   1183   :group 'lsp-rust-analyzer-semantic-tokens
   1184   :package-version '(lsp-mode . "9.0.0"))
   1185 
   1186 (defcustom lsp-rust-analyzer-constant-modifier 'lsp-rust-analyzer-constant-modifier-face
   1187   "Face for semantic token modifier for `constant' attribute."
   1188   :type 'face
   1189   :group 'lsp-rust-analyzer-semantic-tokens
   1190   :package-version '(lsp-mode . "9.0.0"))
   1191 
   1192 (defcustom lsp-rust-analyzer-consuming-modifier 'lsp-rust-analyzer-consuming-modifier-face
   1193   "Face for semantic token modifier for `consuming' attribute."
   1194   :type 'face
   1195   :group 'lsp-rust-analyzer-semantic-tokens
   1196   :package-version '(lsp-mode . "9.0.0"))
   1197 
   1198 (defcustom lsp-rust-analyzer-control-flow-modifier 'lsp-rust-analyzer-control-flow-modifier-face
   1199   "Face for semantic token modifier for `control_flow' attribute."
   1200   :type 'face
   1201   :group 'lsp-rust-analyzer-semantic-tokens
   1202   :package-version '(lsp-mode . "9.0.0"))
   1203 
   1204 (defcustom lsp-rust-analyzer-crate-root-modifier 'lsp-rust-analyzer-crate-root-modifier-face
   1205   "Face for semantic token modifier for `crate_root' attribute."
   1206   :type 'face
   1207   :group 'lsp-rust-analyzer-semantic-tokens
   1208   :package-version '(lsp-mode . "9.0.0"))
   1209 
   1210 (defcustom lsp-rust-analyzer-injected-modifier 'lsp-rust-analyzer-injected-modifier-face
   1211   "Face for semantic token modifier for `injected' attribute."
   1212   :type 'face
   1213   :group 'lsp-rust-analyzer-semantic-tokens
   1214   :package-version '(lsp-mode . "9.0.0"))
   1215 
   1216 (defcustom lsp-rust-analyzer-intra-doc-link-modifier 'lsp-rust-analyzer-intra-doc-link-modifier-face
   1217   "Face for semantic token modifier for `intra_doc_link' attribute."
   1218   :type 'face
   1219   :group 'lsp-rust-analyzer-semantic-tokens
   1220   :package-version '(lsp-mode . "9.0.0"))
   1221 
   1222 (defcustom lsp-rust-analyzer-library-modifier 'lsp-rust-analyzer-library-modifier-face
   1223   "Face for semantic token modifier for `library' attribute."
   1224   :type 'face
   1225   :group 'lsp-rust-analyzer-semantic-tokens
   1226   :package-version '(lsp-mode . "9.0.0"))
   1227 
   1228 (defcustom lsp-rust-analyzer-mutable-modifier 'lsp-rust-analyzer-mutable-modifier-face
   1229   "Face for semantic token modifier for `mutable' attribute."
   1230   :type 'face
   1231   :group 'lsp-rust-analyzer-semantic-tokens
   1232   :package-version '(lsp-mode . "9.0.0"))
   1233 
   1234 (defcustom lsp-rust-analyzer-public-modifier 'lsp-rust-analyzer-public-modifier-face
   1235   "Face for semantic token modifier for `public' attribute."
   1236   :type 'face
   1237   :group 'lsp-rust-analyzer-semantic-tokens
   1238   :package-version '(lsp-mode . "9.0.0"))
   1239 
   1240 (defcustom lsp-rust-analyzer-reference-modifier 'lsp-rust-analyzer-reference-modifier-face
   1241   "Face for semantic token modifier for `reference' attribute."
   1242   :type 'face
   1243   :group 'lsp-rust-analyzer-semantic-tokens
   1244   :package-version '(lsp-mode . "9.0.0"))
   1245 
   1246 (defcustom lsp-rust-analyzer-trait-modifier 'lsp-rust-analyzer-trait-modifier-face
   1247   "Face for semantic token modifier for `trait' attribute."
   1248   :type 'face
   1249   :group 'lsp-rust-analyzer-semantic-tokens
   1250   :package-version '(lsp-mode . "9.0.0"))
   1251 
   1252 (defcustom lsp-rust-analyzer-unsafe-modifier 'lsp-rust-analyzer-unsafe-modifier-face
   1253   "Face for semantic token modifier for `unsafe' attribute."
   1254   :type 'face
   1255   :group 'lsp-rust-analyzer-semantic-tokens
   1256   :package-version '(lsp-mode . "9.0.0"))
   1257 
   1258 ;; ---------------------------------------------------------------------
   1259 
   1260 (defun lsp-rust-analyzer--semantic-modifiers ()
   1261   "Mapping between rust-analyzer keywords and fonts to apply.
   1262 The keywords are sent in the initialize response, in the semantic
   1263 tokens legend."
   1264   `(("documentation"   . ,lsp-rust-analyzer-documentation-modifier)
   1265     ("declaration"     . ,lsp-rust-analyzer-declaration-modifier)
   1266     ("definition"      . ,lsp-rust-analyzer-definition-modifier)
   1267     ("static"          . ,lsp-rust-analyzer-static-modifier)
   1268     ("abstract"        . ,lsp-rust-analyzer-abstract-modifier)
   1269     ("deprecated"      . ,lsp-rust-analyzer-deprecated-modifier)
   1270     ("readonly"        . ,lsp-rust-analyzer-readonly-modifier)
   1271     ("default_library" . ,lsp-rust-analyzer-default-library-modifier)
   1272     ("async"           . ,lsp-rust-analyzer-async-modifier)
   1273     ("attribute"       . ,lsp-rust-analyzer-attribute-modifier)
   1274     ("callable"        . ,lsp-rust-analyzer-callable-modifier)
   1275     ("constant"        . ,lsp-rust-analyzer-constant-modifier)
   1276     ("consuming"       . ,lsp-rust-analyzer-consuming-modifier)
   1277     ("control_flow"    . ,lsp-rust-analyzer-control-flow-modifier)
   1278     ("crate_root"      . ,lsp-rust-analyzer-crate-root-modifier)
   1279     ("injected"        . ,lsp-rust-analyzer-injected-modifier)
   1280     ("intra_doc_link"  . ,lsp-rust-analyzer-intra-doc-link-modifier)
   1281     ("library"         . ,lsp-rust-analyzer-library-modifier)
   1282     ("mutable"         . ,lsp-rust-analyzer-mutable-modifier)
   1283     ("public"          . ,lsp-rust-analyzer-public-modifier)
   1284     ("reference"       . ,lsp-rust-analyzer-reference-modifier)
   1285     ("trait"           . ,lsp-rust-analyzer-trait-modifier)
   1286     ("unsafe"          . ,lsp-rust-analyzer-unsafe-modifier)))
   1287 
   1288 (defun lsp-rust-switch-server (&optional lsp-server)
   1289   "Switch priorities of lsp servers, unless LSP-SERVER is already active."
   1290   (interactive)
   1291   (let ((current-server (if (> (lsp--client-priority (gethash 'rls lsp-clients)) 0)
   1292                             'rls
   1293                           'rust-analyzer)))
   1294     (unless (eq lsp-server current-server)
   1295       (dolist (server '(rls rust-analyzer))
   1296         (when (natnump (setf (lsp--client-priority (gethash server lsp-clients))
   1297                              (* (lsp--client-priority (gethash server lsp-clients)) -1)))
   1298           (message (format "Switched to server %s." server)))))))
   1299 
   1300 ;;
   1301 ;;; Inlay hints
   1302 
   1303 (defcustom lsp-rust-analyzer-debug-lens-extra-dap-args
   1304   '(:MIMode "gdb" :miDebuggerPath "gdb" :stopAtEntry t :externalConsole :json-false)
   1305   "Extra arguments to pass to DAP template when debugging a test from code lens.
   1306 
   1307 As a rule of the thumb, do not add extra keys to this plist unless you exactly
   1308 what you are doing, it might break the \"Debug test\" lens otherwise.
   1309 
   1310 See dap-mode documentation and cpptools documentation for the extra variables
   1311 meaning."
   1312   :type 'plist
   1313   :group 'lsp-rust-analyzer
   1314   :package-version '(lsp-mode . "8.0.0"))
   1315 
   1316 ;;
   1317 ;;; Lenses
   1318 
   1319 (defgroup lsp-rust-analyzer-lens nil
   1320   "LSP lens support for Rust when using rust-analyzer.
   1321 
   1322 Lenses are (depending on your configuration) clickable links to
   1323 the right of function definitions and the like. These display
   1324 some useful information in their own right and/or perform a
   1325 shortcut action when clicked such as displaying uses of that
   1326 function or running an individual test.
   1327 "
   1328   :prefix "lsp-rust-analyzer-lens-"
   1329   :group 'lsp-rust-analyzer
   1330   :link '(url-link "https://emacs-lsp.github.io/lsp-mode/")
   1331   :package-version '(lsp-mode . "9.0.0"))
   1332 
   1333 (defcustom lsp-rust-analyzer-lens-debug-enable t
   1334   "Enable or disable the Debug lens."
   1335   :type 'boolean
   1336   :group 'lsp-rust-analyzer-lens
   1337   :package-version '(lsp-mode . "9.0.0"))
   1338 
   1339 (defcustom lsp-rust-analyzer-lens-enable t
   1340   "Master-enable of lenses in Rust files."
   1341   :type 'boolean
   1342   :group 'lsp-rust-analyzer-lens
   1343   :package-version '(lsp-mode . "9.0.0"))
   1344 
   1345 ;; This customisation "works" in that it works as described, but the default is fine and changing it
   1346 ;; from the default will either stop lenses working or do nothing.
   1347 ;;
   1348 ;; If this is ever uncommented to re-enable the option, don't forget to also uncomment it in defun
   1349 ;; lsp-rust-analyzer--make-init-options too or it'll not do anything.
   1350 
   1351 ;; (defcustom lsp-rust-analyzer-lens-force-custom-commands t
   1352 ;;   "Internal config: use custom client-side commands even when the
   1353 ;; client doesn't set the corresponding capability."
   1354 ;;   :type 'boolean
   1355 ;;   :group 'lsp-rust-analyzer-lens
   1356 ;;   :package-version '(lsp-mode . "9.0.0"))
   1357 
   1358 (defcustom lsp-rust-analyzer-lens-implementations-enable t
   1359   "Enable or disable the Implementations lens.
   1360 
   1361 The Implementations lens shows `NN implementations' to the right
   1362 of the first line of an enum, struct, or union declaration. This
   1363 is the count of impl blocks, including derived traits. Clicking
   1364 on it gives a list of the impls of that type.
   1365 "
   1366   :type 'boolean
   1367   :group 'lsp-rust-analyzer-lens
   1368   :package-version '(lsp-mode . "9.0.0"))
   1369 
   1370 ;; The valid range of values for this is documented in the rust-lang/rust-analyzer repository at the
   1371 ;; path "editors/code/package.json"; the TL:DR is that it's "above_name" or "above_whole_item".
   1372 ;; However, setting it to "above_whole_item" causes lenses to disappear in Emacs. I suspect this
   1373 ;; feature has only ever been tested in some other IDE and it's broken in Emacs. So I've disabled it
   1374 ;; for now.
   1375 ;;
   1376 ;; If this is ever uncommented to re-enable the option, don't forget to also uncomment it in defun
   1377 ;; lsp-rust-analyzer--make-init-options too or it'll not do anything.
   1378 
   1379 ;; (defcustom lsp-rust-analyzer-lens-location "above_name"
   1380 ;;   "Where to render annotations."
   1381 ;;    :type '(choice
   1382 ;;            (const :tag "Above name" "above_name")
   1383 ;;            (const :tag "Above whole item" "above_whole_item")
   1384 ;;    :group 'lsp-rust-analyzer-lens
   1385 ;;    :package-version '(lsp-mode . "9.0.0"))
   1386 
   1387 (defcustom lsp-rust-analyzer-lens-references-adt-enable nil
   1388   "Enable or disable the References lens on enums, structs, and traits.
   1389 
   1390 The References lens shows `NN references` to the right of the
   1391 first line of each enum, struct, or union declaration. This is
   1392 the count of uses of that type. Clicking on it gives a list of
   1393 where that type is used."
   1394   :type 'boolean
   1395   :group 'lsp-rust-analyzer-lens
   1396   :package-version '(lsp-mode . "9.0.0"))
   1397 
   1398 (defcustom lsp-rust-analyzer-lens-references-enum-variant-enable nil
   1399   "Enable or disable the References lens on enum variants.
   1400 
   1401 The References lens shows `NN references` to the right of the
   1402 first (or only) line of each enum variant. This is the count of
   1403 uses of that enum variant. Clicking on it gives a list of where
   1404 that enum variant is used."
   1405   :type 'boolean
   1406   :group 'lsp-rust-analyzer-lens
   1407   :package-version '(lsp-mode . "9.0.0"))
   1408 
   1409 (defcustom lsp-rust-analyzer-lens-references-method-enable nil
   1410   "Enable or disable the References lens on functions.
   1411 
   1412 The References lens shows `NN references` to the right of the
   1413 first line of each function declaration. This is the count of
   1414 uses of that function. Clicking on it gives a list of where that
   1415 function is used."
   1416 
   1417   :type 'boolean
   1418   :group 'lsp-rust-analyzer-lens
   1419   :package-version '(lsp-mode . "9.0.0"))
   1420 
   1421 (defcustom lsp-rust-analyzer-lens-references-trait-enable nil
   1422   "Enable or disable the References lens on traits.
   1423 
   1424 The References lens shows `NN references` to the right of the
   1425 first line of each trait declaration. This is a count of uses of
   1426 that trait. Clicking on it gives a list of where that trait is
   1427 used.
   1428 
   1429 There is some overlap with the Implementations lens which slows
   1430 all of the trait's impl blocks, but this also shows other uses
   1431 such as imports and dyn traits."
   1432   :type 'boolean
   1433   :group 'lsp-rust-analyzer-lens
   1434   :package-version '(lsp-mode . "9.0.0"))
   1435 
   1436 (defcustom lsp-rust-analyzer-lens-run-enable t
   1437   "Enable or disable the Run lens."
   1438   :type 'boolean
   1439   :group 'lsp-rust-analyzer-lens
   1440   :package-version '(lsp-mode . "9.0.0"))
   1441 
   1442 (defun lsp-rust-analyzer-initialized? ()
   1443   (when-let ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name))))
   1444     (eq 'initialized (lsp--workspace-status workspace))))
   1445 
   1446 (defun lsp-rust-analyzer-expand-macro ()
   1447   "Expands the macro call at point recursively."
   1448   (interactive)
   1449   (-if-let* ((params (lsp-make-rust-analyzer-expand-macro-params
   1450                       :text-document (lsp--text-document-identifier)
   1451                       :position (lsp--cur-position)))
   1452              (response (lsp-request
   1453                         "rust-analyzer/expandMacro"
   1454                         params))
   1455              ((&rust-analyzer:ExpandedMacro :expansion) response))
   1456       (funcall lsp-rust-analyzer-macro-expansion-method expansion)
   1457     (lsp--error "No macro found at point, or it could not be expanded.")))
   1458 
   1459 (defun lsp-rust-analyzer-macro-expansion-default (result)
   1460   "Default method for displaying macro expansion."
   1461   (let* ((root (lsp-workspace-root default-directory))
   1462          (buf (get-buffer-create (get-buffer-create (format "*rust-analyzer macro expansion %s*" root)))))
   1463     (with-current-buffer buf
   1464       (let ((inhibit-read-only t))
   1465         (erase-buffer)
   1466         (insert (lsp--render-string result "rust"))
   1467         (special-mode)))
   1468     (pop-to-buffer buf)))
   1469 
   1470 ;;
   1471 ;;; Runnables
   1472 
   1473 (defvar lsp-rust-analyzer--last-runnable nil
   1474   "Record the last runnable.")
   1475 
   1476 (defun lsp-rust-analyzer--runnables ()
   1477   "Return list of runnables."
   1478   (lsp-send-request (lsp-make-request
   1479                      "experimental/runnables"
   1480                      (lsp-make-rust-analyzer-runnables-params
   1481                       :text-document (lsp--text-document-identifier)
   1482                       :position? (lsp--cur-position)))))
   1483 
   1484 (defun lsp-rust-analyzer--select-runnable ()
   1485   "Select runnable."
   1486   (lsp--completing-read
   1487    "Select runnable:"
   1488    (if lsp-rust-analyzer--last-runnable
   1489        (cons lsp-rust-analyzer--last-runnable
   1490              (-remove (-lambda ((&rust-analyzer:Runnable :label))
   1491                         (equal label (lsp-get lsp-rust-analyzer--last-runnable :label)))
   1492                       (lsp-rust-analyzer--runnables)))
   1493      (lsp-rust-analyzer--runnables))
   1494    (-lambda ((&rust-analyzer:Runnable :label)) label)))
   1495 
   1496 (defun lsp-rust-analyzer--common-runner (runnable)
   1497   "Execute a given RUNNABLE.
   1498 
   1499 Extract the arguments, prepare the minor mode (cargo-process-mode if possible)
   1500 and run a compilation"
   1501   (-let* (((&rust-analyzer:Runnable :kind :label :args) runnable)
   1502           ((&rust-analyzer:RunnableArgs :cargo-args :executable-args :workspace-root? :expect-test?) args)
   1503           (default-directory (or workspace-root? default-directory)))
   1504     (if (not (string-equal kind "cargo"))
   1505         (lsp--error "'%s' runnable is not supported" kind)
   1506       (compilation-start
   1507        (string-join (append (when expect-test? '("env" "UPDATE_EXPECT=1"))
   1508                             (list "cargo") cargo-args
   1509                             (when executable-args '("--")) executable-args '()) " ")
   1510 
   1511        ;; cargo-process-mode is nice, but try to work without it...
   1512        (if (functionp 'cargo-process-mode) 'cargo-process-mode nil)
   1513        (lambda (_) (concat "*" label "*"))))))
   1514 
   1515 (defun lsp-rust-analyzer-run (runnable)
   1516   "Select and run a RUNNABLE action."
   1517   (interactive (list (lsp-rust-analyzer--select-runnable)))
   1518   (when (lsp-rust-analyzer--common-runner runnable)
   1519     (setq lsp-rust-analyzer--last-runnable runnable)))
   1520 
   1521 (defun lsp-rust-analyzer-debug (runnable)
   1522   "Select and debug a RUNNABLE action."
   1523   (interactive (list (lsp-rust-analyzer--select-runnable)))
   1524   (unless (or (featurep 'dap-cpptools) (featurep 'dap-gdb))
   1525     (user-error "You must require `dap-cpptools' or 'dap-gdb'"))
   1526   (-let (((&rust-analyzer:Runnable
   1527            :args (&rust-analyzer:RunnableArgs :cargo-args :workspace-root? :executable-args)
   1528            :label) runnable))
   1529     (pcase (aref cargo-args 0)
   1530       ("run" (aset cargo-args 0 "build"))
   1531       ("test" (when (-contains? (append cargo-args ()) "--no-run")
   1532                 (cl-callf append cargo-args (list "--no-run")))))
   1533     (->> (append (list (executable-find "cargo"))
   1534                  cargo-args
   1535                  (list "--message-format=json"))
   1536          (s-join " ")
   1537          (shell-command-to-string)
   1538          (s-lines)
   1539          (-keep (lambda (s)
   1540                   (condition-case nil
   1541                       (-let* ((json-object-type 'plist)
   1542                               ((msg &as &plist :reason :executable) (json-read-from-string s)))
   1543                         (when (and executable (string= "compiler-artifact" reason))
   1544                           executable))
   1545                     (error))))
   1546          (funcall
   1547           (lambda (artifact-spec)
   1548             (pcase artifact-spec
   1549               (`() (user-error "No compilation artifacts or obtaining the runnable artifacts failed"))
   1550               (`(,spec) spec)
   1551               (_ (user-error "Multiple compilation artifacts are not supported")))))
   1552          (list :type (if (featurep 'dap-gdb) "gdb" "cppdbg")
   1553                :request "launch"
   1554                :name label
   1555                :args executable-args
   1556                :cwd workspace-root?
   1557                :sourceLanguages ["rust"]
   1558                :program)
   1559          (append lsp-rust-analyzer-debug-lens-extra-dap-args)
   1560          (dap-debug))))
   1561 
   1562 (defun lsp-rust-analyzer-rerun (&optional runnable)
   1563   (interactive (list (or lsp-rust-analyzer--last-runnable
   1564                          (lsp-rust-analyzer--select-runnable))))
   1565   (lsp-rust-analyzer-run (or runnable lsp-rust-analyzer--last-runnable)))
   1566 
   1567 ;; goto parent module
   1568 (cl-defun lsp-rust-find-parent-module (&key display-action)
   1569   "Find parent module of current module."
   1570   (interactive)
   1571   (lsp-find-locations "experimental/parentModule" nil :display-action display-action))
   1572 
   1573 (defun lsp-rust-analyzer-open-cargo-toml (&optional new-window)
   1574   "Open the closest Cargo.toml from the current file.
   1575 
   1576 Rust-Analyzer LSP protocol documented here and added in November 2020
   1577 https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#open-cargotoml
   1578 
   1579 If NEW-WINDOW (interactively the prefix argument) is non-nil,
   1580 open in a new window."
   1581   (interactive "P")
   1582   (-if-let (workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))
   1583       (-if-let* ((response (with-lsp-workspace workspace
   1584                              (lsp-send-request (lsp-make-request
   1585                                                 "experimental/openCargoToml"
   1586                                                 (lsp-make-rust-analyzer-open-cargo-toml-params
   1587                                                  :text-document (lsp--text-document-identifier))))))
   1588                  ((&Location :uri :range) response))
   1589           (funcall (if new-window #'find-file-other-window #'find-file)
   1590                    (lsp--uri-to-path uri))
   1591         (lsp--warn "Couldn't find a Cargo.toml file or your version of rust-analyzer doesn't support this extension"))
   1592     (lsp--error "OpenCargoToml is an extension available only with rust-analyzer")))
   1593 
   1594 (defun lsp-rust-analyzer-open-external-docs ()
   1595   "Open a URL for documentation related to the current TextDocumentPosition.
   1596 
   1597 Rust-Analyzer LSP protocol documented here
   1598 https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#open-external-documentation"
   1599   (interactive)
   1600   (-if-let* ((params (lsp-make-rust-analyzer-open-external-docs-params
   1601                       :text-document (lsp--text-document-identifier)
   1602                       :position (lsp--cur-position)))
   1603              (url (lsp-request "experimental/externalDocs" params)))
   1604       (browse-url url)
   1605     (lsp--warn "Couldn't find documentation URL or your version of rust-analyzer doesn't support this extension")))
   1606 
   1607 (defun lsp-rust-analyzer--related-tests ()
   1608   "Get runnable test items related to the current TextDocumentPosition.
   1609 Calls a rust-analyzer LSP extension endpoint that returns a wrapper over
   1610 Runnable[]."
   1611   (lsp-send-request (lsp-make-request
   1612                      "rust-analyzer/relatedTests"
   1613                      (lsp--text-document-position-params))))
   1614 
   1615 (defun lsp-rust-analyzer--select-related-test ()
   1616   "Call the endpoint and ask for user selection.
   1617 
   1618 Cannot reuse `lsp-rust-analyzer--select-runnable' because the runnables endpoint
   1619 responds with Runnable[], while relatedTests responds with TestInfo[],
   1620 which is a wrapper over runnable. Also, this method doesn't set
   1621 the `lsp-rust-analyzer--last-runnable' variable."
   1622   (-if-let* ((resp (lsp-rust-analyzer--related-tests))
   1623              (runnables (seq-map
   1624                          #'lsp:rust-analyzer-related-tests-runnable
   1625                          resp)))
   1626       (lsp--completing-read
   1627        "Select test: "
   1628        runnables
   1629        #'lsp:rust-analyzer-runnable-label)))
   1630 
   1631 (defun lsp-rust-analyzer-related-tests (runnable)
   1632   "Execute a RUNNABLE test related to the current document position.
   1633 
   1634 Rust-Analyzer LSP protocol extension
   1635 https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#related-tests"
   1636   (interactive (list (lsp-rust-analyzer--select-related-test)))
   1637   (if runnable
   1638       (lsp-rust-analyzer--common-runner runnable)
   1639     (lsp--info "There are no tests related to the symbol at point")))
   1640 
   1641 (defun lsp-rust-analyzer-move-item (direction)
   1642   "Move item under cursor or selection in some DIRECTION"
   1643   (let* ((params (lsp-make-rust-analyzer-move-item-params
   1644                   :text-document (lsp--text-document-identifier)
   1645                   :range (if (use-region-p)
   1646                              (lsp--region-to-range (region-beginning) (region-end))
   1647                            (lsp--region-to-range (point) (point)))
   1648                   :direction direction))
   1649          (edits (lsp-request "experimental/moveItem" params)))
   1650     (lsp--apply-text-edits edits 'code-action)))
   1651 
   1652 (defun lsp-rust-analyzer-move-item-up ()
   1653   "Move item under cursor or selection up"
   1654   (interactive)
   1655   (lsp-rust-analyzer-move-item "Up"))
   1656 
   1657 (defun lsp-rust-analyzer-move-item-down ()
   1658   "Move item under cursor or selection down"
   1659   (interactive)
   1660   (lsp-rust-analyzer-move-item "Down"))
   1661 
   1662 (defun lsp-rust-analyzer--make-init-options ()
   1663   "Init options for rust-analyzer"
   1664   `(:diagnostics
   1665     ( :enable ,(lsp-json-bool lsp-rust-analyzer-diagnostics-enable)
   1666       :enableExperimental ,(lsp-json-bool lsp-rust-analyzer-diagnostics-enable-experimental)
   1667       :disabled ,lsp-rust-analyzer-diagnostics-disabled
   1668       :warningsAsHint ,lsp-rust-analyzer-diagnostics-warnings-as-hint
   1669       :warningsAsInfo ,lsp-rust-analyzer-diagnostics-warnings-as-info)
   1670     :imports ( :granularity ( :enforce ,(lsp-json-bool lsp-rust-analyzer-import-enforce-granularity)
   1671                               :group ,lsp-rust-analyzer-import-granularity)
   1672                :group ,(lsp-json-bool lsp-rust-analyzer-import-group)
   1673                :merge (:glob ,(lsp-json-bool lsp-rust-analyzer-imports-merge-glob))
   1674                :prefix ,lsp-rust-analyzer-import-prefix)
   1675     :lruCapacity ,lsp-rust-analyzer-lru-capacity
   1676     ;; This `checkOnSave` is called `check` in the `rust-analyzer` docs, not
   1677     ;; `checkOnSave`, but the `rust-analyzer` source code shows that both names
   1678     ;; work. The `checkOnSave` name has been supported by `rust-analyzer` for a
   1679     ;; long time, whereas the `check` name was introduced here in 2023:
   1680     ;; https://github.com/rust-lang/rust-analyzer/commit/d2bb62b6a81d26f1e41712e04d4ac760f860d3b3
   1681     :checkOnSave ( :enable ,(lsp-json-bool lsp-rust-analyzer-cargo-watch-enable)
   1682                    :command ,lsp-rust-analyzer-cargo-watch-command
   1683                    :extraArgs ,lsp-rust-analyzer-cargo-watch-args
   1684                    :allTargets ,(lsp-json-bool lsp-rust-analyzer-check-all-targets)
   1685                    ;; We need to distinguish between setting this to the empty
   1686                    ;; vector, and not setting it at all, which `rust-analyzer`
   1687                    ;; interprets as "inherit from
   1688                    ;; `rust-analyzer.cargo.features`". We use `nil` to mean
   1689                    ;; "unset".
   1690                    ,@(when (vectorp lsp-rust-analyzer-checkonsave-features)
   1691                        `(:features ,lsp-rust-analyzer-checkonsave-features))
   1692                    :overrideCommand ,lsp-rust-analyzer-cargo-override-command)
   1693     :highlightRelated ( :breakPoints (:enable ,(lsp-json-bool lsp-rust-analyzer-highlight-breakpoints))
   1694                         :closureCaptures (:enable ,(lsp-json-bool lsp-rust-analyzer-highlight-closure-captures))
   1695                         :exitPoints (:enable ,(lsp-json-bool lsp-rust-analyzer-highlight-exit-points))
   1696                         :references (:enable ,(lsp-json-bool lsp-rust-analyzer-highlight-references))
   1697                         :yieldPoints (:enable ,(lsp-json-bool lsp-rust-analyzer-highlight-yield-points)))
   1698     :files ( :exclude ,lsp-rust-analyzer-exclude-globs
   1699              :watcher ,(if lsp-rust-analyzer-use-client-watching "client" "notify")
   1700              :excludeDirs ,lsp-rust-analyzer-exclude-dirs)
   1701     :cargo ( :allFeatures ,(lsp-json-bool lsp-rust-all-features)
   1702              :noDefaultFeatures ,(lsp-json-bool lsp-rust-no-default-features)
   1703              :features ,lsp-rust-features
   1704              :extraArgs ,lsp-rust-analyzer-cargo-extra-args
   1705              :extraEnv ,lsp-rust-analyzer-cargo-extra-env
   1706              :target ,lsp-rust-analyzer-cargo-target
   1707              :runBuildScripts ,(lsp-json-bool lsp-rust-analyzer-cargo-run-build-scripts)
   1708              ;; Obsolete, but used by old Rust-Analyzer versions
   1709              :loadOutDirsFromCheck ,(lsp-json-bool lsp-rust-analyzer-cargo-run-build-scripts)
   1710              :autoreload ,(lsp-json-bool lsp-rust-analyzer-cargo-auto-reload)
   1711              :useRustcWrapperForBuildScripts ,(lsp-json-bool lsp-rust-analyzer-use-rustc-wrapper-for-build-scripts)
   1712              :unsetTest ,lsp-rust-analyzer-cargo-unset-test)
   1713     :rustfmt ( :extraArgs ,lsp-rust-analyzer-rustfmt-extra-args
   1714                :overrideCommand ,lsp-rust-analyzer-rustfmt-override-command
   1715                :rangeFormatting (:enable ,(lsp-json-bool lsp-rust-analyzer-rustfmt-rangeformatting-enable)))
   1716     :lens ( :debug (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-debug-enable))
   1717             :enable ,(lsp-json-bool lsp-rust-analyzer-lens-enable)
   1718             ;; :forceCustomCommands ,(lsp-json-bool lsp-rust-analyzer-lens-force-custom-commands)
   1719             :implementations (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-implementations-enable))
   1720             ;; :location ,lsp-rust-analyzer-lens-location
   1721             :references ( :adt (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-references-adt-enable))
   1722                           :enumVariant (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-references-enum-variant-enable))
   1723                           :method (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-references-method-enable))
   1724                           :trait (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-references-trait-enable)))
   1725             :run (:enable ,(lsp-json-bool lsp-rust-analyzer-lens-run-enable)))
   1726 
   1727     :inlayHints ( :bindingModeHints (:enable ,(lsp-json-bool lsp-rust-analyzer-binding-mode-hints))
   1728                   :chainingHints (:enable ,(lsp-json-bool lsp-rust-analyzer-display-chaining-hints))
   1729                   :closingBraceHints ( :enable ,(lsp-json-bool lsp-rust-analyzer-closing-brace-hints)
   1730                                        :minLines ,lsp-rust-analyzer-closing-brace-hints-min-lines)
   1731                   :closureCaptureHints (:enable ,(lsp-json-bool lsp-rust-analyzer-closure-capture-hints))
   1732                   :closureReturnTypeHints (:enable ,lsp-rust-analyzer-closure-return-type-hints)
   1733                   :closureStyle ,lsp-rust-analyzer-closure-style
   1734                   :discriminantHints (:enable ,lsp-rust-analyzer-discriminants-hints)
   1735 
   1736                   :expressionAdjustmentHints ( :enable ,lsp-rust-analyzer-expression-adjustment-hints
   1737                                                :hideOutsideUnsafe ,(lsp-json-bool lsp-rust-analyzer-expression-adjustment-hide-unsafe)
   1738                                                :mode ,lsp-rust-analyzer-expression-adjustment-hints-mode)
   1739                   :implicitDrops (:enable ,(lsp-json-bool lsp-rust-analyzer-implicit-drops))
   1740                   :lifetimeElisionHints ( :enable ,lsp-rust-analyzer-display-lifetime-elision-hints-enable
   1741                                           :useParameterNames ,(lsp-json-bool lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names))
   1742                   :maxLength ,lsp-rust-analyzer-max-inlay-hint-length
   1743                   :parameterHints (:enable ,(lsp-json-bool lsp-rust-analyzer-display-parameter-hints))
   1744                   :reborrowHints (:enable ,lsp-rust-analyzer-display-reborrow-hints)
   1745                   :renderColons ,(lsp-json-bool lsp-rust-analyzer-server-format-inlay-hints)
   1746                   :typeHints ( :enable ,(lsp-json-bool lsp-inlay-hint-enable)
   1747                                :hideClosureInitialization ,(lsp-json-bool lsp-rust-analyzer-hide-closure-initialization)
   1748                                :hideNamedConstructor ,(lsp-json-bool lsp-rust-analyzer-hide-named-constructor)))
   1749     :completion ( :addCallParenthesis ,(lsp-json-bool lsp-rust-analyzer-completion-add-call-parenthesis)
   1750                   :addCallArgumentSnippets ,(lsp-json-bool lsp-rust-analyzer-completion-add-call-argument-snippets)
   1751                   :postfix (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-postfix-enable))
   1752                   :autoimport (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-auto-import-enable))
   1753                   :autoself (:enable ,(lsp-json-bool lsp-rust-analyzer-completion-auto-self-enable)))
   1754     :callInfo (:full ,(lsp-json-bool lsp-rust-analyzer-call-info-full))
   1755     :procMacro (:enable ,(lsp-json-bool lsp-rust-analyzer-proc-macro-enable))
   1756     :rustcSource ,lsp-rust-analyzer-rustc-source
   1757     :linkedProjects ,lsp-rust-analyzer-linked-projects
   1758     :highlighting (:strings ,(lsp-json-bool lsp-rust-analyzer-highlighting-strings))
   1759     :experimental (:procAttrMacros ,(lsp-json-bool lsp-rust-analyzer-experimental-proc-attr-macros))))
   1760 
   1761 (lsp-register-client
   1762  (make-lsp-client
   1763   :new-connection (lsp-stdio-connection
   1764                    (lambda ()
   1765                      `(,(or (executable-find
   1766                              (cl-first lsp-rust-analyzer-server-command))
   1767                             (lsp-package-path 'rust-analyzer)
   1768                             "rust-analyzer")
   1769                        ,@(cl-rest lsp-rust-analyzer-server-command))))
   1770   :activation-fn (lsp-activate-on "rust")
   1771   :priority (if (eq lsp-rust-server 'rust-analyzer) 1 -1)
   1772   :initialization-options 'lsp-rust-analyzer--make-init-options
   1773   :notification-handlers (ht<-alist lsp-rust-notification-handlers)
   1774   :action-handlers (ht ("rust-analyzer.runSingle" #'lsp-rust--analyzer-run-single)
   1775                        ("rust-analyzer.debugSingle" #'lsp-rust--analyzer-debug-lens)
   1776                        ("rust-analyzer.showReferences" #'lsp-rust--analyzer-show-references)
   1777                        ("rust-analyzer.triggerParameterHints" #'lsp--action-trigger-parameter-hints))
   1778   :library-folders-fn (lambda (_workspace) lsp-rust-analyzer-library-directories)
   1779   :semantic-tokens-faces-overrides `( :discard-default-modifiers t
   1780                                       :modifiers ,(lsp-rust-analyzer--semantic-modifiers))
   1781   :server-id 'rust-analyzer
   1782   :custom-capabilities `((experimental .
   1783                                        ((snippetTextEdit . ,(and lsp-enable-snippet (fboundp 'yas-minor-mode)))
   1784                                         (commands . ((commands .
   1785                                                                [
   1786                                                                 "rust-analyzer.runSingle"
   1787                                                                 "rust-analyzer.debugSingle"
   1788                                                                 "rust-analyzer.showReferences"
   1789                                                                 ;; "rust-analyzer.gotoLocation"
   1790                                                                 "rust-analyzer.triggerParameterHints"
   1791                                                                 ;; "rust-analyzer.rename"
   1792                                                                 ]))))))
   1793   :download-server-fn (lambda (_client callback error-callback _update?)
   1794                         (lsp-package-ensure 'rust-analyzer callback error-callback))))
   1795 
   1796 (cl-defmethod lsp-clients-extract-signature-on-hover (contents (_server-id (eql rust-analyzer)))
   1797   "Extract first non-comment line from rust-analyzer's hover CONTENTS.
   1798 The first line of the hover contents is usally about memory layout or notable
   1799 traits starting with //, with the actual signature follows."
   1800   (let* ((lines (s-lines (s-trim (lsp--render-element contents))))
   1801          (non-comment-lines (--filter (not (s-prefix? "//" it)) lines)))
   1802     (if non-comment-lines
   1803         (car non-comment-lines)
   1804       (car lines))))
   1805 
   1806 (lsp-consistency-check lsp-rust)
   1807 
   1808 (provide 'lsp-rust)
   1809 ;;; lsp-rust.el ends here