Auto merge of #129337 - EtomicBomb:rfc, r=notriddle · rust-lang/rust@f827364 (original) (raw)
`@@ -53,12 +53,18 @@ impl TryFrom<&str> for OutputFormat {
`
53
53
`}
`
54
54
`}
`
55
55
``
``
56
`+
/// Either an input crate, markdown file, or nothing (--merge=finalize).
`
``
57
`+
pub(crate) enum InputMode {
`
``
58
`` +
/// The --merge=finalize
step does not need an input crate to rustdoc.
``
``
59
`+
NoInputMergeFinalize,
`
``
60
`+
/// A crate or markdown file.
`
``
61
`+
HasFile(Input),
`
``
62
`+
}
`
``
63
+
56
64
`/// Configuration options for rustdoc.
`
57
65
`#[derive(Clone)]
`
58
66
`pub(crate) struct Options {
`
59
67
`// Basic options / Options passed directly to rustc
`
60
``
`-
/// The crate root or Markdown file to load.
`
61
``
`-
pub(crate) input: Input,
`
62
68
`/// The name of the crate being documented.
`
63
69
`pub(crate) crate_name: Option,
`
64
70
`/// Whether or not this is a bin crate
`
`@@ -179,7 +185,6 @@ impl fmt::Debug for Options {
`
179
185
`}
`
180
186
``
181
187
` f.debug_struct("Options")
`
182
``
`-
.field("input", &self.input.source_name())
`
183
188
`.field("crate_name", &self.crate_name)
`
184
189
`.field("bin_crate", &self.bin_crate)
`
185
190
`.field("proc_macro_crate", &self.proc_macro_crate)
`
`@@ -289,6 +294,12 @@ pub(crate) struct RenderOptions {
`
289
294
`/// This field is only used for the JSON output. If it's set to true, no file will be created
`
290
295
`/// and content will be displayed in stdout directly.
`
291
296
`pub(crate) output_to_stdout: bool,
`
``
297
`+
/// Whether we should read or write rendered cross-crate info in the doc root.
`
``
298
`+
pub(crate) should_merge: ShouldMerge,
`
``
299
`+
/// Path to crate-info for external crates.
`
``
300
`+
pub(crate) include_parts_dir: Vec,
`
``
301
`+
/// Where to write crate-info
`
``
302
`+
pub(crate) parts_out_dir: Option,
`
292
303
`}
`
293
304
``
294
305
`#[derive(Copy, Clone, Debug, PartialEq, Eq)]
`
`@@ -348,7 +359,7 @@ impl Options {
`
348
359
`early_dcx: &mut EarlyDiagCtxt,
`
349
360
`matches: &getopts::Matches,
`
350
361
`args: Vec,
`
351
``
`-
) -> Option<(Options, RenderOptions)> {
`
``
362
`+
) -> Option<(InputMode, Options, RenderOptions)> {
`
352
363
`// Check for unstable options.
`
353
364
` nightly_options::check_nightly_options(early_dcx, matches, &opts());
`
354
365
``
`@@ -478,22 +489,34 @@ impl Options {
`
478
489
`let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
`
479
490
``
480
491
`let input = if describe_lints {
`
481
``
`-
"" // dummy, this won't be used
`
``
492
`+
InputMode::HasFile(make_input(early_dcx, ""))
`
482
493
`} else {
`
483
494
`match matches.free.as_slice() {
`
``
495
`+
[] if matches.opt_str("merge").as_deref() == Some("finalize") => {
`
``
496
`+
InputMode::NoInputMergeFinalize
`
``
497
`+
}
`
484
498
`[] => dcx.fatal("missing file operand"),
`
485
``
`-
[input] => input,
`
``
499
`+
[input] => InputMode::HasFile(make_input(early_dcx, input)),
`
486
500
` _ => dcx.fatal("too many file operands"),
`
487
501
`}
`
488
502
`};
`
489
``
`-
let input = make_input(early_dcx, input);
`
490
503
``
491
504
`let externs = parse_externs(early_dcx, matches, &unstable_opts);
`
492
505
`let extern_html_root_urls = match parse_extern_html_roots(matches) {
`
493
506
`Ok(ex) => ex,
`
494
507
`Err(err) => dcx.fatal(err),
`
495
508
`};
`
496
509
``
``
510
`+
let parts_out_dir =
`
``
511
`+
match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() {
`
``
512
`+
Ok(parts_out_dir) => parts_out_dir,
`
``
513
`+
Err(e) => dcx.fatal(e),
`
``
514
`+
};
`
``
515
`+
let include_parts_dir = match parse_include_parts_dir(matches) {
`
``
516
`+
Ok(include_parts_dir) => include_parts_dir,
`
``
517
`+
Err(e) => dcx.fatal(e),
`
``
518
`+
};
`
``
519
+
497
520
`let default_settings: Vec<Vec<(String, String)>> = vec![
`
498
521
` matches
`
499
522
`.opt_str("default-theme")
`
`@@ -735,6 +758,10 @@ impl Options {
`
735
758
`let extern_html_root_takes_precedence =
`
736
759
` matches.opt_present("extern-html-root-takes-precedence");
`
737
760
`let html_no_source = matches.opt_present("html-no-source");
`
``
761
`+
let should_merge = match parse_merge(matches) {
`
``
762
`+
Ok(result) => result,
`
``
763
`+
Err(e) => dcx.fatal(format!("--merge option error: {e}")),
`
``
764
`+
};
`
738
765
``
739
766
`if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) {
`
740
767
` dcx.struct_warn(
`
`@@ -751,7 +778,6 @@ impl Options {
`
751
778
`let unstable_features =
`
752
779
` rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
`
753
780
`let options = Options {
`
754
``
`-
input,
`
755
781
` bin_crate,
`
756
782
` proc_macro_crate,
`
757
783
` error_format,
`
`@@ -823,16 +849,17 @@ impl Options {
`
823
849
`no_emit_shared: false,
`
824
850
` html_no_source,
`
825
851
` output_to_stdout,
`
``
852
`+
should_merge,
`
``
853
`+
include_parts_dir,
`
``
854
`+
parts_out_dir,
`
826
855
`};
`
827
``
`-
Some((options, render_options))
`
``
856
`+
Some((input, options, render_options))
`
828
857
`}
`
``
858
`+
}
`
829
859
``
830
``
`` -
/// Returns true
if the file given as self.input
is a Markdown file.
``
831
``
`-
pub(crate) fn markdown_input(&self) -> Option<&Path> {
`
832
``
`-
self.input
`
833
``
`-
.opt_path()
`
834
``
`-
.filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
`
835
``
`-
}
`
``
860
`` +
/// Returns true
if the file given as self.input
is a Markdown file.
``
``
861
`+
pub(crate) fn markdown_input(input: &Input) -> Option<&Path> {
`
``
862
`+
input.opt_path().filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
`
836
863
`}
`
837
864
``
838
865
`fn parse_remap_path_prefix(
`
`@@ -900,3 +927,71 @@ fn parse_extern_html_roots(
`
900
927
`}
`
901
928
`Ok(externs)
`
902
929
`}
`
``
930
+
``
931
`+
/// Path directly to crate-info file.
`
``
932
`+
///
`
``
933
`` +
/// For example, /home/user/project/target/doc.parts/<crate>/crate-info
.
``
``
934
`+
#[derive(Clone, Debug)]
`
``
935
`+
pub(crate) struct PathToParts(pub(crate) PathBuf);
`
``
936
+
``
937
`+
impl PathToParts {
`
``
938
`+
fn from_flag(path: String) -> Result<PathToParts, String> {
`
``
939
`+
let mut path = PathBuf::from(path);
`
``
940
`+
// check here is for diagnostics
`
``
941
`+
if path.exists() && !path.is_dir() {
`
``
942
`+
Err(format!(
`
``
943
`+
"--parts-out-dir and --include-parts-dir expect directories, found: {}",
`
``
944
`+
path.display(),
`
``
945
`+
))
`
``
946
`+
} else {
`
``
947
`+
// if it doesn't exist, we'll create it. worry about that in write_shared
`
``
948
`+
path.push("crate-info");
`
``
949
`+
Ok(PathToParts(path))
`
``
950
`+
}
`
``
951
`+
}
`
``
952
`+
}
`
``
953
+
``
954
`+
/// Reports error if --include-parts-dir / crate-info is not a file
`
``
955
`+
fn parse_include_parts_dir(m: &getopts::Matches) -> Result<Vec, String> {
`
``
956
`+
let mut ret = Vec::new();
`
``
957
`+
for p in m.opt_strs("include-parts-dir") {
`
``
958
`+
let p = PathToParts::from_flag(p)?;
`
``
959
`+
// this is just for diagnostic
`
``
960
`+
if !p.0.is_file() {
`
``
961
`+
return Err(format!("--include-parts-dir expected {} to be a file", p.0.display()));
`
``
962
`+
}
`
``
963
`+
ret.push(p);
`
``
964
`+
}
`
``
965
`+
Ok(ret)
`
``
966
`+
}
`
``
967
+
``
968
`+
/// Controls merging of cross-crate information
`
``
969
`+
#[derive(Debug, Clone)]
`
``
970
`+
pub(crate) struct ShouldMerge {
`
``
971
`+
/// Should we append to existing cci in the doc root
`
``
972
`+
pub(crate) read_rendered_cci: bool,
`
``
973
`+
/// Should we write cci to the doc root
`
``
974
`+
pub(crate) write_rendered_cci: bool,
`
``
975
`+
}
`
``
976
+
``
977
`+
/// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or
`
``
978
`+
/// reports an error if an invalid option was provided
`
``
979
`+
fn parse_merge(m: &getopts::Matches) -> Result<ShouldMerge, &'static str> {
`
``
980
`+
match m.opt_str("merge").as_deref() {
`
``
981
`+
// default = read-write
`
``
982
`+
None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
`
``
983
`+
Some("none") if m.opt_present("include-parts-dir") => {
`
``
984
`+
Err("--include-parts-dir not allowed if --merge=none")
`
``
985
`+
}
`
``
986
`+
Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }),
`
``
987
`+
Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => {
`
``
988
`+
Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared")
`
``
989
`+
}
`
``
990
`+
Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
`
``
991
`+
Some("finalize") if m.opt_present("parts-out-dir") => {
`
``
992
`+
Err("--parts-out-dir not allowed if --merge=finalize")
`
``
993
`+
}
`
``
994
`+
Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }),
`
``
995
`` +
Some(_) => Err("argument to --merge must be none
, shared
, or finalize
"),
``
``
996
`+
}
`
``
997
`+
}
`