Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
6a4396b9
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
6a4396b9
编写于
6月 24, 2020
作者:
J
Joseph Ryan
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Extract `Cache` and other types from `html` module
上级
5bc97946
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
808 addition
and
752 deletion
+808
-752
src/librustdoc/clean/types.rs
src/librustdoc/clean/types.rs
+4
-3
src/librustdoc/config.rs
src/librustdoc/config.rs
+1
-1
src/librustdoc/core.rs
src/librustdoc/core.rs
+2
-2
src/librustdoc/formats/cache.rs
src/librustdoc/formats/cache.rs
+498
-0
src/librustdoc/formats/item_type.rs
src/librustdoc/formats/item_type.rs
+1
-1
src/librustdoc/formats/mod.rs
src/librustdoc/formats/mod.rs
+19
-97
src/librustdoc/formats/renderer.rs
src/librustdoc/formats/renderer.rs
+112
-0
src/librustdoc/html/format.rs
src/librustdoc/html/format.rs
+11
-9
src/librustdoc/html/mod.rs
src/librustdoc/html/mod.rs
+9
-0
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/cache.rs
+12
-489
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/mod.rs
+137
-137
src/librustdoc/lib.rs
src/librustdoc/lib.rs
+2
-13
未找到文件。
src/librustdoc/clean/types.rs
浏览文件 @
6a4396b9
...
...
@@ -32,8 +32,9 @@
use
crate
::
clean
::
types
::
Type
::{
QPath
,
ResolvedPath
};
use
crate
::
core
::
DocContext
;
use
crate
::
doctree
;
use
crate
::
html
::
item_type
::
ItemType
;
use
crate
::
html
::
render
::{
cache
,
ExternalLocation
};
use
crate
::
formats
::
cache
::
cache
;
use
crate
::
formats
::
item_type
::
ItemType
;
use
crate
::
html
::
render
::
cache
::
ExternalLocation
;
use
self
::
FnRetTy
::
*
;
use
self
::
ItemEnum
::
*
;
...
...
@@ -1172,7 +1173,7 @@ impl GetDefId for Type {
fn
def_id
(
&
self
)
->
Option
<
DefId
>
{
match
*
self
{
ResolvedPath
{
did
,
..
}
=>
Some
(
did
),
Primitive
(
p
)
=>
c
rate
::
html
::
render
::
c
ache
()
.primitive_locations
.get
(
&
p
)
.cloned
(),
Primitive
(
p
)
=>
cache
()
.primitive_locations
.get
(
&
p
)
.cloned
(),
BorrowedRef
{
type_
:
box
Generic
(
..
),
..
}
=>
{
Primitive
(
PrimitiveType
::
Reference
)
.def_id
()
}
...
...
src/librustdoc/config.rs
浏览文件 @
6a4396b9
...
...
@@ -254,7 +254,7 @@ pub struct RenderOptions {
/// Temporary storage for data obtained during `RustdocVisitor::clean()`.
/// Later on moved into `CACHE_KEY`.
#[derive(Default)]
#[derive(Default
,
Clone
)]
pub
struct
RenderInfo
{
pub
inlined
:
FxHashSet
<
DefId
>
,
pub
external_paths
:
crate
::
core
::
ExternalPaths
,
...
...
src/librustdoc/core.rs
浏览文件 @
6a4396b9
...
...
@@ -44,9 +44,9 @@
pub
struct
DocContext
<
'tcx
>
{
pub
tcx
:
TyCtxt
<
'tcx
>
,
pub
resolver
:
Rc
<
RefCell
<
interface
::
BoxedResolver
>>
,
/// Later on moved into `
html::render
::CACHE_KEY`
/// Later on moved into `
formats::cache
::CACHE_KEY`
pub
renderinfo
:
RefCell
<
RenderInfo
>
,
/// Later on moved through `clean::Crate` into `
html::render
::CACHE_KEY`
/// Later on moved through `clean::Crate` into `
formats::cache
::CACHE_KEY`
pub
external_traits
:
Rc
<
RefCell
<
FxHashMap
<
DefId
,
clean
::
Trait
>>>
,
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
/// the same time.
...
...
src/librustdoc/formats/cache.rs
0 → 100644
浏览文件 @
6a4396b9
use
std
::
cell
::
RefCell
;
use
std
::
collections
::
BTreeMap
;
use
std
::
mem
;
use
std
::
path
::{
Path
,
PathBuf
};
use
std
::
sync
::
Arc
;
use
rustc_data_structures
::
fx
::{
FxHashMap
,
FxHashSet
};
use
rustc_hir
::
def_id
::{
CrateNum
,
DefId
,
CRATE_DEF_INDEX
};
use
rustc_middle
::
middle
::
privacy
::
AccessLevels
;
use
rustc_span
::
source_map
::
FileName
;
use
crate
::
clean
::{
self
,
GetDefId
};
use
crate
::
config
::
RenderInfo
;
use
crate
::
fold
::
DocFolder
;
use
crate
::
formats
::
item_type
::
ItemType
;
use
crate
::
formats
::
Impl
;
use
crate
::
html
::
render
::
cache
::{
extern_location
,
get_index_search_type
,
ExternalLocation
};
use
crate
::
html
::
render
::
IndexItem
;
use
crate
::
html
::
render
::{
plain_summary_line
,
shorten
};
thread_local!
(
crate
static
CACHE_KEY
:
RefCell
<
Arc
<
Cache
>>
=
Default
::
default
());
/// This cache is used to store information about the `clean::Crate` being
/// rendered in order to provide more useful documentation. This contains
/// information like all implementors of a trait, all traits a type implements,
/// documentation for all known traits, etc.
///
/// This structure purposefully does not implement `Clone` because it's intended
/// to be a fairly large and expensive structure to clone. Instead this adheres
/// to `Send` so it may be stored in a `Arc` instance and shared among the various
/// rendering threads.
#[derive(Default)]
pub
struct
Cache
{
/// Maps a type ID to all known implementations for that type. This is only
/// recognized for intra-crate `ResolvedPath` types, and is used to print
/// out extra documentation on the page of an enum/struct.
///
/// The values of the map are a list of implementations and documentation
/// found on that implementation.
pub
impls
:
FxHashMap
<
DefId
,
Vec
<
Impl
>>
,
/// Maintains a mapping of local crate `DefId`s to the fully qualified name
/// and "short type description" of that node. This is used when generating
/// URLs when a type is being linked to. External paths are not located in
/// this map because the `External` type itself has all the information
/// necessary.
pub
paths
:
FxHashMap
<
DefId
,
(
Vec
<
String
>
,
ItemType
)
>
,
/// Similar to `paths`, but only holds external paths. This is only used for
/// generating explicit hyperlinks to other crates.
pub
external_paths
:
FxHashMap
<
DefId
,
(
Vec
<
String
>
,
ItemType
)
>
,
/// Maps local `DefId`s of exported types to fully qualified paths.
/// Unlike 'paths', this mapping ignores any renames that occur
/// due to 'use' statements.
///
/// This map is used when writing out the special 'implementors'
/// javascript file. By using the exact path that the type
/// is declared with, we ensure that each path will be identical
/// to the path used if the corresponding type is inlined. By
/// doing this, we can detect duplicate impls on a trait page, and only display
/// the impl for the inlined type.
pub
exact_paths
:
FxHashMap
<
DefId
,
Vec
<
String
>>
,
/// This map contains information about all known traits of this crate.
/// Implementations of a crate should inherit the documentation of the
/// parent trait if no extra documentation is specified, and default methods
/// should show up in documentation about trait implementations.
pub
traits
:
FxHashMap
<
DefId
,
clean
::
Trait
>
,
/// When rendering traits, it's often useful to be able to list all
/// implementors of the trait, and this mapping is exactly, that: a mapping
/// of trait ids to the list of known implementors of the trait
pub
implementors
:
FxHashMap
<
DefId
,
Vec
<
Impl
>>
,
/// Cache of where external crate documentation can be found.
pub
extern_locations
:
FxHashMap
<
CrateNum
,
(
String
,
PathBuf
,
ExternalLocation
)
>
,
/// Cache of where documentation for primitives can be found.
pub
primitive_locations
:
FxHashMap
<
clean
::
PrimitiveType
,
DefId
>
,
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
// the access levels from the privacy check pass.
pub
access_levels
:
AccessLevels
<
DefId
>
,
/// The version of the crate being documented, if given from the `--crate-version` flag.
pub
crate_version
:
Option
<
String
>
,
/// Whether to document private items.
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
pub
document_private
:
bool
,
// Private fields only used when initially crawling a crate to build a cache
stack
:
Vec
<
String
>
,
parent_stack
:
Vec
<
DefId
>
,
parent_is_trait_impl
:
bool
,
stripped_mod
:
bool
,
masked_crates
:
FxHashSet
<
CrateNum
>
,
pub
search_index
:
Vec
<
IndexItem
>
,
pub
deref_trait_did
:
Option
<
DefId
>
,
pub
deref_mut_trait_did
:
Option
<
DefId
>
,
pub
owned_box_did
:
Option
<
DefId
>
,
// In rare case where a structure is defined in one module but implemented
// in another, if the implementing module is parsed before defining module,
// then the fully qualified name of the structure isn't presented in `paths`
// yet when its implementation methods are being indexed. Caches such methods
// and their parent id here and indexes them at the end of crate parsing.
pub
orphan_impl_items
:
Vec
<
(
DefId
,
clean
::
Item
)
>
,
// Similarly to `orphan_impl_items`, sometimes trait impls are picked up
// even though the trait itself is not exported. This can happen if a trait
// was defined in function/expression scope, since the impl will be picked
// up by `collect-trait-impls` but the trait won't be scraped out in the HIR
// crawl. In order to prevent crashes when looking for spotlight traits or
// when gathering trait documentation on a type, hold impls here while
// folding and add them to the cache later on if we find the trait.
orphan_trait_impls
:
Vec
<
(
DefId
,
FxHashSet
<
DefId
>
,
Impl
)
>
,
/// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
/// we need the alias element to have an array of items.
pub
aliases
:
BTreeMap
<
String
,
Vec
<
usize
>>
,
}
impl
Cache
{
pub
fn
from_krate
(
renderinfo
:
RenderInfo
,
document_private
:
bool
,
extern_html_root_urls
:
&
BTreeMap
<
String
,
String
>
,
dst
:
&
Path
,
mut
krate
:
clean
::
Crate
,
)
->
(
clean
::
Crate
,
Cache
)
{
// Crawl the crate to build various caches used for the output
let
RenderInfo
{
inlined
:
_
,
external_paths
,
exact_paths
,
access_levels
,
deref_trait_did
,
deref_mut_trait_did
,
owned_box_did
,
..
}
=
renderinfo
;
let
external_paths
=
external_paths
.into_iter
()
.map
(|(
k
,
(
v
,
t
))|
(
k
,
(
v
,
ItemType
::
from
(
t
))))
.collect
();
let
mut
cache
=
Cache
{
impls
:
Default
::
default
(),
external_paths
,
exact_paths
,
paths
:
Default
::
default
(),
implementors
:
Default
::
default
(),
stack
:
Vec
::
new
(),
parent_stack
:
Vec
::
new
(),
search_index
:
Vec
::
new
(),
parent_is_trait_impl
:
false
,
extern_locations
:
Default
::
default
(),
primitive_locations
:
Default
::
default
(),
stripped_mod
:
false
,
access_levels
,
crate_version
:
krate
.version
.take
(),
document_private
,
orphan_impl_items
:
Vec
::
new
(),
orphan_trait_impls
:
Vec
::
new
(),
traits
:
krate
.external_traits
.replace
(
Default
::
default
()),
deref_trait_did
,
deref_mut_trait_did
,
owned_box_did
,
masked_crates
:
mem
::
take
(
&
mut
krate
.masked_crates
),
aliases
:
Default
::
default
(),
};
// Cache where all our extern crates are located
// TODO: this part is specific to HTML so it'd be nice to remove it from the common code
for
&
(
n
,
ref
e
)
in
&
krate
.externs
{
let
src_root
=
match
e
.src
{
FileName
::
Real
(
ref
p
)
=>
match
p
.local_path
()
.parent
()
{
Some
(
p
)
=>
p
.to_path_buf
(),
None
=>
PathBuf
::
new
(),
},
_
=>
PathBuf
::
new
(),
};
let
extern_url
=
extern_html_root_urls
.get
(
&
e
.name
)
.map
(|
u
|
&**
u
);
cache
.extern_locations
.insert
(
n
,
(
e
.name
.clone
(),
src_root
,
extern_location
(
e
,
extern_url
,
&
dst
)));
let
did
=
DefId
{
krate
:
n
,
index
:
CRATE_DEF_INDEX
};
cache
.external_paths
.insert
(
did
,
(
vec!
[
e
.name
.to_string
()],
ItemType
::
Module
));
}
// Cache where all known primitives have their documentation located.
//
// Favor linking to as local extern as possible, so iterate all crates in
// reverse topological order.
for
&
(
_
,
ref
e
)
in
krate
.externs
.iter
()
.rev
()
{
for
&
(
def_id
,
prim
,
_
)
in
&
e
.primitives
{
cache
.primitive_locations
.insert
(
prim
,
def_id
);
}
}
for
&
(
def_id
,
prim
,
_
)
in
&
krate
.primitives
{
cache
.primitive_locations
.insert
(
prim
,
def_id
);
}
cache
.stack
.push
(
krate
.name
.clone
());
krate
=
cache
.fold_crate
(
krate
);
for
(
trait_did
,
dids
,
impl_
)
in
cache
.orphan_trait_impls
.drain
(
..
)
{
if
cache
.traits
.contains_key
(
&
trait_did
)
{
for
did
in
dids
{
cache
.impls
.entry
(
did
)
.or_insert
(
vec!
[])
.push
(
impl_
.clone
());
}
}
}
(
krate
,
cache
)
}
}
impl
DocFolder
for
Cache
{
fn
fold_item
(
&
mut
self
,
item
:
clean
::
Item
)
->
Option
<
clean
::
Item
>
{
if
item
.def_id
.is_local
()
{
debug!
(
"folding {}
\"
{:?}
\"
, id {:?}"
,
item
.type_
(),
item
.name
,
item
.def_id
);
}
// If this is a stripped module,
// we don't want it or its children in the search index.
let
orig_stripped_mod
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
..
))
=>
{
mem
::
replace
(
&
mut
self
.stripped_mod
,
true
)
}
_
=>
self
.stripped_mod
,
};
// If the impl is from a masked crate or references something from a
// masked crate then remove it completely.
if
let
clean
::
ImplItem
(
ref
i
)
=
item
.inner
{
if
self
.masked_crates
.contains
(
&
item
.def_id.krate
)
||
i
.trait_
.def_id
()
.map_or
(
false
,
|
d
|
self
.masked_crates
.contains
(
&
d
.krate
))
||
i
.for_
.def_id
()
.map_or
(
false
,
|
d
|
self
.masked_crates
.contains
(
&
d
.krate
))
{
return
None
;
}
}
// Propagate a trait method's documentation to all implementors of the
// trait.
if
let
clean
::
TraitItem
(
ref
t
)
=
item
.inner
{
self
.traits
.entry
(
item
.def_id
)
.or_insert_with
(||
t
.clone
());
}
// Collect all the implementors of traits.
if
let
clean
::
ImplItem
(
ref
i
)
=
item
.inner
{
if
let
Some
(
did
)
=
i
.trait_
.def_id
()
{
if
i
.blanket_impl
.is_none
()
{
self
.implementors
.entry
(
did
)
.or_default
()
.push
(
Impl
{
impl_item
:
item
.clone
()
});
}
}
}
// Index this method for searching later on.
if
let
Some
(
ref
s
)
=
item
.name
{
let
(
parent
,
is_inherent_impl_item
)
=
match
item
.inner
{
clean
::
StrippedItem
(
..
)
=>
((
None
,
None
),
false
),
clean
::
AssocConstItem
(
..
)
|
clean
::
TypedefItem
(
_
,
true
)
if
self
.parent_is_trait_impl
=>
{
// skip associated items in trait impls
((
None
,
None
),
false
)
}
clean
::
AssocTypeItem
(
..
)
|
clean
::
TyMethodItem
(
..
)
|
clean
::
StructFieldItem
(
..
)
|
clean
::
VariantItem
(
..
)
=>
(
(
Some
(
*
self
.parent_stack
.last
()
.expect
(
"parent_stack is empty"
)),
Some
(
&
self
.stack
[
..
self
.stack
.len
()
-
1
]),
),
false
,
),
clean
::
MethodItem
(
..
)
|
clean
::
AssocConstItem
(
..
)
=>
{
if
self
.parent_stack
.is_empty
()
{
((
None
,
None
),
false
)
}
else
{
let
last
=
self
.parent_stack
.last
()
.expect
(
"parent_stack is empty 2"
);
let
did
=
*
last
;
let
path
=
match
self
.paths
.get
(
&
did
)
{
// The current stack not necessarily has correlation
// for where the type was defined. On the other
// hand, `paths` always has the right
// information if present.
Some
(
&
(
ref
fqp
,
ItemType
::
Trait
|
ItemType
::
Struct
|
ItemType
::
Union
|
ItemType
::
Enum
,
))
=>
Some
(
&
fqp
[
..
fqp
.len
()
-
1
]),
Some
(
..
)
=>
Some
(
&*
self
.stack
),
None
=>
None
,
};
((
Some
(
*
last
),
path
),
true
)
}
}
_
=>
((
None
,
Some
(
&*
self
.stack
)),
false
),
};
match
parent
{
(
parent
,
Some
(
path
))
if
is_inherent_impl_item
||
!
self
.stripped_mod
=>
{
debug_assert!
(
!
item
.is_stripped
());
// A crate has a module at its root, containing all items,
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
if
item
.def_id.index
!=
CRATE_DEF_INDEX
{
self
.search_index
.push
(
IndexItem
{
ty
:
item
.type_
(),
name
:
s
.to_string
(),
path
:
path
.join
(
"::"
),
desc
:
shorten
(
plain_summary_line
(
item
.doc_value
())),
parent
,
parent_idx
:
None
,
search_type
:
get_index_search_type
(
&
item
),
});
for
alias
in
item
.attrs
.get_doc_aliases
()
{
self
.aliases
.entry
(
alias
.to_lowercase
())
.or_insert
(
Vec
::
new
())
.push
(
self
.search_index
.len
()
-
1
);
}
}
}
(
Some
(
parent
),
None
)
if
is_inherent_impl_item
=>
{
// We have a parent, but we don't know where they're
// defined yet. Wait for later to index this item.
self
.orphan_impl_items
.push
((
parent
,
item
.clone
()));
}
_
=>
{}
}
}
// Keep track of the fully qualified path for this item.
let
pushed
=
match
item
.name
{
Some
(
ref
n
)
if
!
n
.is_empty
()
=>
{
self
.stack
.push
(
n
.to_string
());
true
}
_
=>
false
,
};
match
item
.inner
{
clean
::
StructItem
(
..
)
|
clean
::
EnumItem
(
..
)
|
clean
::
TypedefItem
(
..
)
|
clean
::
TraitItem
(
..
)
|
clean
::
FunctionItem
(
..
)
|
clean
::
ModuleItem
(
..
)
|
clean
::
ForeignFunctionItem
(
..
)
|
clean
::
ForeignStaticItem
(
..
)
|
clean
::
ConstantItem
(
..
)
|
clean
::
StaticItem
(
..
)
|
clean
::
UnionItem
(
..
)
|
clean
::
ForeignTypeItem
|
clean
::
MacroItem
(
..
)
|
clean
::
ProcMacroItem
(
..
)
|
clean
::
VariantItem
(
..
)
if
!
self
.stripped_mod
=>
{
// Re-exported items mean that the same id can show up twice
// in the rustdoc ast that we're looking at. We know,
// however, that a re-exported item doesn't show up in the
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
if
!
self
.paths
.contains_key
(
&
item
.def_id
)
||
self
.access_levels
.is_public
(
item
.def_id
)
{
self
.paths
.insert
(
item
.def_id
,
(
self
.stack
.clone
(),
item
.type_
()));
}
}
clean
::
PrimitiveItem
(
..
)
=>
{
self
.paths
.insert
(
item
.def_id
,
(
self
.stack
.clone
(),
item
.type_
()));
}
_
=>
{}
}
// Maintain the parent stack
let
orig_parent_is_trait_impl
=
self
.parent_is_trait_impl
;
let
parent_pushed
=
match
item
.inner
{
clean
::
TraitItem
(
..
)
|
clean
::
EnumItem
(
..
)
|
clean
::
ForeignTypeItem
|
clean
::
StructItem
(
..
)
|
clean
::
UnionItem
(
..
)
|
clean
::
VariantItem
(
..
)
=>
{
self
.parent_stack
.push
(
item
.def_id
);
self
.parent_is_trait_impl
=
false
;
true
}
clean
::
ImplItem
(
ref
i
)
=>
{
self
.parent_is_trait_impl
=
i
.trait_
.is_some
();
match
i
.for_
{
clean
::
ResolvedPath
{
did
,
..
}
=>
{
self
.parent_stack
.push
(
did
);
true
}
ref
t
=>
{
let
prim_did
=
t
.primitive_type
()
.and_then
(|
t
|
self
.primitive_locations
.get
(
&
t
)
.cloned
());
match
prim_did
{
Some
(
did
)
=>
{
self
.parent_stack
.push
(
did
);
true
}
None
=>
false
,
}
}
}
}
_
=>
false
,
};
// Once we've recursively found all the generics, hoard off all the
// implementations elsewhere.
let
ret
=
self
.fold_item_recur
(
item
)
.and_then
(|
item
|
{
if
let
clean
::
Item
{
inner
:
clean
::
ImplItem
(
_
),
..
}
=
item
{
// Figure out the id of this impl. This may map to a
// primitive rather than always to a struct/enum.
// Note: matching twice to restrict the lifetime of the `i` borrow.
let
mut
dids
=
FxHashSet
::
default
();
if
let
clean
::
Item
{
inner
:
clean
::
ImplItem
(
ref
i
),
..
}
=
item
{
match
i
.for_
{
clean
::
ResolvedPath
{
did
,
..
}
|
clean
::
BorrowedRef
{
type_
:
box
clean
::
ResolvedPath
{
did
,
..
},
..
}
=>
{
dids
.insert
(
did
);
}
ref
t
=>
{
let
did
=
t
.primitive_type
()
.and_then
(|
t
|
self
.primitive_locations
.get
(
&
t
)
.cloned
());
if
let
Some
(
did
)
=
did
{
dids
.insert
(
did
);
}
}
}
if
let
Some
(
generics
)
=
i
.trait_
.as_ref
()
.and_then
(|
t
|
t
.generics
())
{
for
bound
in
generics
{
if
let
Some
(
did
)
=
bound
.def_id
()
{
dids
.insert
(
did
);
}
}
}
}
else
{
unreachable!
()
};
let
impl_item
=
Impl
{
impl_item
:
item
};
if
impl_item
.trait_did
()
.map_or
(
true
,
|
d
|
self
.traits
.contains_key
(
&
d
))
{
for
did
in
dids
{
self
.impls
.entry
(
did
)
.or_insert
(
vec!
[])
.push
(
impl_item
.clone
());
}
}
else
{
let
trait_did
=
impl_item
.trait_did
()
.expect
(
"no trait did"
);
self
.orphan_trait_impls
.push
((
trait_did
,
dids
,
impl_item
));
}
None
}
else
{
Some
(
item
)
}
});
if
pushed
{
self
.stack
.pop
()
.expect
(
"stack already empty"
);
}
if
parent_pushed
{
self
.parent_stack
.pop
()
.expect
(
"parent stack already empty"
);
}
self
.stripped_mod
=
orig_stripped_mod
;
self
.parent_is_trait_impl
=
orig_parent_is_trait_impl
;
ret
}
}
crate
fn
cache
()
->
Arc
<
Cache
>
{
CACHE_KEY
.with
(|
c
|
c
.borrow
()
.clone
())
}
src/librustdoc/
html
/item_type.rs
→
src/librustdoc/
formats
/item_type.rs
浏览文件 @
6a4396b9
...
...
@@ -13,7 +13,7 @@
/// The search index uses item types encoded as smaller numbers which equal to
/// discriminants. JavaScript then is used to decode them into the original value.
/// Consequently, every change to this type should be synchronized to
/// the `itemTypes` mapping table in `static/main.js`.
/// the `itemTypes` mapping table in `
html/
static/main.js`.
///
/// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
/// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
...
...
src/librustdoc/formats/mod.rs
浏览文件 @
6a4396b9
use
std
::
cell
::
RefCell
;
use
std
::
rc
::
Rc
;
pub
mod
cache
;
pub
mod
item_type
;
pub
mod
renderer
;
use
rustc_span
::
edition
::
Edition
;
pub
use
renderer
::{
FormatRenderer
,
Renderer
}
;
use
crate
::
clean
;
use
crate
::
config
::{
RenderInfo
,
RenderOptions
};
use
crate
::
error
::
Error
;
pub
trait
FormatRenderer
:
Clone
{
type
Output
:
FormatRenderer
;
fn
init
(
krate
:
clean
::
Crate
,
options
:
RenderOptions
,
renderinfo
:
RenderInfo
,
diag
:
&
rustc_errors
::
Handler
,
edition
:
Edition
,
parent
:
Rc
<
RefCell
<
Renderer
>>
,
)
->
Result
<
(
Self
::
Output
,
clean
::
Crate
),
Error
>
;
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
fn
item
(
&
mut
self
,
item
:
clean
::
Item
)
->
Result
<
(),
Error
>
;
use
rustc_span
::
def_id
::
DefId
;
/// Renders a module. Doesn't need to handle recursing into children, the driver does that
/// automatically.
fn
mod_item_in
(
&
mut
self
,
item
:
&
clean
::
Item
,
item_name
:
&
str
,
module
:
&
clean
::
Module
,
)
->
Result
<
(),
Error
>
;
/// Runs after recursively rendering all sub-items of a module.
fn
mod_item_out
(
&
mut
self
)
->
Result
<
(),
Error
>
;
/// Post processing hook for cleanup and dumping output to files.
fn
after_krate
(
&
mut
self
,
krate
:
&
clean
::
Crate
)
->
Result
<
(),
Error
>
;
use
crate
::
clean
;
use
crate
::
clean
::
types
::
GetDefId
;
/// Called after everything else to write out errors.
fn
after_run
(
&
mut
self
,
diag
:
&
rustc_errors
::
Handler
)
->
Result
<
(),
Error
>
;
/// Metadata about implementations for a type or trait.
#[derive(Clone,
Debug)]
pub
struct
Impl
{
pub
impl_item
:
clean
::
Item
,
}
#[derive(Clone)]
pub
struct
Renderer
;
impl
Renderer
{
pub
fn
new
()
->
Renderer
{
Renderer
}
/// Main method for rendering a crate.
pub
fn
run
<
T
:
FormatRenderer
+
Clone
>
(
self
,
krate
:
clean
::
Crate
,
options
:
RenderOptions
,
renderinfo
:
RenderInfo
,
diag
:
&
rustc_errors
::
Handler
,
edition
:
Edition
,
)
->
Result
<
(),
Error
>
{
let
rself
=
Rc
::
new
(
RefCell
::
new
(
self
));
let
(
mut
renderer
,
mut
krate
)
=
T
::
init
(
krate
,
options
,
renderinfo
,
diag
,
edition
,
rself
.clone
())
?
;
let
mut
item
=
match
krate
.module
.take
()
{
Some
(
i
)
=>
i
,
None
=>
return
Ok
(()),
};
item
.name
=
Some
(
krate
.name
.clone
());
// Render the crate documentation
let
mut
work
=
vec!
[(
renderer
.clone
(),
item
)];
while
let
Some
((
mut
cx
,
item
))
=
work
.pop
()
{
if
item
.is_mod
()
{
// modules are special because they add a namespace. We also need to
// recurse into the items of the module as well.
let
name
=
item
.name
.as_ref
()
.unwrap
()
.to_string
();
if
name
.is_empty
()
{
panic!
(
"Unexpected module with empty name"
);
}
let
module
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
ref
m
))
|
clean
::
ModuleItem
(
ref
m
)
=>
m
,
_
=>
unreachable!
(),
};
cx
.mod_item_in
(
&
item
,
&
name
,
module
)
?
;
let
module
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
m
))
|
clean
::
ModuleItem
(
m
)
=>
m
,
_
=>
unreachable!
(),
};
for
it
in
module
.items
{
info!
(
"Adding {:?} to worklist"
,
it
.name
);
work
.push
((
cx
.clone
(),
it
));
}
cx
.mod_item_out
()
?
;
}
else
if
item
.name
.is_some
()
{
cx
.item
(
item
)
?
;
}
impl
Impl
{
pub
fn
inner_impl
(
&
self
)
->
&
clean
::
Impl
{
match
self
.impl_item.inner
{
clean
::
ImplItem
(
ref
impl_
)
=>
impl_
,
_
=>
panic!
(
"non-impl item found in impl"
),
}
}
renderer
.after_krate
(
&
krate
)
?
;
renderer
.after_run
(
diag
)
pub
fn
trait_did
(
&
self
)
->
Option
<
DefId
>
{
self
.inner_impl
()
.trait_
.def_id
(
)
}
}
src/librustdoc/formats/renderer.rs
0 → 100644
浏览文件 @
6a4396b9
use
std
::
sync
::
Arc
;
use
rustc_span
::
edition
::
Edition
;
use
crate
::
clean
;
use
crate
::
config
::{
RenderInfo
,
RenderOptions
};
use
crate
::
error
::
Error
;
use
crate
::
formats
::
cache
::{
Cache
,
CACHE_KEY
};
pub
trait
FormatRenderer
:
Clone
{
type
Output
:
FormatRenderer
;
fn
init
(
krate
:
clean
::
Crate
,
options
:
RenderOptions
,
renderinfo
:
RenderInfo
,
edition
:
Edition
,
cache
:
&
mut
Cache
,
)
->
Result
<
(
Self
::
Output
,
clean
::
Crate
),
Error
>
;
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
fn
item
(
&
mut
self
,
item
:
clean
::
Item
,
cache
:
&
Cache
)
->
Result
<
(),
Error
>
;
/// Renders a module (doesn't need to handle recursing into children).
fn
mod_item_in
(
&
mut
self
,
item
:
&
clean
::
Item
,
item_name
:
&
str
,
cache
:
&
Cache
,
)
->
Result
<
(),
Error
>
;
/// Runs after recursively rendering all sub-items of a module.
fn
mod_item_out
(
&
mut
self
,
name
:
&
str
)
->
Result
<
(),
Error
>
;
/// Post processing hook for cleanup and dumping output to files.
fn
after_krate
(
&
mut
self
,
krate
:
&
clean
::
Crate
,
cache
:
&
Cache
)
->
Result
<
(),
Error
>
;
/// Called after everything else to write out errors.
fn
after_run
(
&
mut
self
,
diag
:
&
rustc_errors
::
Handler
)
->
Result
<
(),
Error
>
;
}
#[derive(Clone)]
pub
struct
Renderer
;
impl
Renderer
{
pub
fn
new
()
->
Renderer
{
Renderer
}
/// Main method for rendering a crate.
pub
fn
run
<
T
:
FormatRenderer
+
Clone
>
(
self
,
krate
:
clean
::
Crate
,
options
:
RenderOptions
,
renderinfo
:
RenderInfo
,
diag
:
&
rustc_errors
::
Handler
,
edition
:
Edition
,
)
->
Result
<
(),
Error
>
{
let
(
krate
,
mut
cache
)
=
Cache
::
from_krate
(
renderinfo
.clone
(),
options
.document_private
,
&
options
.extern_html_root_urls
,
&
options
.output
,
krate
,
);
let
(
mut
renderer
,
mut
krate
)
=
T
::
init
(
krate
,
options
,
renderinfo
,
edition
,
&
mut
cache
)
?
;
let
cache
=
Arc
::
new
(
cache
);
// Freeze the cache now that the index has been built. Put an Arc into TLS for future
// parallelization opportunities
CACHE_KEY
.with
(|
v
|
*
v
.borrow_mut
()
=
cache
.clone
());
let
mut
item
=
match
krate
.module
.take
()
{
Some
(
i
)
=>
i
,
None
=>
return
Ok
(()),
};
item
.name
=
Some
(
krate
.name
.clone
());
// Render the crate documentation
let
mut
work
=
vec!
[(
renderer
.clone
(),
item
)];
while
let
Some
((
mut
cx
,
item
))
=
work
.pop
()
{
if
item
.is_mod
()
{
// modules are special because they add a namespace. We also need to
// recurse into the items of the module as well.
let
name
=
item
.name
.as_ref
()
.unwrap
()
.to_string
();
if
name
.is_empty
()
{
panic!
(
"Unexpected module with empty name"
);
}
cx
.mod_item_in
(
&
item
,
&
name
,
&
cache
)
?
;
let
module
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
m
))
|
clean
::
ModuleItem
(
m
)
=>
m
,
_
=>
unreachable!
(),
};
for
it
in
module
.items
{
info!
(
"Adding {:?} to worklist"
,
it
.name
);
work
.push
((
cx
.clone
(),
it
));
}
cx
.mod_item_out
(
&
name
)
?
;
}
else
if
item
.name
.is_some
()
{
cx
.item
(
item
,
&
cache
)
?
;
}
}
renderer
.after_krate
(
&
krate
,
&
cache
)
?
;
renderer
.after_run
(
diag
)
}
}
src/librustdoc/html/format.rs
浏览文件 @
6a4396b9
...
...
@@ -11,13 +11,15 @@
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_hir
as
hir
;
use
rustc_
hir
::
def_id
::
DefId
;
use
rustc_
span
::
def_id
::
DefId
;
use
rustc_target
::
spec
::
abi
::
Abi
;
use
crate
::
clean
::{
self
,
PrimitiveType
};
use
crate
::
formats
::
cache
::
cache
;
use
crate
::
formats
::
item_type
::
ItemType
;
use
crate
::
html
::
escape
::
Escape
;
use
crate
::
html
::
item_type
::
ItemType
;
use
crate
::
html
::
render
::
{
self
,
cache
,
CURRENT_DEPTH
}
;
use
crate
::
html
::
render
::
cache
::
ExternalLocation
;
use
crate
::
html
::
render
::
CURRENT_DEPTH
;
pub
trait
Print
{
fn
print
(
self
,
buffer
:
&
mut
Buffer
);
...
...
@@ -493,9 +495,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
fqp
,
shortty
,
match
cache
.extern_locations
[
&
did
.krate
]
{
(
..
,
render
::
Remote
(
ref
s
))
=>
s
.to_string
(),
(
..
,
render
::
Local
)
=>
"../"
.repeat
(
depth
),
(
..
,
render
::
Unknown
)
=>
return
None
,
(
..
,
ExternalLocation
::
Remote
(
ref
s
))
=>
s
.to_string
(),
(
..
,
ExternalLocation
::
Local
)
=>
"../"
.repeat
(
depth
),
(
..
,
ExternalLocation
::
Unknown
)
=>
return
None
,
},
)
}
...
...
@@ -574,12 +576,12 @@ fn primitive_link(
}
Some
(
&
def_id
)
=>
{
let
loc
=
match
m
.extern_locations
[
&
def_id
.krate
]
{
(
ref
cname
,
_
,
render
::
Remote
(
ref
s
))
=>
Some
((
cname
,
s
.to_string
())),
(
ref
cname
,
_
,
render
::
Local
)
=>
{
(
ref
cname
,
_
,
ExternalLocation
::
Remote
(
ref
s
))
=>
Some
((
cname
,
s
.to_string
())),
(
ref
cname
,
_
,
ExternalLocation
::
Local
)
=>
{
let
len
=
CURRENT_DEPTH
.with
(|
s
|
s
.get
());
Some
((
cname
,
"../"
.repeat
(
len
)))
}
(
..
,
render
::
Unknown
)
=>
None
,
(
..
,
ExternalLocation
::
Unknown
)
=>
None
,
};
if
let
Some
((
cname
,
root
))
=
loc
{
write!
(
...
...
src/librustdoc/html/mod.rs
0 → 100644
浏览文件 @
6a4396b9
crate
mod
escape
;
crate
mod
format
;
crate
mod
highlight
;
crate
mod
layout
;
pub
mod
markdown
;
pub
mod
render
;
crate
mod
sources
;
crate
mod
static_files
;
crate
mod
toc
;
src/librustdoc/html/render/cache.rs
浏览文件 @
6a4396b9
use
crate
::
clean
::{
self
,
AttributesExt
,
GetDefId
};
use
crate
::
fold
::
DocFolder
;
use
rustc_data_structures
::
fx
::{
FxHashMap
,
FxHashSet
};
use
rustc_hir
::
def_id
::{
CrateNum
,
DefId
,
CRATE_DEF_INDEX
};
use
rustc_middle
::
middle
::
privacy
::
AccessLevels
;
use
rustc_span
::
source_map
::
FileName
;
use
rustc_span
::
symbol
::
sym
;
use
std
::
collections
::
BTreeMap
;
use
std
::
mem
;
use
std
::
path
::{
Path
,
PathBuf
};
use
std
::
path
::
Path
;
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
rustc_span
::
symbol
::
sym
;
use
serde
::
Serialize
;
use
super
::{
plain_summary_line
,
shorten
,
Impl
,
IndexItem
,
IndexItemFunctionType
,
ItemType
};
use
super
::{
Generic
,
RenderType
,
TypeWithKind
};
use
crate
::
config
::
RenderInfo
;
use
crate
::
clean
::
types
::
GetDefId
;
use
crate
::
clean
::{
self
,
AttributesExt
};
use
crate
::
formats
::
cache
::
Cache
;
use
crate
::
formats
::
item_type
::
ItemType
;
use
crate
::
html
::
render
::{
plain_summary_line
,
shorten
};
use
crate
::
html
::
render
::{
Generic
,
IndexItem
,
IndexItemFunctionType
,
RenderType
,
TypeWithKind
};
/// Indicates where an external crate can be found.
pub
enum
ExternalLocation
{
...
...
@@ -25,483 +22,9 @@ pub enum ExternalLocation {
Unknown
,
}
/// This cache is used to store information about the `clean::Crate` being
/// rendered in order to provide more useful documentation. This contains
/// information like all implementors of a trait, all traits a type implements,
/// documentation for all known traits, etc.
///
/// This structure purposefully does not implement `Clone` because it's intended
/// to be a fairly large and expensive structure to clone. Instead this adheres
/// to `Send` so it may be stored in a `Arc` instance and shared among the various
/// rendering threads.
#[derive(Default)]
crate
struct
Cache
{
/// Maps a type ID to all known implementations for that type. This is only
/// recognized for intra-crate `ResolvedPath` types, and is used to print
/// out extra documentation on the page of an enum/struct.
///
/// The values of the map are a list of implementations and documentation
/// found on that implementation.
pub
impls
:
FxHashMap
<
DefId
,
Vec
<
Impl
>>
,
/// Maintains a mapping of local crate `DefId`s to the fully qualified name
/// and "short type description" of that node. This is used when generating
/// URLs when a type is being linked to. External paths are not located in
/// this map because the `External` type itself has all the information
/// necessary.
pub
paths
:
FxHashMap
<
DefId
,
(
Vec
<
String
>
,
ItemType
)
>
,
/// Similar to `paths`, but only holds external paths. This is only used for
/// generating explicit hyperlinks to other crates.
pub
external_paths
:
FxHashMap
<
DefId
,
(
Vec
<
String
>
,
ItemType
)
>
,
/// Maps local `DefId`s of exported types to fully qualified paths.
/// Unlike 'paths', this mapping ignores any renames that occur
/// due to 'use' statements.
///
/// This map is used when writing out the special 'implementors'
/// javascript file. By using the exact path that the type
/// is declared with, we ensure that each path will be identical
/// to the path used if the corresponding type is inlined. By
/// doing this, we can detect duplicate impls on a trait page, and only display
/// the impl for the inlined type.
pub
exact_paths
:
FxHashMap
<
DefId
,
Vec
<
String
>>
,
/// This map contains information about all known traits of this crate.
/// Implementations of a crate should inherit the documentation of the
/// parent trait if no extra documentation is specified, and default methods
/// should show up in documentation about trait implementations.
pub
traits
:
FxHashMap
<
DefId
,
clean
::
Trait
>
,
/// When rendering traits, it's often useful to be able to list all
/// implementors of the trait, and this mapping is exactly, that: a mapping
/// of trait ids to the list of known implementors of the trait
pub
implementors
:
FxHashMap
<
DefId
,
Vec
<
Impl
>>
,
/// Cache of where external crate documentation can be found.
pub
extern_locations
:
FxHashMap
<
CrateNum
,
(
String
,
PathBuf
,
ExternalLocation
)
>
,
/// Cache of where documentation for primitives can be found.
pub
primitive_locations
:
FxHashMap
<
clean
::
PrimitiveType
,
DefId
>
,
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
// the access levels from the privacy check pass.
pub
access_levels
:
AccessLevels
<
DefId
>
,
/// The version of the crate being documented, if given from the `--crate-version` flag.
pub
crate_version
:
Option
<
String
>
,
/// Whether to document private items.
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
pub
document_private
:
bool
,
// Private fields only used when initially crawling a crate to build a cache
stack
:
Vec
<
String
>
,
parent_stack
:
Vec
<
DefId
>
,
parent_is_trait_impl
:
bool
,
search_index
:
Vec
<
IndexItem
>
,
stripped_mod
:
bool
,
pub
deref_trait_did
:
Option
<
DefId
>
,
pub
deref_mut_trait_did
:
Option
<
DefId
>
,
pub
owned_box_did
:
Option
<
DefId
>
,
masked_crates
:
FxHashSet
<
CrateNum
>
,
// In rare case where a structure is defined in one module but implemented
// in another, if the implementing module is parsed before defining module,
// then the fully qualified name of the structure isn't presented in `paths`
// yet when its implementation methods are being indexed. Caches such methods
// and their parent id here and indexes them at the end of crate parsing.
orphan_impl_items
:
Vec
<
(
DefId
,
clean
::
Item
)
>
,
// Similarly to `orphan_impl_items`, sometimes trait impls are picked up
// even though the trait itself is not exported. This can happen if a trait
// was defined in function/expression scope, since the impl will be picked
// up by `collect-trait-impls` but the trait won't be scraped out in the HIR
// crawl. In order to prevent crashes when looking for spotlight traits or
// when gathering trait documentation on a type, hold impls here while
// folding and add them to the cache later on if we find the trait.
orphan_trait_impls
:
Vec
<
(
DefId
,
FxHashSet
<
DefId
>
,
Impl
)
>
,
/// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
/// we need the alias element to have an array of items.
pub
(
super
)
aliases
:
BTreeMap
<
String
,
Vec
<
usize
>>
,
}
impl
Cache
{
pub
fn
from_krate
(
renderinfo
:
RenderInfo
,
document_private
:
bool
,
extern_html_root_urls
:
&
BTreeMap
<
String
,
String
>
,
dst
:
&
Path
,
mut
krate
:
clean
::
Crate
,
)
->
(
clean
::
Crate
,
String
,
Cache
)
{
// Crawl the crate to build various caches used for the output
let
RenderInfo
{
inlined
:
_
,
external_paths
,
exact_paths
,
access_levels
,
deref_trait_did
,
deref_mut_trait_did
,
owned_box_did
,
..
}
=
renderinfo
;
let
external_paths
=
external_paths
.into_iter
()
.map
(|(
k
,
(
v
,
t
))|
(
k
,
(
v
,
ItemType
::
from
(
t
))))
.collect
();
let
mut
cache
=
Cache
{
impls
:
Default
::
default
(),
external_paths
,
exact_paths
,
paths
:
Default
::
default
(),
implementors
:
Default
::
default
(),
stack
:
Vec
::
new
(),
parent_stack
:
Vec
::
new
(),
search_index
:
Vec
::
new
(),
parent_is_trait_impl
:
false
,
extern_locations
:
Default
::
default
(),
primitive_locations
:
Default
::
default
(),
stripped_mod
:
false
,
access_levels
,
crate_version
:
krate
.version
.take
(),
document_private
,
orphan_impl_items
:
Vec
::
new
(),
orphan_trait_impls
:
Vec
::
new
(),
traits
:
krate
.external_traits
.replace
(
Default
::
default
()),
deref_trait_did
,
deref_mut_trait_did
,
owned_box_did
,
masked_crates
:
mem
::
take
(
&
mut
krate
.masked_crates
),
aliases
:
Default
::
default
(),
};
// Cache where all our extern crates are located
for
&
(
n
,
ref
e
)
in
&
krate
.externs
{
let
src_root
=
match
e
.src
{
FileName
::
Real
(
ref
p
)
=>
match
p
.local_path
()
.parent
()
{
Some
(
p
)
=>
p
.to_path_buf
(),
None
=>
PathBuf
::
new
(),
},
_
=>
PathBuf
::
new
(),
};
let
extern_url
=
extern_html_root_urls
.get
(
&
e
.name
)
.map
(|
u
|
&**
u
);
cache
.extern_locations
.insert
(
n
,
(
e
.name
.clone
(),
src_root
,
extern_location
(
e
,
extern_url
,
&
dst
)));
let
did
=
DefId
{
krate
:
n
,
index
:
CRATE_DEF_INDEX
};
cache
.external_paths
.insert
(
did
,
(
vec!
[
e
.name
.to_string
()],
ItemType
::
Module
));
}
// Cache where all known primitives have their documentation located.
//
// Favor linking to as local extern as possible, so iterate all crates in
// reverse topological order.
for
&
(
_
,
ref
e
)
in
krate
.externs
.iter
()
.rev
()
{
for
&
(
def_id
,
prim
,
_
)
in
&
e
.primitives
{
cache
.primitive_locations
.insert
(
prim
,
def_id
);
}
}
for
&
(
def_id
,
prim
,
_
)
in
&
krate
.primitives
{
cache
.primitive_locations
.insert
(
prim
,
def_id
);
}
cache
.stack
.push
(
krate
.name
.clone
());
krate
=
cache
.fold_crate
(
krate
);
for
(
trait_did
,
dids
,
impl_
)
in
cache
.orphan_trait_impls
.drain
(
..
)
{
if
cache
.traits
.contains_key
(
&
trait_did
)
{
for
did
in
dids
{
cache
.impls
.entry
(
did
)
.or_insert
(
vec!
[])
.push
(
impl_
.clone
());
}
}
}
// Build our search index
let
index
=
build_index
(
&
krate
,
&
mut
cache
);
(
krate
,
index
,
cache
)
}
}
impl
DocFolder
for
Cache
{
fn
fold_item
(
&
mut
self
,
item
:
clean
::
Item
)
->
Option
<
clean
::
Item
>
{
if
item
.def_id
.is_local
()
{
debug!
(
"folding {}
\"
{:?}
\"
, id {:?}"
,
item
.type_
(),
item
.name
,
item
.def_id
);
}
// If this is a stripped module,
// we don't want it or its children in the search index.
let
orig_stripped_mod
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
..
))
=>
{
mem
::
replace
(
&
mut
self
.stripped_mod
,
true
)
}
_
=>
self
.stripped_mod
,
};
// If the impl is from a masked crate or references something from a
// masked crate then remove it completely.
if
let
clean
::
ImplItem
(
ref
i
)
=
item
.inner
{
if
self
.masked_crates
.contains
(
&
item
.def_id.krate
)
||
i
.trait_
.def_id
()
.map_or
(
false
,
|
d
|
self
.masked_crates
.contains
(
&
d
.krate
))
||
i
.for_
.def_id
()
.map_or
(
false
,
|
d
|
self
.masked_crates
.contains
(
&
d
.krate
))
{
return
None
;
}
}
// Propagate a trait method's documentation to all implementors of the
// trait.
if
let
clean
::
TraitItem
(
ref
t
)
=
item
.inner
{
self
.traits
.entry
(
item
.def_id
)
.or_insert_with
(||
t
.clone
());
}
// Collect all the implementors of traits.
if
let
clean
::
ImplItem
(
ref
i
)
=
item
.inner
{
if
let
Some
(
did
)
=
i
.trait_
.def_id
()
{
if
i
.blanket_impl
.is_none
()
{
self
.implementors
.entry
(
did
)
.or_default
()
.push
(
Impl
{
impl_item
:
item
.clone
()
});
}
}
}
// Index this method for searching later on.
if
let
Some
(
ref
s
)
=
item
.name
{
let
(
parent
,
is_inherent_impl_item
)
=
match
item
.inner
{
clean
::
StrippedItem
(
..
)
=>
((
None
,
None
),
false
),
clean
::
AssocConstItem
(
..
)
|
clean
::
TypedefItem
(
_
,
true
)
if
self
.parent_is_trait_impl
=>
{
// skip associated items in trait impls
((
None
,
None
),
false
)
}
clean
::
AssocTypeItem
(
..
)
|
clean
::
TyMethodItem
(
..
)
|
clean
::
StructFieldItem
(
..
)
|
clean
::
VariantItem
(
..
)
=>
(
(
Some
(
*
self
.parent_stack
.last
()
.expect
(
"parent_stack is empty"
)),
Some
(
&
self
.stack
[
..
self
.stack
.len
()
-
1
]),
),
false
,
),
clean
::
MethodItem
(
..
)
|
clean
::
AssocConstItem
(
..
)
=>
{
if
self
.parent_stack
.is_empty
()
{
((
None
,
None
),
false
)
}
else
{
let
last
=
self
.parent_stack
.last
()
.expect
(
"parent_stack is empty 2"
);
let
did
=
*
last
;
let
path
=
match
self
.paths
.get
(
&
did
)
{
// The current stack not necessarily has correlation
// for where the type was defined. On the other
// hand, `paths` always has the right
// information if present.
Some
(
&
(
ref
fqp
,
ItemType
::
Trait
|
ItemType
::
Struct
|
ItemType
::
Union
|
ItemType
::
Enum
,
))
=>
Some
(
&
fqp
[
..
fqp
.len
()
-
1
]),
Some
(
..
)
=>
Some
(
&*
self
.stack
),
None
=>
None
,
};
((
Some
(
*
last
),
path
),
true
)
}
}
_
=>
((
None
,
Some
(
&*
self
.stack
)),
false
),
};
match
parent
{
(
parent
,
Some
(
path
))
if
is_inherent_impl_item
||
!
self
.stripped_mod
=>
{
debug_assert!
(
!
item
.is_stripped
());
// A crate has a module at its root, containing all items,
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
if
item
.def_id.index
!=
CRATE_DEF_INDEX
{
self
.search_index
.push
(
IndexItem
{
ty
:
item
.type_
(),
name
:
s
.to_string
(),
path
:
path
.join
(
"::"
),
desc
:
shorten
(
plain_summary_line
(
item
.doc_value
())),
parent
,
parent_idx
:
None
,
search_type
:
get_index_search_type
(
&
item
),
});
for
alias
in
item
.attrs
.get_doc_aliases
()
{
self
.aliases
.entry
(
alias
.to_lowercase
())
.or_insert
(
Vec
::
new
())
.push
(
self
.search_index
.len
()
-
1
);
}
}
}
(
Some
(
parent
),
None
)
if
is_inherent_impl_item
=>
{
// We have a parent, but we don't know where they're
// defined yet. Wait for later to index this item.
self
.orphan_impl_items
.push
((
parent
,
item
.clone
()));
}
_
=>
{}
}
}
// Keep track of the fully qualified path for this item.
let
pushed
=
match
item
.name
{
Some
(
ref
n
)
if
!
n
.is_empty
()
=>
{
self
.stack
.push
(
n
.to_string
());
true
}
_
=>
false
,
};
match
item
.inner
{
clean
::
StructItem
(
..
)
|
clean
::
EnumItem
(
..
)
|
clean
::
TypedefItem
(
..
)
|
clean
::
TraitItem
(
..
)
|
clean
::
FunctionItem
(
..
)
|
clean
::
ModuleItem
(
..
)
|
clean
::
ForeignFunctionItem
(
..
)
|
clean
::
ForeignStaticItem
(
..
)
|
clean
::
ConstantItem
(
..
)
|
clean
::
StaticItem
(
..
)
|
clean
::
UnionItem
(
..
)
|
clean
::
ForeignTypeItem
|
clean
::
MacroItem
(
..
)
|
clean
::
ProcMacroItem
(
..
)
|
clean
::
VariantItem
(
..
)
if
!
self
.stripped_mod
=>
{
// Re-exported items mean that the same id can show up twice
// in the rustdoc ast that we're looking at. We know,
// however, that a re-exported item doesn't show up in the
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
if
!
self
.paths
.contains_key
(
&
item
.def_id
)
||
self
.access_levels
.is_public
(
item
.def_id
)
{
self
.paths
.insert
(
item
.def_id
,
(
self
.stack
.clone
(),
item
.type_
()));
}
}
clean
::
PrimitiveItem
(
..
)
=>
{
self
.paths
.insert
(
item
.def_id
,
(
self
.stack
.clone
(),
item
.type_
()));
}
_
=>
{}
}
// Maintain the parent stack
let
orig_parent_is_trait_impl
=
self
.parent_is_trait_impl
;
let
parent_pushed
=
match
item
.inner
{
clean
::
TraitItem
(
..
)
|
clean
::
EnumItem
(
..
)
|
clean
::
ForeignTypeItem
|
clean
::
StructItem
(
..
)
|
clean
::
UnionItem
(
..
)
|
clean
::
VariantItem
(
..
)
=>
{
self
.parent_stack
.push
(
item
.def_id
);
self
.parent_is_trait_impl
=
false
;
true
}
clean
::
ImplItem
(
ref
i
)
=>
{
self
.parent_is_trait_impl
=
i
.trait_
.is_some
();
match
i
.for_
{
clean
::
ResolvedPath
{
did
,
..
}
=>
{
self
.parent_stack
.push
(
did
);
true
}
ref
t
=>
{
let
prim_did
=
t
.primitive_type
()
.and_then
(|
t
|
self
.primitive_locations
.get
(
&
t
)
.cloned
());
match
prim_did
{
Some
(
did
)
=>
{
self
.parent_stack
.push
(
did
);
true
}
None
=>
false
,
}
}
}
}
_
=>
false
,
};
// Once we've recursively found all the generics, hoard off all the
// implementations elsewhere.
let
ret
=
self
.fold_item_recur
(
item
)
.and_then
(|
item
|
{
if
let
clean
::
Item
{
inner
:
clean
::
ImplItem
(
_
),
..
}
=
item
{
// Figure out the id of this impl. This may map to a
// primitive rather than always to a struct/enum.
// Note: matching twice to restrict the lifetime of the `i` borrow.
let
mut
dids
=
FxHashSet
::
default
();
if
let
clean
::
Item
{
inner
:
clean
::
ImplItem
(
ref
i
),
..
}
=
item
{
match
i
.for_
{
clean
::
ResolvedPath
{
did
,
..
}
|
clean
::
BorrowedRef
{
type_
:
box
clean
::
ResolvedPath
{
did
,
..
},
..
}
=>
{
dids
.insert
(
did
);
}
ref
t
=>
{
let
did
=
t
.primitive_type
()
.and_then
(|
t
|
self
.primitive_locations
.get
(
&
t
)
.cloned
());
if
let
Some
(
did
)
=
did
{
dids
.insert
(
did
);
}
}
}
if
let
Some
(
generics
)
=
i
.trait_
.as_ref
()
.and_then
(|
t
|
t
.generics
())
{
for
bound
in
generics
{
if
let
Some
(
did
)
=
bound
.def_id
()
{
dids
.insert
(
did
);
}
}
}
}
else
{
unreachable!
()
};
let
impl_item
=
Impl
{
impl_item
:
item
};
if
impl_item
.trait_did
()
.map_or
(
true
,
|
d
|
self
.traits
.contains_key
(
&
d
))
{
for
did
in
dids
{
self
.impls
.entry
(
did
)
.or_insert
(
vec!
[])
.push
(
impl_item
.clone
());
}
}
else
{
let
trait_did
=
impl_item
.trait_did
()
.expect
(
"no trait did"
);
self
.orphan_trait_impls
.push
((
trait_did
,
dids
,
impl_item
));
}
None
}
else
{
Some
(
item
)
}
});
if
pushed
{
self
.stack
.pop
()
.expect
(
"stack already empty"
);
}
if
parent_pushed
{
self
.parent_stack
.pop
()
.expect
(
"parent stack already empty"
);
}
self
.stripped_mod
=
orig_stripped_mod
;
self
.parent_is_trait_impl
=
orig_parent_is_trait_impl
;
ret
}
}
/// Attempts to find where an external crate is located, given that we're
/// rendering in to the specified source destination.
fn
extern_location
(
pub
fn
extern_location
(
e
:
&
clean
::
ExternalCrate
,
extern_url
:
Option
<&
str
>
,
dst
:
&
Path
,
...
...
@@ -539,7 +62,7 @@ fn extern_location(
}
/// Builds the search index from the collected metadata
fn
build_index
(
krate
:
&
clean
::
Crate
,
cache
:
&
mut
Cache
)
->
String
{
pub
fn
build_index
(
krate
:
&
clean
::
Crate
,
cache
:
&
mut
Cache
)
->
String
{
let
mut
defid_to_pathid
=
FxHashMap
::
default
();
let
mut
crate_items
=
Vec
::
with_capacity
(
cache
.search_index
.len
());
let
mut
crate_paths
=
vec!
[];
...
...
@@ -641,7 +164,7 @@ struct CrateData<'a> {
)
}
fn
get_index_search_type
(
item
:
&
clean
::
Item
)
->
Option
<
IndexItemFunctionType
>
{
crate
fn
get_index_search_type
(
item
:
&
clean
::
Item
)
->
Option
<
IndexItemFunctionType
>
{
let
(
all_types
,
ret_types
)
=
match
item
.inner
{
clean
::
FunctionItem
(
ref
f
)
=>
(
&
f
.all_types
,
&
f
.ret_types
),
clean
::
MethodItem
(
ref
m
)
=>
(
&
m
.all_types
,
&
m
.ret_types
),
...
...
src/librustdoc/html/render.rs
→
src/librustdoc/html/render
/mod
.rs
浏览文件 @
6a4396b9
...
...
@@ -25,6 +25,11 @@
//! These threads are not parallelized (they haven't been a bottleneck yet), and
//! both occur before the crate is rendered.
pub
mod
cache
;
#[cfg(test)]
mod
tests
;
use
std
::
borrow
::
Cow
;
use
std
::
cell
::{
Cell
,
RefCell
};
use
std
::
cmp
::
Ordering
;
...
...
@@ -63,24 +68,18 @@
use
crate
::
docfs
::{
DocFS
,
ErrorStorage
,
PathError
};
use
crate
::
doctree
;
use
crate
::
error
::
Error
;
use
crate
::
formats
::{
FormatRenderer
,
Renderer
};
use
crate
::
formats
::
cache
::{
cache
,
Cache
};
use
crate
::
formats
::
item_type
::
ItemType
;
use
crate
::
formats
::{
FormatRenderer
,
Impl
};
use
crate
::
html
::
escape
::
Escape
;
use
crate
::
html
::
format
::
fmt_impl_for_trait_page
;
use
crate
::
html
::
format
::
Function
;
use
crate
::
html
::
format
::{
href
,
print_default_space
,
print_generic_bounds
,
WhereClause
};
use
crate
::
html
::
format
::{
print_abi_with_space
,
Buffer
,
PrintWithSpace
};
use
crate
::
html
::
item_type
::
ItemType
;
use
crate
::
html
::
markdown
::{
self
,
ErrorCodes
,
IdMap
,
Markdown
,
MarkdownHtml
,
MarkdownSummaryLine
};
use
crate
::
html
::
sources
;
use
crate
::
html
::{
highlight
,
layout
,
static_files
};
#[cfg(test)]
mod
tests
;
mod
cache
;
use
cache
::
Cache
;
crate
use
cache
::
ExternalLocation
::{
self
,
*
};
use
cache
::{
build_index
,
ExternalLocation
};
/// A pair of name and its optional document.
pub
type
NameDoc
=
(
String
,
Option
<
String
>
);
...
...
@@ -113,8 +112,6 @@
/// The map used to ensure all generated 'id=' attributes are unique.
id_map
:
Rc
<
RefCell
<
IdMap
>>
,
pub
shared
:
Arc
<
SharedContext
>
,
pub
cache
:
Arc
<
Cache
>
,
pub
parent
:
Rc
<
RefCell
<
Renderer
>>
,
all
:
Rc
<
RefCell
<
AllTypes
>>
,
pub
errors
:
Arc
<
ErrorStorage
>
,
}
...
...
@@ -196,39 +193,20 @@ pub fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<Cow
}
}
/// Metadata about implementations for a type or trait.
#[derive(Clone,
Debug)]
pub
struct
Impl
{
pub
impl_item
:
clean
::
Item
,
}
impl
Impl
{
fn
inner_impl
(
&
self
)
->
&
clean
::
Impl
{
match
self
.impl_item.inner
{
clean
::
ImplItem
(
ref
impl_
)
=>
impl_
,
_
=>
panic!
(
"non-impl item found in impl"
),
}
}
fn
trait_did
(
&
self
)
->
Option
<
DefId
>
{
self
.inner_impl
()
.trait_
.def_id
()
}
}
// Helper structs for rendering items/sidebars and carrying along contextual
// information
/// Struct representing one entry in the JS search index. These are all emitted
/// by hand to a large JS file at the end of cache-creation.
#[derive(Debug)]
struct
IndexItem
{
ty
:
ItemType
,
name
:
String
,
path
:
String
,
desc
:
String
,
parent
:
Option
<
DefId
>
,
parent_idx
:
Option
<
usize
>
,
search_type
:
Option
<
IndexItemFunctionType
>
,
pub
struct
IndexItem
{
pub
ty
:
ItemType
,
pub
name
:
String
,
p
ub
p
ath
:
String
,
pub
desc
:
String
,
p
ub
p
arent
:
Option
<
DefId
>
,
p
ub
p
arent_idx
:
Option
<
usize
>
,
pub
search_type
:
Option
<
IndexItemFunctionType
>
,
}
impl
Serialize
for
IndexItem
{
...
...
@@ -250,7 +228,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// A type used for the search index.
#[derive(Debug)]
struct
RenderType
{
pub
struct
RenderType
{
ty
:
Option
<
DefId
>
,
idx
:
Option
<
usize
>
,
name
:
Option
<
String
>
,
...
...
@@ -281,7 +259,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// A type used for the search index.
#[derive(Debug)]
struct
Generic
{
pub
struct
Generic
{
name
:
String
,
defid
:
Option
<
DefId
>
,
idx
:
Option
<
usize
>
,
...
...
@@ -302,7 +280,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// Full type of functions/methods in the search index.
#[derive(Debug)]
struct
IndexItemFunctionType
{
pub
struct
IndexItemFunctionType
{
inputs
:
Vec
<
TypeWithKind
>
,
output
:
Option
<
Vec
<
TypeWithKind
>>
,
}
...
...
@@ -367,7 +345,6 @@ pub struct StylePath {
pub
disabled
:
bool
,
}
thread_local!
(
static
CACHE_KEY
:
RefCell
<
Arc
<
Cache
>>
=
Default
::
default
());
thread_local!
(
pub
static
CURRENT_DEPTH
:
Cell
<
usize
>
=
Cell
::
new
(
0
));
pub
fn
initial_ids
()
->
Vec
<
String
>
{
...
...
@@ -401,10 +378,9 @@ impl FormatRenderer for Context {
fn
init
(
mut
krate
:
clean
::
Crate
,
options
:
RenderOptions
,
renderinfo
:
RenderInfo
,
_
diag
:
&
rustc_errors
::
Handler
,
_
renderinfo
:
RenderInfo
,
edition
:
Edition
,
parent
:
Rc
<
RefCell
<
Renderer
>>
,
cache
:
&
mut
Cache
,
)
->
Result
<
(
Context
,
clean
::
Crate
),
Error
>
{
// need to save a copy of the options for rendering the index page
let
md_opts
=
options
.clone
();
...
...
@@ -416,11 +392,9 @@ fn init(
sort_modules_alphabetically
,
themes
:
style_files
,
extension_css
,
extern_html_root_urls
,
resource_suffix
,
static_root_path
,
generate_search_filter
,
document_private
,
..
}
=
options
;
...
...
@@ -509,9 +483,10 @@ fn init(
let
dst
=
output
;
scx
.ensure_dir
(
&
dst
)
?
;
krate
=
sources
::
render
(
&
dst
,
&
mut
scx
,
krate
)
?
;
let
(
new_crate
,
index
,
cache
)
=
Cache
::
from_krate
(
renderinfo
,
document_private
,
&
extern_html_root_urls
,
&
dst
,
krate
);
krate
=
new_crate
;
// Build our search index
let
index
=
build_index
(
&
krate
,
cache
);
let
cache
=
Arc
::
new
(
cache
);
let
mut
cx
=
Context
{
current
:
Vec
::
new
(),
...
...
@@ -519,20 +494,15 @@ fn init(
render_redirect_pages
:
false
,
id_map
:
Rc
::
new
(
RefCell
::
new
(
id_map
)),
shared
:
Arc
::
new
(
scx
),
cache
:
cache
.clone
(),
parent
,
all
:
Rc
::
new
(
RefCell
::
new
(
AllTypes
::
new
())),
errors
,
};
// Freeze the cache now that the index has been built. Put an Arc into TLS
// for future parallelization opportunities
CACHE_KEY
.with
(|
v
|
*
v
.borrow_mut
()
=
cache
.clone
());
CURRENT_DEPTH
.with
(|
s
|
s
.set
(
0
));
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
Arc
::
get_mut
(
&
mut
cx
.shared
)
.unwrap
()
.fs
.set_sync_only
(
true
);
write_shared
(
&
cx
,
&
krate
,
index
,
&
md_opts
)
?
;
write_shared
(
&
cx
,
&
krate
,
index
,
&
md_opts
,
&
cache
)
?
;
Arc
::
get_mut
(
&
mut
cx
.shared
)
.unwrap
()
.fs
.set_sync_only
(
false
);
Ok
((
cx
,
krate
))
}
...
...
@@ -547,7 +517,7 @@ fn after_run(&mut self, diag: &rustc_errors::Handler) -> Result<(), Error> {
}
}
fn
after_krate
(
&
mut
self
,
krate
:
&
clean
::
Crate
)
->
Result
<
(),
Error
>
{
fn
after_krate
(
&
mut
self
,
krate
:
&
clean
::
Crate
,
cache
:
&
Cache
)
->
Result
<
(),
Error
>
{
let
final_file
=
self
.dst
.join
(
&
krate
.name
)
.join
(
"all.html"
);
let
settings_file
=
self
.dst
.join
(
"settings.html"
);
let
crate_name
=
krate
.name
.clone
();
...
...
@@ -567,7 +537,7 @@ fn after_krate(&mut self, krate: &clean::Crate) -> Result<(), Error> {
extra_scripts
:
&
[],
static_extra_scripts
:
&
[],
};
let
sidebar
=
if
let
Some
(
ref
version
)
=
self
.
cache.crate_version
{
let
sidebar
=
if
let
Some
(
ref
version
)
=
cache
.crate_version
{
format!
(
"<p class='location'>Crate {}</p>
\
<div class='block version'>
\
...
...
@@ -616,7 +586,7 @@ fn mod_item_in(
&
mut
self
,
item
:
&
clean
::
Item
,
item_name
:
&
str
,
module
:
&
clean
::
Modul
e
,
cache
:
&
Cach
e
,
)
->
Result
<
(),
Error
>
{
// Stripped modules survive the rustdoc passes (i.e., `strip-private`)
// if they contain impls for public types. These modules can also
...
...
@@ -634,7 +604,7 @@ fn mod_item_in(
info!
(
"Recursing into {}"
,
self
.dst
.display
());
let
buf
=
self
.render_item
(
item
,
false
);
let
buf
=
self
.render_item
(
item
,
false
,
cache
);
// buf will be empty if the module is stripped and there is no redirect for it
if
!
buf
.is_empty
()
{
self
.shared
.ensure_dir
(
&
self
.dst
)
?
;
...
...
@@ -644,6 +614,10 @@ fn mod_item_in(
// Render sidebar-items.js used throughout this module.
if
!
self
.render_redirect_pages
{
let
module
=
match
item
.inner
{
clean
::
StrippedItem
(
box
clean
::
ModuleItem
(
ref
m
))
|
clean
::
ModuleItem
(
ref
m
)
=>
m
,
_
=>
unreachable!
(),
};
let
items
=
self
.build_sidebar_items
(
module
);
let
js_dst
=
self
.dst
.join
(
"sidebar-items.js"
);
let
v
=
format!
(
"initSidebarItems({});"
,
serde_json
::
to_string
(
&
items
)
.unwrap
());
...
...
@@ -652,7 +626,7 @@ fn mod_item_in(
Ok
(())
}
fn
mod_item_out
(
&
mut
self
)
->
Result
<
(),
Error
>
{
fn
mod_item_out
(
&
mut
self
,
_
name
:
&
str
)
->
Result
<
(),
Error
>
{
info!
(
"Recursed; leaving {}"
,
self
.dst
.display
());
// Go back to where we were at
...
...
@@ -661,7 +635,7 @@ fn mod_item_out(&mut self) -> Result<(), Error> {
Ok
(())
}
fn
item
(
&
mut
self
,
item
:
clean
::
Item
)
->
Result
<
(),
Error
>
{
fn
item
(
&
mut
self
,
item
:
clean
::
Item
,
cache
:
&
Cache
)
->
Result
<
(),
Error
>
{
// Stripped modules survive the rustdoc passes (i.e., `strip-private`)
// if they contain impls for public types. These modules can also
// contain items such as publicly re-exported structures.
...
...
@@ -673,7 +647,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
self
.render_redirect_pages
=
item
.is_stripped
();
}
let
buf
=
self
.render_item
(
&
item
,
true
);
let
buf
=
self
.render_item
(
&
item
,
true
,
cache
);
// buf will be empty if the item is stripped and there is no redirect for it
if
!
buf
.is_empty
()
{
let
name
=
item
.name
.as_ref
()
.unwrap
();
...
...
@@ -704,6 +678,7 @@ fn write_shared(
krate
:
&
clean
::
Crate
,
search_index
:
String
,
options
:
&
RenderOptions
,
cache
:
&
Cache
,
)
->
Result
<
(),
Error
>
{
// Write out the shared files. Note that these are shared among all rustdoc
// docs placed in the output directory, so this needs to be a synchronized
...
...
@@ -1101,7 +1076,7 @@ fn to_json_string(&self) -> String {
// Update the list of all implementors for traits
let
dst
=
cx
.dst
.join
(
"implementors"
);
for
(
&
did
,
imps
)
in
&
c
x
.c
ache.implementors
{
for
(
&
did
,
imps
)
in
&
cache
.implementors
{
// Private modules can leak through to this phase of rustdoc, which
// could contain implementations for otherwise private types. In some
// rare cases we could find an implementation for an item which wasn't
...
...
@@ -1109,9 +1084,9 @@ fn to_json_string(&self) -> String {
//
// FIXME: this is a vague explanation for why this can't be a `get`, in
// theory it should be...
let
&
(
ref
remote_path
,
remote_item_type
)
=
match
c
x
.c
ache.paths
.get
(
&
did
)
{
let
&
(
ref
remote_path
,
remote_item_type
)
=
match
cache
.paths
.get
(
&
did
)
{
Some
(
p
)
=>
p
,
None
=>
match
c
x
.c
ache.external_paths
.get
(
&
did
)
{
None
=>
match
cache
.external_paths
.get
(
&
did
)
{
Some
(
p
)
=>
p
,
None
=>
continue
,
},
...
...
@@ -1149,7 +1124,7 @@ struct Implementor {
// Only create a js file if we have impls to add to it. If the trait is
// documented locally though we always create the file to avoid dead
// links.
if
implementors
.is_empty
()
&&
!
c
x
.c
ache.paths
.contains_key
(
&
did
)
{
if
implementors
.is_empty
()
&&
!
cache
.paths
.contains_key
(
&
did
)
{
continue
;
}
...
...
@@ -1454,7 +1429,7 @@ fn root_path(&self) -> String {
"../"
.repeat
(
self
.current
.len
())
}
fn
render_item
(
&
self
,
it
:
&
clean
::
Item
,
pushname
:
bool
)
->
String
{
fn
render_item
(
&
self
,
it
:
&
clean
::
Item
,
pushname
:
bool
,
cache
:
&
Cache
)
->
String
{
// A little unfortunate that this is done like this, but it sure
// does make formatting *a lot* nicer.
CURRENT_DEPTH
.with
(|
slot
|
{
...
...
@@ -1507,13 +1482,13 @@ fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
layout
::
render
(
&
self
.shared.layout
,
&
page
,
|
buf
:
&
mut
_
|
print_sidebar
(
self
,
it
,
buf
),
|
buf
:
&
mut
_
|
print_item
(
self
,
it
,
buf
),
|
buf
:
&
mut
_
|
print_sidebar
(
self
,
it
,
buf
,
cache
),
|
buf
:
&
mut
_
|
print_item
(
self
,
it
,
buf
,
cache
),
&
self
.shared.style_files
,
)
}
else
{
let
mut
url
=
self
.root_path
();
if
let
Some
(
&
(
ref
names
,
ty
))
=
self
.
cache.paths
.get
(
&
it
.def_id
)
{
if
let
Some
(
&
(
ref
names
,
ty
))
=
cache
.paths
.get
(
&
it
.def_id
)
{
for
name
in
&
names
[
..
names
.len
()
-
1
]
{
url
.push_str
(
name
);
url
.push_str
(
"/"
);
...
...
@@ -1552,9 +1527,7 @@ fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc
}
map
}
}
impl
Context
{
/// Generates a url appropriate for an `href` attribute back to the source of
/// this item.
///
...
...
@@ -1564,7 +1537,7 @@ impl Context {
/// If `None` is returned, then a source link couldn't be generated. This
/// may happen, for example, with externally inlined items where the source
/// of their crate documentation isn't known.
fn
src_href
(
&
self
,
item
:
&
clean
::
Item
)
->
Option
<
String
>
{
fn
src_href
(
&
self
,
item
:
&
clean
::
Item
,
cache
:
&
Cache
)
->
Option
<
String
>
{
let
mut
root
=
self
.root_path
();
let
mut
path
=
String
::
new
();
...
...
@@ -1583,13 +1556,13 @@ fn src_href(&self, item: &clean::Item) -> Option<String> {
return
None
;
}
}
else
{
let
(
krate
,
src_root
)
=
match
*
self
.
cache.extern_locations
.get
(
&
item
.source.cnum
)
?
{
(
ref
name
,
ref
src
,
Local
)
=>
(
name
,
src
),
(
ref
name
,
ref
src
,
Remote
(
ref
s
))
=>
{
let
(
krate
,
src_root
)
=
match
*
cache
.extern_locations
.get
(
&
item
.source.cnum
)
?
{
(
ref
name
,
ref
src
,
ExternalLocation
::
Local
)
=>
(
name
,
src
),
(
ref
name
,
ref
src
,
ExternalLocation
::
Remote
(
ref
s
))
=>
{
root
=
s
.to_string
();
(
name
,
src
)
}
(
_
,
_
,
Unknown
)
=>
return
None
,
(
_
,
_
,
ExternalLocation
::
Unknown
)
=>
return
None
,
};
sources
::
clean_path
(
&
src_root
,
file
,
false
,
|
component
|
{
...
...
@@ -1626,7 +1599,7 @@ fn wrap_into_docblock<F>(w: &mut Buffer, f: F)
write!
(
w
,
"</div>"
)
}
fn
print_item
(
cx
:
&
Context
,
item
:
&
clean
::
Item
,
buf
:
&
mut
Buffer
)
{
fn
print_item
(
cx
:
&
Context
,
item
:
&
clean
::
Item
,
buf
:
&
mut
Buffer
,
cache
:
&
Cache
)
{
debug_assert!
(
!
item
.is_stripped
());
// Write the breadcrumb trail header for the top
write!
(
buf
,
"<h1 class='fqn'><span class='out-of-band'>"
);
...
...
@@ -1654,7 +1627,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
// this page, and this link will be auto-clicked. The `id` attribute is
// used to find the link to auto-click.
if
cx
.shared.include_sources
&&
!
item
.is_primitive
()
{
if
let
Some
(
l
)
=
cx
.src_href
(
item
)
{
if
let
Some
(
l
)
=
cx
.src_href
(
item
,
cache
)
{
write!
(
buf
,
"<a class='srclink' href='{}' title='{}'>[src]</a>"
,
l
,
"goto source code"
);
}
}
...
...
@@ -1715,20 +1688,20 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) {
clean
::
FunctionItem
(
ref
f
)
|
clean
::
ForeignFunctionItem
(
ref
f
)
=>
{
item_function
(
buf
,
cx
,
item
,
f
)
}
clean
::
TraitItem
(
ref
t
)
=>
item_trait
(
buf
,
cx
,
item
,
t
),
clean
::
StructItem
(
ref
s
)
=>
item_struct
(
buf
,
cx
,
item
,
s
),
clean
::
UnionItem
(
ref
s
)
=>
item_union
(
buf
,
cx
,
item
,
s
),
clean
::
EnumItem
(
ref
e
)
=>
item_enum
(
buf
,
cx
,
item
,
e
),
clean
::
TypedefItem
(
ref
t
,
_
)
=>
item_typedef
(
buf
,
cx
,
item
,
t
),
clean
::
TraitItem
(
ref
t
)
=>
item_trait
(
buf
,
cx
,
item
,
t
,
cache
),
clean
::
StructItem
(
ref
s
)
=>
item_struct
(
buf
,
cx
,
item
,
s
,
cache
),
clean
::
UnionItem
(
ref
s
)
=>
item_union
(
buf
,
cx
,
item
,
s
,
cache
),
clean
::
EnumItem
(
ref
e
)
=>
item_enum
(
buf
,
cx
,
item
,
e
,
cache
),
clean
::
TypedefItem
(
ref
t
,
_
)
=>
item_typedef
(
buf
,
cx
,
item
,
t
,
cache
),
clean
::
MacroItem
(
ref
m
)
=>
item_macro
(
buf
,
cx
,
item
,
m
),
clean
::
ProcMacroItem
(
ref
m
)
=>
item_proc_macro
(
buf
,
cx
,
item
,
m
),
clean
::
PrimitiveItem
(
_
)
=>
item_primitive
(
buf
,
cx
,
item
),
clean
::
PrimitiveItem
(
_
)
=>
item_primitive
(
buf
,
cx
,
item
,
cache
),
clean
::
StaticItem
(
ref
i
)
|
clean
::
ForeignStaticItem
(
ref
i
)
=>
item_static
(
buf
,
cx
,
item
,
i
),
clean
::
ConstantItem
(
ref
c
)
=>
item_constant
(
buf
,
cx
,
item
,
c
),
clean
::
ForeignTypeItem
=>
item_foreign_type
(
buf
,
cx
,
item
),
clean
::
ForeignTypeItem
=>
item_foreign_type
(
buf
,
cx
,
item
,
cache
),
clean
::
KeywordItem
(
_
)
=>
item_keyword
(
buf
,
cx
,
item
),
clean
::
OpaqueTyItem
(
ref
e
,
_
)
=>
item_opaque_ty
(
buf
,
cx
,
item
,
e
),
clean
::
TraitAliasItem
(
ref
ta
)
=>
item_trait_alias
(
buf
,
cx
,
item
,
ta
),
clean
::
OpaqueTyItem
(
ref
e
,
_
)
=>
item_opaque_ty
(
buf
,
cx
,
item
,
e
,
cache
),
clean
::
TraitAliasItem
(
ref
ta
)
=>
item_trait_alias
(
buf
,
cx
,
item
,
ta
,
cache
),
_
=>
{
// We don't generate pages for any other type.
unreachable!
();
...
...
@@ -1751,7 +1724,7 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
}
#[inline]
fn
plain_summary_line
(
s
:
Option
<&
str
>
)
->
String
{
crate
fn
plain_summary_line
(
s
:
Option
<&
str
>
)
->
String
{
let
s
=
s
.unwrap_or
(
""
);
// This essentially gets the first paragraph of text in one line.
let
mut
line
=
s
...
...
@@ -1768,7 +1741,7 @@ fn plain_summary_line(s: Option<&str>) -> String {
markdown
::
plain_summary_line
(
&
line
[
..
])
}
fn
shorten
(
s
:
String
)
->
String
{
crate
fn
shorten
(
s
:
String
)
->
String
{
if
s
.chars
()
.count
()
>
60
{
let
mut
len
=
0
;
let
mut
ret
=
s
...
...
@@ -2338,6 +2311,7 @@ fn render_implementor(
w
:
&
mut
Buffer
,
implementor_dups
:
&
FxHashMap
<&
str
,
(
DefId
,
bool
)
>
,
aliases
:
&
[
String
],
cache
:
&
Cache
,
)
{
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
...
...
@@ -2361,10 +2335,17 @@ fn render_implementor(
false
,
false
,
aliases
,
cache
,
);
}
fn
render_impls
(
cx
:
&
Context
,
w
:
&
mut
Buffer
,
traits
:
&
[
&&
Impl
],
containing_item
:
&
clean
::
Item
)
{
fn
render_impls
(
cx
:
&
Context
,
w
:
&
mut
Buffer
,
traits
:
&
[
&&
Impl
],
containing_item
:
&
clean
::
Item
,
cache
:
&
Cache
,
)
{
let
mut
impls
=
traits
.iter
()
.map
(|
i
|
{
...
...
@@ -2383,6 +2364,7 @@ fn render_impls(cx: &Context, w: &mut Buffer, traits: &[&&Impl], containing_item
false
,
true
,
&
[],
cache
,
);
buffer
.into_inner
()
})
...
...
@@ -2415,7 +2397,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering {
name_key
(
&
lhs
)
.cmp
(
&
name_key
(
&
rhs
))
}
fn
item_trait
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
Trait
)
{
fn
item_trait
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
Trait
,
cache
:
&
Cache
)
{
let
bounds
=
bounds
(
&
t
.bounds
,
false
);
let
types
=
t
.items
.iter
()
.filter
(|
m
|
m
.is_associated_type
())
.collect
::
<
Vec
<
_
>>
();
let
consts
=
t
.items
.iter
()
.filter
(|
m
|
m
.is_associated_const
())
.collect
::
<
Vec
<
_
>>
();
...
...
@@ -2575,9 +2557,9 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
}
// If there are methods directly on this trait object, render them here.
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
);
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
);
if
let
Some
(
implementors
)
=
c
x
.c
ache.implementors
.get
(
&
it
.def_id
)
{
if
let
Some
(
implementors
)
=
cache
.implementors
.get
(
&
it
.def_id
)
{
// The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found.
let
mut
implementor_dups
:
FxHashMap
<&
str
,
(
DefId
,
bool
)
>
=
FxHashMap
::
default
();
...
...
@@ -2599,7 +2581,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
}
let
(
local
,
foreign
)
=
implementors
.iter
()
.partition
::
<
Vec
<
_
>
,
_
>
(|
i
|
{
i
.inner_impl
()
.for_
.def_id
()
.map_or
(
true
,
|
d
|
c
x
.c
ache.paths
.contains_key
(
&
d
))
i
.inner_impl
()
.for_
.def_id
()
.map_or
(
true
,
|
d
|
cache
.paths
.contains_key
(
&
d
))
});
let
(
mut
synthetic
,
mut
concrete
):
(
Vec
<&&
Impl
>
,
Vec
<&&
Impl
>
)
=
...
...
@@ -2628,6 +2610,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
true
,
false
,
&
[],
cache
,
);
}
write_loading_content
(
w
,
""
);
...
...
@@ -2640,7 +2623,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
"<div class='item-list' id='implementors-list'>"
,
);
for
implementor
in
concrete
{
render_implementor
(
cx
,
implementor
,
w
,
&
implementor_dups
,
&
[]);
render_implementor
(
cx
,
implementor
,
w
,
&
implementor_dups
,
&
[]
,
cache
);
}
write_loading_content
(
w
,
"</div>"
);
...
...
@@ -2658,6 +2641,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
w
,
&
implementor_dups
,
&
collect_paths_for_type
(
implementor
.inner_impl
()
.for_
.clone
()),
cache
,
);
}
write_loading_content
(
w
,
"</div>"
);
...
...
@@ -2693,7 +2677,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
path
=
if
it
.def_id
.is_local
()
{
cx
.current
.join
(
"/"
)
}
else
{
let
(
ref
path
,
_
)
=
c
x
.c
ache.external_paths
[
&
it
.def_id
];
let
(
ref
path
,
_
)
=
cache
.external_paths
[
&
it
.def_id
];
path
[
..
path
.len
()
-
1
]
.join
(
"/"
)
},
ty
=
it
.type_
(),
...
...
@@ -2702,7 +2686,7 @@ fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
}
fn
naive_assoc_href
(
it
:
&
clean
::
Item
,
link
:
AssocItemLink
<
'_
>
)
->
String
{
use
crate
::
html
::
item_type
::
ItemType
::
*
;
use
crate
::
formats
::
item_type
::
ItemType
::
*
;
let
name
=
it
.name
.as_ref
()
.unwrap
();
let
ty
=
match
it
.type_
()
{
...
...
@@ -2868,7 +2852,7 @@ fn method(
}
}
fn
item_struct
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
s
:
&
clean
::
Struct
)
{
fn
item_struct
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
s
:
&
clean
::
Struct
,
cache
:
&
Cache
)
{
wrap_into_docblock
(
w
,
|
w
|
{
write!
(
w
,
"<pre class='rust struct'>"
);
render_attributes
(
w
,
it
,
true
);
...
...
@@ -2915,10 +2899,10 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
}
}
}
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_union
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
s
:
&
clean
::
Union
)
{
fn
item_union
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
s
:
&
clean
::
Union
,
cache
:
&
Cache
)
{
wrap_into_docblock
(
w
,
|
w
|
{
write!
(
w
,
"<pre class='rust union'>"
);
render_attributes
(
w
,
it
,
true
);
...
...
@@ -2961,10 +2945,10 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union)
document
(
w
,
cx
,
field
);
}
}
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_enum
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
e
:
&
clean
::
Enum
)
{
fn
item_enum
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
e
:
&
clean
::
Enum
,
cache
:
&
Cache
)
{
wrap_into_docblock
(
w
,
|
w
|
{
write!
(
w
,
"<pre class='rust enum'>"
);
render_attributes
(
w
,
it
,
true
);
...
...
@@ -3089,7 +3073,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
render_stability_since
(
w
,
variant
,
it
);
}
}
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
const
ALLOWED_ATTRIBUTES
:
&
[
Symbol
]
=
&
[
...
...
@@ -3288,9 +3272,9 @@ fn render_assoc_items(
containing_item
:
&
clean
::
Item
,
it
:
DefId
,
what
:
AssocItemRender
<
'_
>
,
cache
:
&
Cache
,
)
{
let
c
=
&
cx
.cache
;
let
v
=
match
c
.impls
.get
(
&
it
)
{
let
v
=
match
cache
.impls
.get
(
&
it
)
{
Some
(
v
)
=>
v
,
None
=>
return
,
};
...
...
@@ -3336,6 +3320,7 @@ fn render_assoc_items(
false
,
true
,
&
[],
cache
,
);
}
}
...
...
@@ -3344,11 +3329,11 @@ fn render_assoc_items(
}
if
!
traits
.is_empty
()
{
let
deref_impl
=
traits
.iter
()
.find
(|
t
|
t
.inner_impl
()
.trait_
.def_id
()
==
c
.deref_trait_did
);
traits
.iter
()
.find
(|
t
|
t
.inner_impl
()
.trait_
.def_id
()
==
c
ache
.deref_trait_did
);
if
let
Some
(
impl_
)
=
deref_impl
{
let
has_deref_mut
=
traits
.iter
()
.any
(|
t
|
t
.inner_impl
()
.trait_
.def_id
()
==
c
.deref_mut_trait_did
);
render_deref_methods
(
w
,
cx
,
impl_
,
containing_item
,
has_deref_mut
);
traits
.iter
()
.any
(|
t
|
t
.inner_impl
()
.trait_
.def_id
()
==
c
ache
.deref_mut_trait_did
);
render_deref_methods
(
w
,
cx
,
impl_
,
containing_item
,
has_deref_mut
,
cache
);
}
let
(
synthetic
,
concrete
):
(
Vec
<&&
Impl
>
,
Vec
<&&
Impl
>
)
=
...
...
@@ -3357,7 +3342,7 @@ fn render_assoc_items(
concrete
.into_iter
()
.partition
(|
t
|
t
.inner_impl
()
.blanket_impl
.is_some
());
let
mut
impls
=
Buffer
::
empty_from
(
&
w
);
render_impls
(
cx
,
&
mut
impls
,
&
concrete
,
containing_item
);
render_impls
(
cx
,
&
mut
impls
,
&
concrete
,
containing_item
,
cache
);
let
impls
=
impls
.into_inner
();
if
!
impls
.is_empty
()
{
write!
(
...
...
@@ -3382,7 +3367,7 @@ fn render_assoc_items(
<div id='synthetic-implementations-list'>
\
"
);
render_impls
(
cx
,
w
,
&
synthetic
,
containing_item
);
render_impls
(
cx
,
w
,
&
synthetic
,
containing_item
,
cache
);
write!
(
w
,
"</div>"
);
}
...
...
@@ -3397,7 +3382,7 @@ fn render_assoc_items(
<div id='blanket-implementations-list'>
\
"
);
render_impls
(
cx
,
w
,
&
blanket_impl
,
containing_item
);
render_impls
(
cx
,
w
,
&
blanket_impl
,
containing_item
,
cache
);
write!
(
w
,
"</div>"
);
}
}
...
...
@@ -3409,6 +3394,7 @@ fn render_deref_methods(
impl_
:
&
Impl
,
container_item
:
&
clean
::
Item
,
deref_mut
:
bool
,
cache
:
&
Cache
,
)
{
let
deref_type
=
impl_
.inner_impl
()
.trait_
.as_ref
()
.unwrap
();
let
(
target
,
real_target
)
=
impl_
...
...
@@ -3426,11 +3412,11 @@ fn render_deref_methods(
let
what
=
AssocItemRender
::
DerefFor
{
trait_
:
deref_type
,
type_
:
real_target
,
deref_mut_
:
deref_mut
};
if
let
Some
(
did
)
=
target
.def_id
()
{
render_assoc_items
(
w
,
cx
,
container_item
,
did
,
what
);
render_assoc_items
(
w
,
cx
,
container_item
,
did
,
what
,
cache
);
}
else
{
if
let
Some
(
prim
)
=
target
.primitive_type
()
{
if
let
Some
(
&
did
)
=
c
x
.c
ache.primitive_locations
.get
(
&
prim
)
{
render_assoc_items
(
w
,
cx
,
container_item
,
did
,
what
);
if
let
Some
(
&
did
)
=
cache
.primitive_locations
.get
(
&
prim
)
{
render_assoc_items
(
w
,
cx
,
container_item
,
did
,
what
,
cache
);
}
}
}
...
...
@@ -3532,6 +3518,7 @@ fn render_impl(
// This argument is used to reference same type with different paths to avoid duplication
// in documentation pages for trait with automatic implementations like "Send" and "Sync".
aliases
:
&
[
String
],
cache
:
&
Cache
,
)
{
if
render_mode
==
RenderMode
::
Normal
{
let
id
=
cx
.derive_id
(
match
i
.inner_impl
()
.trait_
{
...
...
@@ -3574,7 +3561,7 @@ fn render_impl(
write!
(
w
,
"<a href='#{}' class='anchor'></a>"
,
id
);
let
since
=
i
.impl_item.stability
.as_ref
()
.map
(|
s
|
&
s
.since
[
..
]);
render_stability_since_raw
(
w
,
since
,
outer_version
);
if
let
Some
(
l
)
=
cx
.src_href
(
&
i
.impl_item
)
{
if
let
Some
(
l
)
=
cx
.src_href
(
&
i
.impl_item
,
cache
)
{
write!
(
w
,
"<a class='srclink' href='{}' title='{}'>[src]</a>"
,
l
,
"goto source code"
);
}
write!
(
w
,
"</h3>"
);
...
...
@@ -3606,6 +3593,7 @@ fn doc_impl_item(
outer_version
:
Option
<&
str
>
,
trait_
:
Option
<&
clean
::
Trait
>
,
show_def_docs
:
bool
,
cache
:
&
Cache
,
)
{
let
item_type
=
item
.type_
();
let
name
=
item
.name
.as_ref
()
.unwrap
();
...
...
@@ -3634,7 +3622,7 @@ fn doc_impl_item(
render_assoc_item
(
w
,
item
,
link
.anchor
(
&
id
),
ItemType
::
Impl
);
write!
(
w
,
"</code>"
);
render_stability_since_raw
(
w
,
item
.stable_since
(),
outer_version
);
if
let
Some
(
l
)
=
cx
.src_href
(
item
)
{
if
let
Some
(
l
)
=
cx
.src_href
(
item
,
cache
)
{
write!
(
w
,
"<a class='srclink' href='{}' title='{}'>[src]</a>"
,
...
...
@@ -3656,7 +3644,7 @@ fn doc_impl_item(
assoc_const
(
w
,
item
,
ty
,
default
.as_ref
(),
link
.anchor
(
&
id
),
""
);
write!
(
w
,
"</code>"
);
render_stability_since_raw
(
w
,
item
.stable_since
(),
outer_version
);
if
let
Some
(
l
)
=
cx
.src_href
(
item
)
{
if
let
Some
(
l
)
=
cx
.src_href
(
item
,
cache
)
{
write!
(
w
,
"<a class='srclink' href='{}' title='{}'>[src]</a>"
,
...
...
@@ -3707,7 +3695,7 @@ fn doc_impl_item(
}
}
let
traits
=
&
c
x
.c
ache.traits
;
let
traits
=
&
cache
.traits
;
let
trait_
=
i
.trait_did
()
.map
(|
did
|
&
traits
[
&
did
]);
write!
(
w
,
"<div class='impl-items'>"
);
...
...
@@ -3722,6 +3710,7 @@ fn doc_impl_item(
outer_version
,
trait_
,
show_def_docs
,
cache
,
);
}
...
...
@@ -3733,6 +3722,7 @@ fn render_default_items(
render_mode
:
RenderMode
,
outer_version
:
Option
<&
str
>
,
show_def_docs
:
bool
,
cache
:
&
Cache
,
)
{
for
trait_item
in
&
t
.items
{
let
n
=
trait_item
.name
.clone
();
...
...
@@ -3752,6 +3742,7 @@ fn render_default_items(
outer_version
,
None
,
show_def_docs
,
cache
,
);
}
}
...
...
@@ -3770,13 +3761,20 @@ fn render_default_items(
render_mode
,
outer_version
,
show_def_docs
,
cache
,
);
}
}
write!
(
w
,
"</div>"
);
}
fn
item_opaque_ty
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
OpaqueTy
)
{
fn
item_opaque_ty
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
OpaqueTy
,
cache
:
&
Cache
,
)
{
write!
(
w
,
"<pre class='rust opaque'>"
);
render_attributes
(
w
,
it
,
false
);
write!
(
...
...
@@ -3794,10 +3792,16 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Opa
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_trait_alias
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
TraitAlias
)
{
fn
item_trait_alias
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
TraitAlias
,
cache
:
&
Cache
,
)
{
write!
(
w
,
"<pre class='rust trait-alias'>"
);
render_attributes
(
w
,
it
,
false
);
write!
(
...
...
@@ -3815,10 +3819,10 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::T
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_typedef
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
Typedef
)
{
fn
item_typedef
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
t
:
&
clean
::
Typedef
,
cache
:
&
Cache
)
{
write!
(
w
,
"<pre class='rust typedef'>"
);
render_attributes
(
w
,
it
,
false
);
write!
(
...
...
@@ -3836,10 +3840,10 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_foreign_type
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
)
{
fn
item_foreign_type
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
cache
:
&
Cache
)
{
writeln!
(
w
,
"<pre class='rust foreigntype'>extern {{"
);
render_attributes
(
w
,
it
,
false
);
write!
(
...
...
@@ -3851,10 +3855,10 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) {
document
(
w
,
cx
,
it
);
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
print_sidebar
(
cx
:
&
Context
,
it
:
&
clean
::
Item
,
buffer
:
&
mut
Buffer
)
{
fn
print_sidebar
(
cx
:
&
Context
,
it
:
&
clean
::
Item
,
buffer
:
&
mut
Buffer
,
cache
:
&
Cache
)
{
let
parentlen
=
cx
.current
.len
()
-
if
it
.is_mod
()
{
1
}
else
{
0
};
if
it
.is_struct
()
...
...
@@ -3889,7 +3893,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) {
}
if
it
.is_crate
()
{
if
let
Some
(
ref
version
)
=
c
x
.c
ache.crate_version
{
if
let
Some
(
ref
version
)
=
cache
.crate_version
{
write!
(
buffer
,
"<div class='block version'>
\
...
...
@@ -4526,9 +4530,9 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
document
(
w
,
cx
,
it
)
}
fn
item_primitive
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
)
{
fn
item_primitive
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
,
cache
:
&
Cache
)
{
document
(
w
,
cx
,
it
);
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
)
render_assoc_items
(
w
,
cx
,
it
,
it
.def_id
,
AssocItemRender
::
All
,
cache
)
}
fn
item_keyword
(
w
:
&
mut
Buffer
,
cx
:
&
Context
,
it
:
&
clean
::
Item
)
{
...
...
@@ -4593,7 +4597,3 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
}
out
}
crate
fn
cache
()
->
Arc
<
Cache
>
{
CACHE_KEY
.with
(|
c
|
c
.borrow
()
.clone
())
}
src/librustdoc/lib.rs
浏览文件 @
6a4396b9
...
...
@@ -66,19 +66,8 @@
#[macro_use]
mod
error
;
mod
fold
;
mod
formats
;
pub
mod
html
{
crate
mod
escape
;
crate
mod
format
;
crate
mod
highlight
;
crate
mod
item_type
;
crate
mod
layout
;
pub
mod
markdown
;
crate
mod
render
;
crate
mod
sources
;
crate
mod
static_files
;
crate
mod
toc
;
}
crate
mod
formats
;
crate
mod
html
;
mod
markdown
;
mod
passes
;
mod
test
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录