mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #108588 - ehuss:lint-docs-produces, r=eholk
Fix the ffi_unwind_calls lint documentation This fixes the [`ffi_unwind_calls`](https://doc.rust-lang.org/nightly/rustc/lints/listing/allowed-by-default.html#ffi-unwind-calls) documentation to show its output correctly. Currently it is showing the text `{{produces}}` which is not how it should look. This fixes it by not ignoring the example. I'm not sure why it was ignored, as the way the lint currently works it doesn't seem to require external linkage. This also fixes several mistakes in the example: * There is no `ffi_unwind_calls` feature. * Denies the lint (which is otherwise allow be default). * Removes the `mod impl` which is not valid Rust syntax, and doesn't appear to be needed anyways. The output now looks like: ``` warning: call to foreign function with FFI-unwind ABI --> lint_example.rs:10:14 | 10 | unsafe { foo(); } | ^^^^^ call to foreign function with FFI-unwind ABI | note: the lint level is defined here --> lint_example.rs:2:9 | 2 | #![warn(ffi_unwind_calls)] | ^^^^^^^^^^^^^^^^ warning: call to function pointer with FFI-unwind ABI --> lint_example.rs:12:14 | 12 | unsafe { ptr(); } | ^^^^^ call to function pointer with FFI-unwind ABI ``` This also includes some updates to the lint-docs tool to help with this issue: * Adds a check if a lint documentation has `{{produces}}` with an ignored example, and generates an error. * All instances of a lint are now displayed. Previously it only showed the first time the lint fires. Some examples may trigger a lint multiple times, and they are all now displayed.
This commit is contained in:
commit
fc5516b782
@ -4008,14 +4008,9 @@ declare_lint! {
|
|||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
///
|
///
|
||||||
/// ```rust,ignore (need FFI)
|
/// ```rust
|
||||||
/// #![feature(ffi_unwind_calls)]
|
|
||||||
/// #![feature(c_unwind)]
|
/// #![feature(c_unwind)]
|
||||||
///
|
/// #![warn(ffi_unwind_calls)]
|
||||||
/// # mod impl {
|
|
||||||
/// # #[no_mangle]
|
|
||||||
/// # pub fn "C-unwind" fn foo() {}
|
|
||||||
/// # }
|
|
||||||
///
|
///
|
||||||
/// extern "C-unwind" {
|
/// extern "C-unwind" {
|
||||||
/// fn foo();
|
/// fn foo();
|
||||||
|
@ -45,6 +45,36 @@ impl Lint {
|
|||||||
fn check_style(&self) -> Result<(), Box<dyn Error>> {
|
fn check_style(&self) -> Result<(), Box<dyn Error>> {
|
||||||
for &expected in &["### Example", "### Explanation", "{{produces}}"] {
|
for &expected in &["### Example", "### Explanation", "{{produces}}"] {
|
||||||
if expected == "{{produces}}" && self.is_ignored() {
|
if expected == "{{produces}}" && self.is_ignored() {
|
||||||
|
if self.doc_contains("{{produces}}") {
|
||||||
|
return Err(format!(
|
||||||
|
"the lint example has `ignore`, but also contains the {{{{produces}}}} marker\n\
|
||||||
|
\n\
|
||||||
|
The documentation generator cannot generate the example output when the \
|
||||||
|
example is ignored.\n\
|
||||||
|
Manually include the sample output below the example. For example:\n\
|
||||||
|
\n\
|
||||||
|
/// ```rust,ignore (needs command line option)\n\
|
||||||
|
/// #[cfg(widnows)]\n\
|
||||||
|
/// fn foo() {{}}\n\
|
||||||
|
/// ```\n\
|
||||||
|
///\n\
|
||||||
|
/// This will produce:\n\
|
||||||
|
/// \n\
|
||||||
|
/// ```text\n\
|
||||||
|
/// warning: unknown condition name used\n\
|
||||||
|
/// --> lint_example.rs:1:7\n\
|
||||||
|
/// |\n\
|
||||||
|
/// 1 | #[cfg(widnows)]\n\
|
||||||
|
/// | ^^^^^^^\n\
|
||||||
|
/// |\n\
|
||||||
|
/// = note: `#[warn(unexpected_cfgs)]` on by default\n\
|
||||||
|
/// ```\n\
|
||||||
|
\n\
|
||||||
|
Replacing the output with the text of the example you \
|
||||||
|
compiled manually yourself.\n\
|
||||||
|
"
|
||||||
|
).into());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !self.doc_contains(expected) {
|
if !self.doc_contains(expected) {
|
||||||
@ -317,10 +347,10 @@ impl<'a> LintExtractor<'a> {
|
|||||||
..,
|
..,
|
||||||
&format!(
|
&format!(
|
||||||
"This will produce:\n\
|
"This will produce:\n\
|
||||||
\n\
|
\n\
|
||||||
```text\n\
|
```text\n\
|
||||||
{}\
|
{}\
|
||||||
```",
|
```",
|
||||||
output
|
output
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -392,37 +422,36 @@ impl<'a> LintExtractor<'a> {
|
|||||||
.filter(|line| line.starts_with('{'))
|
.filter(|line| line.starts_with('{'))
|
||||||
.map(serde_json::from_str)
|
.map(serde_json::from_str)
|
||||||
.collect::<Result<Vec<serde_json::Value>, _>>()?;
|
.collect::<Result<Vec<serde_json::Value>, _>>()?;
|
||||||
match msgs
|
// First try to find the messages with the `code` field set to our lint.
|
||||||
|
let matches: Vec<_> = msgs
|
||||||
.iter()
|
.iter()
|
||||||
.find(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
|
.filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
|
||||||
{
|
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
|
||||||
Some(msg) => {
|
.collect();
|
||||||
let rendered = msg["rendered"].as_str().expect("rendered field should exist");
|
if matches.is_empty() {
|
||||||
Ok(rendered.to_string())
|
// Some lints override their code to something else (E0566).
|
||||||
}
|
// Try to find something that looks like it could be our lint.
|
||||||
None => {
|
let matches: Vec<_> = msgs.iter().filter(|msg|
|
||||||
match msgs.iter().find(
|
matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)))
|
||||||
|msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)),
|
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
|
||||||
) {
|
.collect();
|
||||||
Some(msg) => {
|
if matches.is_empty() {
|
||||||
let rendered = msg["rendered"].as_str().expect("rendered field should exist");
|
let rendered: Vec<&str> =
|
||||||
Ok(rendered.to_string())
|
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
|
||||||
}
|
let non_json: Vec<&str> =
|
||||||
None => {
|
stderr.lines().filter(|line| !line.starts_with('{')).collect();
|
||||||
let rendered: Vec<&str> =
|
Err(format!(
|
||||||
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
|
"did not find lint `{}` in output of example, got:\n{}\n{}",
|
||||||
let non_json: Vec<&str> =
|
name,
|
||||||
stderr.lines().filter(|line| !line.starts_with('{')).collect();
|
non_json.join("\n"),
|
||||||
Err(format!(
|
rendered.join("\n")
|
||||||
"did not find lint `{}` in output of example, got:\n{}\n{}",
|
)
|
||||||
name,
|
.into())
|
||||||
non_json.join("\n"),
|
} else {
|
||||||
rendered.join("\n")
|
Ok(matches.join("\n"))
|
||||||
)
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(matches.join("\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user