Skip to content

Commit 6b269e4

Browse files
committed
Auto merge of #73767 - P1n3appl3:rustdoc-formats, r=tmandry
Refactor librustdoc html backend This PR moves several types out of the librustdoc::html module so that they can be used by a future json backend. These changes are a re-implementation of [some work done 6 months ago](master...GuillaumeGomez:multiple-output-formats) by @GuillaumeGomez. I'm currently working on said json backend and will put up an RFC soon with the proposed implementation. There are a couple of changes that are more substantial than relocating structs to a different module: 1. The `Cache` is no longer part of the `html::render::Context` type and therefor it needs to be explicitly passed to any functions that access it. 2. The driving function `html::render::run` has been rewritten to use the `FormatRenderer` trait which should allow different backends to re-use the driving code. r? @GuillaumeGomez cc @tmandry @betamos
2 parents db0492a + 29df050 commit 6b269e4

File tree

15 files changed

+1203
-1072
lines changed

15 files changed

+1203
-1072
lines changed

src/librustdoc/clean/types.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ use crate::clean::inline;
3232
use crate::clean::types::Type::{QPath, ResolvedPath};
3333
use crate::core::DocContext;
3434
use crate::doctree;
35-
use crate::html::item_type::ItemType;
36-
use crate::html::render::{cache, ExternalLocation};
35+
use crate::formats::cache::cache;
36+
use crate::formats::item_type::ItemType;
37+
use crate::html::render::cache::ExternalLocation;
3738

3839
use self::FnRetTy::*;
3940
use self::ItemEnum::*;
@@ -1172,7 +1173,7 @@ impl GetDefId for Type {
11721173
fn def_id(&self) -> Option<DefId> {
11731174
match *self {
11741175
ResolvedPath { did, .. } => Some(did),
1175-
Primitive(p) => crate::html::render::cache().primitive_locations.get(&p).cloned(),
1176+
Primitive(p) => cache().primitive_locations.get(&p).cloned(),
11761177
BorrowedRef { type_: box Generic(..), .. } => {
11771178
Primitive(PrimitiveType::Reference).def_id()
11781179
}

src/librustdoc/config.rs

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ use std::ffi::OsStr;
44
use std::fmt;
55
use std::path::PathBuf;
66

7+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8+
use rustc_hir::def_id::DefId;
9+
use rustc_middle::middle::privacy::AccessLevels;
710
use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType};
811
use rustc_session::config::{
912
build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple,
@@ -249,6 +252,20 @@ pub struct RenderOptions {
249252
pub document_hidden: bool,
250253
}
251254

255+
/// Temporary storage for data obtained during `RustdocVisitor::clean()`.
256+
/// Later on moved into `CACHE_KEY`.
257+
#[derive(Default, Clone)]
258+
pub struct RenderInfo {
259+
pub inlined: FxHashSet<DefId>,
260+
pub external_paths: crate::core::ExternalPaths,
261+
pub exact_paths: FxHashMap<DefId, Vec<String>>,
262+
pub access_levels: AccessLevels<DefId>,
263+
pub deref_trait_did: Option<DefId>,
264+
pub deref_mut_trait_did: Option<DefId>,
265+
pub owned_box_did: Option<DefId>,
266+
pub output_format: Option<OutputFormat>,
267+
}
268+
252269
impl Options {
253270
/// Parses the given command-line for options. If an error message or other early-return has
254271
/// been printed, returns `Err` with the exit code.

src/librustdoc/core.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use std::rc::Rc;
3232

3333
use crate::clean;
3434
use crate::clean::{AttributesExt, MAX_DEF_ID};
35+
use crate::config::RenderInfo;
3536
use crate::config::{Options as RustdocOptions, RenderOptions};
36-
use crate::html::render::RenderInfo;
3737
use crate::passes::{self, Condition::*, ConditionalPass};
3838

3939
pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
@@ -44,9 +44,9 @@ pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
4444
pub struct DocContext<'tcx> {
4545
pub tcx: TyCtxt<'tcx>,
4646
pub resolver: Rc<RefCell<interface::BoxedResolver>>,
47-
/// Later on moved into `html::render::CACHE_KEY`
47+
/// Later on moved into `CACHE_KEY`
4848
pub renderinfo: RefCell<RenderInfo>,
49-
/// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
49+
/// Later on moved through `clean::Crate` into `CACHE_KEY`
5050
pub external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>,
5151
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
5252
/// the same time.

src/librustdoc/docfs.rs

+16-45
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use std::fs;
1313
use std::io;
1414
use std::path::Path;
1515
use std::string::ToString;
16-
use std::sync::mpsc::{channel, Receiver, Sender};
17-
use std::sync::Arc;
16+
use std::sync::mpsc::Sender;
1817

1918
macro_rules! try_err {
2019
($e:expr, $file:expr) => {
@@ -31,47 +30,24 @@ pub trait PathError {
3130
S: ToString + Sized;
3231
}
3332

34-
pub struct ErrorStorage {
35-
sender: Option<Sender<Option<String>>>,
36-
receiver: Receiver<Option<String>>,
37-
}
38-
39-
impl ErrorStorage {
40-
pub fn new() -> ErrorStorage {
41-
let (sender, receiver) = channel();
42-
ErrorStorage { sender: Some(sender), receiver }
43-
}
44-
45-
/// Prints all stored errors. Returns the number of printed errors.
46-
pub fn write_errors(&mut self, diag: &rustc_errors::Handler) -> usize {
47-
let mut printed = 0;
48-
// In order to drop the sender part of the channel.
49-
self.sender = None;
50-
51-
for msg in self.receiver.iter() {
52-
if let Some(ref error) = msg {
53-
diag.struct_err(&error).emit();
54-
printed += 1;
55-
}
56-
}
57-
printed
58-
}
59-
}
60-
6133
pub struct DocFS {
6234
sync_only: bool,
63-
errors: Arc<ErrorStorage>,
35+
errors: Option<Sender<String>>,
6436
}
6537

6638
impl DocFS {
67-
pub fn new(errors: &Arc<ErrorStorage>) -> DocFS {
68-
DocFS { sync_only: false, errors: Arc::clone(errors) }
39+
pub fn new(errors: Sender<String>) -> DocFS {
40+
DocFS { sync_only: false, errors: Some(errors) }
6941
}
7042

7143
pub fn set_sync_only(&mut self, sync_only: bool) {
7244
self.sync_only = sync_only;
7345
}
7446

47+
pub fn close(&mut self) {
48+
self.errors = None;
49+
}
50+
7551
pub fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
7652
// For now, dir creation isn't a huge time consideration, do it
7753
// synchronously, which avoids needing ordering between write() actions
@@ -88,20 +64,15 @@ impl DocFS {
8864
if !self.sync_only && cfg!(windows) {
8965
// A possible future enhancement after more detailed profiling would
9066
// be to create the file sync so errors are reported eagerly.
91-
let contents = contents.as_ref().to_vec();
9267
let path = path.as_ref().to_path_buf();
93-
let sender = self.errors.sender.clone().unwrap();
94-
rayon::spawn(move || match fs::write(&path, &contents) {
95-
Ok(_) => {
96-
sender.send(None).unwrap_or_else(|_| {
97-
panic!("failed to send error on \"{}\"", path.display())
98-
});
99-
}
100-
Err(e) => {
101-
sender.send(Some(format!("\"{}\": {}", path.display(), e))).unwrap_or_else(
102-
|_| panic!("failed to send non-error on \"{}\"", path.display()),
103-
);
104-
}
68+
let contents = contents.as_ref().to_vec();
69+
let sender = self.errors.clone().expect("can't write after closing");
70+
rayon::spawn(move || {
71+
fs::write(&path, contents).unwrap_or_else(|e| {
72+
sender
73+
.send(format!("\"{}\": {}", path.display(), e))
74+
.expect(&format!("failed to send error on \"{}\"", path.display()));
75+
});
10576
});
10677
Ok(())
10778
} else {

src/librustdoc/error.rs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use std::error;
2+
use std::fmt::{self, Formatter};
3+
use std::path::{Path, PathBuf};
4+
5+
use crate::docfs::PathError;
6+
7+
#[derive(Debug)]
8+
pub struct Error {
9+
pub file: PathBuf,
10+
pub error: String,
11+
}
12+
13+
impl error::Error for Error {}
14+
15+
impl std::fmt::Display for Error {
16+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
17+
let file = self.file.display().to_string();
18+
if file.is_empty() {
19+
write!(f, "{}", self.error)
20+
} else {
21+
write!(f, "\"{}\": {}", self.file.display(), self.error)
22+
}
23+
}
24+
}
25+
26+
impl PathError for Error {
27+
fn new<S, P: AsRef<Path>>(e: S, path: P) -> Error
28+
where
29+
S: ToString + Sized,
30+
{
31+
Error { file: path.as_ref().to_path_buf(), error: e.to_string() }
32+
}
33+
}
34+
35+
#[macro_export]
36+
macro_rules! try_none {
37+
($e:expr, $file:expr) => {{
38+
use std::io;
39+
match $e {
40+
Some(e) => e,
41+
None => {
42+
return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
43+
}
44+
}
45+
}};
46+
}
47+
48+
#[macro_export]
49+
macro_rules! try_err {
50+
($e:expr, $file:expr) => {{
51+
match $e {
52+
Ok(e) => e,
53+
Err(e) => return Err(Error::new(e, $file)),
54+
}
55+
}};
56+
}

0 commit comments

Comments
 (0)