1
Fork 0

only store locations in extern_locations

This commit is contained in:
Timothée Delabrouille 2021-04-29 19:14:29 +02:00
parent 7d09dba728
commit 2cc263988e
5 changed files with 48 additions and 44 deletions

View file

@ -106,38 +106,39 @@ impl ExternalCrate {
crate fn location( crate fn location(
&self, &self,
extern_url: Option<&str>, extern_url: Option<&str>,
ast_attrs: &[ast::Attribute],
dst: &std::path::Path, dst: &std::path::Path,
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
) -> ExternalLocation { ) -> ExternalLocation {
use ExternalLocation::*; use ExternalLocation::*;
fn to_remote(url: impl ToString) -> ExternalLocation {
let mut url = url.to_string();
if !url.ends_with('/') {
url.push('/');
}
Remote(url)
}
// See if there's documentation generated into the local directory // See if there's documentation generated into the local directory
// WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
// Make sure to call `location()` by that time.
let local_location = dst.join(&*self.name(tcx).as_str()); let local_location = dst.join(&*self.name(tcx).as_str());
if local_location.is_dir() { if local_location.is_dir() {
return Local; return Local;
} }
if let Some(url) = extern_url { if let Some(url) = extern_url {
let mut url = url.to_string(); return to_remote(url);
if !url.ends_with('/') {
url.push('/');
}
return Remote(url);
} }
// Failing that, see if there's an attribute specifying where to find this // Failing that, see if there's an attribute specifying where to find this
// external crate // external crate
ast_attrs let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
tcx.get_attrs(did)
.lists(sym::doc) .lists(sym::doc)
.filter(|a| a.has_name(sym::html_root_url)) .filter(|a| a.has_name(sym::html_root_url))
.filter_map(|a| a.value_str()) .filter_map(|a| a.value_str())
.map(|url| { .map(to_remote)
let mut url = url.to_string();
if !url.ends_with('/') {
url.push('/')
}
Remote(url)
})
.next() .next()
.unwrap_or(Unknown) // Well, at least we tried. .unwrap_or(Unknown) // Well, at least we tried.
} }
@ -433,7 +434,7 @@ impl Item {
let relative_to = &cx.current; let relative_to = &cx.current;
if let Some(ref fragment) = *fragment { if let Some(ref fragment) = *fragment {
let url = match cx.cache().extern_locations.get(&self.def_id.krate) { let url = match cx.cache().extern_locations.get(&self.def_id.krate) {
Some(&(_, _, ExternalLocation::Local)) => { Some(ExternalLocation::Local) => {
if relative_to[0] == "std" { if relative_to[0] == "std" {
let depth = relative_to.len() - 1; let depth = relative_to.len() - 1;
"../".repeat(depth) "../".repeat(depth)
@ -442,10 +443,10 @@ impl Item {
format!("{}std/", "../".repeat(depth)) format!("{}std/", "../".repeat(depth))
} }
} }
Some(&(_, _, ExternalLocation::Remote(ref s))) => { Some(ExternalLocation::Remote(ref s)) => {
format!("{}/std/", s.trim_end_matches('/')) format!("{}/std/", s.trim_end_matches('/'))
} }
Some(&(_, _, ExternalLocation::Unknown)) | None => format!( Some(ExternalLocation::Unknown) | None => format!(
"https://doc.rust-lang.org/{}/std/", "https://doc.rust-lang.org/{}/std/",
crate::doc_rust_lang_org_channel(), crate::doc_rust_lang_org_channel(),
), ),

View file

@ -1,13 +1,12 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::mem; use std::mem;
use std::path::{Path, PathBuf}; use std::path::Path;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Symbol;
use crate::clean::{self, GetDefId}; use crate::clean::{self, GetDefId};
use crate::fold::DocFolder; use crate::fold::DocFolder;
@ -71,7 +70,7 @@ crate struct Cache {
crate implementors: FxHashMap<DefId, Vec<Impl>>, crate implementors: FxHashMap<DefId, Vec<Impl>>,
/// Cache of where external crate documentation can be found. /// Cache of where external crate documentation can be found.
crate extern_locations: FxHashMap<CrateNum, (Symbol, PathBuf, ExternalLocation)>, crate extern_locations: FxHashMap<CrateNum, ExternalLocation>,
/// Cache of where documentation for primitives can be found. /// Cache of where documentation for primitives can be found.
crate primitive_locations: FxHashMap<clean::PrimitiveType, DefId>, crate primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
@ -157,10 +156,7 @@ impl Cache {
let name = e.name(tcx); let name = e.name(tcx);
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u); let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
let did = DefId { krate: n, index: CRATE_DEF_INDEX }; let did = DefId { krate: n, index: CRATE_DEF_INDEX };
self.extern_locations.insert( self.extern_locations.insert(n, e.location(extern_url, &dst, tcx));
n,
(name, e.src_root(tcx), e.location(extern_url, tcx.get_attrs(did), &dst, tcx)),
);
self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module)); self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
} }

View file

@ -16,7 +16,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType}; use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, PrimitiveType};
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::escape::Escape; use crate::html::escape::Escape;
use crate::html::render::cache::ExternalLocation; use crate::html::render::cache::ExternalLocation;
@ -461,14 +461,14 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
fqp, fqp,
shortty, shortty,
match cache.extern_locations[&did.krate] { match cache.extern_locations[&did.krate] {
(.., ExternalLocation::Remote(ref s)) => { ExternalLocation::Remote(ref s) => {
let s = s.trim_end_matches('/'); let s = s.trim_end_matches('/');
let mut s = vec![&s[..]]; let mut s = vec![&s[..]];
s.extend(module_fqp[..].iter().map(String::as_str)); s.extend(module_fqp[..].iter().map(String::as_str));
s s
} }
(.., ExternalLocation::Local) => href_relative_parts(module_fqp, relative_to), ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
(.., ExternalLocation::Unknown) => return None, ExternalLocation::Unknown => return None,
}, },
) )
} }
@ -574,12 +574,14 @@ fn primitive_link(
Some(&def_id) => { Some(&def_id) => {
let cname_str; let cname_str;
let loc = match m.extern_locations[&def_id.krate] { let loc = match m.extern_locations[&def_id.krate] {
(ref cname, _, ExternalLocation::Remote(ref s)) => { ExternalLocation::Remote(ref s) => {
cname_str = cname.as_str(); cname_str =
ExternalCrate { crate_num: def_id.krate }.name(cx.tcx()).as_str();
Some(vec![s.trim_end_matches('/'), &cname_str[..]]) Some(vec![s.trim_end_matches('/'), &cname_str[..]])
} }
(ref cname, _, ExternalLocation::Local) => { ExternalLocation::Local => {
cname_str = cname.as_str(); cname_str =
ExternalCrate { crate_num: def_id.krate }.name(cx.tcx()).as_str();
Some(if cx.current.first().map(|x| &x[..]) == Some(&cname_str[..]) { Some(if cx.current.first().map(|x| &x[..]) == Some(&cname_str[..]) {
iter::repeat("..").take(cx.current.len() - 1).collect() iter::repeat("..").take(cx.current.len() - 1).collect()
} else { } else {
@ -587,7 +589,7 @@ fn primitive_link(
iter::repeat("..").take(cx.current.len()).chain(cname).collect() iter::repeat("..").take(cx.current.len()).chain(cname).collect()
}) })
} }
(.., ExternalLocation::Unknown) => None, ExternalLocation::Unknown => None,
}; };
if let Some(loc) = loc { if let Some(loc) = loc {
write!( write!(

View file

@ -18,7 +18,7 @@ use super::print_item::{full_path, item_path, print_item};
use super::write_shared::write_shared; use super::write_shared::write_shared;
use super::{print_sidebar, settings, AllTypes, NameDoc, StylePath, BASIC_KEYWORDS}; use super::{print_sidebar, settings, AllTypes, NameDoc, StylePath, BASIC_KEYWORDS};
use crate::clean; use crate::clean::{self, ExternalCrate};
use crate::config::RenderOptions; use crate::config::RenderOptions;
use crate::docfs::{DocFS, PathError}; use crate::docfs::{DocFS, PathError};
use crate::error::Error; use crate::error::Error;
@ -304,12 +304,16 @@ impl<'tcx> Context<'tcx> {
} }
} else { } else {
let (krate, src_root) = match *self.cache.extern_locations.get(&cnum)? { let (krate, src_root) = match *self.cache.extern_locations.get(&cnum)? {
(name, ref src, ExternalLocation::Local) => (name, src), ExternalLocation::Local => {
(name, ref src, ExternalLocation::Remote(ref s)) => { let e = ExternalCrate { crate_num: cnum };
root = s.to_string(); (e.name(self.tcx()), e.src_root(self.tcx()))
(name, src)
} }
(_, _, ExternalLocation::Unknown) => return None, ExternalLocation::Remote(ref s) => {
root = s.to_string();
let e = ExternalCrate { crate_num: cnum };
(e.name(self.tcx()), e.src_root(self.tcx()))
}
ExternalLocation::Unknown => return None,
}; };
sources::clean_path(&src_root, file, false, |component| { sources::clean_path(&src_root, file, false, |component| {

View file

@ -17,7 +17,7 @@ use rustc_session::Session;
use rustdoc_json_types as types; use rustdoc_json_types as types;
use crate::clean; use crate::clean::{self, ExternalCrate};
use crate::config::RenderOptions; use crate::config::RenderOptions;
use crate::error::Error; use crate::error::Error;
use crate::formats::cache::Cache; use crate::formats::cache::Cache;
@ -218,12 +218,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
.cache .cache
.extern_locations .extern_locations
.iter() .iter()
.map(|(k, v)| { .map(|(crate_num, external_location)| {
let e = ExternalCrate { crate_num: *crate_num };
( (
k.as_u32(), crate_num.as_u32(),
types::ExternalCrate { types::ExternalCrate {
name: v.0.to_string(), name: e.name(self.tcx).to_string(),
html_root_url: match &v.2 { html_root_url: match external_location {
ExternalLocation::Remote(s) => Some(s.clone()), ExternalLocation::Remote(s) => Some(s.clone()),
_ => None, _ => None,
}, },