Skip to content

Commit

Permalink
Auto merge of #52800 - QuietMisdreavus:do-not-pass-go, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
rustdoc: refactor how passes are structured, and turn intra-doc-link collection into a pass

This builds on #52751 and should not be merged until that finally finishes the bors queue

Part 2 of my passes refactor. This introduces the concept of an "early pass", which is run right before exiting the compiler context. This is important for passes that may want to ask the compiler about things. For example, i took out the intra-doc-link collection and turned it into a early pass. I also made the `strip-hidden`, `strip-private` and `strip-priv-imports` passes occur as early passes, so that intra-doc-link collection wouldn't run on docs that weren't getting printed.

Fixes #51684, technically #51468 too but that version of `h2` hits a legit intra-link error after that `>_>`

r? @rust-lang/rustdoc
  • Loading branch information
bors committed Aug 5, 2018
2 parents 93a4cab + e332985 commit 73c7873
Show file tree
Hide file tree
Showing 15 changed files with 899 additions and 672 deletions.
564 changes: 13 additions & 551 deletions src/librustdoc/clean/mod.rs

Large diffs are not rendered by default.

83 changes: 74 additions & 9 deletions src/librustdoc/core.rs
Expand Up @@ -26,7 +26,7 @@ use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use rustc_target::spec::TargetTriple;

use syntax::ast::{self, Ident, Name, NodeId};
use syntax::ast::{self, Ident};
use syntax::codemap;
use syntax::edition::Edition;
use syntax::feature_gate::UnstableFeatures;
Expand All @@ -45,8 +45,9 @@ use std::path::PathBuf;

use visit_ast::RustdocVisitor;
use clean;
use clean::{get_path_for_type, Clean, MAX_DEF_ID};
use clean::{get_path_for_type, Clean, MAX_DEF_ID, AttributesExt};
use html::render::RenderInfo;
use passes;

pub use rustc::session::config::{Input, Options, CodegenOptions};
pub use rustc::session::search_paths::SearchPaths;
Expand All @@ -57,7 +58,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub resolver: &'a RefCell<resolve::Resolver<'rcx, 'cstore>>,
/// The stack of module NodeIds up till this point
pub mod_ids: RefCell<Vec<NodeId>>,
pub crate_name: Option<String>,
pub cstore: Rc<CStore>,
pub populated_all_crate_impls: Cell<bool>,
Expand Down Expand Up @@ -87,7 +87,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
/// Maps (type_id, trait_id) -> auto trait impl
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>,
pub current_item_name: RefCell<Option<Name>>,
pub all_traits: Vec<DefId>,
}

Expand Down Expand Up @@ -322,7 +321,10 @@ pub fn run_core(search_paths: SearchPaths,
error_format: ErrorOutputType,
cmd_lints: Vec<(String, lint::Level)>,
lint_cap: Option<lint::Level>,
describe_lints: bool) -> (clean::Crate, RenderInfo)
describe_lints: bool,
mut manual_passes: Vec<String>,
mut default_passes: passes::DefaultPassOption)
-> (clean::Crate, RenderInfo, Vec<String>)
{
// Parse, resolve, and typecheck the given crate.

Expand Down Expand Up @@ -517,23 +519,86 @@ pub fn run_core(search_paths: SearchPaths,
ty_substs: Default::default(),
lt_substs: Default::default(),
impl_trait_bounds: Default::default(),
mod_ids: Default::default(),
send_trait: send_trait,
fake_def_ids: RefCell::new(FxHashMap()),
all_fake_def_ids: RefCell::new(FxHashSet()),
generated_synthetics: RefCell::new(FxHashSet()),
current_item_name: RefCell::new(None),
all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(),
};
debug!("crate: {:?}", tcx.hir.krate());

let krate = {
let mut krate = {
let mut v = RustdocVisitor::new(&ctxt);
v.visit(tcx.hir.krate());
v.clean(&ctxt)
};

(krate, ctxt.renderinfo.into_inner())
fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \
considered deprecated", name));
msg.warn("please see https://github.com/rust-lang/rust/issues/44136");

if name == "no_default_passes" {
msg.help("you may want to use `#![doc(document_private_items)]`");
}

msg.emit();
}

// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
let diag = ctxt.sess().diagnostic();

let name = attr.name().map(|s| s.as_str());
let name = name.as_ref().map(|s| &s[..]);
if attr.is_word() {
if name == Some("no_default_passes") {
report_deprecated_attr("no_default_passes", diag);
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::None;
}
}
} else if let Some(value) = attr.value_str() {
let sink = match name {
Some("passes") => {
report_deprecated_attr("passes = \"...\"", diag);
&mut manual_passes
},
Some("plugins") => {
report_deprecated_attr("plugins = \"...\"", diag);
eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
see CVE-2018-1000622");
continue
},
_ => continue,
};
for p in value.as_str().split_whitespace() {
sink.push(p.to_string());
}
}

