use std::collections::BTreeMap;
+use std::ffi::OsStr;
use std::fmt;
use std::path::PathBuf;
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;
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.
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.
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!
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.
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()
}
}
.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)
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,
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)"),
}
}
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);
}
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) => {
};
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));
}
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);
}
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),
};
}
}
- 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
};
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);
}
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);
should_test,
test_args,
default_passes,
+ document_private,
+ document_hidden,
manual_passes,
display_warnings,
show_coverage,
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" {
}
}
- let removed_flags = [
- "plugins",
- "plugin-path",
- ];
+ let removed_flags = ["plugins", "plugin-path"];
for &flag in removed_flags.iter() {
if matches.opt_present(flag) {
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))
-}