diff options
| author | bors <bors@rust-lang.org> | 2024-05-18 10:53:47 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-05-18 10:53:47 +0000 |
| commit | bb97203e37bbdd4588bd684728002077d0073978 (patch) | |
| tree | 7854c16653291ce69a8cc0af87ed13a9e43b75a2 | |
| parent | 1c90b9fe6eac122b4d3965913b3615f47751a4d3 (diff) | |
| parent | 7e1dc742d620123f251c696c8aae864a226d1c89 (diff) | |
| download | rust-bb97203e37bbdd4588bd684728002077d0073978.tar.gz rust-bb97203e37bbdd4588bd684728002077d0073978.zip | |
Auto merge of #124611 - Urgau:rustdoc-stdin, r=GuillaumeGomez
Add `-` (stdin) support in rustdoc This PR adds support for the special `-` input which threats the input as coming from *stdin* instead of being a filepath. Doing this also makes `rustdoc` consistent with `rustc` and ~~every~~ other tools. Full [motivation](https://github.com/rust-lang/rust/pull/124611#issuecomment-2094234876). Fixes https://github.com/rust-lang/rust/issues/123671 r? `@fmease`
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 1 | ||||
| -rw-r--r-- | src/doc/rustdoc/src/command-line-arguments.md | 6 | ||||
| -rw-r--r-- | src/librustdoc/config.rs | 51 | ||||
| -rw-r--r-- | src/librustdoc/core.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/doctest.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 10 | ||||
| -rw-r--r-- | src/librustdoc/markdown.rs | 14 | ||||
| -rw-r--r-- | tests/run-make/stdin-rustdoc/rmake.rs | 25 |
8 files changed, 86 insertions, 29 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f2bdabbf394..7dd9fdf60f9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -798,6 +798,7 @@ pub enum DumpSolverProofTree { Never, } +#[derive(Clone)] pub enum Input { /// Load source code from a file. File(PathBuf), diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 69fb7e3313f..3e104bdb470 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 d4468fecba4..012afada1e5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,6 +1,9 @@ use std::collections::BTreeMap; use std::ffi::OsStr; use std::fmt; +use std::io; +use std::io::Read; +use std::path::Path; use std::path::PathBuf; use std::str::FromStr; @@ -9,14 +12,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 +63,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 +182,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) @@ -320,6 +323,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. @@ -447,15 +467,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) { @@ -792,8 +813,10 @@ 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") + pub(crate) fn markdown_input(&self) -> Option<&Path> { + self.input + .opt_path() + .filter(|p| matches!(p.extension(), Some(e) if 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