diff options
| author | Urgau <urgau@numericable.fr> | 2024-05-01 23:42:59 +0200 |
|---|---|---|
| committer | Urgau <urgau@numericable.fr> | 2024-05-04 17:52:35 +0200 |
| commit | 1193e965a3d3169f5543e5f5de680a4b9feea1d9 (patch) | |
| tree | 30bd3029de0f3cac1252fd968262f03ce990364b | |
| parent | c773b19540a30a6ffa80ec11c1013616b99c2633 (diff) | |
| download | rust-1193e965a3d3169f5543e5f5de680a4b9feea1d9.tar.gz rust-1193e965a3d3169f5543e5f5de680a4b9feea1d9.zip | |
Add `-` (stdin) support to rustdoc
| -rw-r--r-- | src/doc/rustdoc/src/command-line-arguments.md | 6 | ||||
| -rw-r--r-- | src/librustdoc/config.rs | 50 | ||||
| -rw-r--r-- | src/librustdoc/core.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/doctest.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 7 | ||||
| -rw-r--r-- | src/librustdoc/markdown.rs | 14 | ||||
| -rw-r--r-- | tests/run-make/stdin-rustdoc/rmake.rs | 25 |
7 files changed, 86 insertions, 24 deletions
diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 822f341b370..9edfb873f0b 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -417,6 +417,12 @@ When `rustdoc` receives this flag, it will print an extra "Version (version)" in the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation. +## `-`: load source code from the standard input + +If you specify `-` as the INPUT on the command line, then `rustdoc` will read the +source code from stdin (standard input stream) until the EOF, instead of the file +system with an otherwise specified path. + ## `@path`: load command-line flags from a path If you specify `@path` on the command-line, then it will open `path` and read diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 465f969435d..c3236d4c9c5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; use std::ffi::OsStr; use std::fmt; +use std::io; +use std::io::Read; use std::path::PathBuf; use std::str::FromStr; @@ -9,14 +11,14 @@ 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}; -use rustc_session::config::{ - CodegenOptions, ErrorOutputType, Externs, JsonUnusedExterns, UnstableOptions, -}; +use rustc_session::config::{CodegenOptions, ErrorOutputType, Externs, Input}; +use rustc_session::config::{JsonUnusedExterns, UnstableOptions}; use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::EarlyDiagCtxt; use rustc_span::edition::Edition; +use rustc_span::FileName; use rustc_target::spec::TargetTriple; use crate::core::new_dcx; @@ -60,7 +62,7 @@ impl TryFrom<&str> for OutputFormat { pub(crate) struct Options { // Basic options / Options passed directly to rustc /// The crate root or Markdown file to load. - pub(crate) input: PathBuf, + pub(crate) input: Input, /// The name of the crate being documented. pub(crate) crate_name: Option<String>, /// Whether or not this is a bin crate @@ -179,7 +181,7 @@ impl fmt::Debug for Options { } f.debug_struct("Options") - .field("input", &self.input) + .field("input", &self.input.source_name()) .field("crate_name", &self.crate_name) .field("bin_crate", &self.bin_crate) .field("proc_macro_crate", &self.proc_macro_crate) @@ -322,6 +324,23 @@ impl RenderOptions { } } +/// Create the input (string or file path) +/// +/// Warning: Return an unrecoverable error in case of error! +fn make_input(early_dcx: &EarlyDiagCtxt, input: &str) -> Input { + if input == "-" { + let mut src = String::new(); + if io::stdin().read_to_string(&mut src).is_err() { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + early_dcx.early_fatal("couldn't read from stdin, as it did not contain valid UTF-8"); + } + Input::Str { name: FileName::anon_source_code(&src), input: src } + } else { + Input::File(PathBuf::from(input)) + } +} + 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. @@ -450,15 +469,16 @@ impl Options { let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); - let input = PathBuf::from(if describe_lints { + let input = if describe_lints { "" // dummy, this won't be used - } else if matches.free.is_empty() { - dcx.fatal("missing file operand"); - } else if matches.free.len() > 1 { - dcx.fatal("too many file operands"); } else { - &matches.free[0] - }); + match matches.free.as_slice() { + [] => dcx.fatal("missing file operand"), + [input] => input, + _ => dcx.fatal("too many file operands"), + } + }; + let input = make_input(early_dcx, &input); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { @@ -797,7 +817,11 @@ impl Options { /// Returns `true` if the file given as `self.input` is a Markdown file. pub(crate) fn markdown_input(&self) -> bool { - self.input.extension().is_some_and(|e| e == "md" || e == "markdown") + self.input + .opt_path() + .map(std::path::Path::extension) + .flatten() + .is_some_and(|e| e == "md" || e == "markdown") } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 25b78d9598d..feb03b9a823 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -32,7 +32,7 @@ use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; use crate::passes::{self, Condition::*}; -pub(crate) use rustc_session::config::{Input, Options, UnstableOptions}; +pub(crate) use rustc_session::config::{Options, UnstableOptions}; pub(crate) struct DocContext<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, @@ -204,8 +204,6 @@ pub(crate) fn create_config( // Add the doc cfg into the doc build. cfgs.push("doc".to_string()); - let input = Input::File(input); - // By default, rustdoc ignores all lints. // Specifically unblock lints relevant to documentation or the lint machinery itself. let mut lints_to_show = vec