From c3cd11149d39802c431381d8f4d685581ab8c0f5 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 6 Aug 2026 17:23:34 +0800 Subject: feat(linter): refactor lint registry into program resource Extract lint registry loading from cmd_explain into a shared program-level resource initialized via setup. --- mingling_cli/src/linter.rs | 2 +- mingling_cli/src/linter/cmd_explain.rs | 63 ++++++++-------------------------- mingling_cli/src/linter/registry.rs | 33 ++++++++++++++++++ mingling_cli/src/main.rs | 14 +++++--- 4 files changed, 58 insertions(+), 54 deletions(-) create mode 100644 mingling_cli/src/linter/registry.rs (limited to 'mingling_cli/src') diff --git a/mingling_cli/src/linter.rs b/mingling_cli/src/linter.rs index 4916eba..30d79de 100644 --- a/mingling_cli/src/linter.rs +++ b/mingling_cli/src/linter.rs @@ -3,4 +3,4 @@ pub mod cmd_lint; pub mod cmd_ra_lints; pub mod mlint_attr; pub mod mlint_report; - +pub mod registry; diff --git a/mingling_cli/src/linter/cmd_explain.rs b/mingling_cli/src/linter/cmd_explain.rs index d1dffc5..f0a7571 100644 --- a/mingling_cli/src/linter/cmd_explain.rs +++ b/mingling_cli/src/linter/cmd_explain.rs @@ -1,5 +1,6 @@ +use crate::{Next, linter::registry::LintRegistry}; use mingling::{ - Grouped, Routable, ShellContext, StructuralData, Suggest, SuggestItem, + Grouped, LazyRes, Routable, ShellContext, StructuralData, Suggest, SuggestItem, macros::{ arg, buffer, chain, completion, dispatcher, metadata, pack, pack_err_structural, r_println, renderer, routeify, @@ -7,10 +8,7 @@ use mingling::{ metadata::Description, picker::EntryPicker, }; -use serde::{Deserialize, Serialize}; -use std::sync::OnceLock; - -use crate::Next; +use serde::Serialize; dispatcher!("explain"); @@ -43,43 +41,14 @@ pub fn handle_explain(args: EntryExplain) -> Next { StateExplainLint::new(lint_name).into() } -/// Mirror of the lint registry JSON generated by `build.rs` (`registry.json`). -#[derive(Debug, Deserialize)] -struct LintRegistry { - lints: Vec, -} - -#[derive(Debug, Deserialize)] -struct LintEntry { - name: String, - title: String, - summary: String, - metadata: LintMetadata, -} - -#[derive(Debug, Deserialize)] -struct LintMetadata { - active_on: String, - author: String, - default: String, -} - -/// The lint registry, embedded at compile time via `include_str!`. -/// -/// `registry.json` is regenerated by `build.rs` on every build, so the -/// embedded copy always reflects the lints in `src/lints/`. -fn lint_registry() -> &'static LintRegistry { - static REGISTRY: OnceLock = OnceLock::new(); - REGISTRY.get_or_init(|| { - serde_json::from_str(include_str!("../../registry.json")) - .expect("failed to parse embedded registry.json") - }) -} - #[chain] -pub fn handle_state_explain_lint(p: StateExplainLint) -> Next { +pub fn handle_state_explain_lint( + p: StateExplainLint, + registry: &mut LazyRes, +) -> Next { + let registry = registry.get_ref(); let lint_name = p.inner; - let Some(entry) = lint_registry().lints.iter().find(|l| l.name == lint_name) else { + let Some(entry) = registry.lints.iter().find(|l| l.name == lint_name) else { return ErrorNoSuchLint::new(lint_name).to_chain(); }; ResultExplainLint { @@ -111,25 +80,23 @@ pub fn render_error_no_explain_lint_provided(_: ErrorNoExplainLintProvided) { } #[renderer(buffer)] -pub fn render_error_no_such_lint(err: ErrorNoSuchLint) { +pub fn render_error_no_such_lint(err: ErrorNoSuchLint, registry: &mut LazyRes) { + let registry = registry.get_ref(); r_println!("No such lint: \"{}\"", err.info); r_println!(""); r_println!("Available lints:"); - for entry in &lint_registry().lints { + for entry in registry.lints.iter() { r_println!(" {}", entry.name); } } #[completion(EntryExplain)] -pub fn complete_explain(ctx: &ShellContext) -> Suggest { +pub fn complete_explain(ctx: &ShellContext, registry: &mut LazyRes) -> Suggest { + let registry = registry.get_ref(); if ctx.previous_word != "explain" { return Suggest::FileCompletion; } - let lints: Vec = lint_registry() - .lints - .iter() - .map(|l| l.name.clone()) - .collect(); + let lints: Vec = registry.lints.iter().map(|l| l.name.clone()).collect(); let mut suggest = Suggest::new(); for lint in lints { suggest.insert(SuggestItem::Simple(lint)); diff --git a/mingling_cli/src/linter/registry.rs b/mingling_cli/src/linter/registry.rs new file mode 100644 index 0000000..5241c29 --- /dev/null +++ b/mingling_cli/src/linter/registry.rs @@ -0,0 +1,33 @@ +use mingling::{LazyInit, Program, macros::program_setup}; +use serde::Deserialize; + +use crate::ThisProgram; + +#[derive(Debug, Default, Clone, Deserialize)] +pub struct LintRegistry { + pub lints: Vec, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct LintEntry { + pub name: String, + pub title: String, + pub summary: String, + pub metadata: LintMetadata, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct LintMetadata { + pub active_on: String, + pub author: String, + pub default: String, +} + +#[program_setup] +pub fn lint_registry_setup(p: &mut Program) { + p.with_resource(LintRegistry::lazy_init(|| { + let registry: LintRegistry = serde_json::from_str(include_str!("../../registry.json")) + .expect("failed to parse embedded registry.json"); + registry + })); +} diff --git a/mingling_cli/src/main.rs b/mingling_cli/src/main.rs index da30861..7c71bcd 100644 --- a/mingling_cli/src/main.rs +++ b/mingling_cli/src/main.rs @@ -1,8 +1,11 @@ -use crate::metadata::{ - MinglingMetadataSetup, - setup::{ - ARG_ALL_FEATURES, ARG_FEATURES, ARG_MANIFEST_PATH, ARG_MESSAGE_FORMAT, - ARG_NO_DEFAULT_FEATURES, ARG_NO_DEPS, +use crate::{ + linter::registry::LintRegistrySetup, + metadata::{ + MinglingMetadataSetup, + setup::{ + ARG_ALL_FEATURES, ARG_FEATURES, ARG_MANIFEST_PATH, ARG_MESSAGE_FORMAT, + ARG_NO_DEFAULT_FEATURES, ARG_NO_DEPS, + }, }, }; use mingling::{ @@ -34,6 +37,7 @@ async fn main() { program.with_setup(ExitCodeSetup::default()); program.with_setup(MinglingMetadataSetup); + program.with_setup(LintRegistrySetup); // Exec program.exec_and_exit().await; -- cgit