3个稳定版本

3.0.1 2024年4月10日
3.0.0 2024年4月8日
2.6.1 2024年3月18日

1228解析器实现

Download history 917/week @ 2024-04-08 628/week @ 2024-04-15 315/week @ 2024-04-22 332/week @ 2024-04-29 951/week @ 2024-05-06 440/week @ 2024-05-13 44/week @ 2024-05-20 30/week @ 2024-05-27 12/week @ 2024-06-03 191/week @ 2024-06-10 45/week @ 2024-06-17 60/week @ 2024-06-24 85/week @ 2024-07-01 150/week @ 2024-07-08 56/week @ 2024-07-15 2/week @ 2024-07-22

298 每月下载量

MIT/Apache

81KB
1.5K SLoC

dylint_linting

docs.rs 文档

此包提供用于创建Dylint库的宏,以及用于创建可配置库的工具。

内容

dylint_library!

dylint_library!宏展开为以下内容

#[allow(unused_extern_crates)]
extern crate rustc_driver;

#[no_mangle]
pub extern "C" fn dylint_version() -> *mut std::os::raw::c_char {
    std::ffi::CString::new($crate::DYLINT_VERSION)
        .unwrap()
        .into_raw()
}

如果你的库使用dylint_library!宏和dylint-link工具,那么你只需要实现register_lints函数。请参阅此存储库中的示例

declare_late_lint!等。

如果你的库只包含一个lint,使用declare_late_lint!等可以使你的代码更简洁。这些宏都需要与declare_lint!相同的参数,并包装以下内容

  • dylint_library!的调用
  • register_lints函数的实现
  • declare_lint!的调用
  • declare_lint_pass!的调用

例如,declare_late_lint!(vis NAME, Level, "description")展开为以下内容

dylint_linting::dylint_library!();

extern crate rustc_lint;
extern crate rustc_session;

#[no_mangle]
pub fn register_lints(sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) {
    dylint_linting::init_config(sess);
    lint_store.register_lints(&[NAME]);
    lint_store.register_late_pass(|_| Box::new(Name));
}

rustc_session::declare_lint!(vis NAME, Level, "description");

rustc_session::declare_lint_pass!(Name => [NAME]);

declare_early_lint!declare_pre_expansion_lint!定义类似。

impl_late_lint!等。

impl_late_lint!等与declare_late_lint!等类似,除了

  • 每个调用都使用impl_lint_pass!而不是declare_lint_pass!;
  • 每个调用都需要一个额外的参数来指定LintPass结构体的值。

也就是说,impl_late_lint!的额外参数就是这里所用的

    lint_store.register_late_pass(|_| Box::new(...));
                                               ^^^

下面是一个在env_cargo_path中的impl_pre_expansion_lint!使用示例。

constituent功能

启用包级别的constituent特性会改变上述宏的工作方式。具体来说,它会排除

  • dylint_library!的调用
  • register_lints声明之前使用#[no_mangle]

这些更改使得将使用上述宏之一声明的lint包含到更大的库中变得容易。也就是说

  • 当关闭该特性时,lint可以作为一个独立的库来构建。
  • 当开启该特性时,lint可以作为更大库的一部分来构建,与其他lints一起。

此存储库中的通用补充lints使用了这种技术。也就是说,每个通用lint都可以作为一个独立的库来构建,或者作为general的一部分。类似的说法也适用于补充lints和supplementary。使这一切成为可能的底层机制是constituent特性。

可配置库

可以通过在目标工作空间的根目录中包含一个dylint.toml文件来配置库。此crate提供了以下用于读取和解析dylint.toml文件的功能

仅包含一个lint的可配置库通常具有以下形式的lib.rs文件

dylint_linting::impl_late_lint! {
    ...,
    LintName::new()
}

// Lint configuration
#[derive(Default, serde::Deserialize)]
struct Config {
    boolean: bool,
    strings: Vec<String>,
}

// Keep a copy of the configuration in the `LintPass` structure.
struct LintName {
    config: Config,
}

// Read the configuration from the `dylint.toml` file, or use the default configuration if
// none is present.
impl LintName {
    pub fn new() -> Self {
        Self {
            config: dylint_linting::config_or_default(env!("CARGO_PKG_NAME")),
        }
    }
}

有关此形式lib.rs文件的具体示例,请参阅此存储库中的non_local_effect_before_error_return库。

包含多个lint的库必须实现register_lints函数,而不依赖于上述宏。如果库是可配置的,那么其register_lints函数应该包含对dylint_linting::init_config的调用,如下例所示

#[no_mangle]
pub fn register_lints(sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) {
    // `init_config` or `try_init_config` must be called before `config_or_default`, `config`,
    // or `config_toml` is called.
    dylint_linting::init_config(sess);

    lint_store.register_lints(&[FIRST_LINT_NAME, SECOND_LINT_NAME]);

    lint_store.register_late_pass(|_| Box::new(LintPassName::new()));
}

有关config_or_default等更多文档,请参阅docs.rs

依赖项

~1.3–2.2MB
~45K SLoC