marker_api 0.5.0

Marker's API, designed for stability and usability
Documentation
use crate::common::{Level, MacroReport};

/// This struct defines a lint.
///
/// It should never be constructed directly, the [`declare_lint`](crate::declare_lint)
/// macro should be used instead, like this:
///
/// ```
/// marker_api::declare_lint!{
///     /// # What it does
///     /// Here you can describe what your lint does.
///     ///
///     /// # Example
///     /// ```
///     /// <bad example>
///     /// ```
///     ///
///     /// Use instead
///     /// ```
///     /// <bad example>
///     /// ```
///     ITEM_WITH_TEST_NAME,
///     Warn,
/// }
/// ```
///
/// The fields of this struct are public, to allow the instantiation in constant
/// context. Marker reserves the right to add new fields, as long the lint can still
/// be constructed using the [`declare_lint`](crate::declare_lint) macro.
#[repr(C)]
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Lint {
    /// The string identifier of this lint.
    ///
    /// Identifiers use underscores, to connect multiple words, e.g., "unused_imports".
    /// Lint names in console arguments use dashes instead of underscores. These are
    /// automatically converted to underscores internally.
    ///
    /// Identifiers in Marker are split into three parts:
    /// 1. The `marker` prefix, specifying that the lint comes from Marker
    /// 2. The lint crate name, as an infix
    /// 3. The name of the lint, as the postfix
    ///
    /// See <https://rustc-dev-guide.rust-lang.org/diagnostics.html#lint-naming>
    /// for naming guidelines.
    pub name: &'static str,

    /// Default level for the lint.
    ///
    /// See <https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-levels>
    /// for guidelines on choosing a default level.
    pub default_level: Level,

    /// Description of the lint or the issue it detects.
    ///
    /// e.g., "imports that are never used"
    pub explanation: &'static str,

    /// The level of macro reporting.
    ///
    /// See [`MacroReport`] for the possible levels.
    pub report_in_macro: MacroReport,

    /// Fully qualiefied name of the static variable that defines the lint.
    /// It includes the module and the name of the variable.
    pub fqn: &'static str,

    /// This struct should always be instantiated using the [`declare_lint`](crate::declare_lint)
    /// macro. This value is simply here, to force any construction to acknowledge the
    /// instability of manual construction.
    pub _unstable_i_accept_the_risk_of_instability: (),
}

/// This macro creates a new lint instance. The doc comment of the lint will be
/// available in the crate documentation and any documentation generated by Marker.
/// The content will be rendered with Markdown.
///
/// It's recommended to include a section explaining what the lint does, and an
/// example. You can also provide additional information, like "limitations" or
/// "known problems". Here is a recommended template:
///
/// ```
/// marker_api::declare_lint!{
///     /// # What it does
///     /// Here you can describe what your lint does.
///     ///
///     /// # Example
///     /// ```
///     /// <bad example>
///     /// ```
///     ///
///     /// Use instead
///     /// ```
///     /// <bad example>
///     /// ```
///     ITEM_WITH_TEST_NAME,
///     Warn,
/// }
/// ```
#[macro_export]
macro_rules! declare_lint {
    (
        $(#[doc = $doc:literal])+
        $NAME: ident,
        $LEVEL: ident $(,)?
    ) => {
        $crate::declare_lint!{
            $(#[doc = $doc])+
            $NAME,
            $LEVEL,
            $crate::common::MacroReport::No,
        }
    };
    (
        $(#[doc = $doc:literal])+
        $NAME: ident,
        $LEVEL: ident,
        $REPORT_IN_MACRO: expr $(,)?
    ) => {
        $(#[doc = $doc])+
        pub static $NAME: &$crate::Lint = &$crate::Lint {
            // The `CARGO_CRATE_NAME` environment value is set by Cargo during compilation.
            // The name has already been normalized to use underscores, instead of dashes,
            // which is ideal for Marker.
            //
            // The name is taken from the `Cargo.toml` file of the lint crate, even if the
            // dependency has been renamed. This is fine for now, since Marker doesn't expose
            // any interface for the users to rename the lint crates. We might need to add our
            // own environment value later, if we want to support lint crate renaming.
            //
            // Example, how the package could be renamed in the `Cargo.toml` of Marker's dummy
            // crate for lint crate fetching:
            // ```toml
            // [dependencies]
            // ducks = { version = "0.3", package = "marker_lints" }
            // ```
            // The environment value would still have the value `marker_lints`
            name: concat!("marker::", std::env!("CARGO_CRATE_NAME"), "::", stringify!($NAME)),
            default_level: $crate::common::Level::$LEVEL,
            explanation: concat!($($doc, '\n',)*),
            report_in_macro: $REPORT_IN_MACRO,
            fqn: concat!(module_path!(), "::", stringify!($NAME)),
            _unstable_i_accept_the_risk_of_instability: (),
        };
    };
}