前言
Rust 的 VSCode 官方外掛體驗常常不盡人意,今天逛社群時發現了 rls 2.0 - rust-analyzer,
體驗之後我覺得 rust-analyzer 雖然還有不少瑕疵,但至少比 rls 1.0 要好,希望 Rust 工作組
多投入點精力在提升編輯器體驗吧: )。
安裝
需要 nodejs 10+ 和 npm,可以參考 node.js and npm,不再贅述。
有可能還需要安裝 rust 標準庫
rustup component add rust-src
確保 code
命令在 PATH
環境變數中,並解除安裝 Rust 外掛避免衝突,執行以下命名安裝 rust-analyzer
git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
cd rust-analyzer
cargo install-ra
如果安裝沒有出錯,這將會在機器上安裝 rls 和 vscode 外掛。
如果要更新 rust-analyzer,pull 最新程式碼後重跑一次 cargo install-ra
即可。
配置
開啟 VSCode,[[ctrl + ,]] 搜尋 rust 即可看到 rust-analyzer 所有配置。
常用配置有:
{
"rust-analyzer.enableCargoWatchOnStartup": "true", // 開啟專案時自動開啟 cargo watch
"rust-analyzer.highlightingOn": true, // 覆蓋內建語法高亮
"rust-analyzer.lruCapacity": 1000, // 分析器最大快取深度
}
更多配置參考 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 和 結構體
trait Foo {
fn foo(&self);
fn bar(&self);
fn baz(&self);
}
struct S;
如果這個結構體要實現這個 trait 你可以在輸入 impl Foo for S {}
看到左邊的輔助提示,按 [[ctrl + .]] 看到 add missing impl members
,回車確定後
會自動填充如下程式碼
impl Foo for s {
fn foo(&self) { unimplemented!() }
fn bar(&self) { unimplemented!() }
fn baz(&self) { unimplemented!() }
}
個人覺得這個功能還是非常方便的,特別是實現一些不熟悉的 trait 時不必翻 trait 定義。
路徑匯入
假如有一段這樣的程式碼
impl std::fmt::Debug for Foo {
}
游標移動到 Debug
後使用程式碼輔助會幫你如下重構程式碼
use std::fmt::Debug;
impl Debug for Foo {
}
改變函式可見性
當游標移動到私有函式名時可以透過程式碼輔助快速地將函式改為 pub
或 pub (crate)
填充模式匹配分支
假設有如下列舉體
enum A {
As,
Bs,
Cs(String),
Ds(String, String),
Es{x: usize, y: usize}
}
fn main() {
let a = A::As;
match a {}
}
在輸入 match a {}
後程式碼輔助會自動幫你展開匹配,如:
fn main() {
let a = A::As;
match <|>a {
A::As => (),
A::Bs => (),
A::Cs(_) => (),
A::Ds(_, _) => (),
A::Es{x, y} => (),
}
}
也是一個非常實用的功能
除了上述輔助特性,rust-analyzer 還有更多程式碼輔助特性,有興趣可以參考 Code Actions(Assists)
Magic 填充
這個功能給我的感覺就像使用 IPython 的 %command
魔術命令一樣,酷炫又實用。
假設有如下函式:
foo() -> bool { true }
呼叫函式後跟隨 .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 文件: rust-analyzer-Github
本作品採用《CC 協議》,轉載必須註明作者和本文連結