Skip to content

Commit ce014be

Browse files
committed
Link rustdoc lint docs to the rustdoc book.
1 parent 45c1e0a commit ce014be

File tree

5 files changed

+88
-158
lines changed

5 files changed

+88
-158
lines changed

compiler/rustc_session/src/lint/builtin.rs

+13-125
Original file line numberDiff line numberDiff line change
@@ -1817,35 +1817,10 @@ declare_lint! {
18171817

18181818
declare_lint! {
18191819
/// The `broken_intra_doc_links` lint detects failures in resolving
1820-
/// intra-doc link targets. This is a `rustdoc` only lint, and only works
1821-
/// on the [**nightly channel**].
1820+
/// intra-doc link targets. This is a `rustdoc` only lint, see the
1821+
/// documentation in the [rustdoc book].
18221822
///
1823-
/// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
1824-
///
1825-
/// ### Example
1826-
///
1827-
/// ```rust,rustdoc
1828-
/// /// This is a doc comment.
1829-
/// ///
1830-
/// /// See also [`bar`].
1831-
/// pub fn foo() {
1832-
/// }
1833-
/// ```
1834-
///
1835-
/// {{produces}}
1836-
///
1837-
/// ### Explanation
1838-
///
1839-
/// `rustdoc` allows [linking to items by name][intra] which will
1840-
/// automatically generate links in the documentation to the item. This
1841-
/// lint is issued when `rustdoc` is unable to find the named item. Check
1842-
/// that the name is correct, that it is in scope, or if you need to
1843-
/// qualify it with a path. If you intended to have square brackets appear
1844-
/// literally in the text, surround the brackets with backticks such as ``
1845-
/// `[example]` `` to indicate a code span, or prefix it with a backslash
1846-
/// such as `\[example]`.
1847-
///
1848-
/// [intra]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#linking-to-items-by-name
1823+
/// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links
18491824
pub BROKEN_INTRA_DOC_LINKS,
18501825
Warn,
18511826
"failures in resolving intra-doc link targets"
@@ -1854,52 +1829,20 @@ declare_lint! {
18541829
declare_lint! {
18551830
/// The `invalid_codeblock_attributes` lint detects code block attributes
18561831
/// in documentation examples that have potentially mis-typed values. This
1857-
/// is a `rustdoc` only lint.
1858-
///
1859-
/// ### Example
1832+
/// is a `rustdoc` only lint, see the documentation in the [rustdoc book].
18601833
///
1861-
/// ```rust,rustdoc
1862-
/// /// Example.
1863-
/// ///
1864-
/// /// ```should-panic
1865-
/// /// assert_eq!(1, 2);
1866-
/// /// ```
1867-
/// pub fn foo() {}
1868-
/// ```
1869-
///
1870-
/// {{produces}}
1871-
///
1872-
/// ### Explanation
1873-
///
1874-
/// This lint is issued when `rustdoc` detects an example code block
1875-
/// attribute that appears similar to a valid one. In the example above,
1876-
/// the correct form is `should_panic`. This helps detect typo mistakes
1877-
/// for some common attributes.
1834+
/// [rustdoc book]: ../../../rustdoc/lints.html#invalid_codeblock_attributes
18781835
pub INVALID_CODEBLOCK_ATTRIBUTES,
18791836
Warn,
18801837
"codeblock attribute looks a lot like a known one"
18811838
}
18821839

18831840
declare_lint! {
18841841
/// The `missing_crate_level_docs` lint detects if documentation is
1885-
/// missing at the crate root. This is a `rustdoc` only lint. This is a
1886-
/// `rustdoc` only lint.
1887-
///
1888-
/// ### Example
1889-
///
1890-
/// ```rust,rustdoc
1891-
/// #![deny(missing_crate_level_docs)]
1892-
/// ```
1893-
///
1894-
/// {{produces}}
1895-
///
1896-
/// ### Explanation
1842+
/// missing at the crate root. This is a `rustdoc` only lint, see the
1843+
/// documentation in the [rustdoc book].
18971844
///
1898-
/// This lint causes `rustdoc` to check if the crate root is missing
1899-
/// documentation. This is currently "allow" by default, but it is
1900-
/// intended to make this a warning in the future. This is intended as a
1901-
/// means to introduce new users on *how* to document their crate by
1902-
/// pointing them to some instructions on how to get started.
1845+
/// [rustdoc book]: ../../../rustdoc/lints.html#missing_crate_level_docs
19031846
pub MISSING_CRATE_LEVEL_DOCS,
19041847
Allow,
19051848
"detects crates with no crate-level documentation"
@@ -1908,75 +1851,20 @@ declare_lint! {
19081851
declare_lint! {
19091852
/// The `missing_doc_code_examples` lint detects publicly-exported items
19101853
/// without code samples in their documentation. This is a `rustdoc` only
1911-
/// lint, and only works on the [**nightly channel**].
1854+
/// lint, see the documentation in the [rustdoc book].
19121855
///
1913-
/// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
1914-
///
1915-
/// ### Example
1916-
///
1917-
/// ```rust,rustdoc
1918-
/// #![warn(missing_doc_code_examples)]
1919-
///
1920-
/// /// There is no code example!
1921-
/// pub fn no_code_example() {}
1922-
/// ```
1923-
///
1924-
/// {{produces}}
1925-
///
1926-
/// ### Explanation
1927-
///
1928-
/// This lint is to ensure a high level of quality for documentation. Code
1929-
/// examples can be very useful to see how to use an API. To add an
1930-
/// example, include a markdown code block with an example of how to use
1931-
/// the item, such as:
1932-
///
1933-
/// ```rust
1934-
/// /// Adds one to the number given.
1935-
/// ///
1936-
/// /// # Examples
1937-
/// ///
1938-
/// /// ```
1939-
/// /// let arg = 5;
1940-
/// /// let answer = my_crate::add_one(arg);
1941-
/// ///
1942-
/// /// assert_eq!(6, answer);
1943-
/// /// ```
1944-
/// pub fn add_one(x: i32) -> i32 {
1945-
/// x + 1
1946-
/// }
1947-
/// ```
1856+
/// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
19481857
pub MISSING_DOC_CODE_EXAMPLES,
19491858
Allow,
19501859
"detects publicly-exported items without code samples in their documentation"
19511860
}
19521861

19531862
declare_lint! {
19541863
/// The `private_doc_tests` lint detects code samples in docs of private
1955-
/// items not documented by `rustdoc`. This is a `rustdoc` only lint.
1956-
///
1957-
/// ### Example
1958-
///
1959-
/// ```rust,rustdoc
1960-
/// #![deny(private_doc_tests)]
1864+
/// items not documented by `rustdoc`. This is a `rustdoc` only lint, see
1865+
/// the documentation in the [rustdoc book].
19611866
///
1962-
/// mod foo {
1963-
/// /// private doc test
1964-
/// ///
1965-
/// /// ```
1966-
/// /// assert!(false);
1967-
/// /// ```
1968-
/// fn bar() {}
1969-
/// }
1970-
/// ```
1971-
///
1972-
/// {{produces}}
1973-
///
1974-
/// ### Explanation
1975-
///
1976-
/// Because documentation examples link against the public API of the
1977-
/// crate, it is not possible for an example to access a private item.
1978-
/// This means it was likely a mistake to add a code example to a private
1979-
/// item.
1867+
/// [rustdoc book]: ../../../rustdoc/lints.html#private_doc_tests
19801868
pub PRIVATE_DOC_TESTS,
19811869
Allow,
19821870
"detects code samples in docs of private items not documented by rustdoc"

src/bootstrap/doc.rs

-3
Original file line numberDiff line numberDiff line change
@@ -756,16 +756,13 @@ impl Step for RustcBook {
756756
// The tool runs `rustc` for extracting output examples, so it needs a
757757
// functional sysroot.
758758
builder.ensure(compile::Std { compiler: self.compiler, target: self.target });
759-
let rustdoc = builder.rustdoc(self.compiler);
760759
let mut cmd = builder.tool_cmd(Tool::LintDocs);
761760
cmd.arg("--src");
762761
cmd.arg(builder.src.join("compiler"));
763762
cmd.arg("--out");
764763
cmd.arg(&out_listing);
765764
cmd.arg("--rustc");
766765
cmd.arg(rustc);
767-
cmd.arg("--rustdoc");
768-
cmd.arg(rustdoc);
769766
if builder.config.verbose() {
770767
cmd.arg("--verbose");
771768
}

src/doc/rustdoc/src/lints.md

+58
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,30 @@ warning: missing documentation for a function
4949
| ^^^^^^^^^^^^^^^^^^^^^
5050
```
5151

52+
## missing_crate_level_docs
53+
54+
This lint is **allowed by default**. It detects if there is no documentation
55+
at the crate root. For example:
56+
57+
```rust
58+
#![warn(missing_crate_level_docs)]
59+
```
60+
61+
This will generate the following warning:
62+
63+
```text
64+
warning: no documentation found for this crate's top-level module
65+
|
66+
= help: The following guide may be of use:
67+
https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
68+
```
69+
70+
This is currently "allow" by default, but it is intended to make this a
71+
warning in the future. This is intended as a means to introduce new users on
72+
*how* to document their crate by pointing them to some instructions on how to
73+
get started, without providing overwhelming warnings like `missing_docs`
74+
might.
75+
5276
## missing_doc_code_examples
5377

5478
This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block
@@ -117,3 +141,37 @@ warning: Documentation test in private item
117141
8 | | /// ```
118142
| |___________^
119143
```
144+
145+
## invalid_codeblock_attributes
146+
147+
This lint **warns by default**. It detects code block attributes in
148+
documentation examples that have potentially mis-typed values. For example:
149+
150+
```rust
151+
/// Example.
152+
///
153+
/// ```should-panic
154+
/// assert_eq!(1, 2);
155+
/// ```
156+
pub fn foo() {}
157+
```
158+
159+
Which will give:
160+
161+
```text
162+
warning: unknown attribute `should-panic`. Did you mean `should_panic`?
163+
--> src/lib.rs:1:1
164+
|
165+
1 | / /// Example.
166+
2 | | ///
167+
3 | | /// ```should-panic
168+
4 | | /// assert_eq!(1, 2);
169+
5 | | /// ```
170+
| |_______^
171+
|
172+
= note: `#[warn(invalid_codeblock_attributes)]` on by default
173+
= help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
174+
```
175+
176+
In the example above, the correct form is `should_panic`. This helps detect
177+
typo mistakes for some common attributes.

src/tools/lint-docs/src/lib.rs

+17-19
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ struct Lint {
1515
lineno: usize,
1616
}
1717

18+
impl Lint {
19+
fn doc_contains(&self, text: &str) -> bool {
20+
self.doc.iter().any(|line| line.contains(text))
21+
}
22+
}
23+
1824
#[derive(Clone, Copy, PartialEq)]
1925
enum Level {
2026
Allow,
@@ -37,12 +43,11 @@ pub fn extract_lint_docs(
3743
src_path: &Path,
3844
out_path: &Path,
3945
rustc_path: &Path,
40-
rustdoc_path: &Path,
4146
verbose: bool,
4247
) -> Result<(), Box<dyn Error>> {
4348
let mut lints = gather_lints(src_path)?;
4449
for lint in &mut lints {
45-
generate_output_example(lint, rustc_path, rustdoc_path, verbose).map_err(|e| {
50+
generate_output_example(lint, rustc_path, verbose).map_err(|e| {
4651
format!(
4752
"failed to test example in lint docs for `{}` in {}:{}: {}",
4853
lint.name,
@@ -197,7 +202,6 @@ fn lint_name(line: &str) -> Result<String, &'static str> {
197202
fn generate_output_example(
198203
lint: &mut Lint,
199204
rustc_path: &Path,
200-
rustdoc_path: &Path,
201205
verbose: bool,
202206
) -> Result<(), Box<dyn Error>> {
203207
// Explicit list of lints that are allowed to not have an example. Please
@@ -214,15 +218,19 @@ fn generate_output_example(
214218
) {
215219
return Ok(());
216220
}
221+
if lint.doc_contains("[rustdoc book]") && !lint.doc_contains("{{produces}}") {
222+
// Rustdoc lints are documented in the rustdoc book, don't check these.
223+
return Ok(());
224+
}
217225
check_style(lint)?;
218-
replace_produces(lint, rustc_path, rustdoc_path, verbose)?;
226+
replace_produces(lint, rustc_path, verbose)?;
219227
Ok(())
220228
}
221229

222230
/// Checks the doc style of the lint.
223231
fn check_style(lint: &Lint) -> Result<(), Box<dyn Error>> {
224232
for expected in &["### Example", "### Explanation", "{{produces}}"] {
225-
if !lint.doc.iter().any(|line| line.contains(expected)) {
233+
if !lint.doc_contains(expected) {
226234
return Err(format!("lint docs should contain the line `{}`", expected).into());
227235
}
228236
}
@@ -243,7 +251,6 @@ fn check_style(lint: &Lint) -> Result<(), Box<dyn Error>> {
243251
fn replace_produces(
244252
lint: &mut Lint,
245253
rustc_path: &Path,
246-
rustdoc_path: &Path,
247254
verbose: bool,
248255
) -> Result<(), Box<dyn Error>> {
249256
let mut lines = lint.doc.iter_mut();
@@ -283,14 +290,8 @@ fn replace_produces(
283290
match lines.next() {
284291
Some(line) if line.is_empty() => {}
285292
Some(line) if line == "{{produces}}" => {
286-
let output = generate_lint_output(
287-
&lint.name,
288-
&example,
289-
&options,
290-
rustc_path,
291-
rustdoc_path,
292-
verbose,
293-
)?;
293+
let output =
294+
generate_lint_output(&lint.name, &example, &options, rustc_path, verbose)?;
294295
line.replace_range(
295296
..,
296297
&format!(
@@ -318,7 +319,6 @@ fn generate_lint_output(
318319
example: &[&mut String],
319320
options: &[&str],
320321
rustc_path: &Path,
321-
rustdoc_path: &Path,
322322
verbose: bool,
323323
) -> Result<String, Box<dyn Error>> {
324324
if verbose {
@@ -327,8 +327,7 @@ fn generate_lint_output(
327327
let tempdir = tempfile::TempDir::new()?;
328328
let tempfile = tempdir.path().join("lint_example.rs");
329329
let mut source = String::new();
330-
let is_rustdoc = options.contains(&"rustdoc");
331-
let needs_main = !example.iter().any(|line| line.contains("fn main")) && !is_rustdoc;
330+
let needs_main = !example.iter().any(|line| line.contains("fn main"));
332331
// Remove `# ` prefix for hidden lines.
333332
let unhidden =
334333
example.iter().map(|line| if line.starts_with("# ") { &line[2..] } else { line });
@@ -354,8 +353,7 @@ fn generate_lint_output(
354353
}
355354
fs::write(&tempfile, source)
356355
.map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?;
357-
let program = if is_rustdoc { rustdoc_path } else { rustc_path };
358-
let mut cmd = Command::new(program);
356+
let mut cmd = Command::new(rustc_path);
359357
if options.contains(&"edition2015") {
360358
cmd.arg("--edition=2015");
361359
} else {

0 commit comments

Comments
 (0)