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 开发工具

MIT/Apache

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。之后,您可以像调用以下命令一样调用redpencargo 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工具,旨在作为cargorustc之间的中继。它通过以下命令调用: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