2020-12-31 23:25:30 -05:00
use std ::collections ::BTreeMap ;
2019-11-16 16:12:09 +01:00
use std ::convert ::TryFrom ;
2020-02-17 13:53:27 +01:00
use std ::ffi ::OsStr ;
2018-11-04 16:39:24 -06:00
use std ::fmt ;
2018-10-30 08:47:54 -05:00
use std ::path ::PathBuf ;
2021-03-25 12:46:35 -04:00
use std ::str ::FromStr ;
2018-10-30 08:47:54 -05:00
2021-02-12 00:03:24 -05:00
use rustc_data_structures ::fx ::FxHashMap ;
2021-05-16 15:35:10 +02:00
use rustc_session ::config ::{
self , parse_crate_types_from_list , parse_externs , parse_target_triple , CrateType ,
} ;
use rustc_session ::config ::{ get_cmd_lint_options , nightly_options } ;
2020-03-11 12:49:08 +01:00
use rustc_session ::config ::{ CodegenOptions , DebuggingOptions , ErrorOutputType , Externs } ;
2020-04-10 22:42:19 +02:00
use rustc_session ::getopts ;
2020-03-11 12:49:08 +01:00
use rustc_session ::lint ::Level ;
use rustc_session ::search_paths ::SearchPath ;
2021-02-16 19:17:01 -08:00
use rustc_span ::edition ::Edition ;
2018-10-30 08:47:54 -05:00
use rustc_target ::spec ::TargetTriple ;
2019-02-23 16:40:07 +09:00
use crate ::core ::new_handler ;
use crate ::externalfiles ::ExternalHtml ;
use crate ::html ;
2019-12-22 17:42:04 -05:00
use crate ::html ::markdown ::IdMap ;
2020-07-12 14:37:22 -04:00
use crate ::html ::render ::StylePath ;
2019-12-22 17:42:04 -05:00
use crate ::html ::static_files ;
2019-02-23 16:40:07 +09:00
use crate ::opts ;
2020-01-04 10:58:32 -08:00
use crate ::passes ::{ self , Condition , DefaultPassOption } ;
2019-02-23 16:40:07 +09:00
use crate ::theme ;
2018-10-30 08:47:54 -05:00
2019-11-16 16:12:09 +01:00
#[ derive(Clone, Copy, PartialEq, Eq, Debug) ]
2020-11-14 17:59:58 -05:00
crate enum OutputFormat {
2019-11-16 16:12:09 +01:00
Json ,
2020-02-17 13:53:27 +01:00
Html ,
2019-11-16 16:12:09 +01:00
}
2021-01-28 18:00:07 -08:00
impl Default for OutputFormat {
fn default ( ) -> OutputFormat {
OutputFormat ::Html
}
}
2019-11-16 16:12:09 +01:00
impl OutputFormat {
2020-11-14 17:59:58 -05:00
crate fn is_json ( & self ) -> bool {
2020-12-31 02:49:44 +01:00
matches! ( self , OutputFormat ::Json )
2019-11-16 16:12:09 +01:00
}
}
impl TryFrom < & str > for OutputFormat {
type Error = String ;
fn try_from ( value : & str ) -> Result < Self , Self ::Error > {
match value {
" json " = > Ok ( OutputFormat ::Json ) ,
2020-02-17 13:53:27 +01:00
" html " = > Ok ( OutputFormat ::Html ) ,
2019-11-16 16:12:09 +01:00
_ = > Err ( format! ( " unknown output format ` {} ` " , value ) ) ,
}
}
}
2018-10-30 10:53:46 -05:00
/// Configuration options for rustdoc.
2018-10-30 10:20:58 -05:00
#[ derive(Clone) ]
2020-11-14 17:59:58 -05:00
crate struct Options {
2018-10-30 08:47:54 -05:00
// Basic options / Options passed directly to rustc
/// The crate root or Markdown file to load.
2020-11-14 17:59:58 -05:00
crate input : PathBuf ,
2018-10-30 08:47:54 -05:00
/// The name of the crate being documented.
2020-11-14 17:59:58 -05:00
crate crate_name : Option < String > ,
2019-07-20 16:34:41 -04:00
/// Whether or not this is a proc-macro crate
2020-11-14 17:59:58 -05:00
crate proc_macro_crate : bool ,
2018-10-30 08:47:54 -05:00
/// How to format errors and warnings.
2020-11-14 17:59:58 -05:00
crate error_format : ErrorOutputType ,
2018-10-30 08:47:54 -05:00
/// Library search paths to hand to the compiler.
2020-11-14 17:59:58 -05:00
crate libs : Vec < SearchPath > ,
2019-08-29 23:15:31 +02:00
/// Library search paths strings to hand to the compiler.
2020-11-14 17:59:58 -05:00
crate lib_strs : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// The list of external crates to link against.
2020-11-14 17:59:58 -05:00
crate externs : Externs ,
2019-08-29 23:15:31 +02:00
/// The list of external crates strings to link against.
2020-11-14 17:59:58 -05:00
crate extern_strs : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`.
2020-11-14 17:59:58 -05:00
crate cfgs : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// Codegen options to hand to the compiler.
2020-11-14 17:59:58 -05:00
crate codegen_options : CodegenOptions ,
2019-08-29 23:15:31 +02:00
/// Codegen options strings to hand to the compiler.
2020-11-14 17:59:58 -05:00
crate codegen_options_strs : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// Debugging (`-Z`) options to pass to the compiler.
2020-11-14 17:59:58 -05:00
crate debugging_opts : DebuggingOptions ,
2019-10-11 00:00:00 +00:00
/// Debugging (`-Z`) options strings to pass to the compiler.
2020-11-14 17:59:58 -05:00
crate debugging_opts_strs : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// The target used to compile the crate against.
2020-11-14 17:59:58 -05:00
crate target : TargetTriple ,
2018-10-30 08:47:54 -05:00
/// Edition used when reading the crate. Defaults to "2015". Also used by default when
/// compiling doctests from the crate.
2020-11-14 17:59:58 -05:00
crate edition : Edition ,
2018-10-30 08:47:54 -05:00
/// The path to the sysroot. Used during the compilation process.
2020-11-14 17:59:58 -05:00
crate maybe_sysroot : Option < PathBuf > ,
2018-10-30 08:47:54 -05:00
/// Lint information passed over the command-line.
2020-11-14 17:59:58 -05:00
crate lint_opts : Vec < ( String , Level ) > ,
2021-04-06 02:09:43 +01:00
/// Whether to ask rustc to describe the lints it knows.
2020-11-14 17:59:58 -05:00
crate describe_lints : bool ,
2018-10-30 08:47:54 -05:00
/// What level to cap lints at.
2020-11-14 17:59:58 -05:00
crate lint_cap : Option < Level > ,
2018-10-30 08:47:54 -05:00
// Options specific to running doctests
/// Whether we should run doctests instead of generating docs.
2020-11-14 17:59:58 -05:00
crate should_test : bool ,
2018-10-30 08:47:54 -05:00
/// List of arguments to pass to the test harness, if running tests.
2020-11-14 17:59:58 -05:00
crate test_args : Vec < String > ,
2021-01-22 10:54:53 +01:00
/// The working directory in which to run tests.
crate test_run_directory : Option < PathBuf > ,
2018-12-31 18:05:57 -05:00
/// Optional path to persist the doctest executables to, defaults to a
/// temporary directory if not set.
2020-11-14 17:59:58 -05:00
crate persist_doctests : Option < PathBuf > ,
2019-04-26 13:52:56 -07:00
/// Runtool to run doctests with
2020-11-14 17:59:58 -05:00
crate runtool : Option < String > ,
2019-04-26 13:52:56 -07:00
/// Arguments to pass to the runtool
2020-11-14 17:59:58 -05:00
crate runtool_args : Vec < String > ,
2019-06-06 16:01:53 -07:00
/// Whether to allow ignoring doctests on a per-target basis
/// For example, using ignore-foo to ignore running the doctest on any target that
/// contains "foo" as a substring
2020-11-14 17:59:58 -05:00
crate enable_per_target_ignores : bool ,
2021-04-07 15:45:40 +02:00
/// Do not run doctests, compile them if should_test is active.
2021-04-04 16:53:59 +02:00
crate no_run : bool ,
2018-10-30 08:47:54 -05:00
2019-09-09 21:11:27 -04:00
/// The path to a rustc-like binary to build tests with. If not set, we
2021-01-28 18:00:07 -08:00
/// default to loading from `$sysroot/bin/rustc`.
2020-11-14 17:59:58 -05:00
crate test_builder : Option < PathBuf > ,
2019-09-09 21:11:27 -04:00
2018-10-30 08:47:54 -05:00
// 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!
2020-11-14 17:59:58 -05:00
crate default_passes : DefaultPassOption ,
2018-10-30 08:47:54 -05:00
/// Any passes manually selected by the user.
///
/// Be aware: This option can come both from the CLI and from crate attributes!
2020-11-14 17:59:58 -05:00
crate manual_passes : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// Whether to display warnings during doc generation or while gathering doctests. By default,
/// all non-rustdoc-specific lints are allowed when generating docs.
2020-11-14 17:59:58 -05:00
crate display_warnings : bool ,
2019-01-30 14:04:56 -06:00
/// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
/// with and without documentation.
2020-11-14 17:59:58 -05:00
crate show_coverage : bool ,
2018-10-30 08:47:54 -05:00
// Options that alter generated documentation pages
2018-10-30 10:53:46 -05:00
/// Crate version to note on the sidebar of generated docs.
2020-11-14 17:59:58 -05:00
crate crate_version : Option < String > ,
2018-10-30 10:53:46 -05:00
/// Collected options specific to outputting final pages.
2020-11-14 17:59:58 -05:00
crate render_options : RenderOptions ,
2021-01-28 18:00:07 -08:00
/// The format that we output when rendering.
///
/// Currently used only for the `--show-coverage` option.
crate output_format : OutputFormat ,
2020-11-12 14:57:44 +01:00
/// If this option is set to `true`, rustdoc will only run checks and not generate
/// documentation.
2020-11-14 17:59:58 -05:00
crate run_check : bool ,
2020-08-01 12:57:35 +02:00
/// Whether doctests should emit unused externs
crate json_unused_externs : bool ,
2018-10-30 10:53:46 -05:00
}
2018-11-04 16:39:24 -06:00
impl fmt ::Debug for Options {
2019-02-23 16:40:07 +09:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2018-11-04 16:39:24 -06:00
struct FmtExterns < ' a > ( & ' a Externs ) ;
impl < ' a > fmt ::Debug for FmtExterns < ' a > {
2019-02-23 16:40:07 +09:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2019-12-22 17:42:04 -05:00
f . debug_map ( ) . entries ( self . 0. iter ( ) ) . finish ( )
2018-11-04 16:39:24 -06:00
}
}
f . debug_struct ( " Options " )
. field ( " input " , & self . input )
. field ( " crate_name " , & self . crate_name )
2019-07-20 16:34:41 -04:00
. field ( " proc_macro_crate " , & self . proc_macro_crate )
2018-11-04 16:39:24 -06:00
. field ( " error_format " , & self . error_format )
. field ( " libs " , & self . libs )
. field ( " externs " , & FmtExterns ( & self . externs ) )
. field ( " cfgs " , & self . cfgs )
. field ( " codegen_options " , & " ... " )
. field ( " debugging_options " , & " ... " )
. field ( " target " , & self . target )
. field ( " edition " , & self . edition )
. field ( " maybe_sysroot " , & self . maybe_sysroot )
. field ( " lint_opts " , & self . lint_opts )
. field ( " describe_lints " , & self . describe_lints )
. field ( " lint_cap " , & self . lint_cap )
. field ( " should_test " , & self . should_test )
. field ( " test_args " , & self . test_args )
2021-01-22 10:54:53 +01:00
. field ( " test_run_directory " , & self . test_run_directory )
2018-12-16 17:31:36 -05:00
. field ( " persist_doctests " , & self . persist_doctests )
2018-11-04 16:39:24 -06:00
. field ( " default_passes " , & self . default_passes )
. field ( " manual_passes " , & self . manual_passes )
. field ( " display_warnings " , & self . display_warnings )
2019-01-30 14:04:56 -06:00
. field ( " show_coverage " , & self . show_coverage )
2018-11-04 16:39:24 -06:00
. field ( " crate_version " , & self . crate_version )
. field ( " render_options " , & self . render_options )
2019-04-26 13:52:56 -07:00
. field ( " runtool " , & self . runtool )
. field ( " runtool_args " , & self . runtool_args )
2019-06-06 16:01:53 -07:00
. field ( " enable-per-target-ignores " , & self . enable_per_target_ignores )
2020-11-12 14:57:44 +01:00
. field ( " run_check " , & self . run_check )
2021-04-04 16:53:59 +02:00
. field ( " no_run " , & self . no_run )
2018-11-04 16:39:24 -06:00
. finish ( )
}
}
2018-10-30 10:53:46 -05:00
/// Configuration options for the HTML page-creation process.
2018-11-04 16:39:24 -06:00
#[ derive(Clone, Debug) ]
2020-11-14 17:59:58 -05:00
crate struct RenderOptions {
2018-10-30 10:53:46 -05:00
/// Output directory to generate docs into. Defaults to `doc`.
2020-11-14 17:59:58 -05:00
crate output : PathBuf ,
2018-10-30 08:47:54 -05:00
/// External files to insert into generated pages.
2020-11-14 17:59:58 -05:00
crate external_html : ExternalHtml ,
2018-10-30 10:53:46 -05:00
/// A pre-populated `IdMap` with the default headings and any headings added by Markdown files
/// processed by `external_html`.
2020-11-14 17:59:58 -05:00
crate id_map : IdMap ,
2018-10-30 08:47:54 -05:00
/// If present, playground URL to use in the "Run" button added to code samples.
///
/// Be aware: This option can come both from the CLI and from crate attributes!
2020-11-14 17:59:58 -05:00
crate playground_url : Option < String > ,
2018-10-30 08:47:54 -05:00
/// Whether to sort modules alphabetically on a module page instead of using declaration order.
/// `true` by default.
2019-02-08 14:53:55 +01:00
//
// FIXME(misdreavus): the flag name is `--sort-modules-by-appearance` but the meaning is
// inverted once read.
2020-11-14 17:59:58 -05:00
crate sort_modules_alphabetically : bool ,
2018-10-30 08:47:54 -05:00
/// List of themes to extend the docs with. Original argument name is included to assist in
/// displaying errors if it fails a theme check.
2020-11-14 17:59:58 -05:00
crate themes : Vec < StylePath > ,
2018-10-30 08:47:54 -05:00
/// If present, CSS file that contains rules to add to the default CSS.
2020-11-14 17:59:58 -05:00
crate extension_css : Option < PathBuf > ,
2018-10-30 08:47:54 -05:00
/// A map of crate names to the URL to use instead of querying the crate's `html_root_url`.
2020-11-14 17:59:58 -05:00
crate extern_html_root_urls : BTreeMap < String , String > ,
2020-10-28 20:12:15 +00:00
/// A map of the default settings (values are as for DOM storage API). Keys should lack the
2020-09-23 22:44:54 +01:00
/// `rustdoc-` prefix.
2020-12-31 23:25:30 -05:00
crate default_settings : FxHashMap < String , String > ,
2018-10-30 08:47:54 -05:00
/// If present, suffix added to CSS/JavaScript files when referencing them in generated pages.
2020-11-14 17:59:58 -05:00
crate resource_suffix : String ,
2018-10-30 08:47:54 -05:00
/// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by
/// default.
2019-02-08 14:53:55 +01:00
//
// FIXME(misdreavus): the flag name is `--disable-minification` but the meaning is inverted
// once read.
2020-11-14 17:59:58 -05:00
crate enable_minification : bool ,
2018-10-30 08:47:54 -05:00
/// Whether to create an index page in the root of the output directory. If this is true but
/// `enable_index_page` is None, generate a static listing of crates instead.
2020-11-14 17:59:58 -05:00
crate enable_index_page : bool ,
2018-10-30 08:47:54 -05:00
/// A file to use as the index page at the root of the output directory. Overrides
/// `enable_index_page` to be true if set.
2020-11-14 17:59:58 -05:00
crate index_page : Option < PathBuf > ,
2018-12-20 10:18:45 -06:00
/// An optional path to use as the location of static files. If not set, uses combinations of
/// `../` to reach the documentation root.
2020-11-14 17:59:58 -05:00
crate static_root_path : Option < String > ,
2018-10-30 08:47:54 -05:00
// Options specific to reading standalone Markdown files
/// Whether to generate a table of contents on the output file when reading a standalone
/// Markdown file.
2020-11-14 17:59:58 -05:00
crate markdown_no_toc : bool ,
2018-11-12 13:05:20 -05:00
/// Additional CSS files to link in pages generated from standalone Markdown files.
2020-11-14 17:59:58 -05:00
crate markdown_css : Vec < String > ,
2018-10-30 08:47:54 -05:00
/// If present, playground URL to use in the "Run" button added to code samples generated from
/// standalone Markdown files. If not present, `playground_url` is used.
2020-11-14 17:59:58 -05:00
crate markdown_playground_url : Option < String > ,
2018-12-20 13:28:55 +01:00
/// If false, the `select` element to have search filtering by crates on rendered docs
/// won't be generated.
2020-11-14 17:59:58 -05:00
crate generate_search_filter : bool ,
2020-05-30 11:35:35 -04:00
/// Document items that have lower than `pub` visibility.
2020-11-14 17:59:58 -05:00
crate document_private : bool ,
2020-05-30 11:35:35 -04:00
/// Document items that have `doc(hidden)`.
2020-11-14 17:59:58 -05:00
crate document_hidden : bool ,
2021-01-20 20:56:47 +01:00
/// If `true`, generate a JSON file in the crate folder instead of HTML redirection files.
crate generate_redirect_map : bool ,
2021-04-12 19:42:26 -07:00
/// Show the memory layout of types in the docs.
crate show_type_layout : bool ,
2020-11-14 17:59:58 -05:00
crate unstable_features : rustc_feature ::UnstableFeatures ,
2021-03-25 12:46:35 -04:00
crate emit : Vec < EmitType > ,
}
#[ derive(Copy, Clone, Debug, PartialEq, Eq) ]
crate enum EmitType {
Unversioned ,
Toolchain ,
2021-03-31 11:35:57 -04:00
InvocationSpecific ,
2021-03-25 12:46:35 -04:00
}
impl FromStr for EmitType {
type Err = ( ) ;
fn from_str ( s : & str ) -> Result < Self , Self ::Err > {
use EmitType ::* ;
match s {
" unversioned-shared-resources " = > Ok ( Unversioned ) ,
" toolchain-shared-resources " = > Ok ( Toolchain ) ,
2021-03-31 11:35:57 -04:00
" invocation-specific " = > Ok ( InvocationSpecific ) ,
2021-03-25 12:46:35 -04:00
_ = > Err ( ( ) ) ,
}
}
}
impl RenderOptions {
crate fn should_emit_crate ( & self ) -> bool {
2021-03-31 11:35:57 -04:00
self . emit . is_empty ( ) | | self . emit . contains ( & EmitType ::InvocationSpecific )
2021-03-25 12:46:35 -04:00
}
2018-10-30 08:47:54 -05:00
}
impl Options {
/// Parses the given command-line for options. If an error message or other early-return has
/// been printed, returns `Err` with the exit code.
2020-11-14 17:59:58 -05:00
crate fn from_matches ( matches : & getopts ::Matches ) -> Result < Options , i32 > {
2018-10-30 08:47:54 -05:00
// Check for unstable options.
nightly_options ::check_nightly_options ( & matches , & opts ( ) ) ;
if matches . opt_present ( " h " ) | | matches . opt_present ( " help " ) {
2019-02-23 16:40:07 +09:00
crate ::usage ( " rustdoc " ) ;
2018-10-30 08:47:54 -05:00
return Err ( 0 ) ;
} else if matches . opt_present ( " version " ) {
rustc_driver ::version ( " rustdoc " , & matches ) ;
return Err ( 0 ) ;
}
if matches . opt_strs ( " passes " ) = = [ " list " ] {
println! ( " Available passes for running rustdoc: " ) ;
for pass in passes ::PASSES {
2019-02-23 15:10:56 -05:00
println! ( " {:>20} - {} " , pass . name , pass . description ) ;
2018-10-30 08:47:54 -05:00
}
println! ( " \n Default passes for rustdoc: " ) ;
2020-01-04 10:58:32 -08:00
for p in passes ::DEFAULT_PASSES {
print! ( " {:>20} " , p . pass . name ) ;
println_condition ( p . condition ) ;
2018-10-30 08:47:54 -05:00
}
2019-03-05 14:23:37 -06:00
2020-10-10 14:27:52 -04:00
if nightly_options ::match_is_nightly_build ( matches ) {
2019-03-05 14:23:37 -06:00
println! ( " \n Passes run with `--show-coverage`: " ) ;
2020-01-04 10:58:32 -08:00
for p in passes ::COVERAGE_PASSES {
print! ( " {:>20} " , p . pass . name ) ;
println_condition ( p . condition ) ;
2019-03-05 14:23:37 -06:00
}
2020-01-04 10:58:32 -08:00
}
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) " ) ,
2019-03-05 14:23:37 -06:00
}
2019-02-21 11:10:12 -06:00
}
2019-03-05 14:23:37 -06:00
2018-10-30 08:47:54 -05:00
return Err ( 0 ) ;
}
2020-03-11 12:49:08 +01:00
let color = config ::parse_color ( & matches ) ;
2020-08-01 12:57:35 +02:00
let config ::JsonConfig { json_rendered , json_unused_externs , .. } =
config ::parse_json ( & matches ) ;
2020-03-11 12:49:08 +01:00
let error_format = config ::parse_error_format ( & matches , color , json_rendered ) ;
2018-10-30 08:47:54 -05:00
2021-05-07 15:18:19 +03:00
let codegen_options = CodegenOptions ::build ( matches , error_format ) ;
let debugging_opts = DebuggingOptions ::build ( matches , error_format ) ;
2018-10-30 08:47:54 -05:00
2020-08-25 09:22:26 -04:00
let diag = new_handler ( error_format , None , & debugging_opts ) ;
2018-10-30 08:47:54 -05:00
// check for deprecated options
check_deprecated_options ( & matches , & diag ) ;
2021-03-25 12:46:35 -04:00
let mut emit = Vec ::new ( ) ;
for list in matches . opt_strs ( " emit " ) {
for kind in list . split ( ',' ) {
match kind . parse ( ) {
Ok ( kind ) = > emit . push ( kind ) ,
Err ( ( ) ) = > {
diag . err ( & format! ( " unrecognized emission type: {} " , kind ) ) ;
return Err ( 1 ) ;
}
}
}
}
2021-02-24 16:16:49 -05:00
// check for `--output-format=json`
if ! matches! ( matches . opt_str ( " output-format " ) . as_deref ( ) , None | Some ( " html " ) )
& & ! matches . opt_present ( " show-coverage " )
& & ! nightly_options ::is_unstable_enabled ( matches )
{
rustc_session ::early_error (
error_format ,
" the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578) " ,
) ;
}
2019-09-22 22:35:25 +02:00
let to_check = matches . opt_strs ( " check-theme " ) ;
2018-10-30 08:47:54 -05:00
if ! to_check . is_empty ( ) {
2018-11-10 16:05:29 -06:00
let paths = theme ::load_css_paths ( static_files ::themes ::LIGHT . as_bytes ( ) ) ;
2018-10-30 08:47:54 -05:00
let mut errors = 0 ;
2019-09-22 22:35:25 +02:00
println! ( " rustdoc: [check-theme] Starting tests! (Ignoring all other arguments) " ) ;
2018-10-30 08:47:54 -05:00
for theme_file in to_check . iter ( ) {
print! ( " - Checking \" {} \" ... " , theme_file ) ;
let ( success , differences ) = theme ::test_theme_against ( theme_file , & paths , & diag ) ;
if ! differences . is_empty ( ) | | ! success {
println! ( " FAILED " ) ;
errors + = 1 ;
if ! differences . is_empty ( ) {
println! ( " {} " , differences . join ( " \n " ) ) ;
}
} else {
println! ( " OK " ) ;
}
}
if errors ! = 0 {
return Err ( 1 ) ;
}
return Err ( 0 ) ;
}
if matches . free . is_empty ( ) {
diag . struct_err ( " missing file operand " ) . emit ( ) ;
return Err ( 1 ) ;
}
if matches . free . len ( ) > 1 {
diag . struct_err ( " too many file operands " ) . emit ( ) ;
return Err ( 1 ) ;
}
let input = PathBuf ::from ( & matches . free [ 0 ] ) ;
2019-12-22 17:42:04 -05:00
let libs = matches
. opt_strs ( " L " )
. iter ( )
2018-11-22 16:33:07 +11:00
. map ( | s | SearchPath ::from_cli_opt ( s , error_format ) )
. collect ( ) ;
2020-08-25 09:22:26 -04:00
let externs = parse_externs ( & matches , & debugging_opts , error_format ) ;
2018-10-30 08:47:54 -05:00
let extern_html_root_urls = match parse_extern_html_roots ( & matches ) {
Ok ( ex ) = > ex ,
Err ( err ) = > {
diag . struct_err ( err ) . emit ( ) ;
return Err ( 1 ) ;
}
} ;
2020-10-28 21:29:21 +00:00
let default_settings : Vec < Vec < ( String , String ) > > = vec! [
2020-10-28 17:53:12 +00:00
matches
. opt_str ( " default-theme " )
. iter ( )
. map ( | theme | {
vec! [
( " use-system-theme " . to_string ( ) , " false " . to_string ( ) ) ,
( " theme " . to_string ( ) , theme . to_string ( ) ) ,
]
} )
. flatten ( )
. collect ( ) ,
2020-10-13 18:52:43 +01:00
matches
. opt_strs ( " default-setting " )
. iter ( )
2020-12-07 14:00:31 -07:00
. map ( | s | match s . split_once ( '=' ) {
None = > ( s . clone ( ) , " true " . to_string ( ) ) ,
Some ( ( k , v ) ) = > ( k . to_string ( ) , v . to_string ( ) ) ,
2020-10-13 18:52:43 +01:00
} )
. collect ( ) ,
] ;
2020-10-28 21:29:21 +00:00
let default_settings = default_settings . into_iter ( ) . flatten ( ) . collect ( ) ;
2020-10-13 18:52:43 +01:00
2018-10-30 08:47:54 -05:00
let test_args = matches . opt_strs ( " test-args " ) ;
2019-12-22 17:42:04 -05:00
let test_args : Vec < String > =
test_args . iter ( ) . flat_map ( | s | s . split_whitespace ( ) ) . map ( | s | s . to_string ( ) ) . collect ( ) ;
2018-10-30 08:47:54 -05:00
let should_test = matches . opt_present ( " test " ) ;
2021-04-30 12:36:22 +02:00
let no_run = matches . opt_present ( " no-run " ) ;
if ! should_test & & no_run {
2021-05-01 11:46:00 +02:00
diag . err ( " the `--test` flag must be passed to enable `--no-run` " ) ;
2021-04-30 12:36:22 +02:00
return Err ( 1 ) ;
}
2018-10-30 08:47:54 -05:00
2019-12-22 17:42:04 -05:00
let output =
matches . opt_str ( " o " ) . map ( | s | PathBuf ::from ( & s ) ) . unwrap_or_else ( | | PathBuf ::from ( " doc " ) ) ;
2019-10-07 23:08:54 +02:00
let cfgs = matches . opt_strs ( " cfg " ) ;
2018-10-30 08:47:54 -05:00
let extension_css = matches . opt_str ( " e " ) . map ( | s | PathBuf ::from ( & s ) ) ;
if let Some ( ref p ) = extension_css {
if ! p . is_file ( ) {
diag . struct_err ( " option --extend-css argument must be a file " ) . emit ( ) ;
return Err ( 1 ) ;
}
}
let mut themes = Vec ::new ( ) ;
2019-09-22 22:35:25 +02:00
if matches . opt_present ( " theme " ) {
2018-11-10 16:05:29 -06:00
let paths = theme ::load_css_paths ( static_files ::themes ::LIGHT . as_bytes ( ) ) ;
2018-10-30 08:47:54 -05:00
2019-12-22 17:42:04 -05:00
for ( theme_file , theme_s ) in
matches . opt_strs ( " theme " ) . iter ( ) . map ( | s | ( PathBuf ::from ( & s ) , s . to_owned ( ) ) )
{
2018-10-30 08:47:54 -05:00
if ! theme_file . is_file ( ) {
2019-10-17 14:26:21 +02:00
diag . struct_err ( & format! ( " invalid argument: \" {} \" " , theme_s ) )
. help ( " arguments to --theme must be files " )
2018-10-01 22:28:12 +02:00
. emit ( ) ;
2018-10-30 08:47:54 -05:00
return Err ( 1 ) ;
}
2019-08-21 15:48:26 +02:00
if theme_file . extension ( ) ! = Some ( OsStr ::new ( " css " ) ) {
2021-03-31 10:27:01 -04:00
diag . struct_err ( & format! ( " invalid argument: \" {} \" " , theme_s ) )
. help ( " arguments to --theme must have a .css extension " )
. emit ( ) ;
2019-08-21 15:48:26 +02:00
return Err ( 1 ) ;
}
2018-10-30 08:47:54 -05:00
let ( success , ret ) = theme ::test_theme_against ( & theme_file , & paths , & diag ) ;
2019-05-24 10:39:49 +02:00
if ! success {
2019-08-21 15:48:26 +02:00
diag . struct_err ( & format! ( " error loading theme file: \" {} \" " , theme_s ) ) . emit ( ) ;
2019-05-24 10:39:49 +02:00
return Err ( 1 ) ;
} else if ! ret . is_empty ( ) {
2019-12-22 17:42:04 -05:00
diag . struct_warn ( & format! (
2020-08-31 13:16:50 +02:00
" theme file \" {} \" is missing CSS rules from the default theme " ,
2019-12-22 17:42:04 -05:00
theme_s
) )
. warn ( " the theme may appear incorrect when loaded " )
. help ( & format! (
2020-08-31 13:16:50 +02:00
" to see what rules are missing, call `rustdoc --check-theme \" {} \" ` " ,
2019-12-22 17:42:04 -05:00
theme_s
) )
. emit ( ) ;
2018-10-30 08:47:54 -05:00
}
2020-07-12 14:37:22 -04:00
themes . push ( StylePath { path : theme_file , disabled : true } ) ;
2018-10-30 08:47:54 -05:00
}
}
2021-02-16 19:17:01 -08:00
let edition = config ::parse_crate_edition ( & matches ) ;
2019-04-17 20:17:12 -05:00
2018-10-30 08:47:54 -05:00
let mut id_map = html ::markdown ::IdMap ::new ( ) ;
let external_html = match ExternalHtml ::load (
2019-12-22 17:42:04 -05:00
& 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 " ) ,
2020-10-10 14:27:52 -04:00
nightly_options ::match_is_nightly_build ( & matches ) ,
2019-12-22 17:42:04 -05:00
& diag ,
& mut id_map ,
edition ,
& None ,
) {
2018-10-30 08:47:54 -05:00
Some ( eh ) = > eh ,
None = > return Err ( 3 ) ,
} ;
Fix clippy warnings
Fixes clippy::{cone_on_copy, filter_next, redundant_closure, single_char_pattern, len_zero,redundant_field_names, useless_format, identity_conversion, map_clone, into_iter_on_ref, needless_return, option_as_ref_deref, unused_unit, unnecessary_mut_passed}
2020-05-11 13:01:37 +02:00
match matches . opt_str ( " r " ) . as_deref ( ) {
2018-10-30 10:20:58 -05:00
Some ( " rust " ) | None = > { }
Some ( s ) = > {
diag . struct_err ( & format! ( " unknown input format: {} " , s ) ) . emit ( ) ;
return Err ( 1 ) ;
}
}
2018-10-30 08:47:54 -05:00
let index_page = matches . opt_str ( " index-page " ) . map ( | s | PathBuf ::from ( & s ) ) ;
if let Some ( ref index_page ) = index_page {
if ! index_page . is_file ( ) {
diag . struct_err ( " option `--index-page` argument must be a file " ) . emit ( ) ;
return Err ( 1 ) ;
}
}
2021-05-16 15:35:10 +02:00
let target = parse_target_triple ( matches , error_format ) ;
2018-10-30 08:47:54 -05:00
2019-02-21 11:10:12 -06:00
let show_coverage = matches . opt_present ( " show-coverage " ) ;
2018-10-30 08:47:54 -05:00
let default_passes = if matches . opt_present ( " no-defaults " ) {
passes ::DefaultPassOption ::None
2019-02-21 11:10:12 -06:00
} else if show_coverage {
2019-01-30 14:04:56 -06:00
passes ::DefaultPassOption ::Coverage
2018-10-30 08:47:54 -05:00
} else {
passes ::DefaultPassOption ::Default
} ;
let manual_passes = matches . opt_strs ( " passes " ) ;
2019-07-20 16:34:41 -04:00
let crate_types = match parse_crate_types_from_list ( matches . opt_strs ( " crate-type " ) ) {
Ok ( types ) = > types ,
2019-12-22 17:42:04 -05:00
Err ( e ) = > {
2019-07-20 16:34:41 -04:00
diag . struct_err ( & format! ( " unknown crate type: {} " , e ) ) . emit ( ) ;
return Err ( 1 ) ;
}
} ;
2019-11-16 16:12:09 +01:00
let output_format = match matches . opt_str ( " output-format " ) {
Some ( s ) = > match OutputFormat ::try_from ( s . as_str ( ) ) {
2021-01-28 18:00:07 -08:00
Ok ( out_fmt ) = > {
2021-02-24 16:16:49 -05:00
if ! out_fmt . is_json ( ) & & show_coverage {
2020-02-17 13:53:27 +01:00
diag . struct_err (
" html output format isn't supported for the --show-coverage option " ,
)
. emit ( ) ;
return Err ( 1 ) ;
2019-11-16 16:12:09 +01:00
}
2021-01-28 18:00:07 -08:00
out_fmt
2019-11-16 16:12:09 +01:00
}
Err ( e ) = > {
diag . struct_err ( & e ) . emit ( ) ;
return Err ( 1 ) ;
}
2020-02-17 13:53:27 +01:00
} ,
2021-01-28 18:00:07 -08:00
None = > OutputFormat ::default ( ) ,
2019-11-16 16:12:09 +01:00
} ;
2018-10-30 08:47:54 -05:00
let crate_name = matches . opt_str ( " crate-name " ) ;
2019-07-20 16:34:41 -04:00
let proc_macro_crate = crate_types . contains ( & CrateType ::ProcMacro ) ;
2018-10-30 08:47:54 -05:00
let playground_url = matches . opt_str ( " playground-url " ) ;
let maybe_sysroot = matches . opt_str ( " sysroot " ) . map ( PathBuf ::from ) ;
let display_warnings = matches . opt_present ( " display-warnings " ) ;
let sort_modules_alphabetically = ! matches . opt_present ( " sort-modules-by-appearance " ) ;
let resource_suffix = matches . opt_str ( " resource-suffix " ) . unwrap_or_default ( ) ;
let enable_minification = ! matches . opt_present ( " disable-minification " ) ;
let markdown_no_toc = matches . opt_present ( " markdown-no-toc " ) ;
let markdown_css = matches . opt_strs ( " markdown-css " ) ;
let markdown_playground_url = matches . opt_str ( " markdown-playground-url " ) ;
let crate_version = matches . opt_str ( " crate-version " ) ;
let enable_index_page = matches . opt_present ( " enable-index-page " ) | | index_page . is_some ( ) ;
2018-12-20 10:18:45 -06:00
let static_root_path = matches . opt_str ( " static-root-path " ) ;
2018-12-20 13:28:55 +01:00
let generate_search_filter = ! matches . opt_present ( " disable-per-crate-search " ) ;
2021-01-22 10:54:53 +01:00
let test_run_directory = matches . opt_str ( " test-run-directory " ) . map ( PathBuf ::from ) ;
2018-12-08 14:17:50 -05:00
let persist_doctests = matches . opt_str ( " persist-doctests " ) . map ( PathBuf ::from ) ;
2019-09-09 21:11:27 -04:00
let test_builder = matches . opt_str ( " test-builder " ) . map ( PathBuf ::from ) ;
2019-08-29 23:15:31 +02:00
let codegen_options_strs = matches . opt_strs ( " C " ) ;
2020-08-25 09:22:26 -04:00
let debugging_opts_strs = matches . opt_strs ( " Z " ) ;
2019-08-29 23:15:31 +02:00
let lib_strs = matches . opt_strs ( " L " ) ;
let extern_strs = matches . opt_strs ( " extern " ) ;
2019-04-26 13:52:56 -07:00
let runtool = matches . opt_str ( " runtool " ) ;
let runtool_args = matches . opt_strs ( " runtool-arg " ) ;
2019-06-06 16:01:53 -07:00
let enable_per_target_ignores = matches . opt_present ( " enable-per-target-ignores " ) ;
2020-01-04 10:58:32 -08:00
let document_private = matches . opt_present ( " document-private-items " ) ;
let document_hidden = matches . opt_present ( " document-hidden-items " ) ;
2020-11-12 14:57:44 +01:00
let run_check = matches . opt_present ( " check " ) ;
2021-01-20 20:56:47 +01:00
let generate_redirect_map = matches . opt_present ( " generate-redirect-map " ) ;
2021-04-12 19:42:26 -07:00
let show_type_layout = matches . opt_present ( " show-type-layout " ) ;
2018-10-30 08:47:54 -05:00
2021-06-02 17:09:07 +02:00
let ( lint_opts , describe_lints , lint_cap , _ ) =
get_cmd_lint_options ( matches , error_format , & debugging_opts ) ;
2018-10-30 08:47:54 -05:00
Ok ( Options {
input ,
2019-07-20 16:34:41 -04:00
proc_macro_crate ,
2018-10-30 08:47:54 -05:00
error_format ,
libs ,
2019-08-29 23:15:31 +02:00
lib_strs ,
2018-10-30 08:47:54 -05:00
externs ,
2019-08-29 23:15:31 +02:00
extern_strs ,
2018-10-30 08:47:54 -05:00
cfgs ,
codegen_options ,
2019-08-29 23:15:31 +02:00
codegen_options_strs ,
2020-08-25 09:22:26 -04:00
debugging_opts ,
debugging_opts_strs ,
2018-10-30 08:47:54 -05:00
target ,
edition ,
maybe_sysroot ,
lint_opts ,
describe_lints ,
lint_cap ,
should_test ,
test_args ,
default_passes ,
manual_passes ,
display_warnings ,
2019-01-30 14:04:56 -06:00
show_coverage ,
2018-10-30 08:47:54 -05:00
crate_version ,
2021-01-22 10:54:53 +01:00
test_run_directory ,
2018-12-08 14:17:50 -05:00
persist_doctests ,
2019-04-26 13:52:56 -07:00
runtool ,
runtool_args ,
2019-06-06 16:01:53 -07:00
enable_per_target_ignores ,
2019-09-09 21:11:27 -04:00
test_builder ,
2020-11-12 14:57:44 +01:00
run_check ,
2021-04-04 16:53:59 +02:00
no_run ,
2018-10-30 10:53:46 -05:00
render_options : RenderOptions {
output ,
external_html ,
id_map ,
playground_url ,
sort_modules_alphabetically ,
themes ,
extension_css ,
extern_html_root_urls ,
2020-10-13 18:52:43 +01:00
default_settings ,
2018-10-30 10:53:46 -05:00
resource_suffix ,
enable_minification ,
enable_index_page ,
index_page ,
2018-12-20 10:18:45 -06:00
static_root_path ,
2018-10-30 10:53:46 -05:00
markdown_no_toc ,
markdown_css ,
markdown_playground_url ,
2018-12-20 13:28:55 +01:00
generate_search_filter ,
2020-05-30 11:35:35 -04:00
document_private ,
document_hidden ,
2021-01-20 20:56:47 +01:00
generate_redirect_map ,
2021-04-12 19:42:26 -07:00
show_type_layout ,
2020-10-10 14:27:52 -04:00
unstable_features : rustc_feature ::UnstableFeatures ::from_environment (
crate_name . as_deref ( ) ,
) ,
2021-03-25 12:46:35 -04:00
emit ,
2019-12-22 17:42:04 -05:00
} ,
2020-10-10 14:27:52 -04:00
crate_name ,
2019-11-16 16:12:09 +01:00
output_format ,
2020-08-01 12:57:35 +02:00
json_unused_externs ,
2018-10-30 08:47:54 -05:00
} )
}
2019-02-08 14:53:55 +01:00
/// Returns `true` if the file given as `self.input` is a Markdown file.
2020-11-14 17:59:58 -05:00
crate fn markdown_input ( & self ) -> bool {
2019-12-22 17:42:04 -05:00
self . input . extension ( ) . map_or ( false , | e | e = = " md " | | e = = " markdown " )
2018-10-30 08:47:54 -05:00
}
}
/// Prints deprecation warnings for deprecated options
2020-01-09 11:18:47 +01:00
fn check_deprecated_options ( matches : & getopts ::Matches , diag : & rustc_errors ::Handler ) {
2021-02-24 16:16:49 -05:00
let deprecated_flags = [ " input-format " , " no-defaults " , " passes " ] ;
2018-10-30 08:47:54 -05:00
2019-05-17 19:56:35 -07:00
for flag in deprecated_flags . iter ( ) {
2018-10-30 08:47:54 -05:00
if matches . opt_present ( flag ) {
2021-02-28 22:41:05 -05:00
let mut err = diag . struct_warn ( & format! ( " the ` {} ` flag is deprecated " , flag ) ) ;
err . note (
2020-02-07 13:06:35 +01:00
" see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
for more information " ,
) ;
2018-10-30 08:47:54 -05:00
if * flag = = " no-defaults " {
err . help ( " you may want to use --document-private-items " ) ;
}
err . emit ( ) ;
}
}
2018-10-30 10:20:58 -05:00
2019-12-22 17:42:04 -05:00
let removed_flags = [ " plugins " , " plugin-path " ] ;
2018-10-30 10:20:58 -05:00
for & flag in removed_flags . iter ( ) {
if matches . opt_present ( flag ) {
diag . struct_warn ( & format! ( " the ' {} ' flag no longer functions " , flag ) )
. warn ( " see CVE-2018-1000622 " )
. emit ( ) ;
}
}
2018-10-30 08:47:54 -05:00
}
/// Extracts `--extern-html-root-url` arguments from `matches` and returns a map of crate names to
/// the given URLs. If an `--extern-html-root-url` argument was ill-formed, returns an error
/// describing the issue.
2018-11-04 16:44:28 -06:00
fn parse_extern_html_roots (
matches : & getopts ::Matches ,
) -> Result < BTreeMap < String , String > , & 'static str > {
2018-10-30 08:47:54 -05:00
let mut externs = BTreeMap ::new ( ) ;
for arg in & matches . opt_strs ( " extern-html-root-url " ) {
2020-12-07 14:00:31 -07:00
let ( name , url ) =
arg . split_once ( '=' ) . ok_or ( " --extern-html-root-url must be of the form name=url " ) ? ;
2018-10-30 08:47:54 -05:00
externs . insert ( name . to_string ( ) , url . to_string ( ) ) ;
}
Ok ( externs )
}