Auto merge of #66675 - GuillaumeGomez:support-anchors-intra-doc-links, r=kinnison

Support anchors intra doc links

Fixes #62833
Part of #43466.

cc @ollie27
r? @kinnison
This commit is contained in:
bors 2019-11-27 04:51:31 +00:00
commit b5f265eeed
11 changed files with 328 additions and 106 deletions

View File

@ -38,6 +38,11 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
}
}
enum ErrorKind {
ResolutionFailure,
AnchorFailure(&'static str),
}
struct LinkCollector<'a, 'tcx> {
cx: &'a DocContext<'tcx>,
mod_ids: Vec<hir::HirId>,
@ -53,13 +58,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
/// Resolves a string as a path within a particular namespace. Also returns an optional
/// URL fragment in the case of variants and methods.
fn resolve(&self,
path_str: &str,
ns: Namespace,
current_item: &Option<String>,
parent_id: Option<hir::HirId>)
-> Result<(Res, Option<String>), ()>
{
fn resolve(
&self,
path_str: &str,
ns: Namespace,
current_item: &Option<String>,
parent_id: Option<hir::HirId>,
extra_fragment: &Option<String>,
) -> Result<(Res, Option<String>), ErrorKind> {
let cx = self.cx;
// In case we're in a module, try to resolve the relative path.
@ -69,8 +75,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
});
let result = match result {
Ok((_, Res::Err)) => Err(()),
_ => result,
Ok((_, Res::Err)) => Err(ErrorKind::ResolutionFailure),
_ => result.map_err(|_| ErrorKind::ResolutionFailure),
};
if let Ok((_, res)) = result {
@ -80,23 +86,36 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
let value = match res {
Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true,
Res::Def(DefKind::AssocTy, _) => false,
Res::Def(DefKind::Variant, _) => return handle_variant(cx, res),
Res::Def(DefKind::Variant, _) => {
return handle_variant(cx, res, extra_fragment);
}
// Not a trait item; just return what we found.
Res::PrimTy(..) => return Ok((res, Some(path_str.to_owned()))),
_ => return Ok((res, None))
Res::PrimTy(..) => {
if extra_fragment.is_some() {
return Err(
ErrorKind::AnchorFailure(
"primitive types cannot be followed by anchors"));
}
return Ok((res, Some(path_str.to_owned())));
}
_ => return Ok((res, extra_fragment.clone()))
};
if value != (ns == ValueNS) {
return Err(())
return Err(ErrorKind::ResolutionFailure)
}
} else if let Some(prim) = is_primitive(path_str, ns) {
if extra_fragment.is_some() {
return Err(
ErrorKind::AnchorFailure("primitive types cannot be followed by anchors"));
}
return Ok((prim, Some(path_str.to_owned())))
} else {
// If resolution failed, it may still be a method
// because methods are not handled by the resolver
// If so, bail when we're not looking for a value.
if ns != ValueNS {
return Err(())
return Err(ErrorKind::ResolutionFailure)
}
}
@ -105,13 +124,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
let item_name = if let Some(first) = split.next() {
Symbol::intern(first)
} else {
return Err(())
return Err(ErrorKind::ResolutionFailure)
};
let mut path = if let Some(second) = split.next() {
second.to_owned()
} else {
return Err(())
return Err(ErrorKind::ResolutionFailure)
};
if path == "self" || path == "Self" {
@ -120,7 +139,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
}
if let Some(prim) = is_primitive(&path, TypeNS) {
let did = primitive_impl(cx, &path).ok_or(())?;
let did = primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?;
return cx.tcx.associated_items(did)
.find(|item| item.ident.name == item_name)
.and_then(|item| match item.kind {
@ -128,14 +147,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
_ => None,
})
.map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name))))
.ok_or(());
.ok_or(ErrorKind::ResolutionFailure);
}
let (_, ty_res) = cx.enter_resolver(|resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
})?;
}).map_err(|_| ErrorKind::ResolutionFailure)?;
if let Res::Err = ty_res {
return Err(());
return Err(ErrorKind::ResolutionFailure);
}
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
match ty_res {
@ -151,9 +170,18 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
let out = match item.kind {
ty::AssocKind::Method if ns == ValueNS => "method",
ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
_ => return Err(())
_ => return Err(ErrorKind::ResolutionFailure)
};
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(
if item.kind == ty::AssocKind::Method {
"methods cannot be followed by anchors"
} else {
"associated constants cannot be followed by anchors"
}))
} else {
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
}
} else {
match cx.tcx.type_of(did).kind {
ty::Adt(def, _) => {
@ -165,19 +193,28 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
.iter()
.find(|item| item.ident.name == item_name)
} {
Ok((ty_res,
Some(format!("{}.{}",
if def.is_enum() {
"variant"
} else {
"structfield"
},
item.ident))))
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(
if def.is_enum() {
"enum variants cannot be followed by anchors"
} else {
"struct fields cannot be followed by anchors"
}))
} else {
Ok((ty_res,
Some(format!("{}.{}",
if def.is_enum() {
"variant"
} else {
"structfield"
},
item.ident))))
}
} else {
Err(())
Err(ErrorKind::ResolutionFailure)
}
}
_ => Err(()),
_ => Err(ErrorKind::ResolutionFailure),
}
}
}
@ -196,19 +233,30 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
"tymethod"
}
}
_ => return Err(())
_ => return Err(ErrorKind::ResolutionFailure)
};
Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
if extra_fragment.is_some() {
Err(ErrorKind::AnchorFailure(
if item.kind == ty::AssocKind::Const {
"associated constants cannot be followed by anchors"
} else if item.kind == ty::AssocKind::Type {
"associated types cannot be followed by anchors"
} else {
"methods cannot be followed by anchors"
}))
} else {
Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
}
} else {
Err(())
Err(ErrorKind::ResolutionFailure)
}
}
_ => Err(())
_ => Err(ErrorKind::ResolutionFailure)
}
} else {
debug!("attempting to resolve item without parent module: {}", path_str);
Err(())
Err(ErrorKind::ResolutionFailure)
}
}
}
@ -289,6 +337,22 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}
let link = ori_link.replace("`", "");
let parts = link.split('#').collect::<Vec<_>>();
let (link, extra_fragment) = if parts.len() > 2 {
build_diagnostic(cx, &item, &link, &dox, link_range,
"has an issue with the link anchor.",
"only one `#` is allowed in a link",
None);
continue;
} else if parts.len() == 2 {
if parts[0].trim().is_empty() {
// This is an anchor to an element of the current page, nothing to do in here!
continue;
}
(parts[0].to_owned(), Some(parts[1].to_owned()))
} else {
(parts[0].to_owned(), None)
};
let (res, fragment) = {
let mut kind = None;
let path_str = if let Some(prefix) =
@ -341,42 +405,73 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
match kind {
Some(ns @ ValueNS) => {
if let Ok(res) = self.resolve(path_str, ns, &current_item, base_node) {
res
} else {
resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link or a broken link
// we could potentially check if something is
// "intra-doc-link-like" and warn in that case.
continue;
match self.resolve(path_str, ns, &current_item, base_node,
&extra_fragment) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link or a broken link
// we could potentially check if something is
// "intra-doc-link-like" and warn in that case.
continue;
}
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
continue
}
}
}
Some(ns @ TypeNS) => {
if let Ok(res) = self.resolve(path_str, ns, &current_item, base_node) {
res
} else {
resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link.
continue;
match self.resolve(path_str, ns, &current_item, base_node,
&extra_fragment) {
Ok(res) => res,
Err(ErrorKind::ResolutionFailure) => {
resolution_failure(cx, &item, path_str, &dox, link_range);
// This could just be a normal link.
continue;
}
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
continue
}
}
}
None => {
// Try everything!
let candidates = PerNS {
macro_ns: macro_resolve(cx, path_str).map(|res| (res, None)),
type_ns: self
.resolve(path_str, TypeNS, &current_item, base_node)
.ok(),
value_ns: self
.resolve(path_str, ValueNS, &current_item, base_node)
.ok()
.and_then(|(res, fragment)| {
// Constructors are picked up in the type namespace.
match res {
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => None,
_ => Some((res, fragment))
}
}),
macro_ns: macro_resolve(cx, path_str)
.map(|res| (res, extra_fragment.clone())),
type_ns: match self.resolve(path_str, TypeNS, &current_item, base_node,
&extra_fragment) {
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
continue;
}
x => x.ok(),
},
value_ns: match self.resolve(path_str, ValueNS, &current_item,
base_node, &extra_fragment) {
Err(ErrorKind::AnchorFailure(msg)) => {
anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
continue;
}
x => x.ok(),
}
.and_then(|(res, fragment)| {
// Constructors are picked up in the type namespace.
match res {
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => None,
_ => match (fragment, extra_fragment) {
(Some(fragment), Some(_)) => {
// Shouldn't happen but who knows?
Some((res, Some(fragment)))
}
(fragment, None) | (None, fragment) => {
Some((res, fragment))
}
},
}
}),
};
if candidates.is_empty() {
@ -402,7 +497,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
}
Some(MacroNS) => {
if let Some(res) = macro_resolve(cx, path_str) {
(res, None)
(res, extra_fragment)
} else {
resolution_failure(cx, &item, path_str, &dox, link_range);
continue
@ -462,17 +557,15 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
})
}
/// Reports a resolution failure diagnostic.
///
/// If we cannot find the exact source span of the resolution failure, we use the span of the
/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
/// line containing the failure as a note as well.
fn resolution_failure(
fn build_diagnostic(
cx: &DocContext<'_>,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
err_msg: &str,
short_err_msg: &str,
help_msg: Option<&str>,
) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
@ -488,12 +581,12 @@ fn resolution_failure(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir_id,
sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str),
&format!("`[{}]` {}", path_str, err_msg),
);
if let Some(link_range) = link_range {
if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
diag.set_span(sp);
diag.span_label(sp, "cannot be resolved, ignoring");
diag.span_label(sp, short_err_msg);
} else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~
@ -513,11 +606,44 @@ fn resolution_failure(
));
}
};
diag.help("to escape `[` and `]` characters, just add '\\' before them like \
`\\[` or `\\]`");
if let Some(help_msg) = help_msg {
diag.help(help_msg);
}
diag.emit();
}
/// Reports a resolution failure diagnostic.
///
/// If we cannot find the exact source span of the resolution failure, we use the span of the
/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
/// line containing the failure as a note as well.
fn resolution_failure(
cx: &DocContext<'_>,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
) {
build_diagnostic(cx, item, path_str, dox, link_range,
"cannot be resolved, ignoring it.",
"cannot be resolved, ignoring",
Some("to escape `[` and `]` characters, just add '\\' before them like `\\[` or `\\]`"));
}
fn anchor_failure(
cx: &DocContext<'_>,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
msg: &str,
) {
build_diagnostic(cx, item, path_str, dox, link_range,
"has an issue with the link anchor.",
msg,
None);
}
fn ambiguity_error(
cx: &DocContext<'_>,
item: &Item,
@ -637,13 +763,20 @@ fn ambiguity_error(
}
/// Given an enum variant's res, return the res of its enum and the associated fragment.
fn handle_variant(cx: &DocContext<'_>, res: Res) -> Result<(Res, Option<String>), ()> {
fn handle_variant(
cx: &DocContext<'_>,
res: Res,
extra_fragment: &Option<String>,
) -> Result<(Res, Option<String>), ErrorKind> {
use rustc::ty::DefIdTree;
if extra_fragment.is_some() {
return Err(ErrorKind::AnchorFailure("variants cannot be followed by anchors"));
}
let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) {
parent
} else {
return Err(())
return Err(ErrorKind::ResolutionFailure)
};
let parent_def = Res::Def(DefKind::Enum, parent);
let variant = cx.tcx.expect_variant_res(res);

View File

@ -1,4 +1,4 @@
error: `[v2]` cannot be resolved, ignoring it...
error: `[v2]` cannot be resolved, ignoring it.
--> $DIR/deny-intra-link-resolution-failure.rs:3:6
|
LL | /// [v2]

View File

@ -1,4 +1,4 @@
error: `[TypeAlias::hoge]` cannot be resolved, ignoring it...
error: `[TypeAlias::hoge]` cannot be resolved, ignoring it.
--> $DIR/intra-doc-alias-ice.rs:5:30
|
LL | /// [broken cross-reference](TypeAlias::hoge)

View File

@ -7,7 +7,7 @@
/// ## For example:
///
/// arr[i]
//~^ ERROR `[i]` cannot be resolved, ignoring it...
//~^ ERROR `[i]` cannot be resolved, ignoring it.
pub fn test_ice() {
unimplemented!();
}

View File

@ -1,4 +1,4 @@
error: `[i]` cannot be resolved, ignoring it...
error: `[i]` cannot be resolved, ignoring it.
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
LL | /// arr[i]

View File

@ -0,0 +1,45 @@
#![deny(intra_doc_link_resolution_failure)]
// A few tests on anchors.
/// Hello people.
///
/// You can anchors? Here's one!
///
/// # hola
///
/// Isn't it amazing?
pub struct Foo {
pub f: u8,
}
pub enum Enum {
A,
B,
}
/// Have you heard about stuff?
///
/// Like [Foo#hola].
///
/// Or maybe [Foo::f#hola].
//~^ ERROR `[Foo::f#hola]` has an issue with the link anchor.
pub fn foo() {}
/// Empty.
///
/// Another anchor error: [hello#people#!].
//~^ ERROR `[hello#people#!]` has an issue with the link anchor.
pub fn bar() {}
/// Empty?
///
/// Damn enum's variants: [Enum::A#whatever].
//~^ ERROR `[Enum::A#whatever]` has an issue with the link anchor.
pub fn enum_link() {}
/// Primitives?
///
/// [u32#hello]
//~^ ERROR `[u32#hello]` has an issue with the link anchor.
pub fn x() {}

View File

@ -0,0 +1,32 @@
error: `[Foo::f#hola]` has an issue with the link anchor.
--> $DIR/intra-links-anchors.rs:25:15
|
LL | /// Or maybe [Foo::f#hola].
| ^^^^^^^^^^^ struct fields cannot be followed by anchors
|
note: lint level defined here
--> $DIR/intra-links-anchors.rs:1:9
|
LL | #![deny(intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[hello#people#!]` has an issue with the link anchor.
--> $DIR/intra-links-anchors.rs:31:28
|
LL | /// Another anchor error: [hello#people#!].
| ^^^^^^^^^^^^^^ only one `#` is allowed in a link
error: `[Enum::A#whatever]` has an issue with the link anchor.
--> $DIR/intra-links-anchors.rs:37:28
|
LL | /// Damn enum's variants: [Enum::A#whatever].
| ^^^^^^^^^^^^^^^^ variants cannot be followed by anchors
error: `[u32#hello]` has an issue with the link anchor.
--> $DIR/intra-links-anchors.rs:43:6
|
LL | /// [u32#hello]
| ^^^^^^^^^ primitive types cannot be followed by anchors
error: aborting due to 4 previous errors

View File

@ -1,4 +1,4 @@
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:7:6
|
LL | /// [error]
@ -7,7 +7,7 @@ LL | /// [error]
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error1]` cannot be resolved, ignoring it...
warning: `[error1]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:12:11
|
LL | /// docs [error1]
@ -15,7 +15,7 @@ LL | /// docs [error1]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error2]` cannot be resolved, ignoring it...
warning: `[error2]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:15:11
|
LL | /// docs [error2]
@ -23,7 +23,7 @@ LL | /// docs [error2]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:23:20
|
LL | * It also has an [error].

View File

@ -1,4 +1,4 @@
warning: `[Foo::baz]` cannot be resolved, ignoring it...
warning: `[Foo::baz]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:3:23
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
@ -7,7 +7,7 @@ LL | //! Test with [Foo::baz], [Bar::foo], ...
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Bar::foo]` cannot be resolved, ignoring it...
warning: `[Bar::foo]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:3:35
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
@ -15,7 +15,7 @@ LL | //! Test with [Foo::baz], [Bar::foo], ...
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
warning: `[Uniooon::X]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:6:13
|
LL | //! , [Uniooon::X] and [Qux::Z].
@ -23,7 +23,7 @@ LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Qux::Z]` cannot be resolved, ignoring it...
warning: `[Qux::Z]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:6:30
|
LL | //! , [Uniooon::X] and [Qux::Z].
@ -31,7 +31,7 @@ LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Uniooon::X]` cannot be resolved, ignoring it...
warning: `[Uniooon::X]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:10:14
|
LL | //! , [Uniooon::X] and [Qux::Z].
@ -39,7 +39,7 @@ LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Qux::Z]` cannot be resolved, ignoring it...
warning: `[Qux::Z]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:10:31
|
LL | //! , [Uniooon::X] and [Qux::Z].
@ -47,7 +47,7 @@ LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[Qux:Y]` cannot be resolved, ignoring it...
warning: `[Qux:Y]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:14:13
|
LL | /// [Qux:Y]
@ -55,7 +55,7 @@ LL | /// [Qux:Y]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:58:30
|
LL | * time to introduce a link [error]*/
@ -63,7 +63,7 @@ LL | * time to introduce a link [error]*/
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:64:30
|
LL | * time to introduce a link [error]
@ -71,7 +71,7 @@ LL | * time to introduce a link [error]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:68:1
|
LL | #[doc = "single line [error]"]
@ -83,7 +83,7 @@ LL | #[doc = "single line [error]"]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:71:1
|
LL | #[doc = "single line with \"escaping\" [error]"]
@ -95,7 +95,7 @@ LL | #[doc = "single line with \"escaping\" [error]"]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error]` cannot be resolved, ignoring it...
warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:74:1
|
LL | / /// Item docs.
@ -109,7 +109,7 @@ LL | | /// [error]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error1]` cannot be resolved, ignoring it...
warning: `[error1]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:80:11
|
LL | /// docs [error1]
@ -117,7 +117,7 @@ LL | /// docs [error1]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[error2]` cannot be resolved, ignoring it...
warning: `[error2]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:82:11
|
LL | /// docs [error2]
@ -125,7 +125,7 @@ LL | /// docs [error2]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[BarA]` cannot be resolved, ignoring it...
warning: `[BarA]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:21:10
|
LL | /// bar [BarA] bar
@ -133,7 +133,7 @@ LL | /// bar [BarA] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[BarB]` cannot be resolved, ignoring it...
warning: `[BarB]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:27:9
|
LL | * bar [BarB] bar
@ -141,7 +141,7 @@ LL | * bar [BarB] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[BarC]` cannot be resolved, ignoring it...
warning: `[BarC]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:34:6
|
LL | bar [BarC] bar
@ -149,7 +149,7 @@ LL | bar [BarC] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[BarD]` cannot be resolved, ignoring it...
warning: `[BarD]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:45:1
|
LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
@ -161,7 +161,7 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
warning: `[BarF]` cannot be resolved, ignoring it...
warning: `[BarF]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:50:9
|
LL | #[doc = $f]

View File

@ -15,7 +15,7 @@ LL | #![deny(rustdoc)]
| ^^^^^^^
= note: `#[deny(private_doc_tests)]` implied by `#[deny(rustdoc)]`
error: `[error]` cannot be resolved, ignoring it...
error: `[error]` cannot be resolved, ignoring it.
--> $DIR/lint-group.rs:9:29
|
LL | /// what up, let's make an [error]

View File

@ -0,0 +1,12 @@
/// I want...
///
/// # Anchor!
pub struct Something;
// @has intra_links_anchors/struct.SomeOtherType.html
// @has - '//a/@href' '../intra_links_anchors/struct.Something.html#Anchor!'
/// I want...
///
/// To link to [Something#Anchor!]
pub struct SomeOtherType;