Allow generic parameters in intra-doc links
The contents of the generics will be mostly ignored (except for warning if fully-qualified syntax is used, which is currently unsupported in intra-doc links - see issue #74563). * Allow links like `Vec<T>`, `Result<T, E>`, and `Option<Box<T>>` * Allow links like `Vec::<T>::new()` * Warn on * Unbalanced angle brackets (e.g. `Vec<T` or `Vec<T>>`) * Missing type to apply generics to (`<T>` or `<Box<T>>`) * Use of fully-qualified syntax (`<Vec as IntoIterator>::into_iter`) * Invalid path separator (`Vec:<T>:new`) * Too many angle brackets (`Vec<<T>>`) * Empty angle brackets (`Vec<>`) Note that this implementation *does* allow some constructs that aren't valid in the actual Rust syntax, for example `Box::<T>new()`. That may not be supported in rustdoc in the future; it is an implementation detail.
This commit is contained in:
parent
9ba1d21868
commit
4c765f66a4
6 changed files with 381 additions and 2 deletions
|
|
@ -2,7 +2,7 @@
|
|||
//~^ NOTE lint level is defined
|
||||
|
||||
// FIXME: this should say that it was skipped (maybe an allowed by default lint?)
|
||||
/// [<invalid syntax>]
|
||||
/// [invalid intra-doc syntax!!]
|
||||
|
||||
/// [path::to::nonexistent::module]
|
||||
//~^ ERROR unresolved link
|
||||
|
|
|
|||
19
src/test/rustdoc-ui/intra-link-malformed-generics.rs
Normal file
19
src/test/rustdoc-ui/intra-link-malformed-generics.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#![deny(broken_intra_doc_links)]
|
||||
|
||||
//! [Vec<] //~ ERROR
|
||||
//! [Vec<Box<T] //~ ERROR
|
||||
//! [Vec<Box<T>] //~ ERROR
|
||||
//! [Vec<Box<T>>>] //~ ERROR
|
||||
//! [Vec<T>>>] //~ ERROR
|
||||
//! [<Vec] //~ ERROR
|
||||
//! [Vec::<] //~ ERROR
|
||||
//! [<T>] //~ ERROR
|
||||
//! [<invalid syntax>] //~ ERROR
|
||||
//! [Vec:<T>:new()] //~ ERROR
|
||||
//! [Vec<<T>>] //~ ERROR
|
||||
//! [Vec<>] //~ ERROR
|
||||
//! [Vec<<>>] //~ ERROR
|
||||
|
||||
// FIXME(#74563) support UFCS
|
||||
//! [<Vec as IntoIterator>::into_iter] //~ ERROR
|
||||
//! [<Vec<T> as IntoIterator>::iter] //~ ERROR
|
||||
102
src/test/rustdoc-ui/intra-link-malformed-generics.stderr
Normal file
102
src/test/rustdoc-ui/intra-link-malformed-generics.stderr
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
error: unresolved link to `Vec<`
|
||||
--> $DIR/intra-link-malformed-generics.rs:3:6
|
||||
|
|
||||
LL | //! [Vec<]
|
||||
| ^^^^ unbalanced angle brackets
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/intra-link-malformed-generics.rs:1:9
|
||||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unresolved link to `Vec<Box<T`
|
||||
--> $DIR/intra-link-malformed-generics.rs:4:6
|
||||
|
|
||||
LL | //! [Vec<Box<T]
|
||||
| ^^^^^^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `Vec<Box<T>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:5:6
|
||||
|
|
||||
LL | //! [Vec<Box<T>]
|
||||
| ^^^^^^^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `Vec<Box<T>>>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:6:6
|
||||
|
|
||||
LL | //! [Vec<Box<T>>>]
|
||||
| ^^^^^^^^^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `Vec<T>>>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:7:6
|
||||
|
|
||||
LL | //! [Vec<T>>>]
|
||||
| ^^^^^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `<Vec`
|
||||
--> $DIR/intra-link-malformed-generics.rs:8:6
|
||||
|
|
||||
LL | //! [<Vec]
|
||||
| ^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `Vec::<`
|
||||
--> $DIR/intra-link-malformed-generics.rs:9:6
|
||||
|
|
||||
LL | //! [Vec::<]
|
||||
| ^^^^^^ unbalanced angle brackets
|
||||
|
||||
error: unresolved link to `<T>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:10:6
|
||||
|
|
||||
LL | //! [<T>]
|
||||
| ^^^ missing type for generic parameters
|
||||
|
||||
error: unresolved link to `<invalid syntax>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:11:6
|
||||
|
|
||||
LL | //! [<invalid syntax>]
|
||||
| ^^^^^^^^^^^^^^^^ missing type for generic parameters
|
||||
|
||||
error: unresolved link to `Vec:<T>:new`
|
||||
--> $DIR/intra-link-malformed-generics.rs:12:6
|
||||
|
|
||||
LL | //! [Vec:<T>:new()]
|
||||
| ^^^^^^^^^^^^^ has invalid path separator
|
||||
|
||||
error: unresolved link to `Vec<<T>>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:13:6
|
||||
|
|
||||
LL | //! [Vec<<T>>]
|
||||
| ^^^^^^^^ too many angle brackets
|
||||
|
||||
error: unresolved link to `Vec<>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:14:6
|
||||
|
|
||||
LL | //! [Vec<>]
|
||||
| ^^^^^ empty angle brackets
|
||||
|
||||
error: unresolved link to `Vec<<>>`
|
||||
--> $DIR/intra-link-malformed-generics.rs:15:6
|
||||
|
|
||||
LL | //! [Vec<<>>]
|
||||
| ^^^^^^^ too many angle brackets
|
||||
|
||||
error: unresolved link to `<Vec as IntoIterator>::into_iter`
|
||||
--> $DIR/intra-link-malformed-generics.rs:18:6
|
||||
|
|
||||
LL | //! [<Vec as IntoIterator>::into_iter]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
|
||||
|
|
||||
= note: see https://github.com/rust-lang/rust/issues/74563 for more information
|
||||
|
||||
error: unresolved link to `<Vec<T> as IntoIterator>::iter`
|
||||
--> $DIR/intra-link-malformed-generics.rs:19:6
|
||||
|
|
||||
LL | //! [<Vec<T> as IntoIterator>::iter]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
|
||||
|
|
||||
= note: see https://github.com/rust-lang/rust/issues/74563 for more information
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
55
src/test/rustdoc/intra-doc-link-generic-params.rs
Normal file
55
src/test/rustdoc/intra-doc-link-generic-params.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
//! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
|
||||
//! Here's a link to [`Iterator<Box<T>>::Item`].
|
||||
//!
|
||||
//! And what about a link to [just `Option`](Option) and, [with the generic, `Option<T>`](Option<T>)?
|
||||
//!
|
||||
//! We should also try linking to [`Result<T, E>`]; it has *two* generics!
|
||||
//!
|
||||
//! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
|
||||
//! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
|
||||
//! And what about something even harder? That would be [`Vec::<Box<T>>::new()`].
|
||||
//!
|
||||
//! This is also pretty tricky: [`TypeId::of::<String>()`].
|
||||
//! And this too: [`Vec::<std::error::Error>::len`].
|
||||
//!
|
||||
//! We unofficially and implicitly support things that aren't valid in the actual Rust syntax, like
|
||||
//! [`Box::<T>new()`]. We may not support them in the future!
|
||||
//!
|
||||
//! These will be resolved as regular links:
|
||||
//! - [`this is <invalid syntax> first`](https://www.rust-lang.org)
|
||||
//! - [`this is <invalid syntax> twice`]
|
||||
//! - [`<invalid syntax> thrice`](https://www.rust-lang.org)
|
||||
//! - [`<invalid syntax> four times`][rlo]
|
||||
//! - [a < b][rlo]
|
||||
//! - [c > d]
|
||||
//!
|
||||
//! [`this is <invalid syntax> twice`]: https://www.rust-lang.org
|
||||
//! [rlo]: https://www.rust-lang.org
|
||||
//! [c > d]: https://www.rust-lang.org
|
||||
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html"]' 'Vec<T>'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'just Option'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option<T>'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, E>'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
|
||||
|
||||
// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
|
||||
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'this is <invalid syntax> first'
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'this is <invalid syntax> twice'
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' '<invalid syntax> thrice'
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' '<invalid syntax> four times'
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'a < b'
|
||||
// @has foo/index.html '//a[@href="https://www.rust-lang.org"]' 'c > d'
|
||||
|
||||
use std::any::TypeId;
|
||||
Loading…
Add table
Add a link
Reference in a new issue