config

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

lsp-rust.el (72643B)


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