drahnr / cargo-spellcheck

Checks all your documentation for spelling and grammar mistakes with hunspell and a nlprule based checker for grammar

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Contents of doctests are not seen as code after a "#[doc = ...]" line

ssokolow opened this issue · comments

Describe the bug

In docstrings, a line using #[doc = concat!(...)] for substitution inside a doctest causes the following lines to be spell-checked as ordinary text.

This is a particularly big problem for functions generated using macros which use templated docstrings.

To Reproduce

Steps to reproduce the behaviour:

/// ```
/// use std::path::PathBuf as A;
#[doc = "// Hello"]
/// use std::path::PathBuf as B;
/// ```
fn main() {
    println!("Hello, world!");
}
  1. Create a main.rs containing this minimual reproducer
  2. Run cargo spellcheck check

Expected behavior

Neither PathBuf should be checked as an English word.

Screenshots

error: spellcheck(Hunspell)
  --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/temp/src/main.rs:4
   |
 4 |  use std::path::PathBuf as B;
   |                 ^^^^^^^
   | - Paths
   |
   |   Possible spelling mistake found.

Please complete the following information:

  • System: Kubuntu Linux 20.04.3 LTS
  • Obtained: cargo
  • Version: cargo-spellcheck 0.9.0

Commonly the generated code is produced on demand from within the build.rs or as a proc macro. This is the first time I've seen generated code to be spellchecked for sure, could you give me a few pointer what your rationale is around that? Thanks! (The issue will be fixed regardless)

The macro is used for generating API adapters so command-line argument validators written for clap and StructOpt also have versions for Gumdrop and Argh.

Here's the actual macro in its current form since I think just seeing it will make things clear. (TL;DR: build.rs would be the wrong tool and a whole separate proc macro crate would be inefficient and overkill.)

/// Helper for generating the gumdrop/argh-compatible `*_from_str` variants of validators
///
/// **NOTE:** This macro hard-codes [`PathBuf`](std::path::PathBuf) for its output type so that it
/// is only necessary to test the correctness of the functions being wrapped and one of the
/// wrappers to have confidence in the correctness of the wrappers.
#[rustfmt::skip]  // TODO: Report that rustfmt breaks the #[doc] hack I'm using here
macro_rules! from_str_variant {
    ($base_name:ident) => {
        paste! {
        from_str_variant!([<$base_name _from_str>], $base_name, stringify!($base_name));
        }
    };
    ($from_str_name:ident, $base_name:ident, $base_name_string:expr) => {
        #[cfg(feature = "allow-unavoidable-panics")]
        #[doc = "Compatibility wrapper for [`"]
        #[doc = $base_name_string]
        #[doc = "`]."]
        ///
        /// ## Cautions:
        #[doc = "* **Also read the documentation for [`"]
        #[doc = $base_name_string]
        #[doc = "`]**."]
        /// * This function is only available when the `allow-unavoidable-panics` feature
        ///   is enabled.
        #[doc = "* `&str` cannot represent some valid paths. Prefer [`"]
        #[doc = $base_name_string]
        #[doc = "`] where possible."]
        ///
        /// ## Panics:
        ///
        /// * Argument parsers which mandate the use of this function rely on [`std::env::args`] or
        ///   otherwise use [`String`] internally, which will `panic!` upon encountering valid
        ///   filesystem paths which contain bytes or codepoints which cannot be converted to
        ///   UTF-8. Use it only as a last resort.
        ///
        /// ## Usage (argh):
        ///
        /// ```no_run
        /// use std::path::PathBuf;
        /// use argh::FromArgs;
        #[doc = concat!("use cli_validators::path::", stringify!($from_str_name), ";")]
        ///
        /// #[derive(FromArgs)]
        /// #[argh(description = "Example program")]
        /// struct CliArgs {
        #[doc = concat!("    #[argh(positional, from_str_fn(", stringify!($from_str_name), "))]")]
        ///     path: Vec<PathBuf>,
        /// }
        ///
        /// fn main() {
        ///     let matches: CliArgs = argh::from_env();
        ///
        ///     for path in matches.path {
        ///         println!("{}", path.display());
        ///     }
        /// }
        /// ```
        /// ## Usage (Gumdrop):
        ///
        /// ```no_run
        /// use std::path::PathBuf;
        /// use gumdrop::Options;
        /// use cli_validators::path;
        ///
        /// #[derive(Options)]
        /// struct CliArgs {
        #[doc = concat!("    #[options(free, parse(try_from_str = \"path::",
            stringify!($from_str_name), "\"))]")]
        ///     path: Vec<PathBuf>,
        /// }
        ///
        /// fn main() {
        ///     let matches = CliArgs::parse_args_default_or_exit();
        ///
        ///     for path in matches.path {
        ///         println!("{}", path.display());
        ///     }
        /// }
        /// ```
        ///
        /// **NOTE:** These examples are compile-tested but not actually run. Please report any
        /// regressions.

        pub fn $from_str_name(value: &str) -> Result<PathBuf, String> {
            match $base_name(value) {
                Ok(()) => Ok(value.into()),
                Err(e) => Err(e.to_string_lossy().into_owned()),
            }
        }
    };
}

Feel free to re-open if this doesn't solve all your use-cases! I much appreciate issues like these which outline the limits of cargo-spellcheck! Thank you!

I don't have a button to reopen it, but I'm still seeing the following spurious results under cargo-spellcheck 0.9.2 from inside the from_str_variant docstring when I remove the temporary entries I've added to my custom.dic:

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:252
     |
 252 |  #[derive(FromArgs)]
     |           ^^^^^^^^
     | - Frogmarch
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:253
     |
 253 |  #[argh(description = "Example program")]
     |                     ^
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:254
     |
 254 |  struct CliArgs {
     |  ^^^^^^
     | - strict, strut, struck, structure, StructOpt, obstruct, instruct, or one of 1 others
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:254
     |
 254 |  struct CliArgs {
     |         ^^^^^^^
     | - Clings
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:259
     |
 259 |  fn main() {
     |  ^^
     | - fen, fin, fan, fun, en, in, fa, or one of 7 others
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:260
     |
 260 |      let matches: CliArgs = argh::from_env();
     |                   ^^^^^^^
     | - Clings
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:260
     |
 260 |      let matches: CliArgs = argh::from_env();
     |                           ^
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:260
     |
 260 |      let matches: CliArgs = argh::from_env();
     |                                   ^^^^^^^^
     | - frogmen
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:281
     |
 281 |  fn main() {
     |  ^^
     | - fen, fin, fan, fun, en, in, fa, or one of 7 others
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:282
     |
 282 |      let matches = CliArgs::parse_args_default_or_exit();
     |                  ^
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:282
     |
 282 |      let matches = CliArgs::parse_args_default_or_exit();
     |                    ^^^^^^^
     | - Clings
     |
     |   Possible spelling mistake found.

error: spellcheck(Hunspell)
    --> /home/ssokolow/src/rust-cli-boilerplate/cli_validators/src/path.rs:282
     |
 282 |      let matches = CliArgs::parse_args_default_or_exit();
     |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
     |   Possible spelling mistake found.

The spurious results with the [1]-style citation links are fixed though.

Could you please open a new issue, with a minimal example. The initial one must work, since it's a verbatim copy of your case as test.

It may take me a day or two to find time to minimize the reproducer, but will do.