1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 pub use self::MaybeTyped
::*;
13 use rustc_driver
::{driver, target_features, abort_on_err}
;
14 use rustc
::dep_graph
::DepGraph
;
15 use rustc
::session
::{self, config}
;
16 use rustc
::hir
::def_id
::DefId
;
17 use rustc
::hir
::def
::Def
;
18 use rustc
::middle
::privacy
::AccessLevels
;
19 use rustc
::ty
::{self, TyCtxt}
;
20 use rustc
::hir
::map
as hir_map
;
22 use rustc
::util
::nodemap
::FnvHashMap
;
23 use rustc_trans
::back
::link
;
24 use rustc_resolve
as resolve
;
25 use rustc_metadata
::cstore
::CStore
;
27 use syntax
::{ast, codemap}
;
28 use syntax
::feature_gate
::UnstableFeatures
;
30 use errors
::emitter
::ColorConfig
;
32 use std
::cell
::{RefCell, Cell}
;
35 use std
::path
::PathBuf
;
37 use visit_ast
::RustdocVisitor
;
40 use html
::render
::RenderInfo
;
42 pub use rustc
::session
::config
::Input
;
43 pub use rustc
::session
::search_paths
::SearchPaths
;
45 /// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
46 pub enum MaybeTyped
<'a
, 'tcx
: 'a
> {
47 Typed(TyCtxt
<'a
, 'tcx
, 'tcx
>),
48 NotTyped(&'a session
::Session
)
51 pub type ExternalPaths
= FnvHashMap
<DefId
, (Vec
<String
>, clean
::TypeKind
)>;
53 pub struct DocContext
<'a
, 'tcx
: 'a
> {
54 pub map
: &'a hir_map
::Map
<'tcx
>,
55 pub maybe_typed
: MaybeTyped
<'a
, 'tcx
>,
57 pub populated_all_crate_impls
: Cell
<bool
>,
58 pub deref_trait_did
: Cell
<Option
<DefId
>>,
59 pub deref_mut_trait_did
: Cell
<Option
<DefId
>>,
60 // Note that external items for which `doc(hidden)` applies to are shown as
61 // non-reachable while local items aren't. This is because we're reusing
62 // the access levels from crateanalysis.
63 /// Later on moved into `clean::Crate`
64 pub access_levels
: RefCell
<AccessLevels
<DefId
>>,
65 /// Later on moved into `html::render::CACHE_KEY`
66 pub renderinfo
: RefCell
<RenderInfo
>,
67 /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
68 pub external_traits
: RefCell
<FnvHashMap
<DefId
, clean
::Trait
>>,
70 // The current set of type and lifetime substitutions,
71 // for expanding type aliases at the HIR level:
73 /// Table type parameter definition -> substituted type
74 pub ty_substs
: RefCell
<FnvHashMap
<Def
, clean
::Type
>>,
75 /// Table node id of lifetime parameter definition -> substituted lifetime
76 pub lt_substs
: RefCell
<FnvHashMap
<ast
::NodeId
, clean
::Lifetime
>>,
79 impl<'b
, 'tcx
> DocContext
<'b
, 'tcx
> {
80 pub fn sess
<'a
>(&'a
self) -> &'a session
::Session
{
81 match self.maybe_typed
{
82 Typed(tcx
) => &tcx
.sess
,
83 NotTyped(ref sess
) => sess
87 pub fn tcx_opt
<'a
>(&'a
self) -> Option
<TyCtxt
<'a
, 'tcx
, 'tcx
>> {
88 match self.maybe_typed
{
89 Typed(tcx
) => Some(tcx
),
94 pub fn tcx
<'a
>(&'a
self) -> TyCtxt
<'a
, 'tcx
, 'tcx
> {
95 let tcx_opt
= self.tcx_opt();
96 tcx_opt
.expect("tcx not present")
99 /// Call the closure with the given parameters set as
100 /// the substitutions for a type alias' RHS.
101 pub fn enter_alias
<F
, R
>(&self,
102 ty_substs
: FnvHashMap
<Def
, clean
::Type
>,
103 lt_substs
: FnvHashMap
<ast
::NodeId
, clean
::Lifetime
>,
105 where F
: FnOnce() -> R
{
106 let (old_tys
, old_lts
) =
107 (mem
::replace(&mut *self.ty_substs
.borrow_mut(), ty_substs
),
108 mem
::replace(&mut *self.lt_substs
.borrow_mut(), lt_substs
));
110 *self.ty_substs
.borrow_mut() = old_tys
;
111 *self.lt_substs
.borrow_mut() = old_lts
;
116 pub trait DocAccessLevels
{
117 fn is_doc_reachable(&self, DefId
) -> bool
;
120 impl DocAccessLevels
for AccessLevels
<DefId
> {
121 fn is_doc_reachable(&self, did
: DefId
) -> bool
{
127 pub fn run_core(search_paths
: SearchPaths
,
129 externs
: config
::Externs
,
131 triple
: Option
<String
>,
132 maybe_sysroot
: Option
<PathBuf
>) -> (clean
::Crate
, RenderInfo
)
134 // Parse, resolve, and typecheck the given crate.
136 let cpath
= match input
{
137 Input
::File(ref p
) => Some(p
.clone()),
141 let warning_lint
= lint
::builtin
::WARNINGS
.name_lower();
143 let sessopts
= config
::Options
{
144 maybe_sysroot
: maybe_sysroot
,
145 search_paths
: search_paths
,
146 crate_types
: vec
!(config
::CrateTypeRlib
),
147 lint_opts
: vec
!((warning_lint
, lint
::Allow
)),
148 lint_cap
: Some(lint
::Allow
),
150 target_triple
: triple
.unwrap_or(config
::host_triple().to_string()),
151 // Ensure that rustdoc works even if rustc is feature-staged
152 unstable_features
: UnstableFeatures
::Allow
,
153 ..config
::basic_options().clone()
156 let codemap
= Rc
::new(codemap
::CodeMap
::new());
157 let diagnostic_handler
= errors
::Handler
::with_tty_emitter(ColorConfig
::Auto
,
160 Some(codemap
.clone()));
162 let dep_graph
= DepGraph
::new(false);
163 let _ignore
= dep_graph
.in_ignore();
164 let cstore
= Rc
::new(CStore
::new(&dep_graph
));
165 let sess
= session
::build_session_(sessopts
, &dep_graph
, cpath
, diagnostic_handler
,
166 codemap
, cstore
.clone());
167 rustc_lint
::register_builtins(&mut sess
.lint_store
.borrow_mut(), Some(&sess
));
169 let mut cfg
= config
::build_configuration(&sess
, config
::parse_cfgspecs(cfgs
));
170 target_features
::add_configuration(&mut cfg
, &sess
);
172 let krate
= panictry
!(driver
::phase_1_parse_input(&sess
, cfg
, &input
));
174 let name
= link
::find_crate_name(Some(&sess
), &krate
.attrs
, &input
);
176 let driver
::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. }
= {
177 driver
::phase_2_configure_and_expand(
178 &sess
, &cstore
, krate
, None
, &name
, None
, resolve
::MakeGlobMap
::No
, |_
| Ok(()),
179 ).expect("phase_2_configure_and_expand aborted in rustdoc!")
182 let arenas
= ty
::CtxtArenas
::new();
183 let hir_map
= hir_map
::map_crate(&mut hir_forest
, defs
);
185 abort_on_err(driver
::phase_3_run_analysis_passes(&sess
,
191 |tcx
, _
, analysis
, _
, result
| {
192 if let Err(_
) = result
{
193 sess
.fatal("Compilation failed, aborting rustdoc");
196 let ty
::CrateAnalysis { access_levels, .. }
= analysis
;
198 // Convert from a NodeId set to a DefId set since we don't always have easy access
199 // to the map from defid -> nodeid
200 let access_levels
= AccessLevels
{
201 map
: access_levels
.map
.into_iter()
202 .map(|(k
, v
)| (tcx
.map
.local_def_id(k
), v
))
206 let ctxt
= DocContext
{
208 maybe_typed
: Typed(tcx
),
210 populated_all_crate_impls
: Cell
::new(false),
211 deref_trait_did
: Cell
::new(None
),
212 deref_mut_trait_did
: Cell
::new(None
),
213 access_levels
: RefCell
::new(access_levels
),
214 external_traits
: Default
::default(),
215 renderinfo
: Default
::default(),
216 ty_substs
: Default
::default(),
217 lt_substs
: Default
::default(),
219 debug
!("crate: {:?}", ctxt
.map
.krate());
222 let mut v
= RustdocVisitor
::new(&ctxt
);
223 v
.visit(ctxt
.map
.krate());
227 (krate
, ctxt
.renderinfo
.into_inner())