config

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

lsp-rust.el (73252B)


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