Rollup merge of #58627 - euclio:rustdoc-pass-order, r=QuietMisdreavus
rustdoc: move collapse and unindent docs passes earlier Moves these passes as early as possible so later passes will see the same markdown that is passed to the test collector. Fixes #58473, and a similar issue with the private-doc-tests lint. r? @QuietMisdreavus
This commit is contained in:
commit
f6673a4e7c
17 changed files with 106 additions and 152 deletions
|
|
@ -214,7 +214,7 @@ impl Options {
|
|||
if matches.opt_strs("passes") == ["list"] {
|
||||
println!("Available passes for running rustdoc:");
|
||||
for pass in passes::PASSES {
|
||||
println!("{:>20} - {}", pass.name(), pass.description());
|
||||
println!("{:>20} - {}", pass.name, pass.description);
|
||||
}
|
||||
println!("\nDefault passes for rustdoc:");
|
||||
for &name in passes::DEFAULT_PASSES {
|
||||
|
|
|
|||
|
|
@ -603,10 +603,12 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||
passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
|
||||
passes.extend(manual_passes);
|
||||
|
||||
info!("Executing passes");
|
||||
|
||||
for pass in &passes {
|
||||
// the "unknown pass" error will be reported when late passes are run
|
||||
if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) {
|
||||
krate = pass(krate, &ctxt);
|
||||
match passes::find_pass(pass).map(|p| p.pass) {
|
||||
Some(pass) => krate = pass(krate, &ctxt),
|
||||
None => error!("unknown pass {}, skipping", *pass),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -441,28 +441,6 @@ where R: 'static + Send,
|
|||
|
||||
krate.version = crate_version;
|
||||
|
||||
info!("Executing passes");
|
||||
|
||||
for pass in &passes {
|
||||
// determine if we know about this pass
|
||||
let pass = match passes::find_pass(pass) {
|
||||
Some(pass) => if let Some(pass) = pass.late_fn() {
|
||||
pass
|
||||
} else {
|
||||
// not a late pass, but still valid so don't report the error
|
||||
continue
|
||||
}
|
||||
None => {
|
||||
error!("unknown pass {}, skipping", *pass);
|
||||
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
// run it
|
||||
krate = pass(krate);
|
||||
}
|
||||
|
||||
tx.send(f(Output {
|
||||
krate: krate,
|
||||
renderinfo: renderinfo,
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ use crate::fold::DocFolder;
|
|||
use crate::html::markdown::{self, RustCodeBlock};
|
||||
use crate::passes::Pass;
|
||||
|
||||
pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
|
||||
Pass::early("check-code-block-syntax", check_code_block_syntax,
|
||||
"validates syntax inside Rust code blocks");
|
||||
pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
|
||||
name: "check-code-block-syntax",
|
||||
pass: check_code_block_syntax,
|
||||
description: "validates syntax inside Rust code blocks",
|
||||
};
|
||||
|
||||
pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext<'_, '_, '_>) -> clean::Crate {
|
||||
SyntaxChecker { cx }.fold_crate(krate)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
use crate::clean::{self, DocFragment, Item};
|
||||
use crate::core::DocContext;
|
||||
use crate::fold;
|
||||
use crate::fold::{DocFolder};
|
||||
use crate::passes::Pass;
|
||||
|
||||
use std::mem::replace;
|
||||
|
||||
pub const COLLAPSE_DOCS: Pass =
|
||||
Pass::late("collapse-docs", collapse_docs,
|
||||
"concatenates all document attributes into one document attribute");
|
||||
pub const COLLAPSE_DOCS: Pass = Pass {
|
||||
name: "collapse-docs",
|
||||
pass: collapse_docs,
|
||||
description: "concatenates all document attributes into one document attribute",
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum DocFragmentKind {
|
||||
|
|
@ -26,7 +29,7 @@ impl DocFragment {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn collapse_docs(krate: clean::Crate) -> clean::Crate {
|
||||
pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
|
||||
Collapser.fold_crate(krate)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ use crate::passes::{look_for_tests, Pass};
|
|||
|
||||
use super::span_of_attrs;
|
||||
|
||||
pub const COLLECT_INTRA_DOC_LINKS: Pass =
|
||||
Pass::early("collect-intra-doc-links", collect_intra_doc_links,
|
||||
"reads a crate's documentation to resolve intra-doc-links");
|
||||
pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
|
||||
name: "collect-intra-doc-links",
|
||||
pass: collect_intra_doc_links,
|
||||
description: "reads a crate's documentation to resolve intra-doc-links",
|
||||
};
|
||||
|
||||
pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
|
||||
if !UnstableFeatures::from_environment().is_nightly_build() {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ use super::Pass;
|
|||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
||||
pub const COLLECT_TRAIT_IMPLS: Pass =
|
||||
Pass::early("collect-trait-impls", collect_trait_impls,
|
||||
"retrieves trait impls for items in the crate");
|
||||
pub const COLLECT_TRAIT_IMPLS: Pass = Pass {
|
||||
name: "collect-trait-impls",
|
||||
pass: collect_trait_impls,
|
||||
description: "retrieves trait impls for items in the crate",
|
||||
};
|
||||
|
||||
pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
|
||||
let mut synth = SyntheticImplCollector::new(cx);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use rustc::lint as lint;
|
|||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use std::ops::Range;
|
||||
|
|
@ -46,84 +45,14 @@ pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
|
|||
mod check_code_block_syntax;
|
||||
pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
|
||||
|
||||
/// Represents a single pass.
|
||||
/// A single pass over the cleaned documentation.
|
||||
///
|
||||
/// Runs in the compiler context, so it has access to types and traits and the like.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Pass {
|
||||
/// An "early pass" is run in the compiler context, and can gather information about types and
|
||||
/// traits and the like.
|
||||
EarlyPass {
|
||||
name: &'static str,
|
||||
pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
|
||||
description: &'static str,
|
||||
},
|
||||
/// A "late pass" is run between crate cleaning and page generation.
|
||||
LatePass {
|
||||
name: &'static str,
|
||||
pass: fn(clean::Crate) -> clean::Crate,
|
||||
description: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Debug for Pass {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut dbg = match *self {
|
||||
Pass::EarlyPass { .. } => f.debug_struct("EarlyPass"),
|
||||
Pass::LatePass { .. } => f.debug_struct("LatePass"),
|
||||
};
|
||||
|
||||
dbg.field("name", &self.name())
|
||||
.field("pass", &"...")
|
||||
.field("description", &self.description())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Pass {
|
||||
/// Constructs a new early pass.
|
||||
pub const fn early(name: &'static str,
|
||||
pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
|
||||
description: &'static str) -> Pass {
|
||||
Pass::EarlyPass { name, pass, description }
|
||||
}
|
||||
|
||||
/// Constructs a new late pass.
|
||||
pub const fn late(name: &'static str,
|
||||
pass: fn(clean::Crate) -> clean::Crate,
|
||||
description: &'static str) -> Pass {
|
||||
Pass::LatePass { name, pass, description }
|
||||
}
|
||||
|
||||
/// Returns the name of this pass.
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
Pass::EarlyPass { name, .. } |
|
||||
Pass::LatePass { name, .. } => name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the description of this pass.
|
||||
pub fn description(self) -> &'static str {
|
||||
match self {
|
||||
Pass::EarlyPass { description, .. } |
|
||||
Pass::LatePass { description, .. } => description,
|
||||
}
|
||||
}
|
||||
|
||||
/// If this pass is an early pass, returns the pointer to its function.
|
||||
pub fn early_fn(self) -> Option<fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate> {
|
||||
match self {
|
||||
Pass::EarlyPass { pass, .. } => Some(pass),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// If this pass is a late pass, returns the pointer to its function.
|
||||
pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
|
||||
match self {
|
||||
Pass::LatePass { pass, .. } => Some(pass),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub struct Pass {
|
||||
pub name: &'static str,
|
||||
pub pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
|
||||
pub description: &'static str,
|
||||
}
|
||||
|
||||
/// The full list of passes.
|
||||
|
|
@ -141,27 +70,27 @@ pub const PASSES: &'static [Pass] = &[
|
|||
];
|
||||
|
||||
/// The list of passes run by default.
|
||||
pub const DEFAULT_PASSES: &'static [&'static str] = &[
|
||||
pub const DEFAULT_PASSES: &[&str] = &[
|
||||
"collect-trait-impls",
|
||||
"collapse-docs",
|
||||
"unindent-comments",
|
||||
"check-private-items-doc-tests",
|
||||
"strip-hidden",
|
||||
"strip-private",
|
||||
"collect-intra-doc-links",
|
||||
"check-code-block-syntax",
|
||||
"collapse-docs",
|
||||
"unindent-comments",
|
||||
"propagate-doc-cfg",
|
||||
];
|
||||
|
||||
/// The list of default passes run with `--document-private-items` is passed to rustdoc.
|
||||
pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
|
||||
pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[
|
||||
"collect-trait-impls",
|
||||
"collapse-docs",
|
||||
"unindent-comments",
|
||||
"check-private-items-doc-tests",
|
||||
"strip-priv-imports",
|
||||
"collect-intra-doc-links",
|
||||
"check-code-block-syntax",
|
||||
"collapse-docs",
|
||||
"unindent-comments",
|
||||
"propagate-doc-cfg",
|
||||
];
|
||||
|
||||
|
|
@ -184,8 +113,8 @@ pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
|
|||
}
|
||||
|
||||
/// If the given name matches a known pass, returns its information.
|
||||
pub fn find_pass(pass_name: &str) -> Option<Pass> {
|
||||
PASSES.iter().find(|p| p.name() == pass_name).cloned()
|
||||
pub fn find_pass(pass_name: &str) -> Option<&'static Pass> {
|
||||
PASSES.iter().find(|p| p.name == pass_name)
|
||||
}
|
||||
|
||||
struct Stripper<'a> {
|
||||
|
|
@ -438,11 +367,11 @@ crate fn source_span_for_markdown_range(
|
|||
.span_to_snippet(span_of_attrs(attrs))
|
||||
.ok()?;
|
||||
|
||||
let starting_line = markdown[..md_range.start].lines().count() - 1;
|
||||
let ending_line = markdown[..md_range.end].lines().count() - 1;
|
||||
let starting_line = markdown[..md_range.start].matches('\n').count();
|
||||
let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();
|
||||
|
||||
// We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
|
||||
// we can treat CRLF and LF line endings the same way.
|
||||
// We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we treat
|
||||
// CRLF and LF line endings the same way.
|
||||
let mut src_lines = snippet.split_terminator('\n');
|
||||
let md_lines = markdown.split_terminator('\n');
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ use crate::core::DocContext;
|
|||
use crate::fold::DocFolder;
|
||||
use crate::passes::{look_for_tests, Pass};
|
||||
|
||||
|
||||
pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass =
|
||||
Pass::early("check-private-items-doc-tests", check_private_items_doc_tests,
|
||||
"check private items doc tests");
|
||||
pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
|
||||
name: "check-private-items-doc-tests",
|
||||
pass: check_private_items_doc_tests,
|
||||
description: "check private items doc tests",
|
||||
};
|
||||
|
||||
struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||
cx: &'a DocContext<'a, 'tcx, 'rcx>,
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@ use std::sync::Arc;
|
|||
|
||||
use crate::clean::{Crate, Item};
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::DocFolder;
|
||||
use crate::passes::Pass;
|
||||
|
||||
pub const PROPAGATE_DOC_CFG: Pass =
|
||||
Pass::late("propagate-doc-cfg", propagate_doc_cfg,
|
||||
"propagates `#[doc(cfg(...))]` to child items");
|
||||
pub const PROPAGATE_DOC_CFG: Pass = Pass {
|
||||
name: "propagate-doc-cfg",
|
||||
pass: propagate_doc_cfg,
|
||||
description: "propagates `#[doc(cfg(...))]` to child items",
|
||||
};
|
||||
|
||||
pub fn propagate_doc_cfg(cr: Crate) -> Crate {
|
||||
pub fn propagate_doc_cfg(cr: Crate, _: &DocContext<'_, '_, '_>) -> Crate {
|
||||
CfgPropagator { parent_cfg: None }.fold_crate(cr)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ use crate::core::DocContext;
|
|||
use crate::fold::{DocFolder, StripItem};
|
||||
use crate::passes::{ImplStripper, Pass};
|
||||
|
||||
pub const STRIP_HIDDEN: Pass =
|
||||
Pass::early("strip-hidden", strip_hidden,
|
||||
"strips all doc(hidden) items from the output");
|
||||
pub const STRIP_HIDDEN: Pass = Pass {
|
||||
name: "strip-hidden",
|
||||
pass: strip_hidden,
|
||||
description: "strips all doc(hidden) items from the output",
|
||||
};
|
||||
|
||||
/// Strip items marked `#[doc(hidden)]`
|
||||
pub fn strip_hidden(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@ use crate::fold::{DocFolder};
|
|||
use crate::core::DocContext;
|
||||
use crate::passes::{ImportStripper, Pass};
|
||||
|
||||
pub const STRIP_PRIV_IMPORTS: Pass = Pass::early("strip-priv-imports", strip_priv_imports,
|
||||
"strips all private import statements (`use`, `extern crate`) from a crate");
|
||||
pub const STRIP_PRIV_IMPORTS: Pass = Pass {
|
||||
name: "strip-priv-imports",
|
||||
pass: strip_priv_imports,
|
||||
description: "strips all private import statements (`use`, `extern crate`) from a crate",
|
||||
};
|
||||
|
||||
pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
|
||||
ImportStripper.fold_crate(krate)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ use crate::fold::{DocFolder};
|
|||
use crate::core::DocContext;
|
||||
use crate::passes::{ImplStripper, ImportStripper, Stripper, Pass};
|
||||
|
||||
pub const STRIP_PRIVATE: Pass =
|
||||
Pass::early("strip-private", strip_private,
|
||||
"strips all private items from a crate which cannot be seen externally, \
|
||||
implies strip-priv-imports");
|
||||
pub const STRIP_PRIVATE: Pass = Pass {
|
||||
name: "strip-private",
|
||||
pass: strip_private,
|
||||
description: "strips all private items from a crate which cannot be seen externally, \
|
||||
implies strip-priv-imports",
|
||||
};
|
||||
|
||||
/// Strip private items from the point of view of a crate or externally from a
|
||||
/// crate, specified by the `xcrate` flag.
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ use std::string::String;
|
|||
use std::usize;
|
||||
|
||||
use crate::clean::{self, DocFragment, Item};
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::{self, DocFolder};
|
||||
use crate::passes::Pass;
|
||||
|
||||
pub const UNINDENT_COMMENTS: Pass =
|
||||
Pass::late("unindent-comments", unindent_comments,
|
||||
"removes excess indentation on comments in order for markdown to like it");
|
||||
pub const UNINDENT_COMMENTS: Pass = Pass {
|
||||
name: "unindent-comments",
|
||||
pass: unindent_comments,
|
||||
description: "removes excess indentation on comments in order for markdown to like it",
|
||||
};
|
||||
|
||||
pub fn unindent_comments(krate: clean::Crate) -> clean::Crate {
|
||||
pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
|
||||
CommentCleaner.fold_crate(krate)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,8 +105,8 @@ LL | | /// [error]
|
|||
|
|
||||
= note: the link appears in this line:
|
||||
|
||||
[error]
|
||||
^^^^^
|
||||
[error]
|
||||
^^^^^
|
||||
= help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
|
||||
|
||||
warning: `[error1]` cannot be resolved, ignoring it...
|
||||
|
|
|
|||
12
src/test/rustdoc-ui/issue-58473-2.rs
Normal file
12
src/test/rustdoc-ui/issue-58473-2.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// compile-pass
|
||||
|
||||
#![deny(private_doc_tests)]
|
||||
|
||||
mod foo {
|
||||
/**
|
||||
Does nothing, returns `()`
|
||||
|
||||
yadda-yadda-yadda
|
||||
*/
|
||||
fn foo() {}
|
||||
}
|
||||
10
src/test/rustdoc-ui/issue-58473.rs
Normal file
10
src/test/rustdoc-ui/issue-58473.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// compile-pass
|
||||
|
||||
pub trait Foo {
|
||||
/**
|
||||
Does nothing, returns `()`
|
||||
|
||||
yadda-yadda-yadda
|
||||
*/
|
||||
fn foo() {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue