rustdoc: point at span in include_str!
-ed md file
This commit is contained in:
parent
d74804636f
commit
98642da6a9
10 changed files with 121 additions and 42 deletions
|
@ -194,12 +194,12 @@ pub fn attrs_to_doc_fragments<'a>(
|
|||
for (attr, item_id) in attrs {
|
||||
if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
|
||||
let doc = beautify_doc_string(doc_str, comment_kind);
|
||||
let kind = if attr.is_doc_comment() {
|
||||
DocFragmentKind::SugaredDoc
|
||||
let (span, kind) = if attr.is_doc_comment() {
|
||||
(attr.span, DocFragmentKind::SugaredDoc)
|
||||
} else {
|
||||
DocFragmentKind::RawDoc
|
||||
(span_for_value(attr), DocFragmentKind::RawDoc)
|
||||
};
|
||||
let fragment = DocFragment { span: attr.span, doc, kind, item_id, indent: 0 };
|
||||
let fragment = DocFragment { span, doc, kind, item_id, indent: 0 };
|
||||
doc_fragments.push(fragment);
|
||||
} else if !doc_only {
|
||||
other_attrs.push(attr.clone());
|
||||
|
@ -211,6 +211,16 @@ pub fn attrs_to_doc_fragments<'a>(
|
|||
(doc_fragments, other_attrs)
|
||||
}
|
||||
|
||||
fn span_for_value(attr: &ast::Attribute) -> Span {
|
||||
if let ast::AttrKind::Normal(normal) = &attr.kind
|
||||
&& let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args
|
||||
{
|
||||
meta.span.with_ctxt(attr.span.ctxt())
|
||||
} else {
|
||||
attr.span
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the doc-comments on this item, grouped by the module they came from.
|
||||
/// The module can be different if this is a re-export with added documentation.
|
||||
///
|
||||
|
@ -482,15 +492,36 @@ pub fn span_of_fragments(fragments: &[DocFragment]) -> Option<Span> {
|
|||
|
||||
/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
|
||||
///
|
||||
/// This method will return `None` if we cannot construct a span from the source map or if the
|
||||
/// fragments are not all sugared doc comments. It's difficult to calculate the correct span in
|
||||
/// that case due to escaping and other source features.
|
||||
/// This method does not always work, because markdown bytes don't necessarily match source bytes,
|
||||
/// like if escapes are used in the string. In this case, it returns `None`.
|
||||
///
|
||||
/// This method will return `Some` only if:
|
||||
///
|
||||
/// - The doc is made entirely from sugared doc comments, which cannot contain escapes
|
||||
/// - The doc is entirely from a single doc fragment, with a string literal, exactly equal
|
||||
/// - The doc comes from `include_str!`
|
||||
pub fn source_span_for_markdown_range(
|
||||
tcx: TyCtxt<'_>,
|
||||
markdown: &str,
|
||||
md_range: &Range<usize>,
|
||||
fragments: &[DocFragment],
|
||||
) -> Option<Span> {
|
||||
if let &[fragment] = &fragments
|
||||
&& fragment.kind == DocFragmentKind::RawDoc
|
||||
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(fragment.span)
|
||||
&& snippet.trim_end() == markdown.trim_end()
|
||||
&& let Ok(md_range_lo) = u32::try_from(md_range.start)
|
||||
&& let Ok(md_range_hi) = u32::try_from(md_range.end)
|
||||
{
|
||||
// Single fragment with string that contains same bytes as doc.
|
||||
return Some(Span::new(
|
||||
fragment.span.lo() + rustc_span::BytePos(md_range_lo),
|
||||
fragment.span.lo() + rustc_span::BytePos(md_range_hi),
|
||||
fragment.span.ctxt(),
|
||||
fragment.span.parent(),
|
||||
));
|
||||
}
|
||||
|
||||
let is_all_sugared_doc = fragments.iter().all(|frag| frag.kind == DocFragmentKind::SugaredDoc);
|
||||
|
||||
if !is_all_sugared_doc {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue