]> git.proxmox.com Git - rustc.git/blame - src/librustdoc/lib.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustdoc / lib.rs
CommitLineData
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)]
85aaf69f 6#![feature(box_patterns)]
1a4d82fc 7#![feature(box_syntax)]
532ac7d7 8#![feature(in_band_lifetimes)]
0bf4aa26 9#![feature(nll)]
ba9703b0 10#![feature(or_patterns)]
85aaf69f 11#![feature(test)]
cc61c64b 12#![feature(vec_remove_item)]
94b46f34 13#![feature(ptr_offset_from)]
8faf50e0 14#![feature(crate_visibility_modifier)]
532ac7d7 15#![feature(never_type)]
60c5eb7d 16#![recursion_limit = "256"]
94b46f34 17
cc61c64b 18extern crate env_logger;
74b04a01
XL
19extern crate rustc_ast;
20extern crate rustc_ast_pretty;
21extern crate rustc_attr;
9e0c209e 22extern crate rustc_data_structures;
1a4d82fc 23extern crate rustc_driver;
dfeec247
XL
24extern crate rustc_errors;
25extern crate rustc_expand;
60c5eb7d 26extern crate rustc_feature;
dfeec247 27extern crate rustc_hir;
ba9703b0 28extern crate rustc_hir_pretty;
60c5eb7d 29extern crate rustc_index;
74b04a01 30extern crate rustc_infer;
532ac7d7 31extern crate rustc_interface;
60c5eb7d
XL
32extern crate rustc_lexer;
33extern crate rustc_lint;
92a42be0 34extern crate rustc_metadata;
ba9703b0 35extern crate rustc_middle;
dfeec247 36extern crate rustc_mir;
60c5eb7d
XL
37extern crate rustc_parse;
38extern crate rustc_resolve;
dfeec247
XL
39extern crate rustc_session;
40extern crate rustc_span as rustc_span;
83c7162d 41extern crate rustc_target;
ba9703b0 42extern crate rustc_trait_selection;
7cac9316 43extern crate rustc_typeck;
c34b1796 44extern crate test as testing;
60c5eb7d
XL
45#[macro_use]
46extern crate log;
1a4d82fc 47
9cc50fc6 48use std::default::Default;
85aaf69f 49use std::env;
8faf50e0 50use std::panic;
62682a34 51use std::process;
c34b1796 52
ba9703b0
XL
53use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
54use rustc_session::getopts;
55use rustc_session::{early_error, early_warn};
1a4d82fc
JJ
56
57#[macro_use]
8faf50e0 58mod externalfiles;
1a4d82fc 59
8faf50e0 60mod clean;
a1dfa0c6 61mod config;
8faf50e0 62mod core;
dc9dc135 63mod docfs;
8faf50e0
XL
64mod doctree;
65mod fold;
1a4d82fc 66pub mod html {
8faf50e0 67 crate mod escape;
8faf50e0 68 crate mod format;
60c5eb7d
XL
69 crate mod highlight;
70 crate mod item_type;
8faf50e0 71 crate mod layout;
1a4d82fc 72 pub mod markdown;
8faf50e0 73 crate mod render;
60c5eb7d 74 crate mod sources;
a1dfa0c6 75 crate mod static_files;
8faf50e0 76 crate mod toc;
1a4d82fc 77}
8faf50e0
XL
78mod markdown;
79mod passes;
8faf50e0
XL
80mod test;
81mod theme;
60c5eb7d
XL
82mod visit_ast;
83mod visit_lib;
1a4d82fc 84
1a4d82fc
JJ
85struct Output {
86 krate: clean::Crate,
a7813a04 87 renderinfo: html::render::RenderInfo,
a1dfa0c6 88 renderopts: config::RenderOptions,
1a4d82fc
JJ
89}
90
91pub fn main() {
8faf50e0
XL
92 let thread_stack_size: usize = if cfg!(target_os = "haiku") {
93 16_000_000 // 16MB on Haiku
94 } else {
95 32_000_000 // 32MB on other platforms
96 };
83c7162d 97 rustc_driver::set_sigpipe_handler();
e1599b0c 98 env_logger::init_from_env("RUSTDOC_LOG");
60c5eb7d
XL
99 let res = std::thread::Builder::new()
100 .stack_size(thread_stack_size)
101 .spawn(move || get_args().map(|args| main_args(&args)).unwrap_or(1))
102 .unwrap()
103 .join()
104 .unwrap_or(rustc_driver::EXIT_FAILURE);
532ac7d7 105 process::exit(res);
1a4d82fc
JJ
106}
107
7cac9316 108fn get_args() -> Option<Vec<String>> {
60c5eb7d
XL
109 env::args_os()
110 .enumerate()
111 .map(|(i, arg)| {
112 arg.into_string()
113 .map_err(|arg| {
114 early_warn(
115 ErrorOutputType::default(),
116 &format!("Argument {} is not valid Unicode: {:?}", i, arg),
117 );
118 })
119 .ok()
120 })
7cac9316
XL
121 .collect()
122}
123
041b39d2 124fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
60c5eb7d
XL
125where
126 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2
XL
127{
128 RustcOptGroup::stable(name, f)
129}
130
131fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
60c5eb7d
XL
132where
133 F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
041b39d2
XL
134{
135 RustcOptGroup::unstable(name, f)
136}
54a0048b 137
8faf50e0 138fn opts() -> Vec<RustcOptGroup> {
c30ab7b3 139 vec![
041b39d2
XL
140 stable("h", |o| o.optflag("h", "help", "show this help message")),
141 stable("V", |o| o.optflag("V", "version", "print rustdoc's version")),
142 stable("v", |o| o.optflag("v", "verbose", "use verbose output")),
143 stable("r", |o| {
60c5eb7d 144 o.optopt("r", "input-format", "the input type of the specified file", "[rust]")
041b39d2 145 }),
60c5eb7d 146 stable("w", |o| o.optopt("w", "output-format", "the output type to write", "[html]")),
041b39d2
XL
147 stable("o", |o| o.optopt("o", "output", "where to place the output", "PATH")),
148 stable("crate-name", |o| {
149 o.optopt("", "crate-name", "specify the name of this crate", "NAME")
150 }),
e1599b0c 151 make_crate_type_option(),
041b39d2 152 stable("L", |o| {
60c5eb7d 153 o.optmulti("L", "library-path", "directory to add to crate search path", "DIR")
041b39d2
XL
154 }),
155 stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")),
60c5eb7d 156 stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")),
b7449926 157 unstable("extern-html-root-url", |o| {
60c5eb7d 158 o.optmulti("", "extern-html-root-url", "base URL to use for dependencies", "NAME=URL")
041b39d2 159 }),
60c5eb7d 160 stable("plugin-path", |o| o.optmulti("", "plugin-path", "removed", "DIR")),
83c7162d
XL
161 stable("C", |o| {
162 o.optmulti("C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]")
163 }),
041b39d2 164 stable("passes", |o| {
60c5eb7d
XL
165 o.optmulti(
166 "",
167 "passes",
168 "list of passes to also run, you might want \
041b39d2
XL
169 to pass it multiple times; a value of `list` \
170 will print available passes",
60c5eb7d
XL
171 "PASSES",
172 )
041b39d2 173 }),
60c5eb7d
XL
174 stable("plugins", |o| o.optmulti("", "plugins", "removed", "PLUGINS")),
175 stable("no-default", |o| o.optflag("", "no-defaults", "don't run the default passes")),
abe05a73
XL
176 stable("document-private-items", |o| {
177 o.optflag("", "document-private-items", "document private items")
178 }),
60c5eb7d
XL
179 unstable("document-hidden-items", |o| {
180 o.optflag("", "document-hidden-items", "document items that have doc(hidden)")
181 }),
041b39d2
XL
182 stable("test", |o| o.optflag("", "test", "run code examples as tests")),
183 stable("test-args", |o| {
60c5eb7d 184 o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
041b39d2
XL
185 }),
186 stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")),
187 stable("markdown-css", |o| {
60c5eb7d
XL
188 o.optmulti(
189 "",
190 "markdown-css",
191 "CSS files to include via <link> in a rendered Markdown file",
192 "FILES",
193 )
041b39d2 194 }),
60c5eb7d
XL
195 stable("html-in-header", |o| {
196 o.optmulti(
197 "",
198 "html-in-header",
199 "files to include inline in the <head> section of a rendered Markdown file \
041b39d2 200 or generated documentation",
60c5eb7d
XL
201 "FILES",
202 )
041b39d2
XL
203 }),
204 stable("html-before-content", |o| {
60c5eb7d
XL
205 o.optmulti(
206 "",
207 "html-before-content",
208 "files to include inline between <body> and the content of a rendered \
041b39d2 209 Markdown file or generated documentation",
60c5eb7d
XL
210 "FILES",
211 )
041b39d2
XL
212 }),
213 stable("html-after-content", |o| {
60c5eb7d
XL
214 o.optmulti(
215 "",
216 "html-after-content",
217 "files to include inline between the content and </body> of a rendered \
041b39d2 218 Markdown file or generated documentation",
60c5eb7d
XL
219 "FILES",
220 )
041b39d2
XL
221 }),
222 unstable("markdown-before-content", |o| {
60c5eb7d
XL
223 o.optmulti(
224 "",
225 "markdown-before-content",
226 "files to include inline between <body> and the content of a rendered \
041b39d2 227 Markdown file or generated documentation",
60c5eb7d
XL
228 "FILES",
229 )
041b39d2
XL
230 }),
231 unstable("markdown-after-content", |o| {
60c5eb7d
XL
232 o.optmulti(
233 "",
234 "markdown-after-content",
235 "files to include inline between the content and </body> of a rendered \
041b39d2 236 Markdown file or generated documentation",
60c5eb7d
XL
237 "FILES",
238 )
041b39d2
XL
239 }),
240 stable("markdown-playground-url", |o| {
60c5eb7d 241 o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL")
041b39d2
XL
242 }),
243 stable("markdown-no-toc", |o| {
244 o.optflag("", "markdown-no-toc", "don't include table of contents")
245 }),
246 stable("e", |o| {
60c5eb7d
XL
247 o.optopt(
248 "e",
249 "extend-css",
250 "To add some CSS rules with a given file to generate doc with your \
041b39d2 251 own theme. However, your theme might break if the rustdoc's generated HTML \
60c5eb7d
XL
252 changes, so be careful!",
253 "PATH",
254 )
041b39d2
XL
255 }),
256 unstable("Z", |o| {
60c5eb7d 257 o.optmulti("Z", "", "internal and debugging options (only on nightly build)", "FLAG")
041b39d2 258 }),
60c5eb7d 259 stable("sysroot", |o| o.optopt("", "sysroot", "Override the system root", "PATH")),
041b39d2 260 unstable("playground-url", |o| {
60c5eb7d
XL
261 o.optopt(
262 "",
263 "playground-url",
264 "URL to send code snippets to, may be reset by --markdown-playground-url \
041b39d2 265 or `#![doc(html_playground_url=...)]`",
60c5eb7d
XL
266 "URL",
267 )
041b39d2 268 }),
041b39d2
XL
269 unstable("display-warnings", |o| {
270 o.optflag("", "display-warnings", "to print code warnings when testing doc")
271 }),
ba9703b0 272 stable("crate-version", |o| {
abe05a73
XL
273 o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
274 }),
ff7c6d11 275 unstable("sort-modules-by-appearance", |o| {
60c5eb7d
XL
276 o.optflag(
277 "",
278 "sort-modules-by-appearance",
279 "sort modules by where they appear in the \
280 program, rather than alphabetically",
281 )
ff7c6d11 282 }),
60c5eb7d
XL
283 stable("theme", |o| {
284 o.optmulti(
285 "",
286 "theme",
287 "additional themes which will be added to the generated docs",
288 "FILES",
289 )
2c00a5a8 290 }),
60c5eb7d
XL
291 stable("check-theme", |o| {
292 o.optmulti("", "check-theme", "check if given theme is valid", "FILES")
2c00a5a8 293 }),
0531ce1d 294 unstable("resource-suffix", |o| {
60c5eb7d
XL
295 o.optopt(
296 "",
297 "resource-suffix",
298 "suffix to add to CSS and JavaScript files, e.g., \"light.css\" will become \
0531ce1d 299 \"light-suffix.css\"",
60c5eb7d
XL
300 "PATH",
301 )
0531ce1d 302 }),
0bf4aa26 303 stable("edition", |o| {
60c5eb7d
XL
304 o.optopt(
305 "",
306 "edition",
307 "edition to use when compiling rust code (default: 2015)",
308 "EDITION",
309 )
0531ce1d 310 }),
b7449926 311 stable("color", |o| {
60c5eb7d
XL
312 o.optopt(
313 "",
314 "color",
315 "Configure coloring of output:
83c7162d
XL
316 auto = colorize, if output goes to a tty (default);
317 always = always colorize output;
318 never = never colorize output",
60c5eb7d
XL
319 "auto|always|never",
320 )
83c7162d 321 }),
b7449926 322 stable("error-format", |o| {
60c5eb7d
XL
323 o.optopt(
324 "",
325 "error-format",
326 "How errors and other messages are produced",
327 "human|json|short",
328 )
83c7162d 329 }),
416331ca 330 stable("json", |o| {
60c5eb7d 331 o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG")
416331ca 332 }),
94b46f34 333 unstable("disable-minification", |o| {
60c5eb7d 334 o.optflag("", "disable-minification", "Disable minification applied on JS files")
8faf50e0 335 }),
60c5eb7d
XL
336 stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")),
337 stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")),
338 stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "OPT")),
339 stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "OPT")),
8faf50e0
XL
340 stable("cap-lints", |o| {
341 o.optmulti(
342 "",
343 "cap-lints",
344 "Set the most restrictive lint level. \
345 More restrictive lints are capped at this \
346 level. By default, it is at `forbid` level.",
347 "LEVEL",
348 )
349 }),
a1dfa0c6 350 unstable("index-page", |o| {
60c5eb7d 351 o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
a1dfa0c6
XL
352 }),
353 unstable("enable-index-page", |o| {
60c5eb7d 354 o.optflag("", "enable-index-page", "To enable generation of the index page")
a1dfa0c6 355 }),
0731742a 356 unstable("static-root-path", |o| {
60c5eb7d
XL
357 o.optopt(
358 "",
359 "static-root-path",
360 "Path string to force loading static files from in output pages. \
0731742a 361 If not set, uses combinations of '../' to reach the documentation root.",
60c5eb7d
XL
362 "PATH",
363 )
0731742a
XL
364 }),
365 unstable("disable-per-crate-search", |o| {
60c5eb7d
XL
366 o.optflag(
367 "",
368 "disable-per-crate-search",
369 "disables generating the crate selector on the search box",
370 )
0731742a 371 }),
9fa01778 372 unstable("persist-doctests", |o| {
60c5eb7d
XL
373 o.optopt(
374 "",
375 "persist-doctests",
376 "Directory to persist doctest executables into",
377 "PATH",
378 )
9fa01778
XL
379 }),
380 unstable("generate-redirect-pages", |o| {
60c5eb7d
XL
381 o.optflag(
382 "",
383 "generate-redirect-pages",
384 "Generate extra pages to support legacy URLs and tool links",
385 )
9fa01778 386 }),
532ac7d7 387 unstable("show-coverage", |o| {
60c5eb7d
XL
388 o.optflag(
389 "",
390 "show-coverage",
391 "calculate percentage of public items with documentation",
392 )
532ac7d7 393 }),
e1599b0c 394 unstable("enable-per-target-ignores", |o| {
60c5eb7d
XL
395 o.optflag(
396 "",
397 "enable-per-target-ignores",
398 "parse ignore-foo for ignoring doctests on a per-target basis",
399 )
e1599b0c
XL
400 }),
401 unstable("runtool", |o| {
60c5eb7d
XL
402 o.optopt(
403 "",
404 "runtool",
405 "",
406 "The tool to run tests with when building for a different target than host",
407 )
e1599b0c
XL
408 }),
409 unstable("runtool-arg", |o| {
60c5eb7d
XL
410 o.optmulti(
411 "",
412 "runtool-arg",
413 "",
414 "One (of possibly many) arguments to pass to the runtool",
415 )
e1599b0c
XL
416 }),
417 unstable("test-builder", |o| {
60c5eb7d
XL
418 o.optflag(
419 "",
420 "test-builder",
421 "specified the rustc-like binary to use as the test builder",
422 )
e1599b0c 423 }),
c30ab7b3 424 ]
1a4d82fc
JJ
425}
426
8faf50e0 427fn usage(argv0: &str) {
041b39d2
XL
428 let mut options = getopts::Options::new();
429 for option in opts() {
430 (option.apply)(&mut options);
431 }
432 println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
1a4d82fc
JJ
433}
434
532ac7d7 435fn main_args(args: &[String]) -> i32 {
041b39d2
XL
436 let mut options = getopts::Options::new();
437 for option in opts() {
438 (option.apply)(&mut options);
439 }
440 let matches = match options.parse(&args[1..]) {
1a4d82fc
JJ
441 Ok(m) => m,
442 Err(err) => {
94b46f34 443 early_error(ErrorOutputType::default(), &err.to_string());
1a4d82fc
JJ
444 }
445 };
a1dfa0c6
XL
446 let options = match config::Options::from_matches(&matches) {
447 Ok(opts) => opts,
448 Err(code) => return code,
b7449926 449 };
60c5eb7d 450 rustc_interface::interface::default_thread_pool(options.edition, move || main_options(options))
dc9dc135 451}
1a4d82fc 452
dc9dc135 453fn main_options(options: config::Options) -> i32 {
dfeec247 454 let diag = core::new_handler(options.error_format, None, &options.debugging_options);
1a4d82fc 455
a1dfa0c6
XL
456 match (options.should_test, options.markdown_input()) {
457 (true, true) => return markdown::test(options, &diag),
458 (true, false) => return test::run(options),
60c5eb7d
XL
459 (false, true) => {
460 return markdown::render(options.input, options.render_options, &diag, options.edition);
461 }
1a4d82fc
JJ
462 (false, false) => {}
463 }
476ff2be 464
a1dfa0c6
XL
465 // need to move these items separately because we lose them by the time the closure is called,
466 // but we can't crates the Handler ahead of time because it's not Send
dfeec247 467 let diag_opts = (options.error_format, options.edition, options.debugging_options.clone());
532ac7d7 468 let show_coverage = options.show_coverage;
a1dfa0c6 469 rust_input(options, move |out| {
532ac7d7
XL
470 if show_coverage {
471 // if we ran coverage, bail early, we don't need to also generate docs at this point
472 // (also we didn't load in any of the useful passes)
473 return rustc_driver::EXIT_SUCCESS;
474 }
475
416331ca 476 let Output { krate, renderinfo, renderopts } = out;
476ff2be 477 info!("going to format");
dfeec247
XL
478 let (error_format, edition, debugging_options) = diag_opts;
479 let diag = core::new_handler(error_format, None, &debugging_options);
60c5eb7d 480 match html::render::run(krate, renderopts, renderinfo, &diag, edition) {
0731742a
XL
481 Ok(_) => rustc_driver::EXIT_SUCCESS,
482 Err(e) => {
483 diag.struct_err(&format!("couldn't generate documentation: {}", e.error))
484 .note(&format!("failed to create or modify \"{}\"", e.file.display()))
485 .emit();
486 rustc_driver::EXIT_FAILURE
487 }
488 }
476ff2be
SL
489 })
490}
491
1a4d82fc
JJ
492/// Interprets the input file as a rust source file, passing it through the
493/// compiler all the way through the analysis passes. The rustdoc output is then
494/// generated from the cleaned AST of the crate.
495///
496/// This form of input will run all of the plug/cleaning passes
a1dfa0c6 497fn rust_input<R, F>(options: config::Options, f: F) -> R
60c5eb7d
XL
498where
499 R: 'static + Send,
500 F: 'static + Send + FnOnce(Output) -> R,
0531ce1d 501{
1a4d82fc 502 // First, parse the crate and extract all relevant information.
1a4d82fc 503 info!("starting to run rustc");
8faf50e0 504
e1599b0c 505 let result = rustc_driver::catch_fatal_errors(move || {
a1dfa0c6
XL
506 let crate_name = options.crate_name.clone();
507 let crate_version = options.crate_version.clone();
416331ca 508 let (mut krate, renderinfo, renderopts) = core::run_core(options);
1a4d82fc 509
476ff2be
SL
510 info!("finished with rustc");
511
512 if let Some(name) = crate_name {
513 krate.name = name
514 }
1a4d82fc 515
abe05a73
XL
516 krate.version = crate_version;
517
60c5eb7d 518 f(Output { krate, renderinfo, renderopts })
532ac7d7 519 });
8faf50e0
XL
520
521 match result {
416331ca 522 Ok(output) => output,
dfeec247 523 Err(_) => panic::resume_unwind(Box::new(rustc_errors::FatalErrorMarker)),
8faf50e0 524 }
1a4d82fc 525}