]> git.proxmox.com Git - rustc.git/blobdiff - src/librustdoc/config.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustdoc / config.rs
index 0b8d4d6c302f19bc8986c43dafb5d8374fe090c7..eec1ffd75c502202ae2e826e6c2348d1122dbe4f 100644 (file)
@@ -1,4 +1,5 @@
 use std::collections::BTreeMap;
+use std::ffi::OsStr;
 use std::fmt;
 use std::path::PathBuf;
 
@@ -6,10 +7,12 @@ use errors;
 use getopts;
 use rustc::lint::Level;
 use rustc::session;
-use rustc::session::config::{CrateType, parse_crate_types_from_list};
+use rustc::session::config::{
+    build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple,
+    nightly_options,
+};
+use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType};
 use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
-use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
-                             get_cmd_lint_options, host_triple, ExternEntry};
 use rustc::session::search_paths::SearchPath;
 use rustc_driver;
 use rustc_target::spec::TargetTriple;
@@ -18,17 +21,16 @@ use syntax::edition::{Edition, DEFAULT_EDITION};
 use crate::core::new_handler;
 use crate::externalfiles::ExternalHtml;
 use crate::html;
-use crate::html::{static_files};
-use crate::html::markdown::{IdMap};
+use crate::html::markdown::IdMap;
+use crate::html::static_files;
 use crate::opts;
