]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | #![doc( |
2 | html_root_url = "https://doc.rust-lang.org/nightly/", | |
3 | html_playground_url = "https://play.rust-lang.org/" | |
4 | )] | |
3b2f2976 | 5 | #![feature(rustc_private)] |
29967ef6 | 6 | #![feature(array_methods)] |
c295e0f8 | 7 | #![feature(assert_matches)] |
85aaf69f | 8 | #![feature(box_patterns)] |
5e7ed085 | 9 | #![feature(drain_filter)] |
04454e1e | 10 | #![feature(let_chains)] |
85aaf69f | 11 | #![feature(test)] |
532ac7d7 | 12 | #![feature(never_type)] |
353b0b11 | 13 | #![feature(lazy_cell)] |
fc512014 | 14 | #![feature(type_ascription)] |
dc3f5686 | 15 | #![feature(iter_intersperse)] |
5099ac24 | 16 | #![feature(type_alias_impl_trait)] |
353b0b11 | 17 | #![cfg_attr(not(bootstrap), feature(impl_trait_in_assoc_type))] |
60c5eb7d | 18 | #![recursion_limit = "256"] |
cdc7bbd5 | 19 | #![warn(rustc::internal)] |
5099ac24 | 20 | #![allow(clippy::collapsible_if, clippy::collapsible_else_if)] |
5e7ed085 | 21 | #![allow(rustc::potential_query_instability)] |
94b46f34 | 22 | |
9ffffee4 | 23 | extern crate thin_vec; |
1b1a35ee XL |
24 | #[macro_use] |
25 | extern crate tracing; | |
26 | ||
27 | // N.B. these need `extern crate` even in 2018 edition | |
28 | // because they're loaded implicitly from the sysroot. | |
29 | // The reason they're loaded from the sysroot is because | |
30 | // the rustdoc artifacts aren't stored in rustc's cargo target directory. | |
31 | // So if `rustc` was specified in Cargo.toml, this would spuriously rebuild crates. | |
32 | // | |
33 | // Dependencies listed in Cargo.toml do not need `extern crate`. | |
cdc7bbd5 | 34 | |
9ffffee4 | 35 | extern crate pulldown_cmark; |
74b04a01 XL |
36 | extern crate rustc_ast; |
37 | extern crate rustc_ast_pretty; | |
38 | extern crate rustc_attr; | |
c295e0f8 | 39 | extern crate rustc_const_eval; |
9e0c209e | 40 | extern crate rustc_data_structures; |
1a4d82fc | 41 | extern crate rustc_driver; |
dfeec247 XL |
42 | extern crate rustc_errors; |
43 | extern crate rustc_expand; | |
60c5eb7d | 44 | extern crate rustc_feature; |
dfeec247 | 45 | extern crate rustc_hir; |
2b03887a | 46 | extern crate rustc_hir_analysis; |
ba9703b0 | 47 | extern crate rustc_hir_pretty; |
60c5eb7d | 48 | extern crate rustc_index; |
74b04a01 | 49 | extern crate rustc_infer; |
532ac7d7 | 50 | extern crate rustc_interface; |
60c5eb7d XL |
51 | extern crate rustc_lexer; |
52 | extern crate rustc_lint; | |
6a06907d | 53 | extern crate rustc_lint_defs; |
3c0e092e | 54 | extern crate rustc_macros; |
92a42be0 | 55 | extern crate rustc_metadata; |
ba9703b0 | 56 | extern crate rustc_middle; |
60c5eb7d | 57 | extern crate rustc_parse; |
6a06907d | 58 | extern crate rustc_passes; |
60c5eb7d | 59 | extern crate rustc_resolve; |
3c0e092e | 60 | extern crate rustc_serialize; |
dfeec247 | 61 | extern crate rustc_session; |
136023e0 | 62 | extern crate rustc_span; |
83c7162d | 63 | extern crate rustc_target; |
ba9703b0 | 64 | extern crate rustc_trait_selection; |
136023e0 | 65 | extern crate test; |
1a4d82fc | 66 | |
a2a8927a XL |
67 | // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs |
68 | // about jemalloc. | |
cdc7bbd5 | 69 | #[cfg(feature = "jemalloc")] |
923072b8 | 70 | extern crate jemalloc_sys; |
cdc7bbd5 | 71 | |
5099ac24 | 72 | use std::env::{self, VarError}; |
487cf647 | 73 | use std::io::{self, IsTerminal}; |
62682a34 | 74 | use std::process; |
c34b1796 | 75 | |
064997fb | 76 | use rustc_driver::abort_on_err; |
5e7ed085 | 77 | use rustc_errors::ErrorGuaranteed; |
fc512014 | 78 | use rustc_interface::interface; |
5869c6ff | 79 | use rustc_middle::ty::TyCtxt; |
ba9703b0 XL |
80 | use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; |
81 | use rustc_session::getopts; | |
82 | use rustc_session::{early_error, early_warn}; | |
1a4d82fc | 83 | |
17df50a5 XL |
84 | use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL; |
85 | ||
6a06907d XL |
86 | /// A macro to create a FxHashMap. |
87 | /// | |
88 | /// Example: | |
89 | /// | |
04454e1e | 90 | /// ```ignore(cannot-test-this-because-non-exported-macro) |
6a06907d XL |
91 | /// let letters = map!{"a" => "b", "c" => "d"}; |
92 | /// ``` | |
93 | /// | |
94 | /// Trailing commas are allowed. | |
95 | /// Commas between elements are required (even if the expression is a block). | |
96 | macro_rules! map { | |
97 | ($( $key: expr => $val: expr ),* $(,)*) => {{ | |
98 | let mut map = ::rustc_data_structures::fx::FxHashMap::default(); | |
99 | $( map.insert($key, $val); )* | |
100 | map | |
101 | }} | |
102 | } | |
103 | ||
8faf50e0 | 104 | mod clean; |
a1dfa0c6 | 105 | mod config; |
8faf50e0 | 106 | mod core; |
dc9dc135 | 107 | mod docfs; |
1b1a35ee | 108 | mod doctest; |
3c0e092e XL |
109 | mod error; |
110 | mod externalfiles; | |
8faf50e0 | 111 | mod fold; |
5869c6ff XL |
112 | mod formats; |
113 | // used by the error-index generator, so it needs to be public | |
3dfed10e XL |
114 | pub mod html; |
115 | mod json; | |
923072b8 | 116 | pub(crate) mod lint; |
8faf50e0 XL |
117 | mod markdown; |
118 | mod passes; | |
3c0e092e | 119 | mod scrape_examples; |
8faf50e0 | 120 | mod theme; |
3c0e092e | 121 | mod visit; |
60c5eb7d XL |
122 | mod visit_ast; |
123 | mod visit_lib; | |
1a4d82fc | 124 | |
1a4d82fc | 125 | pub fn main() { |
cdc7bbd5 | 126 | // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs |
a2a8927a | 127 | // about jemalloc. |
cdc7bbd5 XL |
128 | #[cfg(feature = "jemalloc")] |
129 | { | |
130 | use std::os::raw::{c_int, c_void}; | |
131 | ||
132 | #[used] | |
133 | static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; | |
134 | #[used] | |
135 | static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int = | |
136 | jemalloc_sys::posix_memalign; | |
137 | #[used] | |
138 | static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc; | |
139 | #[used] | |
140 | static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc; | |
141 | #[used] | |
142 | static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc; | |
143 | #[used] | |
144 | static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free; | |
145 | ||
cdc7bbd5 XL |
146 | #[cfg(target_os = "macos")] |
147 | { | |
148 | extern "C" { | |
149 | fn _rjem_je_zone_register(); | |
150 | } | |
151 | ||
152 | #[used] | |
153 | static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; | |
154 | } | |
155 | } | |
156 | ||
3dfed10e | 157 | rustc_driver::install_ice_hook(); |
6a06907d XL |
158 | |
159 | // When using CI artifacts (with `download_stage1 = true`), tracing is unconditionally built | |
160 | // with `--features=static_max_level_info`, which disables almost all rustdoc logging. To avoid | |
161 | // this, compile our own version of `tracing` that logs all levels. | |
162 | // NOTE: this compiles both versions of tracing unconditionally, because | |
163 | // - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and | |
164 | // - Otherwise, there's no warning that logging is being ignored when `download_stage1 = true`. | |
165 | // NOTE: The reason this doesn't show double logging when `download_stage1 = false` and | |
166 | // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one | |
167 | // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). | |
168 | init_logging(); | |
3dfed10e | 169 | rustc_driver::init_env_logger("RUSTDOC_LOG"); |
6a06907d | 170 | |
3dfed10e XL |
171 | let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() { |
172 | Some(args) => main_args(&args), | |
5e7ed085 | 173 | _ => Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()), |
3dfed10e XL |
174 | }); |
175 | process::exit(exit_code); | |
1a4d82fc JJ |
176 | } |
177 | ||
6a06907d | 178 | fn init_logging() { |
5099ac24 FG |
179 | let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() { |
180 | Ok("always") => true, | |
181 | Ok("never") => false, | |
487cf647 | 182 | Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(), |
5099ac24 | 183 | Ok(value) => early_error( |
6a06907d | 184 | ErrorOutputType::default(), |
5099ac24 FG |
185 | &format!("invalid log color value '{}': expected one of always, never, or auto", value), |
186 | ), | |
187 | Err(VarError::NotUnicode(value)) => early_error( | |
188 | ErrorOutputType::default(), | |
189 | &format!( | |
190 | "invalid log color value '{}': expected one of always, never, or auto", | |
191 | value.to_string_lossy() | |
192 | ), | |
6a06907d XL |
193 | ), |
194 | }; | |
195 | let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); | |
196 | let layer = tracing_tree::HierarchicalLayer::default() | |
197 | .with_writer(io::stderr) | |
198 | .with_indent_lines(true) | |
199 | .with_ansi(color_logs) | |
200 | .with_targets(true) | |
201 | .with_wraparound(10) | |
202 | .with_verbose_exit(true) | |
203 | .with_verbose_entry(true) | |
204 | .with_indent_amount(2); | |
353b0b11 | 205 | #[cfg(all(parallel_compiler, debug_assertions))] |
6a06907d XL |
206 | let layer = layer.with_thread_ids(true).with_thread_names(true); |
207 | ||
208 | use tracing_subscriber::layer::SubscriberExt; | |
209 | let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); | |
210 | tracing::subscriber::set_global_default(subscriber).unwrap(); | |
211 | } | |
212 | ||
7cac9316 | 213 | fn get_args() -> Option<Vec<String>> { |
60c5eb7d XL |
214 | env::args_os() |
215 | .enumerate() | |
216 | .map(|(i, arg)| { | |
217 | arg.into_string() | |
218 | .map_err(|arg| { | |
219 | early_warn( | |
220 | ErrorOutputType::default(), | |
221 | &format!("Argument {} is not valid Unicode: {:?}", i, arg), | |
222 | ); | |
223 | }) | |
224 | .ok() | |
225 | }) | |
7cac9316 XL |
226 | .collect() |
227 | } | |
228 | ||
8faf50e0 | 229 | fn opts() -> Vec<RustcOptGroup> { |
fc512014 XL |
230 | let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; |
231 | let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; | |
c30ab7b3 | 232 | vec![ |
136023e0 XL |
233 | stable("h", |o| o.optflagmulti("h", "help", "show this help message")), |
234 | stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")), | |
235 | stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")), | |
60c5eb7d | 236 | stable("w", |o| o.optopt("w", "output-format", "the output type to write", "[html]")), |
a2a8927a XL |
237 | stable("output", |o| { |
238 | o.optopt( | |
239 | "", | |
240 | "output", | |
241 | "Which directory to place the output. \ | |
242 | This option is deprecated, use --out-dir instead.", | |
243 | "PATH", | |
244 | ) | |
245 | }), | |
246 | stable("o", |o| o.optopt("o", "out-dir", "which directory to place the output", "PATH")), | |
041b39d2 XL |
247 | stable("crate-name", |o| { |
248 | o.optopt("", "crate-name", "specify the name of this crate", "NAME") | |
249 | }), | |
e1599b0c | 250 | make_crate_type_option(), |
041b39d2 | 251 | stable("L", |o| { |
60c5eb7d | 252 | o.optmulti("L", "library-path", "directory to add to crate search path", "DIR") |
041b39d2 XL |
253 | }), |
254 | stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), | |
5e7ed085 | 255 | unstable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")), |
60c5eb7d | 256 | stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")), |
b7449926 | 257 | unstable("extern-html-root-url", |o| { |
cdc7bbd5 XL |
258 | o.optmulti( |
259 | "", | |
260 | "extern-html-root-url", | |
261 | "base URL to use for dependencies; for example, \ | |
262 | \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", | |
263 | "NAME=URL", | |
264 | ) | |
041b39d2 | 265 | }), |
94222f64 XL |
266 | unstable("extern-html-root-takes-precedence", |o| { |
267 | o.optflagmulti( | |
268 | "", | |
269 | "extern-html-root-takes-precedence", | |
270 | "give precedence to `--extern-html-root-url`, not `html_root_url`", | |
271 | ) | |
272 | }), | |
83c7162d XL |
273 | stable("C", |o| { |
274 | o.optmulti("C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]") | |
275 | }), | |
abe05a73 | 276 | stable("document-private-items", |o| { |
136023e0 | 277 | o.optflagmulti("", "document-private-items", "document private items") |
abe05a73 | 278 | }), |
60c5eb7d | 279 | unstable("document-hidden-items", |o| { |
136023e0 | 280 | o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)") |
60c5eb7d | 281 | }), |
136023e0 | 282 | stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")), |
041b39d2 | 283 | stable("test-args", |o| { |
60c5eb7d | 284 | o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") |
041b39d2 | 285 | }), |
353b0b11 | 286 | stable("test-run-directory", |o| { |
5869c6ff XL |
287 | o.optopt( |
288 | "", | |
289 | "test-run-directory", | |
290 | "The working directory in which to run tests", | |
291 | "PATH", | |
292 | ) | |
293 | }), | |
041b39d2 XL |
294 | stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")), |
295 | stable("markdown-css", |o| { | |
60c5eb7d XL |
296 | o.optmulti( |
297 | "", | |
298 | "markdown-css", | |
299 | "CSS files to include via <link> in a rendered Markdown file", | |
300 | "FILES", | |
301 | ) | |
041b39d2 | 302 | }), |
60c5eb7d XL |
303 | stable("html-in-header", |o| { |
304 | o.optmulti( | |
305 | "", | |
306 | "html-in-header", | |
307 | "files to include inline in the <head> section of a rendered Markdown file \ | |
1b1a35ee | 308 | or generated documentation", |
60c5eb7d XL |
309 | "FILES", |
310 | ) | |
041b39d2 XL |
311 | }), |
312 | stable("html-before-content", |o| { | |
60c5eb7d XL |
313 | o.optmulti( |
314 | "", | |
315 | "html-before-content", | |
316 | "files to include inline between <body> and the content of a rendered \ | |
1b1a35ee | 317 | Markdown file or generated documentation", |
60c5eb7d XL |
318 | "FILES", |
319 | ) | |
041b39d2 XL |
320 | }), |
321 | stable("html-after-content", |o| { | |
60c5eb7d XL |
322 | o.optmulti( |
323 | "", | |
324 | "html-after-content", | |
325 | "files to include inline between the content and </body> of a rendered \ | |
1b1a35ee | 326 | Markdown file or generated documentation", |
60c5eb7d XL |
327 | "FILES", |
328 | ) | |
041b39d2 XL |
329 | }), |
330 | unstable("markdown-before-content", |o| { | |
60c5eb7d XL |
331 | o.optmulti( |
332 | "", | |
333 | "markdown-before-content", | |
334 | "files to include inline between <body> and the content of a rendered \ | |
1b1a35ee | 335 | Markdown file or generated documentation", |
60c5eb7d XL |
336 | "FILES", |
337 | ) | |
041b39d2 XL |
338 | }), |
339 | unstable("markdown-after-content", |o| { | |
60c5eb7d XL |
340 | o.optmulti( |
341 | "", | |
342 | "markdown-after-content", | |
343 | "files to include inline between the content and </body> of a rendered \ | |
1b1a35ee | 344 | Markdown file or generated documentation", |
60c5eb7d XL |
345 | "FILES", |
346 | ) | |
041b39d2 XL |
347 | }), |
348 | stable("markdown-playground-url", |o| { | |
60c5eb7d | 349 | o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") |
041b39d2 XL |
350 | }), |
351 | stable("markdown-no-toc", |o| { | |
136023e0 | 352 | o.optflagmulti("", "markdown-no-toc", "don't include table of contents") |
041b39d2 XL |
353 | }), |
354 | stable("e", |o| { | |
60c5eb7d XL |
355 | o.optopt( |
356 | "e", | |
357 | "extend-css", | |
358 | "To add some CSS rules with a given file to generate doc with your \ | |
1b1a35ee XL |
359 | own theme. However, your theme might break if the rustdoc's generated HTML \ |
360 | changes, so be careful!", | |
60c5eb7d XL |
361 | "PATH", |
362 | ) | |
041b39d2 XL |
363 | }), |
364 | unstable("Z", |o| { | |
064997fb | 365 | o.optmulti("Z", "", "unstable / perma-unstable options (only on nightly build)", "FLAG") |
041b39d2 | 366 | }), |
60c5eb7d | 367 | stable("sysroot", |o| o.optopt("", "sysroot", "Override the system root", "PATH")), |
041b39d2 | 368 | unstable("playground-url", |o| { |
60c5eb7d XL |
369 | o.optopt( |
370 | "", | |
371 | "playground-url", | |
372 | "URL to send code snippets to, may be reset by --markdown-playground-url \ | |
1b1a35ee | 373 | or `#![doc(html_playground_url=...)]`", |
60c5eb7d XL |
374 | "URL", |
375 | ) | |
041b39d2 | 376 | }), |
c295e0f8 XL |
377 | unstable("display-doctest-warnings", |o| { |
378 | o.optflagmulti( | |
379 | "", | |
380 | "display-doctest-warnings", | |
381 | "show warnings that originate in doctests", | |
382 | ) | |
041b39d2 | 383 | }), |
ba9703b0 | 384 | stable("crate-version", |o| { |
abe05a73 XL |
385 | o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") |
386 | }), | |
ff7c6d11 | 387 | unstable("sort-modules-by-appearance", |o| { |
136023e0 | 388 | o.optflagmulti( |
60c5eb7d XL |
389 | "", |
390 | "sort-modules-by-appearance", | |
f035d41b | 391 | "sort modules by where they appear in the program, rather than alphabetically", |
60c5eb7d | 392 | ) |
ff7c6d11 | 393 | }), |
5869c6ff | 394 | stable("default-theme", |o| { |
29967ef6 XL |
395 | o.optopt( |
396 | "", | |
397 | "default-theme", | |
398 | "Set the default theme. THEME should be the theme name, generally lowercase. \ | |
399 | If an unknown default theme is specified, the builtin default is used. \ | |
5869c6ff | 400 | The set of themes, and the rustdoc built-in default, are not stable.", |
29967ef6 XL |
401 | "THEME", |
402 | ) | |
403 | }), | |
404 | unstable("default-setting", |o| { | |
405 | o.optmulti( | |
406 | "", | |
407 | "default-setting", | |
408 | "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \ | |
409 | from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \ | |
410 | Supported SETTINGs and VALUEs are not documented and not stable.", | |
411 | "SETTING[=VALUE]", | |
412 | ) | |
413 | }), | |
60c5eb7d XL |
414 | stable("theme", |o| { |
415 | o.optmulti( | |
416 | "", | |
417 | "theme", | |
418 | "additional themes which will be added to the generated docs", | |
419 | "FILES", | |
420 | ) | |
2c00a5a8 | 421 | }), |
60c5eb7d XL |
422 | stable("check-theme", |o| { |
423 | o.optmulti("", "check-theme", "check if given theme is valid", "FILES") | |
2c00a5a8 | 424 | }), |
0531ce1d | 425 | unstable("resource-suffix", |o| { |
60c5eb7d XL |
426 | o.optopt( |
427 | "", | |
428 | "resource-suffix", | |
429 | "suffix to add to CSS and JavaScript files, e.g., \"light.css\" will become \ | |
1b1a35ee | 430 | \"light-suffix.css\"", |
60c5eb7d XL |
431 | "PATH", |
432 | ) | |
0531ce1d | 433 | }), |
0bf4aa26 | 434 | stable("edition", |o| { |
60c5eb7d XL |
435 | o.optopt( |
436 | "", | |
437 | "edition", | |
438 | "edition to use when compiling rust code (default: 2015)", | |
439 | "EDITION", | |
440 | ) | |
0531ce1d | 441 | }), |
b7449926 | 442 | stable("color", |o| { |
60c5eb7d XL |
443 | o.optopt( |
444 | "", | |
445 | "color", | |
446 | "Configure coloring of output: | |
83c7162d XL |
447 | auto = colorize, if output goes to a tty (default); |
448 | always = always colorize output; | |
449 | never = never colorize output", | |
60c5eb7d XL |
450 | "auto|always|never", |
451 | ) | |
83c7162d | 452 | }), |
b7449926 | 453 | stable("error-format", |o| { |
60c5eb7d XL |
454 | o.optopt( |
455 | "", | |
456 | "error-format", | |
457 | "How errors and other messages are produced", | |
458 | "human|json|short", | |
459 | ) | |
83c7162d | 460 | }), |
2b03887a | 461 | stable("diagnostic-width", |o| { |
064997fb FG |
462 | o.optopt( |
463 | "", | |
464 | "diagnostic-width", | |
465 | "Provide width of the output for truncated error messages", | |
466 | "WIDTH", | |
467 | ) | |
468 | }), | |
416331ca | 469 | stable("json", |o| { |
60c5eb7d | 470 | o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") |
416331ca | 471 | }), |
94222f64 XL |
472 | stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")), |
473 | stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")), | |
474 | stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")), | |
475 | stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "LINT")), | |
476 | stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "LINT")), | |
8faf50e0 XL |
477 | stable("cap-lints", |o| { |
478 | o.optmulti( | |
479 | "", | |
480 | "cap-lints", | |
481 | "Set the most restrictive lint level. \ | |
482 | More restrictive lints are capped at this \ | |
483 | level. By default, it is at `forbid` level.", | |
484 | "LEVEL", | |
485 | ) | |
486 | }), | |
a1dfa0c6 | 487 | unstable("index-page", |o| { |
60c5eb7d | 488 | o.optopt("", "index-page", "Markdown file to be used as index page", "PATH") |
a1dfa0c6 XL |
489 | }), |
490 | unstable("enable-index-page", |o| { | |
136023e0 | 491 | o.optflagmulti("", "enable-index-page", "To enable generation of the index page") |
a1dfa0c6 | 492 | }), |
0731742a | 493 | unstable("static-root-path", |o| { |
60c5eb7d XL |
494 | o.optopt( |
495 | "", | |
496 | "static-root-path", | |
497 | "Path string to force loading static files from in output pages. \ | |
1b1a35ee | 498 | If not set, uses combinations of '../' to reach the documentation root.", |
60c5eb7d XL |
499 | "PATH", |
500 | ) | |
0731742a XL |
501 | }), |
502 | unstable("disable-per-crate-search", |o| { | |
136023e0 | 503 | o.optflagmulti( |
60c5eb7d XL |
504 | "", |
505 | "disable-per-crate-search", | |
506 | "disables generating the crate selector on the search box", | |
507 | ) | |
0731742a | 508 | }), |
9fa01778 | 509 | unstable("persist-doctests", |o| { |
60c5eb7d XL |
510 | o.optopt( |
511 | "", | |
512 | "persist-doctests", | |
513 | "Directory to persist doctest executables into", | |
514 | "PATH", | |
515 | ) | |
9fa01778 | 516 | }), |
532ac7d7 | 517 | unstable("show-coverage", |o| { |
136023e0 | 518 | o.optflagmulti( |
60c5eb7d XL |
519 | "", |
520 | "show-coverage", | |
521 | "calculate percentage of public items with documentation", | |
522 | ) | |
532ac7d7 | 523 | }), |
e1599b0c | 524 | unstable("enable-per-target-ignores", |o| { |
136023e0 | 525 | o.optflagmulti( |
60c5eb7d XL |
526 | "", |
527 | "enable-per-target-ignores", | |
528 | "parse ignore-foo for ignoring doctests on a per-target basis", | |
529 | ) | |
e1599b0c XL |
530 | }), |
531 | unstable("runtool", |o| { | |
60c5eb7d XL |
532 | o.optopt( |
533 | "", | |
534 | "runtool", | |
535 | "", | |
536 | "The tool to run tests with when building for a different target than host", | |
537 | ) | |
e1599b0c XL |
538 | }), |
539 | unstable("runtool-arg", |o| { | |
60c5eb7d XL |
540 | o.optmulti( |
541 | "", | |
542 | "runtool-arg", | |
543 | "", | |
544 | "One (of possibly many) arguments to pass to the runtool", | |
545 | ) | |
e1599b0c XL |
546 | }), |
547 | unstable("test-builder", |o| { | |
5869c6ff | 548 | o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") |
e1599b0c | 549 | }), |
136023e0 | 550 | unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), |
6a06907d | 551 | unstable("generate-redirect-map", |o| { |
136023e0 | 552 | o.optflagmulti( |
6a06907d XL |
553 | "", |
554 | "generate-redirect-map", | |
555 | "Generate JSON file at the top level instead of generating HTML redirection files", | |
556 | ) | |
557 | }), | |
cdc7bbd5 XL |
558 | unstable("emit", |o| { |
559 | o.optmulti( | |
560 | "", | |
561 | "emit", | |
562 | "Comma separated list of types of output for rustdoc to emit", | |
563 | "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", | |
564 | ) | |
565 | }), | |
136023e0 XL |
566 | unstable("no-run", |o| { |
567 | o.optflagmulti("", "no-run", "Compile doctests without running them") | |
568 | }), | |
17df50a5 | 569 | unstable("show-type-layout", |o| { |
136023e0 XL |
570 | o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs") |
571 | }), | |
572 | unstable("nocapture", |o| { | |
573 | o.optflag("", "nocapture", "Don't capture stdout and stderr of tests") | |
17df50a5 | 574 | }), |
94222f64 XL |
575 | unstable("generate-link-to-definition", |o| { |
576 | o.optflag( | |
577 | "", | |
578 | "generate-link-to-definition", | |
579 | "Make the identifiers in the HTML source code pages navigable", | |
580 | ) | |
581 | }), | |
3c0e092e XL |
582 | unstable("scrape-examples-output-path", |o| { |
583 | o.optopt( | |
584 | "", | |
585 | "scrape-examples-output-path", | |
586 | "", | |
587 | "collect function call information and output at the given path", | |
588 | ) | |
589 | }), | |
590 | unstable("scrape-examples-target-crate", |o| { | |
591 | o.optmulti( | |
592 | "", | |
593 | "scrape-examples-target-crate", | |
594 | "", | |
595 | "collect function call information for functions from the target crate", | |
596 | ) | |
597 | }), | |
5099ac24 FG |
598 | unstable("scrape-tests", |o| { |
599 | o.optflag("", "scrape-tests", "Include test code when scraping examples") | |
600 | }), | |
3c0e092e XL |
601 | unstable("with-examples", |o| { |
602 | o.optmulti( | |
603 | "", | |
604 | "with-examples", | |
605 | "", | |
606 | "path to function call information (for displaying examples in the documentation)", | |
607 | ) | |
608 | }), | |
a2a8927a | 609 | // deprecated / removed options |
487cf647 | 610 | unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), |
a2a8927a XL |
611 | stable("plugin-path", |o| { |
612 | o.optmulti( | |
613 | "", | |
614 | "plugin-path", | |
615 | "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \ | |
616 | for more information", | |
617 | "DIR", | |
618 | ) | |
619 | }), | |
620 | stable("passes", |o| { | |
621 | o.optmulti( | |
622 | "", | |
623 | "passes", | |
624 | "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \ | |
625 | for more information", | |
626 | "PASSES", | |
627 | ) | |
628 | }), | |
629 | stable("plugins", |o| { | |
630 | o.optmulti( | |
631 | "", | |
632 | "plugins", | |
633 | "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \ | |
634 | for more information", | |
635 | "PLUGINS", | |
636 | ) | |
637 | }), | |
638 | stable("no-default", |o| { | |
639 | o.optflagmulti( | |
640 | "", | |
641 | "no-defaults", | |
642 | "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \ | |
643 | for more information", | |
644 | ) | |
645 | }), | |
646 | stable("r", |o| { | |
647 | o.optopt( | |
648 | "r", | |
649 | "input-format", | |
650 | "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \ | |
651 | for more information", | |
652 | "[rust]", | |
653 | ) | |
654 | }), | |
c30ab7b3 | 655 | ] |
1a4d82fc JJ |
656 | } |
657 | ||
8faf50e0 | 658 | fn usage(argv0: &str) { |
041b39d2 XL |
659 | let mut options = getopts::Options::new(); |
660 | for option in opts() { | |
661 | (option.apply)(&mut options); | |
662 | } | |
663 | println!("{}", options.usage(&format!("{} [options] <input>", argv0))); | |
6a06907d | 664 | println!(" @path Read newline separated options from `path`\n"); |
17df50a5 XL |
665 | println!( |
666 | "More information available at {}/rustdoc/what-is-rustdoc.html", | |
667 | DOC_RUST_LANG_ORG_CHANNEL | |
668 | ); | |
1a4d82fc JJ |
669 | } |
670 | ||
3dfed10e | 671 | /// A result type used by several functions under `main()`. |
5e7ed085 | 672 | type MainResult = Result<(), ErrorGuaranteed>; |
3dfed10e | 673 | |
3dfed10e | 674 | fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult { |
f9f354fc | 675 | match res { |
487cf647 | 676 | Ok(()) => diag.has_errors().map_or(Ok(()), Err), |
f9f354fc | 677 | Err(err) => { |
5e7ed085 FG |
678 | let reported = diag.struct_err(&err).emit(); |
679 | Err(reported) | |
3dfed10e XL |
680 | } |
681 | } | |
682 | } | |
683 | ||
fc512014 | 684 | fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( |
3dfed10e XL |
685 | krate: clean::Crate, |
686 | renderopts: config::RenderOptions, | |
6a06907d | 687 | cache: formats::cache::Cache, |
5869c6ff | 688 | tcx: TyCtxt<'tcx>, |
3dfed10e | 689 | ) -> MainResult { |
cdc7bbd5 | 690 | match formats::run_format::<T>(krate, renderopts, cache, tcx) { |
487cf647 | 691 | Ok(_) => tcx.sess.has_errors().map_or(Ok(()), Err), |
3dfed10e | 692 | Err(e) => { |
cdc7bbd5 XL |
693 | let mut msg = |
694 | tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error)); | |
3dfed10e | 695 | let file = e.file.display().to_string(); |
5e7ed085 FG |
696 | if !file.is_empty() { |
697 | msg.note(&format!("failed to create or modify \"{}\"", file)); | |
f9f354fc | 698 | } |
5e7ed085 | 699 | Err(msg.emit()) |
f9f354fc XL |
700 | } |
701 | } | |
702 | } | |
703 | ||
2b03887a FG |
704 | fn main_args(at_args: &[String]) -> MainResult { |
705 | let args = rustc_driver::args::arg_expand_all(at_args); | |
706 | ||
707 | let mut options = getopts::Options::new(); | |
708 | for option in opts() { | |
709 | (option.apply)(&mut options); | |
710 | } | |
711 | let matches = match options.parse(&args[1..]) { | |
712 | Ok(m) => m, | |
713 | Err(err) => { | |
714 | early_error(ErrorOutputType::default(), &err.to_string()); | |
715 | } | |
716 | }; | |
717 | ||
718 | // Note that we discard any distinction between different non-zero exit | |
719 | // codes from `from_matches` here. | |
720 | let (options, render_options) = match config::Options::from_matches(&matches, args) { | |
721 | Ok(opts) => opts, | |
722 | Err(code) => { | |
723 | return if code == 0 { | |
724 | Ok(()) | |
725 | } else { | |
726 | Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) | |
727 | }; | |
728 | } | |
729 | }; | |
730 | ||
064997fb FG |
731 | let diag = core::new_handler( |
732 | options.error_format, | |
733 | None, | |
734 | options.diagnostic_width, | |
735 | &options.unstable_opts, | |
736 | ); | |
1a4d82fc | 737 | |
a1dfa0c6 | 738 | match (options.should_test, options.markdown_input()) { |
f9f354fc | 739 | (true, true) => return wrap_return(&diag, markdown::test(options)), |
1b1a35ee | 740 | (true, false) => return doctest::run(options), |
60c5eb7d | 741 | (false, true) => { |
2b03887a FG |
742 | let input = options.input.clone(); |
743 | let edition = options.edition; | |
9ffffee4 | 744 | let config = core::create_config(options, &render_options); |
2b03887a FG |
745 | |
746 | // `markdown::render` can invoke `doctest::make_test`, which | |
747 | // requires session globals and a thread pool, so we use | |
748 | // `run_compiler`. | |
f9f354fc XL |
749 | return wrap_return( |
750 | &diag, | |
2b03887a FG |
751 | interface::run_compiler(config, |_compiler| { |
752 | markdown::render(&input, render_options, edition) | |
753 | }), | |
f9f354fc | 754 | ); |
60c5eb7d | 755 | } |
1a4d82fc JJ |
756 | (false, false) => {} |
757 | } | |
476ff2be | 758 | |
a1dfa0c6 | 759 | // need to move these items separately because we lose them by the time the closure is called, |
fc512014 | 760 | // but we can't create the Handler ahead of time because it's not Send |
532ac7d7 | 761 | let show_coverage = options.show_coverage; |
fc512014 | 762 | let run_check = options.run_check; |
f035d41b XL |
763 | |
764 | // First, parse the crate and extract all relevant information. | |
765 | info!("starting to run rustc"); | |
766 | ||
767 | // Interpret the input file as a rust source file, passing it through the | |
768 | // compiler all the way through the analysis passes. The rustdoc output is | |
769 | // then generated from the cleaned AST of the crate. This runs all the | |
770 | // plug/cleaning passes. | |
3dfed10e | 771 | let crate_version = options.crate_version.clone(); |
fc512014 | 772 | |
3dfed10e | 773 | let output_format = options.output_format; |
3c0e092e | 774 | let scrape_examples_options = options.scrape_examples_options.clone(); |
487cf647 | 775 | let bin_crate = options.bin_crate; |
2b03887a | 776 | |
9ffffee4 | 777 | let config = core::create_config(options, &render_options); |
f035d41b | 778 | |
2b03887a | 779 | interface::run_compiler(config, |compiler| { |
064997fb | 780 | let sess = compiler.session(); |
f035d41b | 781 | |
064997fb | 782 | if sess.opts.describe_lints { |
487cf647 | 783 | let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); |
064997fb FG |
784 | let registered_lints = if let Some(register_lints) = compiler.register_lints() { |
785 | register_lints(sess, &mut lint_store); | |
786 | true | |
787 | } else { | |
788 | false | |
789 | }; | |
790 | rustc_driver::describe_lints(sess, &lint_store, registered_lints); | |
791 | return Ok(()); | |
792 | } | |
cdc7bbd5 | 793 | |
064997fb | 794 | compiler.enter(|queries| { |
9ffffee4 | 795 | let mut gcx = abort_on_err(queries.global_ctxt(), sess); |
5e7ed085 | 796 | if sess.diagnostic().has_errors_or_lint_errors().is_some() { |
fc512014 XL |
797 | sess.fatal("Compilation failed, aborting rustdoc"); |
798 | } | |
f035d41b | 799 | |
9ffffee4 | 800 | gcx.enter(|tcx| { |
6a06907d | 801 | let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || { |
9ffffee4 | 802 | core::run_global_ctxt(tcx, show_coverage, render_options, output_format) |
fc512014 XL |
803 | }); |
804 | info!("finished with rustc"); | |
805 | ||
3c0e092e | 806 | if let Some(options) = scrape_examples_options { |
487cf647 FG |
807 | return scrape_examples::run( |
808 | krate, | |
809 | render_opts, | |
810 | cache, | |
811 | tcx, | |
812 | options, | |
813 | bin_crate, | |
814 | ); | |
3c0e092e XL |
815 | } |
816 | ||
6a06907d | 817 | cache.crate_version = crate_version; |
fc512014 XL |
818 | |
819 | if show_coverage { | |
820 | // if we ran coverage, bail early, we don't need to also generate docs at this point | |
821 | // (also we didn't load in any of the useful passes) | |
822 | return Ok(()); | |
823 | } else if run_check { | |
824 | // Since we're in "check" mode, no need to generate anything beyond this point. | |
825 | return Ok(()); | |
826 | } | |
827 | ||
828 | info!("going to format"); | |
fc512014 | 829 | match output_format { |
5869c6ff | 830 | config::OutputFormat::Html => sess.time("render_html", || { |
cdc7bbd5 | 831 | run_renderer::<html::render::Context<'_>>(krate, render_opts, cache, tcx) |
fc512014 | 832 | }), |
5869c6ff | 833 | config::OutputFormat::Json => sess.time("render_json", || { |
cdc7bbd5 | 834 | run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx) |
fc512014 XL |
835 | }), |
836 | } | |
837 | }) | |
838 | }) | |
839 | }) | |
1a4d82fc | 840 | } |