about summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuietMisdreavus <grey@quietmisdreavus.net>2018-07-27 10:22:16 -0500
committerQuietMisdreavus <grey@quietmisdreavus.net>2018-08-04 18:49:57 -0500
commitd3d6f76887921d2e2ac5444790872bd030c1b669 (patch)
tree6ff3d88a0592195c6794794b1d8816bf9a0c8b98
parentaaec1014d8ec2f3e6cc4af20f01697d36e1f737d (diff)
downloadrust-d3d6f76887921d2e2ac5444790872bd030c1b669.tar.gz
rust-d3d6f76887921d2e2ac5444790872bd030c1b669.zip
introduce "early passes" an convert a few over
-rw-r--r--src/librustdoc/core.rs74
-rw-r--r--src/librustdoc/lib.rs66
-rw-r--r--src/librustdoc/passes/mod.rs67
-rw-r--r--src/librustdoc/passes/strip_hidden.rs7
-rw-r--r--src/librustdoc/passes/strip_priv_imports.rs5
-rw-r--r--src/librustdoc/passes/strip_private.rs5
6 files changed, 150 insertions, 74 deletions
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 88faea9514f..f6310417dac 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -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;
@@ -322,7 +323,9 @@ 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.
 
@@ -527,13 +530,76 @@ pub fn run_core(search_paths: SearchPaths,
             };
             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);
+                }
+            }
+
+            (krate, ctxt.renderinfo.into_inner(), passes)
         }), &sess)
     })
 }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f59d3fb68bf..bd7f7386fd1 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -97,8 +97,6 @@ mod visit_lib;
 mod test;
 mod theme;
 
-use clean::AttributesExt;
-
 struct Output {
     krate: clean::Crate,
     renderinfo: html::render::RenderInfo,
@@ -631,7 +629,7 @@ 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
@@ -639,8 +637,8 @@ where R: 'static + Send,
         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();
@@ -674,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");
 
@@ -688,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");
         }
@@ -752,7 +698,7 @@ where R: 'static + Send,
 
         for pass in &passes {
             // determine if we know about this pass
-            let pass = match passes::PASSES.iter().find(|p| p.name() == pass) {
+            let pass = match passes::find_pass(pass) {
                 Some(pass) => if let Some(pass) = pass.late_fn() {
                     pass
                 } else {
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index e3f867d7fb1..329e489f7b7 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -8,12 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Contains information about "passes", used to modify crate information during the documentation
+//! process.
+
 use rustc::hir::def_id::DefId;
 use rustc::middle::privacy::AccessLevels;
 use rustc::util::nodemap::DefIdSet;
 use std::mem;
+use std::fmt;
 
 use clean::{self, GetDefId, Item};
+use core::DocContext;
 use fold;
 use fold::StripItem;
 
@@ -35,41 +40,87 @@ pub use self::unindent_comments::UNINDENT_COMMENTS;
 mod propagate_doc_cfg;
 pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
 
-#[derive(Copy, Clone, Debug)]
+/// Represents a single pass.
+#[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::LatePass { name, .. } => name,
+            Pass::EarlyPass { name, .. } |
+                Pass::LatePass { name, .. } => name,
         }
     }
 
+    /// Returns the description of this pass.
     pub fn description(self) -> &'static str {
         match self {
-            Pass::LatePass { description, .. } => description,
+            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,
         }
     }
 }
 
+/// The full list of passes.
 pub const PASSES: &'static [Pass] = &[
     STRIP_HIDDEN,
     UNINDENT_COMMENTS,
@@ -79,6 +130,7 @@ pub const PASSES: &'static [Pass] = &[
     PROPAGATE_DOC_CFG,
 ];
 
+/// The list of passes run by default.
 pub const DEFAULT_PASSES: &'static [&'static str] = &[
     "strip-hidden",
     "strip-private",
@@ -87,6 +139,7 @@ pub const DEFAULT_PASSES: &'static [&'static str] = &[
     "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] = &[
     "strip-priv-imports",
     "collapse-docs",
@@ -94,6 +147,8 @@ pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
     "propagate-doc-cfg",
 ];
 
+/// A shorthand way to refer to which set of passes to use, based on the presence of
+/// `--no-defaults` or `--document-private-items`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum DefaultPassOption {
     Default,
@@ -101,6 +156,7 @@ pub enum DefaultPassOption {
     None,
 }
 
+/// Returns the given default set of passes.
 pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
     match default_set {
         DefaultPassOption::Default => DEFAULT_PASSES,
@@ -109,6 +165,11 @@ 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()
+}
+
 struct Stripper<'a> {
     retained: &'a mut DefIdSet,
     access_levels: &'a AccessLevels<DefId>,
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 2093da41222..cc0b6fb6d67 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -13,17 +13,18 @@ use std::mem;
 
 use clean::{self, AttributesExt, NestedAttributesExt};
 use clean::Item;
+use core::DocContext;
 use fold;
 use fold::DocFolder;
 use fold::StripItem;
 use passes::{ImplStripper, Pass};
 
 pub const STRIP_HIDDEN: Pass =
-    Pass::late("strip-hidden", strip_hidden,
-               "strips all doc(hidden) items from the output");
+    Pass::early("strip-hidden", strip_hidden,
+                "strips all doc(hidden) items from the output");
 
 /// Strip items marked `#[doc(hidden)]`
-pub fn strip_hidden(krate: clean::Crate) -> clean::Crate {
+pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
     let mut retained = DefIdSet();
 
     // strip all #[doc(hidden)] items
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index 62f8b1092c7..f01c333d742 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -9,12 +9,13 @@
 // except according to those terms.
 
 use clean;
+use core::DocContext;
 use fold::DocFolder;
 use passes::{ImportStripper, Pass};
 
-pub const STRIP_PRIV_IMPORTS: Pass = Pass::late("strip-priv-imports", strip_priv_imports,
+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 fn strip_priv_imports(krate: clean::Crate)  -> clean::Crate {
+pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext)  -> clean::Crate {
     ImportStripper.fold_crate(krate)
 }
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 0011aedd80a..3b17a768ffd 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -11,17 +11,18 @@
 use rustc::util::nodemap::DefIdSet;
 
 use clean;
+use core::DocContext;
 use fold::DocFolder;
 use passes::{ImplStripper, ImportStripper, Stripper, Pass};
 
 pub const STRIP_PRIVATE: Pass =
-    Pass::late("strip-private", strip_private,
+    Pass::early("strip-private", strip_private,
         "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.
-pub fn strip_private(mut krate: clean::Crate) -> clean::Crate {
+pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = DefIdSet();
     let access_levels = krate.access_levels.clone();