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!");
}
- Create a
main.rs
containing this minimual reproducer - 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.