VSCode 使用 rust-analyzer


VSCode 使用 rust-analyzer


前言

Rust 的 VSCode 官方插件體驗常常不盡人意,今天逛社區時發現了 rls 2.0 - rust-analyzer,體驗之後我覺得 rust-analyzer 雖然還有不少瑕疵,但至少比 rls 1.0 要好,希望 Rust 工作組多投入點精力在提升編輯器體驗吧: )。

安裝

需要 nodejs 10+ 和 npm,可以參考 https://nodejs.org/,不再贅述。有可能還需要安裝 rust 標準庫

<code>rustup component add rust-src/<code>

確保 code 命令在 PATH 環境變量中,並卸載 Rust 插件避免衝突,執行以下命名安裝 rust-analyzer

<code>git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1cd rust-analyzercargo install-ra/<code>

如果安裝沒有出錯,這將會在機器上安裝 rls 和 vscode 插件。

如果要更新 rust-analyzer,pull 最新代碼後重跑一次 cargo install-ra 即可。

配置

打開 VSCode,[[ctrl + ,]] 搜索 rust 即可看到 rust-analyzer 所有配置。常用配置有:

<code>{"rust-analyzer.enableCargoWatchOnStartup": "true", // 打開項目時自動開啟 cargo watch"rust-analyzer.highlightingOn": true, // 覆蓋內建語法高亮"rust-analyzer.lruCapacity": 1000, // 分析器最大緩存深度}/<code>

更多配置參考 https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings

特性


workspace 符號查找 [[ctrl + t]]

除了 VSCode 自帶的模糊搜索外,rust-analyzer 還通過 # 和 * 增強模糊搜索功能。使用快捷鍵 [[ctrl + t]] 打開符號搜索,在搜索框輸入以下內容,忽略開頭的 `#` 號符

  • Foo 在當前工作區搜索名稱為 Foo 的類型
  • foo# 在當前工作區搜索名為 foo 的函數
  • Foo* 在所有依賴,包括 stdlib 中搜索名稱為 Foo 的類型
  • foo#** 在所有依賴中搜索名為 foo 的函數

當前文檔符號搜索 [[ctrl + shift + o]]

提供了完整的符號搜索能力,詳細使用請參考 VSCode 文檔。PS: 我最喜歡的一個特性是在 @ 之後添加 : 就可以對所有符號進行分類,整齊又美觀。

輸入輔助

雖然文檔中說 rust-analyzer 擁有如下特性,但在我的 VSCode 似乎不起作用rust-analyzer 會在輸入特定字符提供輔助:

  • 輸入 let = 時如果 = 跟著一個已知表達式會嘗試自動添加 ;
  • 在註釋中輸入時如果換行會自動在行首添加註釋符號
  • 在鏈式調用中輸入 . 會自動縮進

代碼輔助

rust-analyzer 添加幾個有用的代碼提示或輔助。

結構體代碼輔助

如果把光標移動到結構體名稱上,使用 ctrl + . 可以看到出現了 add #[derive] 和 add impl 兩個提示,顧名思義 add #[derive] 是為結構體添加derive 而 add impl 則會自動添加 impl 語句塊。

自動添加缺失 trait 成員方法

加入有一個 trait 和 結構體

<code>trait Foo {    fn foo(&self);    fn bar(&self);    fn baz(&self);}struct S;/<code>

如果這個結構體要實現這個 trait 你可以在輸入 impl Foo for S {} 看到左邊的輔助提示,按 [[ctrl + .]] 看到 `add missing impl members`,回車確定後會自動填充如下代碼

<code>impl Foo for s {    fn foo(&self) { unimplemented!() }    fn bar(&self) { unimplemented!() }    fn baz(&self) { unimplemented!() }}/<code>

個人覺得這個功能還是非常方便的,特別是實現一些不熟悉的 trait 時不必翻 trait 定義。

路徑導入

假如有一段這樣的代碼

<code>impl std::fmt::Debug for Foo {}/<code>

光標移動到 Debug 後使用代碼輔助會幫你如下重構代碼

<code>use std::fmt::Debug;impl Debug for Foo {}/<code>


改變函數可見性

當光標移動到私有函數名時可以通過代碼輔助快速地將函數改為 pub 或 pub (crate)

填充模式匹配分支

假設有如下枚舉體

<code>enum A {    As,    Bs,    Cs(String),    Ds(String, String),    Es{x: usize, y: usize}}fn main() {    let a = A::As;    match a {}}/<code>

在輸入 match a {} 後代碼輔助會自動幫你展開匹配,如:

<code>fn main() {    let a = A::As;    match a {        A::As => (),        A::Bs => (),        A::Cs(_) => (),        A::Ds(_, _) => (),        A::Es{x, y} => (),    }}/<code>

也是一個非常實用的功能

除了上述輔助特性,rust-analyzer 還有更多代碼輔助特性,有興趣可以參考 https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md#code-actions-assists

Magic 填充

這個功能給我的感覺就像使用 IPython 的 %command 魔術命令一樣,酷炫又實用。假設有如下函數:

<code>foo() -> bool { true }/<code>

調用函數後跟隨 .if 接著按 [[tab]] 會自動展開為 `if foo() {}`。所有可展開表達式如下:

  • expr.if->if expr {}
  • expr.match->match expr {}
  • expr.while->while expr {}
  • expr.ref->&expr
  • expr.refm->&mut expr
  • expr.not->!expr
  • expr.dbg->dbg!(expr)

除此之外在表達式內還有如下 snippets

  • pd->println!("{:?}")
  • ppd->println!("{:#?}")

在模塊中還有提供了測試方法的 snippets

  • tfn->#[test] fn f(){}

總結:

新的 rls 比原來的 rls 提供了更多貼心的功能,但一些基本功能反而沒有原來的 rls 好,也有可能是缺少 snippets 的原因,剛開始用還挺不習慣的,但熟悉了只要感覺還是不錯。


本文參考為 rust-analyzer 文檔: [https://github.com/rust-analyzer/rust-analyzer](https://github.com/rust-analyzer/rust-analyzer)


分享到:


相關文章: