前言
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)
閱讀更多 PrivateRookie 的文章