3个稳定版本
3.0.1 | 2024年4月10日 |
---|---|
3.0.0 | 2024年4月8日 |
2.6.1 | 2024年3月18日 |
1228 在 解析器实现
298 每月下载量
81KB
1.5K SLoC
dylint_linting
此包提供用于创建Dylint库的宏,以及用于创建可配置库的工具。
内容
dylint_library!
declare_late_lint!
,declare_early_lint!
,declare_pre_expansion_lint!
impl_late_lint!
,impl_early_lint!
,impl_pre_expansion_lint!
constituent
功能- 可配置库
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