编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

《成为Rust专家》 三 Rust工具(1)

wxchong 2025-01-11 17:59:05 开源技术 41 ℃ 0 评论

本章涵盖

? 介绍Rust语言核心工具:rust-analyzer、rustfmt、Clippy和sccache

? 将Rust工具与Visual Studio Code集成

? 使用稳定版与夜间版工具链

? 探索你可能会发现有用的其他工具

掌握任何语言都取决于掌握其工具。在本章中,我们将探索一些你使用Rust时需要掌握的关键工具。

Rust提供了多种工具来提高生产力并减少生产高质量软件所需的繁杂工作量。Rust的编译器rustc是建立在LLVM之上的,因此Rust继承了LLVM所包含的丰富工具,例如LLVM的调试器LLDB。除了你期望从其他语言中找到的工具外,Rust还包括了一些其特有的Rust专用工具,这些将在本章中讨论。

本章讨论的主要工具包括rust-analyzer、rustfmt、Clippy和sccache。这些是你每次使用Rust时都可能会用到的工具。此外,我还包括了一些其他工具的说明,这些工具你可能会偶尔使用:cargo-update、cargo-expand、cargo-fuzz、cargo-watch和cargo-tree。

3.1 Rust工具概述

在第二章中,我们专注于使用Cargo,这是Rust的项目管理工具。此外,在使用Rust时,你可能还想使用一些其他工具。与Cargo不同,这些工具是可选的,可以根据个人意愿使用。然而,我发现它们非常有价值,并且几乎在我的所有Rust项目中使用它们。项目可能需要这些工具中的某些,因此熟悉它们是有价值的。

本章讨论的工具通常通过文本编辑器使用,或者作为命令行工具。

3.2 使用rust-analyzer进行Rust IDE集成

rust-analyzer工具是Rust语言最成熟且功能最全面的编辑器。它可以与任何实现了语言服务器协议(LSP,https://microsoft.github.io/language-server-protocol)的编辑器集成。rust-analyzer提供的一些功能包括:

? 代码补全

? 导入插入

? 跳转到定义

? 重命名符号

? 生成文档

? 重构

? 魔法补全

? 内联编译器错误

? 类型和参数的内联提示

? 语义语法高亮

? 显示内联参考文档

在VS(Visual Studio)Code中,可以使用CLI安装rust-analyzer(见图3.1):

$ code --install-extension rust-lang.rust-analyzer

一旦安装,VS Code在处理Rust代码时将显示如图3.1所示。

注意fn main()顶部的Run | Debug按钮,它允许您一键运行或调试代码。

如果您使用IntelliJ Rust,就不需要为Rust支持安装单独的扩展。然而,值得注意的是,IntelliJ Rust与rust-analyzer共享一些代码,特别是用于其宏支持(http://mng.bz/wjAP)。


3.2.1 魔法补全

Rust-analyzer 具有后缀文本补全功能,可以为常见任务(如调试打印或字符串格式化)提供快速补全。熟悉魔法补全是很有帮助的,因为它可以节省你大量的重复打字。此外,你只需要记住补全表达式,而不需要记忆语法。我建议练习魔法补全,因为一旦你掌握了语法,你会发现自己经常使用它们。

魔法补全类似于代码片段(VS Code 和其他编辑器的功能),但有一些 Rust 特定的功能,使它们有点像“代码片段++”。魔法补全也可以在任何支持语言服务器协议的编辑器中使用,不仅仅是 VS Code。

使用魔法补全就像输入一个表达式并使用编辑器的补全下拉菜单一样简单。例如,要在当前源文件中创建一个测试模块,你可以输入 tmod 并选择第一个补全结果,这将创建一个测试模块模板,如下所示:


tmod 完成创建了一个包含单个测试函数的测试模块,可以根据需要填写。除了 tmod,还有一个 tfn 完成,它创建了一个测试函数。

另一个有用的魔法完成是字符串打印。在 Rust 1.58.0 之前的版本不支持字符串插值。为了帮助弥补字符串插值的缺失,rust-analyzer 提供了几个用于打印、记录和格式化字符串的完成项。

注意:虽然字符串插值在 Rust 1.58.0 中被添加,但本节内容仍然保留在书中,因为它很好地展示了 rust-analyzer 的功能。

在你的编辑器中输入以下内容:


在这个阶段,将光标放在字符串引号的末尾并输入.print将字符串转换为println完成选项,如图3.2所示。

如果你通过按一次Enter键选择println选项,该选项将从出现的下拉菜单中被选中,然后rust-analyzer将代码转换为以下形式:

表3.3包含了一些需要注意的重要神奇补全。列表不是详尽无遗的,完整的神奇补全列表和其他rust-analyzer的功能可以在手册中找到,网址为https://rust-analyzer.github.io/manual.html。



3.3 使用rustfmt保持代码整洁

源代码格式化可能会引起烦恼,特别是在有多个开发者的Rust项目中。对于单个贡献者的项目来说,这并不是什么大问题,但是一旦你有超过一个贡献者,编码风格就可能出现分歧。Rustfmt是Rust对编码风格的回答,它提供了一种符合习惯用法、自动化的、有明确意见的样式工具。

如果你来自Golang或其他语言的类似格式化工具,它与gofmt很相似。有意见的格式化这个概念相对较新,而且——以我谦卑的观点来看——它是现代编程语言的一个很好的补充。

运行cargo fmt --check -v的示例输出如图3.3所示,它启用了详细模式和检查模式。传递--check将会导致命令在格式化不符合预期时返回非零值,这对于在持续集成系统上检查代码格式非常有用。


我无法计算我在拉取请求代码格式化争论上浪费了多少小时。这个问题可以通过使用rustfmt并简单地强制代码贡献遵循定义的风格来立即解决。与其发布和维护冗长的风格指南文档,不如使用rustfmt,这样可以为所有人节省大量时间。

3.3.1 安装rustfmt

Rustfmt作为rustup组件进行安装:

$ rustup component add rustfmt
...

安装完成后,可以通过运行Cargo来使用。

$ cargo fmt

3.3.2 配置 rustfmt

虽然默认的 rustfmt 配置对大多数人来说已经足够,但你可能想要稍微调整一些设置以符合你的偏好。这可以通过在项目的源代码树中添加一个 .rustfmt.toml 配置文件来完成。

format_code_in_doc_comments = true
group_imports = "StdExternalCrate"
imports_granularity = "Module"
unstable_features = true
version = "Two"
wrap_comments = true

在撰写本文时,一些显著的rustfmt选项仅限于夜间版本的特性。最新的样式选项列表可以在rustfmt的网站上找到,网址为https://rust-lang.github.io/rustfmt/。

提示 如果你来自C或C++的世界,并希望在那边应用相同的固执己见的格式化模式,请务必查看LLVM的一部分clang-format工具。

3.4 使用Clippy提升代码质量

Clippy是Rust的代码质量工具,在撰写本文时提供了超过450个检查。如果你曾经因为一个喜欢在代码审查中插话并指出小的语法、格式和其他风格改进的同事而感到沮丧,那么Clippy就是为你准备的。Clippy可以做你的同事所做的同样的工作,但没有任何讽刺,而且在许多情况下,它甚至会给你提供代码更改。

Clippy通常可以在你的代码中找到真正的问题。然而,Clippy的真正好处在于它消除了因代码风格问题而争论的需要,因为它强制执行了Rust的惯用风格和模式。Clippy与稍早讨论的rustfmt有关,但比rustfmt稍微先进一些。

3.4.1 安装 Clippy

Clippy 作为 rustup 组件分发;因此,它是这样安装的:

$ rustup component add clippy
...

一旦安装,你可以使用Cargo在任何Rust项目上运行Clippy。

$ cargo clippy
...

当运行时,Clippy将产生类似于rustc编译器输出的输出,如图3.4所示。


3.4.2 Clippy的代码检查

拥有超过450个代码质量检查(称为lints),一个人可以写出一本关于Clippy的完整书籍。lints根据它们的严重性级别(允许、警告、拒绝和弃用)进行分类,并根据它们的类型进行分组,这些类型可以是以下几种之一:正确性、限制、风格、弃用、学究式、复杂性、性能、cargo和育苗室。

其中一个lint是blacklisted_name lint,它不允许使用诸如foo、bar或quux这样的变量名。这个lint可以配置,以包含你希望禁止的自定义变量名列表。

另一个lint的例子是bool_comparison lint,它检查表达式和布尔值之间不必要的比较。例如,以下代码被认为是无效的:

另一方面,以下代码是有效的:

Clippy的大多数检查都是与风格相关的,但它也能帮助发现性能问题。例如,redundant_clone检查可以找出变量被不必要地克隆的情况。通常,这种情况看起来是这样的:

let my_string = String::new("my string");
println!("my_string='{}'", my_string.clone());

在前面的代码中,对 clone() 的调用完全是不必要的。如果你用这段代码运行 Clippy,你会得到以下警告:

Clippy经常更新,稳定版Rust的lint列表可以在Clippy文档中找到,网址为http://mng.bz/qjAr。

3.4.3 配置Clippy

可以通过在项目源树中添加一个.clippy.toml文件或在Rust源文件中放置属性来配置Clippy。在大多数情况下,你可能希望根据需要使用属性来禁用Clippy的lints。有很多情况Clippy可能会生成警告,但代码是按预期编写的。

值得注意的是,当没有更好的替代方案时,可能需要调整或禁用Clippy的一些复杂性警告。例如,当你有一个函数参数超过默认的七个限制时,too_many_arguments警告将被触发。你可以增加默认值,或者简单地为特定函数禁用它:

前面代码中的 allow() 属性是特定于 Clippy 的,并指示它对下一行代码的 too_many_arguments 检查允许一个例外。

或者,要更改整个项目的参数阈值,你可以在你的 .clippy.toml 文件中添加以下内容:

.clippy.toml 文件是一个普通的 TOML 文件,它应该包含一个名称 = 值对的列表,根据您的偏好进行设置。每个代码检查(lint)及其相应的配置参数在 Clippy 文档中有详细描述,网址为 https://rust-lang.github.io/rust-clippy/stable/index.html。

3.4.4 自动应用 Clippy 的建议

在某些情况下,Clippy 可以自动修复代码。特别是当 Clippy 能够为您提供一个精确的建议来修复代码时,它通常也可以自动应用这个修复。要自动修复代码,请使用 --fix 标志运行 Clippy

$ cargo clippy --fix -Z unstable-options
...

请注意,由于在编写本文时,--fix功能仅限于nightly版本,我们还需要传递-Z unstable-options选项。

3.4.5 在CI/CD中使用Clippy

如果你有CI/CD系统,我建议将Clippy作为其中的一部分启用。

通常,你会在构建、测试和格式化之后运行Clippy。此外,你可能还想指示Clippy在警告时失败,为所有特性运行,并检查测试。


如果你维护一个开源项目,将Clippy作为CI/CD检查的一部分启用,将使其他人更容易向你的项目贡献高质量的代码。


第二章包含了一个使用Clippy和rustfmt与GitHub的Actions CI/CD系统一起使用的完整示例。

3.5 使用sccache减少编译时间

sccache工具是一个通用的编译器缓存,可以用于Rust项目。对于大型项目,Rust的编译时间可能会显著增长,而sccache通过缓存编译器产生的未改变的对象来帮助减少编译时间。sccache项目是由非营利组织Mozilla专门为帮助Rust编译而创建的,但它足够通用,可以用于大多数编译器。它受到了你可能从C或C++世界中遇到的ccache工具的启发。

即使你的项目不大,安装sccache并在本地使用它也可以节省你大量重新编译代码的时间。例如,从干净的项目编译dryoc crate在我的电脑上通常需要8.891秒。另一方面,如果启用了sccache,从干净的项目编译只需要5.839秒。那就是没有sccache与有sccache相比,编译一个相对较小的项目多花了52%的时间!这个时间累积起来,对于更大的项目来说可能会变得相当显著。

请注意,sccache只在代码之前已经编译过的情况下有帮助。它不会加速全新的构建。

3.5.1 安装 sccache

Sccache 是用 Rust 编写的,可以通过 Cargo 安装:

$ cargo install sccache

一旦安装,通过使用它作为rustc的包装器与Cargo一起使用,即可启用sccache。Cargo接受RUSTC_WRAPPER参数作为环境变量。你可以通过如下方式导出包装器环境变量来使用sccache编译和构建任何Rust项目:

3.5.2 配置 sccache

如果你之前使用过 ccache,那么 sccache 对你来说会很熟悉。Sccache 有一些 ccache 缺少的显著特点:它可以与多种网络存储后端直接使用,这使得它非常适合用于 CI/CD 系统。它支持中立供应商的 S3 协议,一些供应商的存储服务,以及开源的 Redis 和 Memcached 协议。

要配置 sccache,你可以指定环境变量,但它也可以通过平台依赖的配置文件进行配置。默认情况下,sccache 使用最多 10 GiB 的本地存储。要配置 sccache 使用 Redis 后端,你可以将 Redis 的地址设置为环境变量:

关于sccache配置和使用的详细信息,请查阅官方项目文档,网址为:https://github.com/mozilla/sccache。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表