-use crate::passes::{self, DefaultPassOption};
+use crate::passes::{self, Condition, DefaultPassOption};
 use crate::theme;
 
 /// Configuration options for rustdoc.
 #[derive(Clone)]
 pub struct Options {
     // Basic options / Options passed directly to rustc
-
     /// The crate root or Markdown file to load.
     pub input: PathBuf,
     /// The name of the crate being documented.
@@ -71,7 +73,6 @@ pub struct Options {
     pub lint_cap: Option<Level>,
 
     // Options specific to running doctests
-
     /// Whether we should run doctests instead of generating docs.
     pub should_test: bool,
     /// List of arguments to pass to the test harness, if running tests.
@@ -93,11 +94,14 @@ pub struct Options {
     pub test_builder: Option<PathBuf>,
 
     // Options that affect the documentation process
-
     /// The selected default set of passes to use.
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
     pub default_passes: DefaultPassOption,
+    /// Document items that have lower than `pub` visibility.
+    pub document_private: bool,
+    /// Document items that have `doc(hidden)`.
+    pub document_hidden: bool,
     /// Any passes manually selected by the user.
     ///
     /// Be aware: This option can come both from the CLI and from crate attributes!
@@ -110,7 +114,6 @@ pub struct Options {
     pub show_coverage: bool,
 
     // Options that alter generated documentation pages
-
     /// Crate version to note on the sidebar of generated docs.
     pub crate_version: Option<String>,
     /// Collected options specific to outputting final pages.
@@ -123,9 +126,7 @@ impl fmt::Debug for Options {
 
         impl<'a> fmt::Debug for FmtExterns<'a> {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                f.debug_map()
-                    .entries(self.0.iter())
-                    .finish()
+                f.debug_map().entries(self.0.iter()).finish()
             }
         }
 
@@ -149,6 +150,8 @@ impl fmt::Debug for Options {
             .field("test_args", &self.test_args)
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
+            .field("document_private", &self.document_private)
+            .field("document_hidden", &self.document_hidden)
             .field("manual_passes", &self.manual_passes)
             .field("display_warnings", &self.display_warnings)
             .field("show_coverage", &self.show_coverage)
@@ -207,7 +210,6 @@ pub struct RenderOptions {
     pub static_root_path: Option<String>,
 
     // Options specific to reading standalone Markdown files
-
     /// Whether to generate a table of contents on the output file when reading a standalone
     /// Markdown file.
     pub markdown_no_toc: bool,
@@ -244,22 +246,26 @@ impl Options {
                 println!("{:>20} - {}", pass.name, pass.description);
             }
             println!("\nDefault passes for rustdoc:");
-            for pass in passes::DEFAULT_PASSES {
-                println!("{:>20}", pass.name);
-            }
-            println!("\nPasses run with `--document-private-items`:");
-            for pass in passes::DEFAULT_PRIVATE_PASSES {
-                println!("{:>20}", pass.name);
+            for p in passes::DEFAULT_PASSES {
+                print!("{:>20}", p.pass.name);
+                println_condition(p.condition);
             }
 
             if nightly_options::is_nightly_build() {
                 println!("\nPasses run with `--show-coverage`:");
-                for pass in passes::DEFAULT_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+                for p in passes::COVERAGE_PASSES {
+                    print!("{:>20}", p.pass.name);
+                    println_condition(p.condition);
                 }
-                println!("\nPasses run with `--show-coverage --document-private-items`:");
-                for pass in passes::PRIVATE_COVERAGE_PASSES {
-                    println!("{:>20}", pass.name);
+            }
+
+            fn println_condition(condition: Condition) {
+                use Condition::*;
+                match condition {
+                    Always => println!(),
+                    WhenDocumentPrivate => println!("  (when --document-private-items)"),
+                    WhenNotDocumentPrivate => println!("  (when not --document-private-items)"),
+                    WhenNotDocumentHidden => println!("  (when not --document-hidden-items)"),
                 }
             }
 
@@ -273,20 +279,22 @@ impl Options {
         let codegen_options = build_codegen_options(matches, error_format);
         let debugging_options = build_debugging_options(matches, error_format);
 
-        let diag = new_handler(error_format,
-                               None,
-                               debugging_options.treat_err_as_bug,
-                               debugging_options.ui_testing);
+        let diag = new_handler(
+            error_format,
+            None,
+            debugging_options.treat_err_as_bug,
+            debugging_options.ui_testing,
+        );
 
         // check for deprecated options
         check_deprecated_options(&matches, &diag);
 
-        let to_check = matches.opt_strs("theme-checker");
+        let to_check = matches.opt_strs("check-theme");
         if !to_check.is_empty() {
             let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
             let mut errors = 0;
 
-            println!("rustdoc: [theme-checker] Starting tests!");
+            println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)");
             for theme_file in to_check.iter() {
                 print!(" - Checking \"{}\"...", theme_file);
                 let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag);
@@ -316,16 +324,12 @@ impl Options {
         }
         let input = PathBuf::from(&matches.free[0]);
 
-        let libs = matches.opt_strs("L").iter()
+        let libs = matches
+            .opt_strs("L")
+            .iter()
             .map(|s| SearchPath::from_cli_opt(s, error_format))
             .collect();
-        let externs = match parse_externs(&matches) {
-            Ok(ex) => ex,
-            Err(err) => {
-                diag.struct_err(&err).emit();
-                return Err(1);
-            }
-        };
+        let externs = parse_externs(&matches, &debugging_options, error_format);
         let extern_html_root_urls = match parse_extern_html_roots(&matches) {
             Ok(ex) => ex,
             Err(err) => {
@@ -335,16 +339,13 @@ impl Options {
         };
 
         let test_args = matches.opt_strs("test-args");
-        let test_args: Vec<String> = test_args.iter()
-                                              .flat_map(|s| s.split_whitespace())
-                                              .map(|s| s.to_string())
-                                              .collect();
+        let test_args: Vec<String> =
+            test_args.iter().flat_map(|s| s.split_whitespace()).map(|s| s.to_string()).collect();
 
         let should_test = matches.opt_present("test");
 
-        let output = matches.opt_str("o")
-                            .map(|s| PathBuf::from(&s))
-                            .unwrap_or_else(|| PathBuf::from("doc"));
+        let output =
+            matches.opt_str("o").map(|s| PathBuf::from(&s)).unwrap_or_else(|| PathBuf::from("doc"));
         let cfgs = matches.opt_strs("cfg");
 
         let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
@@ -357,22 +358,39 @@ impl Options {
         }
 
         let mut themes = Vec::new();
-        if matches.opt_present("themes") {
+        if matches.opt_present("theme") {
             let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
 
-            for (theme_file, theme_s) in matches.opt_strs("themes")
-                                                .iter()
-                                                .map(|s| (PathBuf::from(&s), s.to_owned())) {
+            for (theme_file, theme_s) in
+                matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned()))
+            {
                 if !theme_file.is_file() {
-                    diag.struct_err("option --themes arguments must all be files").emit();
+                    diag.struct_err(&format!("invalid argument: \"{}\"", theme_s))
+                        .help("arguments to --theme must be files")
+                        .emit();
+                    return Err(1);
+                }
+                if theme_file.extension() != Some(OsStr::new("css")) {
+                    diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)).emit();
                     return Err(1);
                 }
                 let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
-                if !success || !ret.is_empty() {
-                    diag.struct_err(&format!("invalid theme: \"{}\"", theme_s))
-                        .help("check what's wrong with the --theme-checker option")
-                        .emit();
+                if !success {
+                    diag.struct_err(&format!("error loading theme file: \"{}\"", theme_s)).emit();
                     return Err(1);
+                } else if !ret.is_empty() {
+                    diag.struct_warn(&format!(
+                        "theme file \"{}\" is missing CSS rules from the \
+                                               default theme",
+                        theme_s
+                    ))
+                    .warn("the theme may appear incorrect when loaded")
+                    .help(&format!(
+                        "to see what rules are missing, call `rustdoc \
+                                        --check-theme \"{}\"`",
+                        theme_s
+                    ))
+                    .emit();
                 }
                 themes.push(theme_file);
             }
@@ -393,12 +411,16 @@ impl Options {
         let mut id_map = html::markdown::IdMap::new();
         id_map.populate(html::render::initial_ids());
         let external_html = match ExternalHtml::load(
-                &matches.opt_strs("html-in-header"),
-                &matches.opt_strs("html-before-content"),
-                &matches.opt_strs("html-after-content"),
-                &matches.opt_strs("markdown-before-content"),
-                &matches.opt_strs("markdown-after-content"),
-                &diag, &mut id_map, edition, &None) {
+            &matches.opt_strs("html-in-header"),
+            &matches.opt_strs("html-before-content"),
+            &matches.opt_strs("html-after-content"),
+            &matches.opt_strs("markdown-before-content"),
+            &matches.opt_strs("markdown-after-content"),
+            &diag,
+            &mut id_map,
+            edition,
+            &None,
+        ) {
             Some(eh) => eh,
             None => return Err(3),
         };
@@ -427,27 +449,21 @@ impl Options {
             }
         }
 
-        let target = matches.opt_str("target").map_or(
-            TargetTriple::from_triple(host_triple()),
-            |target| {
-            if target.ends_with(".json") {
-                TargetTriple::TargetPath(PathBuf::from(target))
-            } else {
-                TargetTriple::TargetTriple(target)
-            }
-        });
+        let target =
+            matches.opt_str("target").map_or(TargetTriple::from_triple(host_triple()), |target| {
+                if target.ends_with(".json") {
+                    TargetTriple::TargetPath(PathBuf::from(target))
+                } else {
+                    TargetTriple::TargetTriple(target)
+                }
+            });
 
         let show_coverage = matches.opt_present("show-coverage");
-        let document_private = matches.opt_present("document-private-items");
 
         let default_passes = if matches.opt_present("no-defaults") {
             passes::DefaultPassOption::None
-        } else if show_coverage && document_private {
-            passes::DefaultPassOption::PrivateCoverage
         } else if show_coverage {
             passes::DefaultPassOption::Coverage
-        } else if document_private {
-            passes::DefaultPassOption::Private
         } else {
             passes::DefaultPassOption::Default
         };
@@ -455,7 +471,7 @@ impl Options {
 
         let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
             Ok(types) => types,
-            Err(e) =>{
+            Err(e) => {
                 diag.struct_err(&format!("unknown crate type: {}", e)).emit();
                 return Err(1);
             }
@@ -486,6 +502,8 @@ impl Options {
         let runtool = matches.opt_str("runtool");
         let runtool_args = matches.opt_strs("runtool-arg");
         let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores");
+        let document_private = matches.opt_present("document-private-items");
+        let document_hidden = matches.opt_present("document-hidden-items");
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -512,6 +530,8 @@ impl Options {
             should_test,
             test_args,
             default_passes,
+            document_private,
+            document_hidden,
             manual_passes,
             display_warnings,
             show_coverage,
@@ -540,30 +560,24 @@ impl Options {
                 markdown_playground_url,
                 generate_search_filter,
                 generate_redirect_pages,
-            }
+            },
         })
     }
 
     /// Returns `true` if the file given as `self.input` is a Markdown file.
     pub fn markdown_input(&self) -> bool {
-        self.input.extension()
-            .map_or(false, |e| e == "md" || e == "markdown")
+        self.input.extension().map_or(false, |e| e == "md" || e == "markdown")
     }
 }
 
 /// Prints deprecation warnings for deprecated options
 fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
-    let deprecated_flags = [
-       "input-format",
-       "output-format",
-       "no-defaults",
-       "passes",
-    ];
+    let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"];
 
     for flag in deprecated_flags.iter() {
         if matches.opt_present(flag) {
-            let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated",
-                                                    flag));
+            let mut err =
+                diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag));
             err.warn("please see https://github.com/rust-lang/rust/issues/44136");
 
             if *flag == "no-defaults" {
@@ -574,10 +588,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler)
         }
     }
 
-    let removed_flags = [
-        "plugins",
-        "plugin-path",
-    ];
+    let removed_flags = ["plugins", "plugin-path"];
 
     for &flag in removed_flags.iter() {
         if matches.opt_present(flag) {
@@ -604,26 +615,3 @@ fn parse_extern_html_roots(
 
     Ok(externs)
 }
-
-/// Extracts `--extern CRATE=PATH` arguments from `matches` and
-/// returns a map mapping crate names to their paths or else an
-/// error message.
-// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`.
-fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
-    let mut externs: BTreeMap<_, ExternEntry> = BTreeMap::new();
-    for arg in &matches.opt_strs("extern") {
-        let mut parts = arg.splitn(2, '=');
-        let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
-        let location = parts.next().map(|s| s.to_string());
-        if location.is_none() && !nightly_options::is_unstable_enabled(matches) {
-            return Err("the `-Z unstable-options` flag must also be passed to \
-                        enable `--extern crate_name` without `=path`".to_string());
-        }
-        let name = name.to_string();
-        // For Rustdoc purposes, we can treat all externs as public
-        externs.entry(name)
-            .or_default()
-            .locations.insert(location.clone());
-    }
-    Ok(Externs::new(externs))
-}