From 9f5a0f2e9325264564bc6fe9ff544c034ad16287 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 20 Jul 2026 14:49:47 +0800 Subject: chore: add missing docs lint and document public API Add `#![deny(missing_docs)]` across multiple crates and fill in documentation for all public items, including struct fields, enum variants, trait methods, and proc macros. Also mark two shell scripts as executable. --- .run/src/bin/doc.sh | 0 .run/src/bin/http-page-preview.sh | 0 arg_picker/src/lib.rs | 1 + arg_picker/src/pickable/multi_pickable.rs | 16 +++++ arg_picker/src/value/vec_until.rs | 1 + arg_picker_macros/src/lib.rs | 1 + mingling/src/lib.rs | 4 ++ mingling/src/setups/repl_basic.rs | 2 + mingling_core/src/any.rs | 15 +++++ mingling_core/src/lib.rs | 6 ++ mingling_core/src/program.rs | 20 ++++++ mingling_core/src/program/collection.rs | 8 +++ mingling_core/src/renderer/render_result.rs | 5 ++ mingling_core/src/renderer/structural/error.rs | 1 + mingling_macros/src/lib.rs | 85 ++++++++++++++++++++++++++ mingling_pathf/src/error.rs | 16 ++++- mingling_pathf/src/lib.rs | 1 + mingling_pathf/src/pattern_analyzer.rs | 2 + mingling_pathf/src/patterns/dispatcher.rs | 8 +++ mingling_pathf/src/patterns/dispatcher_clap.rs | 6 ++ 20 files changed, 196 insertions(+), 2 deletions(-) mode change 100644 => 100755 .run/src/bin/doc.sh mode change 100644 => 100755 .run/src/bin/http-page-preview.sh diff --git a/.run/src/bin/doc.sh b/.run/src/bin/doc.sh old mode 100644 new mode 100755 diff --git a/.run/src/bin/http-page-preview.sh b/.run/src/bin/http-page-preview.sh old mode 100644 new mode 100755 diff --git a/arg_picker/src/lib.rs b/arg_picker/src/lib.rs index 285cd16..d292826 100644 --- a/arg_picker/src/lib.rs +++ b/arg_picker/src/lib.rs @@ -1,4 +1,5 @@ #![doc = include_str!("../README.md")] +#![deny(missing_docs)] mod builtin; diff --git a/arg_picker/src/pickable/multi_pickable.rs b/arg_picker/src/pickable/multi_pickable.rs index 84a8068..404c23b 100644 --- a/arg_picker/src/pickable/multi_pickable.rs +++ b/arg_picker/src/pickable/multi_pickable.rs @@ -5,13 +5,29 @@ use crate::{ }; /// Boundary check for multi-value positional parameters. +/// +/// Determines whether a raw string marks the end of a multi-value +/// parameter's input range. pub trait BoundaryCheck { + /// Returns `true` if `raw` indicates a boundary (i.e., the start of + /// a new parameter), stopping greedy collection. fn check_boundary(raw: &str) -> bool; } /// Trait for multi-value parameters. +/// +/// Implementors define how a sequence of raw strings is converted into +/// a single value, with an associated [`BoundaryCheck`] to control where +/// collection stops. pub trait MultiPickableWithBoundary: Sized { + /// The boundary checker type that determines when to stop consuming + /// positional arguments. type Checker: BoundaryCheck; + + /// Parse and collect multiple raw string values into `Self`. + /// + /// The caller should stop passing additional items once the + /// associated [`Checker`](Self::Checker) signals a boundary. fn pick_multi(raw: Vec) -> PickerArgResult; } diff --git a/arg_picker/src/value/vec_until.rs b/arg_picker/src/value/vec_until.rs index 1b79641..04d87ce 100644 --- a/arg_picker/src/value/vec_until.rs +++ b/arg_picker/src/value/vec_until.rs @@ -21,6 +21,7 @@ pub struct VecUntil { } impl VecUntil { + /// Consumes `self` and returns the underlying [`Vec`]. pub fn into_inner(self) -> Vec { self.inner } diff --git a/arg_picker_macros/src/lib.rs b/arg_picker_macros/src/lib.rs index 18cce84..0132e66 100644 --- a/arg_picker_macros/src/lib.rs +++ b/arg_picker_macros/src/lib.rs @@ -1,4 +1,5 @@ #![doc = include_str!("../README.md")] +#![deny(missing_docs)] use proc_macro::TokenStream; diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs index 8f5dc38..f5362d5 100644 --- a/mingling/src/lib.rs +++ b/mingling/src/lib.rs @@ -1,4 +1,8 @@ #![doc(html_logo_url = "https://github.com/mingling-rs/mingling/raw/main/docs/res/icon3.png")] +#![doc( + html_favicon_url = "https://github.com/mingling-rs/mingling/raw/main/docs/res/favicon_small.png" +)] +#![deny(missing_docs)] #![doc = include_str!("lib.md")] #[cfg(feature = "core")] diff --git a/mingling/src/setups/repl_basic.rs b/mingling/src/setups/repl_basic.rs index 71a38d2..cf04372 100644 --- a/mingling/src/setups/repl_basic.rs +++ b/mingling/src/setups/repl_basic.rs @@ -19,7 +19,9 @@ where /// meaning only the last configured instance will take effect globally. /// Do not configure multiple prompts with different values — only one will be used. pub enum BasicREPLPromptSetup { + /// A static prompt string that is displayed before each REPL input. Prompt(String), + /// A function that returns a dynamic prompt string each time the REPL reads input. Func(fn() -> String), } diff --git a/mingling_core/src/any.rs b/mingling_core/src/any.rs index e6b7406..ec29a1b 100644 --- a/mingling_core/src/any.rs +++ b/mingling_core/src/any.rs @@ -17,7 +17,18 @@ pub mod group; #[derive(Debug)] pub struct AnyOutput { pub(crate) inner: Box, + + /// The [`TypeId`] of the concrete type stored in `inner`. + /// + /// This is set during construction and used for type-checking + /// in downcast, restore, and is methods. pub type_id: std::any::TypeId, + + /// The variant identifier returned by [`Grouped::member_id`] for the + /// concrete type stored in `inner`. + /// + /// This is used by the scheduler to dispatch on the correct enum + /// variant when routing the output. pub member_id: G, } @@ -106,7 +117,9 @@ impl std::ops::DerefMut for AnyOutput { /// - Returns `Ok((`[`AnyOutput`](./struct.AnyOutput.html)`, `[`NextProcess::Renderer`](./enum.NextProcess.html)`))` to render this type next and output to the terminal /// - Returns `Err(`[`ChainProcessError`](./error/enum.ChainProcessError.html)`]` to terminate the program directly pub enum ChainProcess { + /// Indicates success, containing the output value and the next step to execute. Ok((AnyOutput, NextProcess)), + /// Indicates a processing failure, containing the error that occurred. Err(ChainProcessError), } @@ -117,7 +130,9 @@ pub enum ChainProcess { #[derive(Debug, PartialEq, Eq)] #[repr(u8)] pub enum NextProcess { + /// Continue execution to the next chain Chain, + /// Send output to renderer and end execution Renderer, } diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs index 4996b19..2cb24b9 100644 --- a/mingling_core/src/lib.rs +++ b/mingling_core/src/lib.rs @@ -8,6 +8,8 @@ //! //! Recommended to import [mingling](https://crates.io/crates/mingling) to use its features. +#![deny(missing_docs)] + mod any; mod asset; mod program; @@ -77,6 +79,10 @@ pub mod comp; #[cfg(feature = "comp")] pub use crate::comp::*; +/// Module for setting up a `Mingling` program. +/// +/// This module provides the [`ProgramSetup`] type, which allows users to configure +/// and initialize the program's execution environment. pub mod setup { pub use crate::program::setup::ProgramSetup; } diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 0d409b7..11e1bbf 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -53,10 +53,30 @@ where #[cfg(not(feature = "dispatch_tree"))] pub(crate) dispatcher: Vec + Send + Sync>>, + /// Program stdout settings. + /// + /// This struct controls the program's output behavior, including whether + /// to output errors, render results, suppress panic messages, enable + /// verbose/quiet/debug modes, colored output, and progress indicators. + /// + /// # Convention-only fields + /// + /// Fields marked with convention only are not enforced by the framework; + /// they serve as a shared convention for applications to follow consistently. pub stdout_setting: ProgramStdoutSetting, + + /// User-defined context that can be accessed throughout the program. + /// + /// This field holds a user-defined context value that can be + /// accessed and modified at any point during program execution. It is + /// useful for passing shared state or configuration across different + /// parts of the program. pub user_context: ProgramUserContext, #[cfg(feature = "structural_renderer")] + /// Setting for the structural renderer. + /// + /// This field is only available when the `structural_renderer` feature is enabled. pub structural_renderer_name: StructuralRendererSetting, pub(crate) hooks: Vec>, diff --git a/mingling_core/src/program/collection.rs b/mingling_core/src/program/collection.rs index fe78979..14705ac 100644 --- a/mingling_core/src/program/collection.rs +++ b/mingling_core/src/program/collection.rs @@ -21,8 +21,16 @@ pub use mock::*; pub trait ProgramCollect { /// Enum type representing internal IDs for the program type Enum; + /// Error type when a dispatcher is not found for the given member type ErrorDispatcherNotFound: Grouped; + + /// Error type when a renderer is not found for the given member type ErrorRendererNotFound: Grouped; + + /// Result type for an empty chain result + /// + /// When the `extra_macros` feature is enabled, + /// you can use the `empty_result!()` macro to create this type ResultEmpty: Grouped; /// Use a prefix tree to quickly match arguments and dispatch to an Entry diff --git a/mingling_core/src/renderer/render_result.rs b/mingling_core/src/renderer/render_result.rs index 763f6fc..2c60fa4 100644 --- a/mingling_core/src/renderer/render_result.rs +++ b/mingling_core/src/renderer/render_result.rs @@ -8,6 +8,11 @@ use std::{ #[derive(Default, Debug, PartialEq)] pub struct RenderResult { render_text: String, + + /// The exit code to return from the rendering process. + /// + /// A value of `0` indicates success, while non-zero values indicate + /// various error conditions. pub exit_code: i32, } diff --git a/mingling_core/src/renderer/structural/error.rs b/mingling_core/src/renderer/structural/error.rs index a7fbc75..63ded81 100644 --- a/mingling_core/src/renderer/structural/error.rs +++ b/mingling_core/src/renderer/structural/error.rs @@ -9,6 +9,7 @@ pub struct StructuralRendererSerializeError { } impl StructuralRendererSerializeError { + /// Creates a new `StructuralRendererSerializeError` with the given error message. #[must_use] pub fn new(error: String) -> Self { Self { error } diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index cc18958..56ed999 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -141,6 +141,8 @@ //! } //! ``` +#![deny(missing_docs)] + #[cfg(feature = "extra_macros")] use quote::quote; @@ -270,6 +272,36 @@ fn entry_has_variant(entry: &str, variant_name: &str) -> bool { entry.contains(&format!(":: {variant_name} =>")) } +/// Registers an outside type (from `std` or other crates) as a type recognizable +/// by the Mingling framework, without modifying the original type definition. +/// +/// This macro generates a newtype wrapper around the given type that implements +/// `Grouped`, `Into`, `Into`, and the `Routable` trait, +/// making the outside type usable in `#[chain]` and `#[renderer]` functions. +/// +/// # Syntax +/// +/// ```rust,ignore +/// // Simple form — creates a wrapper named after the type's last segment: +/// group!(ParseIntError); +/// +/// // Aliased form — creates a wrapper with a custom name: +/// group!(ErrorIo = std::io::Error); +/// ``` +/// +/// # Example +/// +/// See the full example in the crate documentation or run: +/// ```bash +/// cargo run --example example-outside-type -- parse 42 +/// cargo run --example example-outside-type -- parse hello +/// cargo run --example example-outside-type -- error +/// ``` +/// +/// # Requirements +/// +/// - The type must be accessible at the call site (imported or fully qualified). +/// - The alias name (if provided) must not conflict with existing types. #[cfg(feature = "extra_macros")] #[proc_macro] pub fn group(input: TokenStream) -> TokenStream { @@ -1570,6 +1602,28 @@ pub fn gen_program(input: TokenStream) -> TokenStream { func::gen_program::gen_program_impl(input) } +/// Internal macro used by `gen_program!` to generate the completion infrastructure for +/// shell completion support. +/// +/// **This macro is only available with the `comp` feature.** +/// +/// The `program_comp_gen!` macro generates: +/// 1. A hidden `__internal_completion_mod` module containing: +/// - A `CompletionContext` packed type (wrapping `ShellContext`), dispatched via `"__comp"`. +/// - A `CompletionSuggest` packed type (wrapping `(ShellContext, Suggest)`). +/// - An internal dispatcher (`CMDCompletion`) for the `"__comp"` command path. +/// 2. An internal chain function `__exec_completion` that: +/// - Reads a `ShellContext` from the packed `CompletionContext`. +/// - Calls `CompletionHelper::exec_completion::(&ctx)` to generate suggestions. +/// - Routes the result to the completion renderer via `CompletionSuggest`. +/// 3. An internal renderer `__render_completion` that renders the suggestions via +/// `CompletionHelper::render_suggest`. +/// +/// When the `dispatch_tree` feature is enabled, it also imports the internal dispatcher +/// from the generated module into the parent scope for trie-based dispatch. +/// +/// This macro is called automatically by `gen_program!` and should not be called +/// directly by user code. #[cfg(feature = "comp")] #[proc_macro] pub fn program_comp_gen(input: TokenStream) -> TokenStream { @@ -1601,16 +1655,47 @@ pub fn register_type(input: TokenStream) -> TokenStream { func::gen_program::register_type_impl(input) } +/// Registers a chain mapping function into the global chain registry. +/// +/// This macro is called internally by `#[chain]` and is generally not needed +/// in user code. Each call stores a string entry containing the source-to-target +/// type mapping, which is later consumed by `gen_program!` to generate the +/// `has_chain` and `do_chain` dispatch logic in `ProgramCollect`. +/// +/// The entry string format is a match arm: the source variant maps to a call +/// that converts the value into a `ChainProcess` via the destination type. +/// +/// # Panics +/// +/// Panics if the global `CHAINS` mutex is poisoned. #[proc_macro] pub fn register_chain(input: TokenStream) -> TokenStream { func::gen_program::register_chain_impl(input) } +/// Registers a renderer mapping function into the global renderer registry. +/// +/// This macro is called internally by `#[renderer]` and is generally not +/// needed in user code. Each call stores a string entry containing the +/// type-to-render mapping, which is later consumed by `gen_program!` to +/// generate the `has_renderer` and `render` dispatch logic in `ProgramCollect`. +/// +/// The entry string format is a match arm: the type variant maps to a call +/// of the registered renderer function that produces a `RenderResult`. +/// +/// # Panics +/// +/// Panics if the global `RENDERERS` mutex is poisoned. #[proc_macro] pub fn register_renderer(input: TokenStream) -> TokenStream { func::gen_program::register_renderer_impl(input) } +/// Internal macro used by `gen_program!` to generate the fallback types for +/// error cases when no dispatcher or renderer is found. +/// +/// This macro is called automatically by `gen_program!` and should not +/// be called directly by user code. #[proc_macro] pub fn program_fallback_gen(input: TokenStream) -> TokenStream { func::gen_program::program_fallback_gen_impl(input) diff --git a/mingling_pathf/src/error.rs b/mingling_pathf/src/error.rs index 70a8f6e..d384901 100644 --- a/mingling_pathf/src/error.rs +++ b/mingling_pathf/src/error.rs @@ -22,7 +22,9 @@ pub enum MinglingPathfinderError { /// `parent` is the directory containing the file that declared the module. /// `module_name` is the name of the module that could not be found. ModuleNotFound { + /// The directory containing the file that declared the module. parent: PathBuf, + /// The name of the module that could not be found. module_name: String, }, @@ -30,7 +32,12 @@ pub enum MinglingPathfinderError { /// /// `file` is the file containing the invalid attribute. /// `path_attr` is the value of the `#[path]` attribute. - PathPointsOutside { file: PathBuf, path_attr: String }, + PathPointsOutside { + /// The file containing the invalid `#[path]` attribute. + file: PathBuf, + /// The value of the `#[path]` attribute that points outside the project. + path_attr: String, + }, /// No entry point file (`main.rs`, `lib.rs`, or any file under `bin/`) was found. NoEntryPointFound, @@ -39,7 +46,12 @@ pub enum MinglingPathfinderError { /// /// `path` is the file that failed to parse. /// `message` contains details from the parser. - SynError { path: PathBuf, message: String }, + SynError { + /// The file that failed to parse. + path: PathBuf, + /// Details from the parser about the parse failure. + message: String, + }, } impl fmt::Display for MinglingPathfinderError { diff --git a/mingling_pathf/src/lib.rs b/mingling_pathf/src/lib.rs index 557ae45..69ff3ac 100644 --- a/mingling_pathf/src/lib.rs +++ b/mingling_pathf/src/lib.rs @@ -1,5 +1,6 @@ #![allow(clippy::needless_doctest_main)] #![doc = include_str!("../README.md")] +#![deny(missing_docs)] pub mod config; pub mod error; diff --git a/mingling_pathf/src/pattern_analyzer.rs b/mingling_pathf/src/pattern_analyzer.rs index 5bbc3b4..31d6918 100644 --- a/mingling_pathf/src/pattern_analyzer.rs +++ b/mingling_pathf/src/pattern_analyzer.rs @@ -100,10 +100,12 @@ pub struct PatternAnalyzer { } impl PatternAnalyzer { + /// Creates a new empty `PatternAnalyzer`. pub fn new() -> Self { Self::default() } + /// Registers a new pattern for analysis. pub fn add_pattern(&mut self, pattern: impl AnalyzePattern + 'static) { self.patterns.push(Box::new(pattern)); } diff --git a/mingling_pathf/src/patterns/dispatcher.rs b/mingling_pathf/src/patterns/dispatcher.rs index 6796a2c..eaa53f0 100644 --- a/mingling_pathf/src/patterns/dispatcher.rs +++ b/mingling_pathf/src/patterns/dispatcher.rs @@ -20,10 +20,18 @@ use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern}; /// - `CMD*` — the dispatcher struct (always) /// - `__internal_dispatcher_*` — dispatch tree static (when `use_dispatch_tree` is true) pub struct DispatcherPattern { + /// Whether the dispatcher generates a dispatch tree static (`__internal_dispatcher_*`). pub use_dispatch_tree: bool, } impl DispatcherPattern { + /// Creates a new `DispatcherPattern`. + /// + /// # Arguments + /// + /// * `use_dispatch_tree` — when `true`, the generated dispatcher also produces a + /// `__internal_dispatcher_*` static dispatch tree item. Set this based on whether + /// your macro invocation includes the `use_dispatch_tree` configuration. pub fn new(use_dispatch_tree: bool) -> Self { Self { use_dispatch_tree } } diff --git a/mingling_pathf/src/patterns/dispatcher_clap.rs b/mingling_pathf/src/patterns/dispatcher_clap.rs index 1a86ad5..0a249b4 100644 --- a/mingling_pathf/src/patterns/dispatcher_clap.rs +++ b/mingling_pathf/src/patterns/dispatcher_clap.rs @@ -29,10 +29,16 @@ use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern}; /// - `#[dispatcher_clap("greet", CMDGreet, help = true)] struct EntryGreet { ... }` /// - `#[dispatcher_clap("greet", CMDGreet, error = ErrorGreet, help = true)] struct EntryGreet { ... }` pub struct DispatcherClapPattern { + /// Whether to include the `__internal_dispatcher_*` dispatch tree static in the analysis. pub use_dispatch_tree: bool, } impl DispatcherClapPattern { + /// Creates a new `DispatcherClapPattern` with the given configuration. + /// + /// # Parameters + /// - `use_dispatch_tree`: When `true`, enables analysis of the `__internal_dispatcher_*` + /// static dispatch tree for each matched command. pub fn new(use_dispatch_tree: bool) -> Self { Self { use_dispatch_tree } } -- cgit