if attr.is_word() && name == Some("document_private_items") {
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::Private;
}
}
}

let mut passes: Vec<String> =
passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
passes.extend(manual_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);
}
}

ctxt.sess().abort_if_errors();

(krate, ctxt.renderinfo.into_inner(), passes)
}), &sess)
})
}
78 changes: 15 additions & 63 deletions src/librustdoc/lib.rs
Expand Up @@ -26,6 +26,7 @@
#![feature(entry_and_modify)]
#![feature(ptr_offset_from)]
#![feature(crate_visibility_modifier)]
#![feature(const_fn)]

#![recursion_limit="256"]

Expand Down Expand Up @@ -96,8 +97,6 @@ mod visit_lib;
mod test;
mod theme;

use clean::AttributesExt;

struct Output {
krate: clean::Crate,
renderinfo: html::render::RenderInfo,
Expand Down Expand Up @@ -367,8 +366,8 @@ fn main_args(args: &[String]) -> isize {

if matches.opt_strs("passes") == ["list"] {
println!("Available passes for running rustdoc:");
for &(name, _, description) in passes::PASSES {
println!("{:>20} - {}", name, description);
for pass in passes::PASSES {
println!("{:>20} - {}", pass.name(), pass.description());
}
println!("\nDefault passes for rustdoc:");
for &name in passes::DEFAULT_PASSES {
Expand Down Expand Up @@ -630,16 +629,16 @@ fn rust_input<R, F>(cratefile: PathBuf,
where R: 'static + Send,
F: 'static + Send + FnOnce(Output) -> R
{
let mut default_passes = if matches.opt_present("no-defaults") {
let default_passes = if matches.opt_present("no-defaults") {
passes::DefaultPassOption::None
} else if matches.opt_present("document-private-items") {
passes::DefaultPassOption::Private
} else {
passes::DefaultPassOption::Default
};

let mut manual_passes = matches.opt_strs("passes");
let mut plugins = matches.opt_strs("plugins");
let manual_passes = matches.opt_strs("passes");
let plugins = matches.opt_strs("plugins");

// First, parse the crate and extract all relevant information.
let mut paths = SearchPaths::new();
Expand Down Expand Up @@ -673,11 +672,11 @@ where R: 'static + Send,
let result = rustc_driver::monitor(move || syntax::with_globals(move || {
use rustc::session::config::Input;

let (mut krate, renderinfo) =
let (mut krate, renderinfo, passes) =
core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
display_warnings, crate_name.clone(),
force_unstable_if_unmarked, edition, cg, error_format,
lint_opts, lint_cap, describe_lints);
lint_opts, lint_cap, describe_lints, manual_passes, default_passes);

info!("finished with rustc");

Expand All @@ -687,58 +686,6 @@ where R: 'static + Send,

krate.version = crate_version;

let diag = core::new_handler(error_format, None);

fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \
considered deprecated", name));
msg.warn("please see https://github.com/rust-lang/rust/issues/44136");

if name == "no_default_passes" {
msg.help("you may want to use `#![doc(document_private_items)]`");
}

msg.emit();
}

// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
let name = attr.name().map(|s| s.as_str());
let name = name.as_ref().map(|s| &s[..]);
if attr.is_word() {
if name == Some("no_default_passes") {
report_deprecated_attr("no_default_passes", &diag);
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::None;
}
}
} else if let Some(value) = attr.value_str() {
let sink = match name {
Some("passes") => {
report_deprecated_attr("passes = \"...\"", &diag);
&mut manual_passes
},
Some("plugins") => {
report_deprecated_attr("plugins = \"...\"", &diag);
&mut plugins
},
_ => continue,
};
sink.extend(value.as_str().split_whitespace().map(|p| p.to_string()));
}

if attr.is_word() && name == Some("document_private_items") {
if default_passes == passes::DefaultPassOption::Default {
default_passes = passes::DefaultPassOption::Private;
}
}
}

let mut passes: Vec<String> =
passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
passes.extend(manual_passes);

if !plugins.is_empty() {
eprintln!("WARNING: --plugins no longer functions; see CVE-2018-1000622");
}
Expand All @@ -751,8 +698,13 @@ where R: 'static + Send,

for pass in &passes {
// determine if we know about this pass
let pass = match passes::PASSES.iter().find(|(p, ..)| p == pass) {
Some(pass) => pass.1,
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);

Expand Down
5 changes: 5 additions & 0 deletions src/librustdoc/passes/collapse_docs.rs
Expand Up @@ -11,8 +11,13 @@
use clean::{self, DocFragment, Item};
use fold;
use fold::DocFolder;
use 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");

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum DocFragmentKind {
Sugared,
Expand Down

0 comments on commit 73c7873

Please sign in to comment.