]>
Commit | Line | Data |
---|---|---|
48663c56 | 1 | use std::collections::BTreeMap; |
60c5eb7d | 2 | use std::ffi::OsStr; |
a1dfa0c6 XL |
3 | use std::fmt; |
4 | use std::path::PathBuf; | |
5 | ||
6 | use errors; | |
a1dfa0c6 XL |
7 | use getopts; |
8 | use rustc::lint::Level; | |
416331ca | 9 | use rustc::session; |
60c5eb7d XL |
10 | use rustc::session::config::{ |
11 | build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple, | |
12 | nightly_options, | |
13 | }; | |
14 | use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType}; | |
a1dfa0c6 | 15 | use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; |
0731742a | 16 | use rustc::session::search_paths::SearchPath; |
a1dfa0c6 XL |
17 | use rustc_driver; |
18 | use rustc_target::spec::TargetTriple; | |
48663c56 | 19 | use syntax::edition::{Edition, DEFAULT_EDITION}; |
a1dfa0c6 | 20 | |
9fa01778 XL |
21 | use crate::core::new_handler; |
22 | use crate::externalfiles::ExternalHtml; | |
23 | use crate::html; | |
60c5eb7d XL |
24 | use crate::html::markdown::IdMap; |
25 | use crate::html::static_files; | |
9fa01778 | 26 | use crate::opts; |
60c5eb7d | 27 | use crate::passes::{self, Condition, DefaultPassOption}; |
9fa01778 | 28 | use crate::theme; |
a1dfa0c6 XL |
29 | |
30 | /// Configuration options for rustdoc. | |
31 | #[derive(Clone)] | |
32 | pub struct Options { | |
33 | // Basic options / Options passed directly to rustc | |
a1dfa0c6 XL |
34 | /// The crate root or Markdown file to load. |
35 | pub input: PathBuf, | |
36 | /// The name of the crate being documented. | |
37 | pub crate_name: Option<String>, | |
e1599b0c XL |
38 | /// Whether or not this is a proc-macro crate |
39 | pub proc_macro_crate: bool, | |
a1dfa0c6 XL |
40 | /// How to format errors and warnings. |
41 | pub error_format: ErrorOutputType, | |
42 | /// Library search paths to hand to the compiler. | |
0731742a | 43 | pub libs: Vec<SearchPath>, |
e1599b0c XL |
44 | /// Library search paths strings to hand to the compiler. |
45 | pub lib_strs: Vec<String>, | |
a1dfa0c6 XL |
46 | /// The list of external crates to link against. |
47 | pub externs: Externs, | |
e1599b0c XL |
48 | /// The list of external crates strings to link against. |
49 | pub extern_strs: Vec<String>, | |
a1dfa0c6 XL |
50 | /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`. |
51 | pub cfgs: Vec<String>, | |
52 | /// Codegen options to hand to the compiler. | |
53 | pub codegen_options: CodegenOptions, | |
e1599b0c XL |
54 | /// Codegen options strings to hand to the compiler. |
55 | pub codegen_options_strs: Vec<String>, | |
a1dfa0c6 XL |
56 | /// Debugging (`-Z`) options to pass to the compiler. |
57 | pub debugging_options: DebuggingOptions, | |
e74abb32 XL |
58 | /// Debugging (`-Z`) options strings to pass to the compiler. |
59 | pub debugging_options_strs: Vec<String>, | |
a1dfa0c6 | 60 | /// The target used to compile the crate against. |
e1599b0c | 61 | pub target: TargetTriple, |
a1dfa0c6 XL |
62 | /// Edition used when reading the crate. Defaults to "2015". Also used by default when |
63 | /// compiling doctests from the crate. | |
64 | pub edition: Edition, | |
65 | /// The path to the sysroot. Used during the compilation process. | |
66 | pub maybe_sysroot: Option<PathBuf>, | |
a1dfa0c6 XL |
67 | /// Lint information passed over the command-line. |
68 | pub lint_opts: Vec<(String, Level)>, | |
69 | /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be | |
70 | /// used, since we abort if we have no input file, but it's included for completeness. | |
71 | pub describe_lints: bool, | |
72 | /// What level to cap lints at. | |
73 | pub lint_cap: Option<Level>, | |
74 | ||
75 | // Options specific to running doctests | |
a1dfa0c6 XL |
76 | /// Whether we should run doctests instead of generating docs. |
77 | pub should_test: bool, | |
78 | /// List of arguments to pass to the test harness, if running tests. | |
79 | pub test_args: Vec<String>, | |
9fa01778 XL |
80 | /// Optional path to persist the doctest executables to, defaults to a |
81 | /// temporary directory if not set. | |
82 | pub persist_doctests: Option<PathBuf>, | |
e1599b0c XL |
83 | /// Runtool to run doctests with |
84 | pub runtool: Option<String>, | |
85 | /// Arguments to pass to the runtool | |
86 | pub runtool_args: Vec<String>, | |
87 | /// Whether to allow ignoring doctests on a per-target basis | |
88 | /// For example, using ignore-foo to ignore running the doctest on any target that | |
89 | /// contains "foo" as a substring | |
90 | pub enable_per_target_ignores: bool, | |
91 | ||
92 | /// The path to a rustc-like binary to build tests with. If not set, we | |
93 | /// default to loading from $sysroot/bin/rustc. | |
94 | pub test_builder: Option<PathBuf>, | |
a1dfa0c6 XL |
95 | |
96 | // Options that affect the documentation process | |
a1dfa0c6 XL |
97 | /// The selected default set of passes to use. |
98 | /// | |
99 | /// Be aware: This option can come both from the CLI and from crate attributes! | |
100 | pub default_passes: DefaultPassOption, | |
60c5eb7d XL |
101 | /// Document items that have lower than `pub` visibility. |
102 | pub document_private: bool, | |
103 | /// Document items that have `doc(hidden)`. | |
104 | pub document_hidden: bool, | |
a1dfa0c6 XL |
105 | /// Any passes manually selected by the user. |
106 | /// | |
107 | /// Be aware: This option can come both from the CLI and from crate attributes! | |
108 | pub manual_passes: Vec<String>, | |
109 | /// Whether to display warnings during doc generation or while gathering doctests. By default, | |
110 | /// all non-rustdoc-specific lints are allowed when generating docs. | |
111 | pub display_warnings: bool, | |
532ac7d7 XL |
112 | /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items |
113 | /// with and without documentation. | |
114 | pub show_coverage: bool, | |
a1dfa0c6 XL |
115 | |
116 | // Options that alter generated documentation pages | |
a1dfa0c6 XL |
117 | /// Crate version to note on the sidebar of generated docs. |
118 | pub crate_version: Option<String>, | |
119 | /// Collected options specific to outputting final pages. | |
120 | pub render_options: RenderOptions, | |
121 | } | |
122 | ||
123 | impl fmt::Debug for Options { | |
9fa01778 | 124 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 XL |
125 | struct FmtExterns<'a>(&'a Externs); |
126 | ||
127 | impl<'a> fmt::Debug for FmtExterns<'a> { | |
9fa01778 | 128 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
60c5eb7d | 129 | f.debug_map().entries(self.0.iter()).finish() |
a1dfa0c6 XL |
130 | } |
131 | } | |
132 | ||
133 | f.debug_struct("Options") | |
134 | .field("input", &self.input) | |
135 | .field("crate_name", &self.crate_name) | |
e1599b0c | 136 | .field("proc_macro_crate", &self.proc_macro_crate) |
a1dfa0c6 XL |
137 | .field("error_format", &self.error_format) |
138 | .field("libs", &self.libs) | |
139 | .field("externs", &FmtExterns(&self.externs)) | |
140 | .field("cfgs", &self.cfgs) | |
141 | .field("codegen_options", &"...") | |
142 | .field("debugging_options", &"...") | |
143 | .field("target", &self.target) | |
144 | .field("edition", &self.edition) | |
145 | .field("maybe_sysroot", &self.maybe_sysroot) | |
a1dfa0c6 XL |
146 | .field("lint_opts", &self.lint_opts) |
147 | .field("describe_lints", &self.describe_lints) | |
148 | .field("lint_cap", &self.lint_cap) | |
149 | .field("should_test", &self.should_test) | |
150 | .field("test_args", &self.test_args) | |
9fa01778 | 151 | .field("persist_doctests", &self.persist_doctests) |
a1dfa0c6 | 152 | .field("default_passes", &self.default_passes) |
60c5eb7d XL |
153 | .field("document_private", &self.document_private) |
154 | .field("document_hidden", &self.document_hidden) | |
a1dfa0c6 XL |
155 | .field("manual_passes", &self.manual_passes) |
156 | .field("display_warnings", &self.display_warnings) | |
532ac7d7 | 157 | .field("show_coverage", &self.show_coverage) |
a1dfa0c6 XL |
158 | .field("crate_version", &self.crate_version) |
159 | .field("render_options", &self.render_options) | |
e1599b0c XL |
160 | .field("runtool", &self.runtool) |
161 | .field("runtool_args", &self.runtool_args) | |
162 | .field("enable-per-target-ignores", &self.enable_per_target_ignores) | |
a1dfa0c6 XL |
163 | .finish() |
164 | } | |
165 | } | |
166 | ||
167 | /// Configuration options for the HTML page-creation process. | |
168 | #[derive(Clone, Debug)] | |
169 | pub struct RenderOptions { | |
170 | /// Output directory to generate docs into. Defaults to `doc`. | |
171 | pub output: PathBuf, | |
172 | /// External files to insert into generated pages. | |
173 | pub external_html: ExternalHtml, | |
174 | /// A pre-populated `IdMap` with the default headings and any headings added by Markdown files | |
175 | /// processed by `external_html`. | |
176 | pub id_map: IdMap, | |
177 | /// If present, playground URL to use in the "Run" button added to code samples. | |
178 | /// | |
179 | /// Be aware: This option can come both from the CLI and from crate attributes! | |
180 | pub playground_url: Option<String>, | |
181 | /// Whether to sort modules alphabetically on a module page instead of using declaration order. | |
182 | /// `true` by default. | |
9fa01778 XL |
183 | // |
184 | // FIXME(misdreavus): the flag name is `--sort-modules-by-appearance` but the meaning is | |
185 | // inverted once read. | |
a1dfa0c6 XL |
186 | pub sort_modules_alphabetically: bool, |
187 | /// List of themes to extend the docs with. Original argument name is included to assist in | |
188 | /// displaying errors if it fails a theme check. | |
189 | pub themes: Vec<PathBuf>, | |
190 | /// If present, CSS file that contains rules to add to the default CSS. | |
191 | pub extension_css: Option<PathBuf>, | |
192 | /// A map of crate names to the URL to use instead of querying the crate's `html_root_url`. | |
193 | pub extern_html_root_urls: BTreeMap<String, String>, | |
194 | /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages. | |
195 | pub resource_suffix: String, | |
196 | /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by | |
197 | /// default. | |
9fa01778 XL |
198 | // |
199 | // FIXME(misdreavus): the flag name is `--disable-minification` but the meaning is inverted | |
200 | // once read. | |
a1dfa0c6 XL |
201 | pub enable_minification: bool, |
202 | /// Whether to create an index page in the root of the output directory. If this is true but | |
203 | /// `enable_index_page` is None, generate a static listing of crates instead. | |
204 | pub enable_index_page: bool, | |
205 | /// A file to use as the index page at the root of the output directory. Overrides | |
206 | /// `enable_index_page` to be true if set. | |
207 | pub index_page: Option<PathBuf>, | |
0731742a XL |
208 | /// An optional path to use as the location of static files. If not set, uses combinations of |
209 | /// `../` to reach the documentation root. | |
210 | pub static_root_path: Option<String>, | |
a1dfa0c6 XL |
211 | |
212 | // Options specific to reading standalone Markdown files | |
a1dfa0c6 XL |
213 | /// Whether to generate a table of contents on the output file when reading a standalone |
214 | /// Markdown file. | |
215 | pub markdown_no_toc: bool, | |
216 | /// Additional CSS files to link in pages generated from standalone Markdown files. | |
217 | pub markdown_css: Vec<String>, | |
218 | /// If present, playground URL to use in the "Run" button added to code samples generated from | |
219 | /// standalone Markdown files. If not present, `playground_url` is used. | |
220 | pub markdown_playground_url: Option<String>, | |
0731742a XL |
221 | /// If false, the `select` element to have search filtering by crates on rendered docs |
222 | /// won't be generated. | |
223 | pub generate_search_filter: bool, | |
9fa01778 XL |
224 | /// Option (disabled by default) to generate files used by RLS and some other tools. |
225 | pub generate_redirect_pages: bool, | |
a1dfa0c6 XL |
226 | } |
227 | ||
228 | impl Options { | |
229 | /// Parses the given command-line for options. If an error message or other early-return has | |
230 | /// been printed, returns `Err` with the exit code. | |
532ac7d7 | 231 | pub fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> { |
a1dfa0c6 XL |
232 | // Check for unstable options. |
233 | nightly_options::check_nightly_options(&matches, &opts()); | |
234 | ||
235 | if matches.opt_present("h") || matches.opt_present("help") { | |
9fa01778 | 236 | crate::usage("rustdoc"); |
a1dfa0c6 XL |
237 | return Err(0); |
238 | } else if matches.opt_present("version") { | |
239 | rustc_driver::version("rustdoc", &matches); | |
240 | return Err(0); | |
241 | } | |
242 | ||
243 | if matches.opt_strs("passes") == ["list"] { | |
244 | println!("Available passes for running rustdoc:"); | |
245 | for pass in passes::PASSES { | |
532ac7d7 | 246 | println!("{:>20} - {}", pass.name, pass.description); |
a1dfa0c6 XL |
247 | } |
248 | println!("\nDefault passes for rustdoc:"); | |
60c5eb7d XL |
249 | for p in passes::DEFAULT_PASSES { |
250 | print!("{:>20}", p.pass.name); | |
251 | println_condition(p.condition); | |
a1dfa0c6 | 252 | } |
532ac7d7 XL |
253 | |
254 | if nightly_options::is_nightly_build() { | |
255 | println!("\nPasses run with `--show-coverage`:"); | |
60c5eb7d XL |
256 | for p in passes::COVERAGE_PASSES { |
257 | print!("{:>20}", p.pass.name); | |
258 | println_condition(p.condition); | |
532ac7d7 | 259 | } |
60c5eb7d XL |
260 | } |
261 | ||
262 | fn println_condition(condition: Condition) { | |
263 | use Condition::*; | |
264 | match condition { | |
265 | Always => println!(), | |
266 | WhenDocumentPrivate => println!(" (when --document-private-items)"), | |
267 | WhenNotDocumentPrivate => println!(" (when not --document-private-items)"), | |
268 | WhenNotDocumentHidden => println!(" (when not --document-hidden-items)"), | |
532ac7d7 XL |
269 | } |
270 | } | |
271 | ||
a1dfa0c6 XL |
272 | return Err(0); |
273 | } | |
274 | ||
416331ca XL |
275 | let color = session::config::parse_color(&matches); |
276 | let (json_rendered, _artifacts) = session::config::parse_json(&matches); | |
277 | let error_format = session::config::parse_error_format(&matches, color, json_rendered); | |
a1dfa0c6 XL |
278 | |
279 | let codegen_options = build_codegen_options(matches, error_format); | |
280 | let debugging_options = build_debugging_options(matches, error_format); | |
281 | ||
60c5eb7d XL |
282 | let diag = new_handler( |
283 | error_format, | |
284 | None, | |
285 | debugging_options.treat_err_as_bug, | |
286 | debugging_options.ui_testing, | |
287 | ); | |
a1dfa0c6 XL |
288 | |
289 | // check for deprecated options | |
290 | check_deprecated_options(&matches, &diag); | |
291 | ||
60c5eb7d | 292 | let to_check = matches.opt_strs("check-theme"); |
a1dfa0c6 XL |
293 | if !to_check.is_empty() { |
294 | let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes()); | |
295 | let mut errors = 0; | |
296 | ||
60c5eb7d | 297 | println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)"); |
a1dfa0c6 XL |
298 | for theme_file in to_check.iter() { |
299 | print!(" - Checking \"{}\"...", theme_file); | |
300 | let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag); | |
301 | if !differences.is_empty() || !success { | |
302 | println!(" FAILED"); | |
303 | errors += 1; | |
304 | if !differences.is_empty() { | |
305 | println!("{}", differences.join("\n")); | |
306 | } | |
307 | } else { | |
308 | println!(" OK"); | |
309 | } | |
310 | } | |
311 | if errors != 0 { | |
312 | return Err(1); | |
313 | } | |
314 | return Err(0); | |
315 | } | |
316 | ||
317 | if matches.free.is_empty() { | |
318 | diag.struct_err("missing file operand").emit(); | |
319 | return Err(1); | |
320 | } | |
321 | if matches.free.len() > 1 { | |
322 | diag.struct_err("too many file operands").emit(); | |
323 | return Err(1); | |
324 | } | |
325 | let input = PathBuf::from(&matches.free[0]); | |
326 | ||
60c5eb7d XL |
327 | let libs = matches |
328 | .opt_strs("L") | |
329 | .iter() | |
0731742a XL |
330 | .map(|s| SearchPath::from_cli_opt(s, error_format)) |
331 | .collect(); | |
60c5eb7d | 332 | let externs = parse_externs(&matches, &debugging_options, error_format); |
a1dfa0c6 XL |
333 | let extern_html_root_urls = match parse_extern_html_roots(&matches) { |
334 | Ok(ex) => ex, | |
335 | Err(err) => { | |
336 | diag.struct_err(err).emit(); | |
337 | return Err(1); | |
338 | } | |
339 | }; | |
340 | ||
341 | let test_args = matches.opt_strs("test-args"); | |
60c5eb7d XL |
342 | let test_args: Vec<String> = |
343 | test_args.iter().flat_map(|s| s.split_whitespace()).map(|s| s.to_string()).collect(); | |
a1dfa0c6 XL |
344 | |
345 | let should_test = matches.opt_present("test"); | |
346 | ||
60c5eb7d XL |
347 | let output = |
348 | matches.opt_str("o").map(|s| PathBuf::from(&s)).unwrap_or_else(|| PathBuf::from("doc")); | |
e74abb32 | 349 | let cfgs = matches.opt_strs("cfg"); |
a1dfa0c6 XL |
350 | |
351 | let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s)); | |
352 | ||
353 | if let Some(ref p) = extension_css { | |
354 | if !p.is_file() { | |
355 | diag.struct_err("option --extend-css argument must be a file").emit(); | |
356 | return Err(1); | |
357 | } | |
358 | } | |
359 | ||
360 | let mut themes = Vec::new(); | |
60c5eb7d | 361 | if matches.opt_present("theme") { |
a1dfa0c6 XL |
362 | let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes()); |
363 | ||
60c5eb7d XL |
364 | for (theme_file, theme_s) in |
365 | matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned())) | |
366 | { | |
a1dfa0c6 | 367 | if !theme_file.is_file() { |
60c5eb7d XL |
368 | diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)) |
369 | .help("arguments to --theme must be files") | |
370 | .emit(); | |
371 | return Err(1); | |
372 | } | |
373 | if theme_file.extension() != Some(OsStr::new("css")) { | |
374 | diag.struct_err(&format!("invalid argument: \"{}\"", theme_s)).emit(); | |
a1dfa0c6 XL |
375 | return Err(1); |
376 | } | |
377 | let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag); | |
60c5eb7d XL |
378 | if !success { |
379 | diag.struct_err(&format!("error loading theme file: \"{}\"", theme_s)).emit(); | |
a1dfa0c6 | 380 | return Err(1); |
60c5eb7d XL |
381 | } else if !ret.is_empty() { |
382 | diag.struct_warn(&format!( | |
383 | "theme file \"{}\" is missing CSS rules from the \ | |
384 | default theme", | |
385 | theme_s | |
386 | )) | |
387 | .warn("the theme may appear incorrect when loaded") | |
388 | .help(&format!( | |
389 | "to see what rules are missing, call `rustdoc \ | |
390 | --check-theme \"{}\"`", | |
391 | theme_s | |
392 | )) | |
393 | .emit(); | |
a1dfa0c6 XL |
394 | } |
395 | themes.push(theme_file); | |
396 | } | |
397 | } | |
398 | ||
48663c56 XL |
399 | let edition = if let Some(e) = matches.opt_str("edition") { |
400 | match e.parse() { | |
401 | Ok(e) => e, | |
402 | Err(_) => { | |
403 | diag.struct_err("could not parse edition").emit(); | |
404 | return Err(1); | |
405 | } | |
406 | } | |
407 | } else { | |
408 | DEFAULT_EDITION | |
409 | }; | |
410 | ||
a1dfa0c6 XL |
411 | let mut id_map = html::markdown::IdMap::new(); |
412 | id_map.populate(html::render::initial_ids()); | |
413 | let external_html = match ExternalHtml::load( | |
60c5eb7d XL |
414 | &matches.opt_strs("html-in-header"), |
415 | &matches.opt_strs("html-before-content"), | |
416 | &matches.opt_strs("html-after-content"), | |
417 | &matches.opt_strs("markdown-before-content"), | |
418 | &matches.opt_strs("markdown-after-content"), | |
419 | &diag, | |
420 | &mut id_map, | |
421 | edition, | |
422 | &None, | |
423 | ) { | |
a1dfa0c6 XL |
424 | Some(eh) => eh, |
425 | None => return Err(3), | |
426 | }; | |
427 | ||
a1dfa0c6 XL |
428 | match matches.opt_str("r").as_ref().map(|s| &**s) { |
429 | Some("rust") | None => {} | |
430 | Some(s) => { | |
431 | diag.struct_err(&format!("unknown input format: {}", s)).emit(); | |
432 | return Err(1); | |
433 | } | |
434 | } | |
435 | ||
436 | match matches.opt_str("w").as_ref().map(|s| &**s) { | |
437 | Some("html") | None => {} | |
438 | Some(s) => { | |
439 | diag.struct_err(&format!("unknown output format: {}", s)).emit(); | |
440 | return Err(1); | |
441 | } | |
442 | } | |
443 | ||
444 | let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); | |
445 | if let Some(ref index_page) = index_page { | |
446 | if !index_page.is_file() { | |
447 | diag.struct_err("option `--index-page` argument must be a file").emit(); | |
448 | return Err(1); | |
449 | } | |
450 | } | |
451 | ||
60c5eb7d XL |
452 | let target = |
453 | matches.opt_str("target").map_or(TargetTriple::from_triple(host_triple()), |target| { | |
454 | if target.ends_with(".json") { | |
455 | TargetTriple::TargetPath(PathBuf::from(target)) | |
456 | } else { | |
457 | TargetTriple::TargetTriple(target) | |
458 | } | |
459 | }); | |
a1dfa0c6 | 460 | |
532ac7d7 | 461 | let show_coverage = matches.opt_present("show-coverage"); |
532ac7d7 | 462 | |
a1dfa0c6 XL |
463 | let default_passes = if matches.opt_present("no-defaults") { |
464 | passes::DefaultPassOption::None | |
532ac7d7 XL |
465 | } else if show_coverage { |
466 | passes::DefaultPassOption::Coverage | |
a1dfa0c6 XL |
467 | } else { |
468 | passes::DefaultPassOption::Default | |
469 | }; | |
470 | let manual_passes = matches.opt_strs("passes"); | |
471 | ||
e1599b0c XL |
472 | let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) { |
473 | Ok(types) => types, | |
60c5eb7d | 474 | Err(e) => { |
e1599b0c XL |
475 | diag.struct_err(&format!("unknown crate type: {}", e)).emit(); |
476 | return Err(1); | |
477 | } | |
478 | }; | |
479 | ||
a1dfa0c6 | 480 | let crate_name = matches.opt_str("crate-name"); |
e1599b0c | 481 | let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); |
a1dfa0c6 XL |
482 | let playground_url = matches.opt_str("playground-url"); |
483 | let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); | |
484 | let display_warnings = matches.opt_present("display-warnings"); | |
a1dfa0c6 XL |
485 | let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); |
486 | let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default(); | |
487 | let enable_minification = !matches.opt_present("disable-minification"); | |
488 | let markdown_no_toc = matches.opt_present("markdown-no-toc"); | |
489 | let markdown_css = matches.opt_strs("markdown-css"); | |
490 | let markdown_playground_url = matches.opt_str("markdown-playground-url"); | |
491 | let crate_version = matches.opt_str("crate-version"); | |
492 | let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); | |
0731742a XL |
493 | let static_root_path = matches.opt_str("static-root-path"); |
494 | let generate_search_filter = !matches.opt_present("disable-per-crate-search"); | |
9fa01778 XL |
495 | let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from); |
496 | let generate_redirect_pages = matches.opt_present("generate-redirect-pages"); | |
e1599b0c XL |
497 | let test_builder = matches.opt_str("test-builder").map(PathBuf::from); |
498 | let codegen_options_strs = matches.opt_strs("C"); | |
e74abb32 | 499 | let debugging_options_strs = matches.opt_strs("Z"); |
e1599b0c XL |
500 | let lib_strs = matches.opt_strs("L"); |
501 | let extern_strs = matches.opt_strs("extern"); | |
502 | let runtool = matches.opt_str("runtool"); | |
503 | let runtool_args = matches.opt_strs("runtool-arg"); | |
504 | let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); | |
60c5eb7d XL |
505 | let document_private = matches.opt_present("document-private-items"); |
506 | let document_hidden = matches.opt_present("document-hidden-items"); | |
a1dfa0c6 XL |
507 | |
508 | let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); | |
509 | ||
510 | Ok(Options { | |
511 | input, | |
512 | crate_name, | |
e1599b0c | 513 | proc_macro_crate, |
a1dfa0c6 XL |
514 | error_format, |
515 | libs, | |
e1599b0c | 516 | lib_strs, |
a1dfa0c6 | 517 | externs, |
e1599b0c | 518 | extern_strs, |
a1dfa0c6 XL |
519 | cfgs, |
520 | codegen_options, | |
e1599b0c | 521 | codegen_options_strs, |
a1dfa0c6 | 522 | debugging_options, |
e74abb32 | 523 | debugging_options_strs, |
a1dfa0c6 XL |
524 | target, |
525 | edition, | |
526 | maybe_sysroot, | |
a1dfa0c6 XL |
527 | lint_opts, |
528 | describe_lints, | |
529 | lint_cap, | |
530 | should_test, | |
531 | test_args, | |
532 | default_passes, | |
60c5eb7d XL |
533 | document_private, |
534 | document_hidden, | |
a1dfa0c6 XL |
535 | manual_passes, |
536 | display_warnings, | |
532ac7d7 | 537 | show_coverage, |
a1dfa0c6 | 538 | crate_version, |
9fa01778 | 539 | persist_doctests, |
e1599b0c XL |
540 | runtool, |
541 | runtool_args, | |
542 | enable_per_target_ignores, | |
543 | test_builder, | |
a1dfa0c6 XL |
544 | render_options: RenderOptions { |
545 | output, | |
546 | external_html, | |
547 | id_map, | |
548 | playground_url, | |
549 | sort_modules_alphabetically, | |
550 | themes, | |
551 | extension_css, | |
552 | extern_html_root_urls, | |
553 | resource_suffix, | |
554 | enable_minification, | |
555 | enable_index_page, | |
556 | index_page, | |
0731742a | 557 | static_root_path, |
a1dfa0c6 XL |
558 | markdown_no_toc, |
559 | markdown_css, | |
560 | markdown_playground_url, | |
0731742a | 561 | generate_search_filter, |
9fa01778 | 562 | generate_redirect_pages, |
60c5eb7d | 563 | }, |
a1dfa0c6 XL |
564 | }) |
565 | } | |
566 | ||
9fa01778 | 567 | /// Returns `true` if the file given as `self.input` is a Markdown file. |
a1dfa0c6 | 568 | pub fn markdown_input(&self) -> bool { |
60c5eb7d | 569 | self.input.extension().map_or(false, |e| e == "md" || e == "markdown") |
a1dfa0c6 XL |
570 | } |
571 | } | |
572 | ||
573 | /// Prints deprecation warnings for deprecated options | |
574 | fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) { | |
60c5eb7d | 575 | let deprecated_flags = ["input-format", "output-format", "no-defaults", "passes"]; |
a1dfa0c6 | 576 | |
48663c56 | 577 | for flag in deprecated_flags.iter() { |
a1dfa0c6 | 578 | if matches.opt_present(flag) { |
60c5eb7d XL |
579 | let mut err = |
580 | diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag)); | |
a1dfa0c6 XL |
581 | err.warn("please see https://github.com/rust-lang/rust/issues/44136"); |
582 | ||
583 | if *flag == "no-defaults" { | |
584 | err.help("you may want to use --document-private-items"); | |
585 | } | |
586 | ||
587 | err.emit(); | |
588 | } | |
589 | } | |
590 | ||
60c5eb7d | 591 | let removed_flags = ["plugins", "plugin-path"]; |
a1dfa0c6 XL |
592 | |
593 | for &flag in removed_flags.iter() { | |
594 | if matches.opt_present(flag) { | |
595 | diag.struct_warn(&format!("the '{}' flag no longer functions", flag)) | |
596 | .warn("see CVE-2018-1000622") | |
597 | .emit(); | |
598 | } | |
599 | } | |
600 | } | |
601 | ||
602 | /// Extracts `--extern-html-root-url` arguments from `matches` and returns a map of crate names to | |
603 | /// the given URLs. If an `--extern-html-root-url` argument was ill-formed, returns an error | |
604 | /// describing the issue. | |
605 | fn parse_extern_html_roots( | |
606 | matches: &getopts::Matches, | |
607 | ) -> Result<BTreeMap<String, String>, &'static str> { | |
608 | let mut externs = BTreeMap::new(); | |
609 | for arg in &matches.opt_strs("extern-html-root-url") { | |
610 | let mut parts = arg.splitn(2, '='); | |
611 | let name = parts.next().ok_or("--extern-html-root-url must not be empty")?; | |
612 | let url = parts.next().ok_or("--extern-html-root-url must be of the form name=url")?; | |
613 | externs.insert(name.to_string(), url.to_string()); | |
614 | } | |
615 | ||
616 | Ok(externs) | |
617 | } |