Change DocFragments from enum variant fields to structs with a nested enum

This makes the code a lot easier to work with. It also makes it easier
to add new fields without updating each variant and `match`
individually.

- Name the `Kind` variant after `DocFragmentKind` from `collapse_docs`
- Remove unneeded impls
This commit is contained in:
Joshua Nelson 2020-10-03 19:15:27 -04:00
parent 782013564e
commit 5f76b95e9b
5 changed files with 50 additions and 90 deletions

View File

@ -370,32 +370,22 @@ impl<I: IntoIterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
/// kept separate because of issue #42760.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum DocFragment {
/// A doc fragment created from a `///` or `//!` doc comment.
SugaredDoc(usize, rustc_span::Span, String),
/// A doc fragment created from a "raw" `#[doc=""]` attribute.
RawDoc(usize, rustc_span::Span, String),
/// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
/// given filename and the file contents.
Include(usize, rustc_span::Span, String, String),
pub struct DocFragment {
pub line: usize,
pub span: rustc_span::Span,
pub doc: String,
pub kind: DocFragmentKind,
}
impl DocFragment {
pub fn as_str(&self) -> &str {
match *self {
DocFragment::SugaredDoc(_, _, ref s) => &s[..],
DocFragment::RawDoc(_, _, ref s) => &s[..],
DocFragment::Include(_, _, _, ref s) => &s[..],
}
}
pub fn span(&self) -> rustc_span::Span {
match *self {
DocFragment::SugaredDoc(_, span, _)
| DocFragment::RawDoc(_, span, _)
| DocFragment::Include(_, span, _, _) => span,
}
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub enum DocFragmentKind {
/// A doc fragment created from a `///` or `//!` doc comment.
SugaredDoc,
/// A doc fragment created from a "raw" `#[doc=""]` attribute.
RawDoc,
/// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
/// given filename and the file contents.
Include { filename: String },
}
impl<'a> FromIterator<&'a DocFragment> for String {
@ -407,12 +397,7 @@ impl<'a> FromIterator<&'a DocFragment> for String {
if !acc.is_empty() {
acc.push('\n');
}
match *frag {
DocFragment::SugaredDoc(_, _, ref docs)
| DocFragment::RawDoc(_, _, ref docs)
| DocFragment::Include(_, _, _, ref docs) => acc.push_str(docs),
}
acc.push_str(&frag.doc);
acc
})
}
@ -547,15 +532,15 @@ impl Attributes {
.filter_map(|attr| {
if let Some(value) = attr.doc_str() {
let value = beautify_doc_string(value);
let mk_fragment: fn(_, _, _) -> _ = if attr.is_doc_comment() {
DocFragment::SugaredDoc
let kind = if attr.is_doc_comment() {
DocFragmentKind::SugaredDoc
} else {
DocFragment::RawDoc
DocFragmentKind::RawDoc
};
let line = doc_line;
doc_line += value.lines().count();
doc_strings.push(mk_fragment(line, attr.span, value));
doc_strings.push(DocFragment { line, span: attr.span, doc: value, kind });
if sp.is_none() {
sp = Some(attr.span);
@ -575,9 +560,12 @@ impl Attributes {
{
let line = doc_line;
doc_line += contents.lines().count();
doc_strings.push(DocFragment::Include(
line, attr.span, filename, contents,
));
doc_strings.push(DocFragment {
line,
span: attr.span,
doc: contents,
kind: DocFragmentKind::Include { filename },
});
}
}
}
@ -621,7 +609,7 @@ impl Attributes {
/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
pub fn doc_value(&self) -> Option<&str> {
self.doc_strings.first().map(|s| s.as_str())
self.doc_strings.first().map(|s| s.doc.as_str())
}
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined

View File

@ -232,7 +232,12 @@ impl fold::DocFolder for CoverageCalculator {
let mut tests = Tests { found_tests: 0 };
find_testable_code(
&i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
&i.attrs
.doc_strings
.iter()
.map(|d| d.doc.as_str())
.collect::<Vec<_>>()
.join("\n"),
&mut tests,
ErrorCodes::No,
false,

View File

@ -1,4 +1,4 @@
use crate::clean::{self, DocFragment, Item};
use crate::clean::{self, DocFragment, DocFragmentKind, Item};
use crate::core::DocContext;
use crate::fold;
use crate::fold::DocFolder;
@ -12,23 +12,6 @@ pub const COLLAPSE_DOCS: Pass = Pass {
description: "concatenates all document attributes into one document attribute",
};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DocFragmentKind {
Sugared,
Raw,
Include,
}
impl DocFragment {
fn kind(&self) -> DocFragmentKind {
match *self {
DocFragment::SugaredDoc(..) => DocFragmentKind::Sugared,
DocFragment::RawDoc(..) => DocFragmentKind::Raw,
DocFragment::Include(..) => DocFragmentKind::Include,
}
}
}
pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
let mut krate = Collapser.fold_crate(krate);
krate.collapsed = true;
@ -50,30 +33,22 @@ fn collapse(doc_strings: &mut Vec<DocFragment>) {
for frag in take(doc_strings) {
if let Some(mut curr_frag) = last_frag.take() {
let curr_kind = curr_frag.kind();
let new_kind = frag.kind();
let curr_kind = &curr_frag.kind;
let new_kind = &frag.kind;
if curr_kind == DocFragmentKind::Include || curr_kind != new_kind {
match curr_frag {
DocFragment::SugaredDoc(_, _, ref mut doc_string)
| DocFragment::RawDoc(_, _, ref mut doc_string) => {
// add a newline for extra padding between segments
doc_string.push('\n');
}
_ => {}
if matches!(*curr_kind, DocFragmentKind::Include { .. }) || curr_kind != new_kind {
if *curr_kind == DocFragmentKind::SugaredDoc
|| *curr_kind == DocFragmentKind::RawDoc
{
// add a newline for extra padding between segments
curr_frag.doc.push('\n');
}
docs.push(curr_frag);
last_frag = Some(frag);
} else {
match curr_frag {
DocFragment::SugaredDoc(_, ref mut span, ref mut doc_string)
| DocFragment::RawDoc(_, ref mut span, ref mut doc_string) => {
doc_string.push('\n');
doc_string.push_str(frag.as_str());
*span = span.to(frag.span());
}
_ => unreachable!(),
}
curr_frag.doc.push('\n');
curr_frag.doc.push_str(&frag.doc);
curr_frag.span = curr_frag.span.to(frag.span);
last_frag = Some(curr_frag);
}
} else {

View File

@ -8,7 +8,7 @@ use std::mem;
use std::ops::Range;
use self::Condition::*;
use crate::clean::{self, GetDefId, Item};
use crate::clean::{self, DocFragmentKind, GetDefId, Item};
use crate::core::DocContext;
use crate::fold::{DocFolder, StripItem};
@ -314,11 +314,11 @@ crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
if attrs.doc_strings.is_empty() {
return None;
}
let start = attrs.doc_strings[0].span();
let start = attrs.doc_strings[0].span;
if start == DUMMY_SP {
return None;
}
let end = attrs.doc_strings.last().expect("no doc strings provided").span();
let end = attrs.doc_strings.last().expect("no doc strings provided").span;
Some(start.to(end))
}
@ -333,10 +333,8 @@ crate fn source_span_for_markdown_range(
md_range: &Range<usize>,
attrs: &clean::Attributes,
) -> Option<Span> {
let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
clean::DocFragment::SugaredDoc(..) => true,
_ => false,
});
let is_all_sugared_doc =
attrs.doc_strings.iter().all(|frag| frag.kind == DocFragmentKind::SugaredDoc);
if !is_all_sugared_doc {
return None;

View File

@ -36,13 +36,7 @@ impl clean::Attributes {
fn unindent_fragments(docs: &mut Vec<DocFragment>) {
for fragment in docs {
match *fragment {
DocFragment::SugaredDoc(_, _, ref mut doc_string)
| DocFragment::RawDoc(_, _, ref mut doc_string)
| DocFragment::Include(_, _, _, ref mut doc_string) => {
*doc_string = unindent(doc_string)
}
}
fragment.doc = unindent(&fragment.doc);
}
}