4个版本 (重大更新)
0.4.0 | 2024年5月13日 |
---|---|
0.3.0 | 2023年11月9日 |
0.2.0 | 2023年9月1日 |
0.1.0 | 2023年9月1日 |
#688 in 开发工具
120KB
2.5K SLoC
红笔 ️❌🖊
redpen
是一个用于Rust代码的代码检查器。
目标
该工具的目标是
- 拥有自己的自定义代码检查集,独立于clippy,以便允许不同的默认设置
- 作为内部
rustc
API稳定性的测试平台 - 作为为该工具编写的代码检查和内部API之间的缓冲区,通过提供自己的编译器内部API,以便修改
rustc
API内部不需要经常重写代码检查(这项工作尚未开始) - 快速编译,作为CI的一部分,以便项目可以编写特定于项目的代码检查
实现的代码检查
目前,只编写了两个代码检查
- 一个简单的代码检查,作为“否定特质检查”运行,如果使用特定类型的注解类型参数则发出警告
- 一个非常有用的断言,注解的fn不会间接调用panic
名称的含义
该工具以教师用来标记你论文中错误的手写笔命名。 rustc
是一位严格的教师。 redpen
是一位非常严格的教师。
安装和使用
使用此工具有两种方式。如果您只想使用现有的lint,则可以通过以下命令通过cargo
安装:cargo +nightly-2024-05-06 install redpen-linter
。之后,您可以像调用以下命令一样调用redpen
:cargo check
。您必须确保已安装适当的Rust 1.72编译器,使用以下命令:rustup toolchain add nightly-2024-05-06
,因为redpen
与特定编译器版本的内部API紧密耦合。此外,您还必须在Cargo.toml
文件中的以下部分添加以下内容:
[dependencies]
cargo-redpen-shim = { version = "0.1", package = "redpen" }
这是必要的,以便在运行常规cargo
命令时,如cargo build
,自定义lint检查注解将被识别为有效的项目属性,而不会使您的构建失败。
如果您想保留自己的lint集,那么您将不得不保留自己工作的redpen
组件副本。
克隆此存储库并运行以下命令:cargo install
export LD_LIBRARY_PATH=$(rustup run nightly-2024-05-06 bash -c "echo \$LD_LIBRARY_PATH")
git clone https://github.com/estebank/redpen.git
cd redpen
cargo install --path .
请注意,由于redpen
与Rust版本绑定,因此运行以下命令可能不会按预期工作:cargo install --git
,因为它不会使用存储库中的rust-toolchain
文件。
如果您正在添加新的lint,您还需要提供自己的redpen
proc-macro crate。
外观
给定以下内容的src/main.rs
#[redpen::disallow(T = "Pineapple")]
struct Pizza<T>(T);
struct Pineapple;
#[allow(dead_code)]
type Alias = Pizza<Pineapple>;
impl Pineapple {
fn foo(&self) {
panic!("foo");
}
}
#[redpen::dont_panic]
fn bar() {
Pineapple.foo();
let mut v = vec![1];
v.swap_remove(0);
v[1];
panic!("asdf");
}
fn main() {
bar();
let _ = Pizza(Pineapple);
}
执行redpen
将产生以下输出
$ redpen
Compiling pizza v0.1.0 (/home/gh-estebank/pizza)
error: `bar` can panic
--> src/main.rs:16:1
|
15 | #[redpen::dont_panic]
| --------------------- the function can't panic due to this annotation
16 | fn bar() {
| ^^^^^^^^ this function can panic
17 | Pineapple.foo();
| --- panic can occur here
18 | let mut v = vec![1];
19 | v.swap_remove(0);
| ----------- panic can occur here
20 | v[1];
| ---- panic can occur here
21 | panic!("asdf");
| -------------- panic can occur here
|
= note: `#[deny(redpen::dont_panic)]` on by default
error: type parameter `T` in `Pizza` can't be `Pineapple`
--> src/main.rs:7:20
|
7 | type Alias = Pizza<Pineapple>;
| ^^^^^^^^^
|
= note: `#[deny(redpen::disallow)]` on by default
error: type parameter `T` in `Pizza` can't be `Pineapple`
--> src/main.rs:26:13
|
26 | let _ = Pizza(Pineapple);
| ^^^^^^^^^^^^^^^^ this expression is of type `Pizza<Pineapple>`
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
工作原理
此lint实现为一个rustc_driver
,实际上是一个对常规rustc
实现的另一个入口点。它链接到预构建的rustc_*
组件,因此您只需编译少量的代码,使其构建相当快。
redpen_wrapper
是一个非常小的CLI工具,旨在作为cargo
和rustc
之间的中继。它通过以下命令调用:RUST_WRAPPER=redpen_wrapper cargo build
。这允许我们使用rustc
构建指定的crate,并且只有在完成此操作后,才执行redpen
以执行lint并收集跨crate分析所需的数据(如panic!()
可达性lint)。
cargo-redpen
是一个小的CLI,它使用适当的环镜变量调用cargo build
。
export LD_LIBRARY_PATH=$(rustup run nightly-2024-05-06 bash -c "echo \$LD_LIBRARY_PATH")
RUSTC_WRAPPER=$PATH_TO/redpen_wrapper \
RUSTC_BOOTSTRAP=1 \
cargo +nightly-2024-05-06 build \
-Zbuild-std \
--target x86_64-unknown-linux-gnu # haven't tried in other platforms, experiment replacing this for your case
祖先通知
此lint最初是基于Rust-on-Linux linter klint构建的,而后者又利用了rustc
代码库。
依赖关系
~0–6.5MB
~33K SLoC