{"record":{"id":"5d9f1623941b89b7","repo":"astral-sh/ruff","slug":"expected-a-doc-comment","errorCode":null,"errorMessage":"expected a doc comment","messagePattern":"expected a doc comment","errorType":"exception","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/ruff_macros/src/rule_namespace.rs","lineNumber":93,"sourceCode":"                }\n                Ok(str)\n            })\n            .collect();\n        let prefixes = prefixes?;\n\n        if prefixes.is_empty() {\n            return Err(Error::new(\n                variant.span(),\n                r#\"Missing #[prefix = \"...\"] attribute\"#,\n            ));\n        }\n\n        let Some(doc_attr) = variant\n            .attrs\n            .iter()\n            .find(|attr| attr.path().is_ident(\"doc\"))\n        else {\n            return Err(Error::new(variant.span(), \"expected a doc comment\"));\n        };\n\n        let variant_ident = variant.ident;\n\n        if variant_ident != \"Ruff\" && variant_ident != \"Numpy\" {\n            let (name, url) = parse_doc_attr(doc_attr)?;\n            name_match_arms.extend(quote! {Self::#variant_ident => #name,});\n            url_match_arms.extend(quote! {Self::#variant_ident => Some(#url),});\n        }\n\n        for lit in &prefixes {\n            parsed.push((\n                lit.clone(),\n                variant_ident.clone(),\n                match prefixes.len() {\n                    1 => ParseStrategy::SinglePrefix,\n                    _ => ParseStrategy::MultiplePrefixes,\n                },","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_macros/src/rule_namespace.rs#L75-L111","documentation":"The rule-namespace derive macro requires every non-special enum variant to have a doc comment (`/// ...`) whose content is a markdown link naming the linter and linking to its documentation. This error is emitted when a variant has a prefix but no `#[doc]` attribute at all; the doc comment is parsed later into the linter's display name and URL.","triggerScenarios":"Declaring a variant on the linter namespace enum with `#[prefix = \"...\"]` set but no preceding `/// [name](url)` doc comment. Raised at rule_namespace.rs:93 when `attrs.iter().find(|attr| attr.path().is_ident(\"doc\"))` returns None.","commonSituations":"Adding a new linter variant and writing only the prefix attribute; stripping doc comments via a linter/codemod; suppressing a missing-docs lint that also removed the comment.","solutions":["Add a doc comment of the form `/// [Linter Name](https://example.com/docs)` directly above the variant.","Keep the comment attached to the variant (no blank line between the doc comment and the variant).","Rebuild so the macro can parse the doc attribute into the name/URL pair."],"exampleFix":"// before\n#[prefix = \"MYL\"]\nMyLinter,\n// after\n/// [MyLinter](https://docs.example.com/mylinter)\n#[prefix = \"MYL\"]\nMyLinter,","handlingStrategy":"validation","validationCode":"// Pre-commit check that each linter variant is preceded by a /// line:\n// if rust code variant has no preceding '///' line -> fail the script.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write the doc link before the #[prefix] attribute.","Never disable the missing-docs lint for this enum.","Run the build immediately after adding a variant; the macro reports the offending span."],"tags":["proc-macro","compile-time","rust","doc-comment"],"backgroundTag":"missing-macro-attribute","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}