Auto merge of #93605 - notriddle:notriddle/rustdoc-html-tags-resolve, r=GuillaumeGomez
rustdoc: resolve intra-doc links when checking HTML Similar to #86451 CC #67799 Given this test case: ```rust #![warn(rustdoc::invalid_html_tags)] #![warn(rustdoc::broken_intra_doc_links)] pub struct ExistentStruct<T>(T); /// This [test][ExistentStruct<i32>] thing! pub struct NoError; ``` This pull request silences the following, spurious warning: ```text warning: unclosed HTML tag `i32` --> test.rs:6:31 | 6 | /// This [test][ExistentStruct<i32>] thing! | ^^^^^ | note: the lint level is defined here --> test.rs:1:9 | 1 | #![warn(rustdoc::invalid_html_tags)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try marking as source code | 6 | /// This [test][`ExistentStruct<i32>`] thing! | + + warning: 1 warning emitted ```
This commit is contained in:
commit
6d7aa4763f
3 changed files with 120 additions and 2 deletions
|
@ -5,7 +5,7 @@ use crate::core::DocContext;
|
|||
use crate::html::markdown::main_body_opts;
|
||||
use crate::visit::DocVisitor;
|
||||
|
||||
use pulldown_cmark::{Event, Parser, Tag};
|
||||
use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag};
|
||||
|
||||
use std::iter::Peekable;
|
||||
use std::ops::Range;
|
||||
|
@ -249,7 +249,31 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
|
|||
let mut is_in_comment = None;
|
||||
let mut in_code_block = false;
|
||||
|
||||
let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
|
||||
let link_names = item.link_names(&self.cx.cache);
|
||||
|
||||
let mut replacer = |broken_link: BrokenLink<'_>| {
|
||||
if let Some(link) =
|
||||
link_names.iter().find(|link| *link.original_text == *broken_link.reference)
|
||||
{
|
||||
Some((link.href.as_str().into(), link.new_text.as_str().into()))
|
||||
} else if matches!(
|
||||
&broken_link.link_type,
|
||||
LinkType::Reference | LinkType::ReferenceUnknown
|
||||
) {
|
||||
// If the link is shaped [like][this], suppress any broken HTML in the [this] part.
|
||||
// The `broken_intra_doc_links` will report typos in there anyway.
|
||||
Some((
|
||||
broken_link.reference.to_string().into(),
|
||||
broken_link.reference.to_string().into(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let p =
|
||||
Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer))
|
||||
.into_offset_iter();
|
||||
|
||||
for (event, range) in p {
|
||||
match event {
|
||||
|
|
25
src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs
Normal file
25
src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
#![deny(rustdoc::invalid_html_tags)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
|
||||
pub struct ExistentStruct<T>(T);
|
||||
|
||||
/// This [test][ExistentStruct<i32>] thing!
|
||||
pub struct NoError;
|
||||
|
||||
/// This [ExistentStruct<i32>] thing!
|
||||
//~^ ERROR unclosed HTML tag `i32`
|
||||
pub struct PartialErrorOnlyHtml;
|
||||
|
||||
/// This [test][NonExistentStruct<i32>] thing!
|
||||
//~^ ERROR unresolved link
|
||||
pub struct PartialErrorOnlyResolve;
|
||||
|
||||
/// This [NonExistentStruct2<i32>] thing!
|
||||
//~^ ERROR unclosed HTML tag `i32`
|
||||
//~| ERROR unresolved link
|
||||
pub struct YesError;
|
||||
|
||||
/// This [NonExistentStruct3<i32>][] thing!
|
||||
//~^ ERROR unclosed HTML tag `i32`
|
||||
//~| ERROR unresolved link
|
||||
pub struct YesErrorCollapsed;
|
|
@ -0,0 +1,69 @@
|
|||
error: unresolved link to `NonExistentStruct`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:13:17
|
||||
|
|
||||
LL | /// This [test][NonExistentStruct<i32>] thing!
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/html-as-generics-intra-doc.rs:2:9
|
||||
|
|
||||
LL | #![deny(rustdoc::broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
|
||||
error: unresolved link to `NonExistentStruct2`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:17:11
|
||||
|
|
||||
LL | /// This [NonExistentStruct2<i32>] thing!
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct2` in scope
|
||||
|
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
|
||||
error: unresolved link to `NonExistentStruct3`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:22:11
|
||||
|
|
||||
LL | /// This [NonExistentStruct3<i32>][] thing!
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct3` in scope
|
||||
|
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
|
||||
error: unclosed HTML tag `i32`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:9:25
|
||||
|
|
||||
LL | /// This [ExistentStruct<i32>] thing!
|
||||
| ^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/html-as-generics-intra-doc.rs:1:9
|
||||
|
|
||||
LL | #![deny(rustdoc::invalid_html_tags)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: try marking as source code
|
||||
|
|
||||
LL | /// This [`ExistentStruct<i32>`] thing!
|
||||
| + +
|
||||
|
||||
error: unclosed HTML tag `i32`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:17:29
|
||||
|
|
||||
LL | /// This [NonExistentStruct2<i32>] thing!
|
||||
| ^^^^^
|
||||
|
|
||||
help: try marking as source code
|
||||
|
|
||||
LL | /// This [`NonExistentStruct2<i32>`] thing!
|
||||
| + +
|
||||
|
||||
error: unclosed HTML tag `i32`
|
||||
--> $DIR/html-as-generics-intra-doc.rs:22:29
|
||||
|
|
||||
LL | /// This [NonExistentStruct3<i32>][] thing!
|
||||
| ^^^^^
|
||||
|
|
||||
help: try marking as source code
|
||||
|
|
||||
LL | /// This [`NonExistentStruct3<i32>`][] thing!
|
||||
| + +
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue