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.
12 use rustc_driver
::{driver, target_features, abort_on_err}
;
13 use rustc_driver
::pretty
::ReplaceBodyWithLoop
;
14 use rustc
::session
::{self, config}
;
15 use rustc
::hir
::def_id
::DefId
;
16 use rustc
::hir
::def
::Def
;
17 use rustc
::middle
::privacy
::AccessLevels
;
18 use rustc
::ty
::{self, TyCtxt, GlobalArenas}
;
19 use rustc
::hir
::map
as hir_map
;
21 use rustc
::util
::nodemap
::FxHashMap
;
23 use rustc_trans
::back
::link
;
24 use rustc_resolve
as resolve
;
25 use rustc_metadata
::cstore
::CStore
;
28 use syntax
::feature_gate
::UnstableFeatures
;
29 use syntax
::fold
::Folder
;
31 use errors
::emitter
::ColorConfig
;
33 use std
::cell
::{RefCell, Cell}
;
36 use std
::path
::PathBuf
;
38 use visit_ast
::RustdocVisitor
;
41 use html
::render
::RenderInfo
;
42 use arena
::DroplessArena
;
44 pub use rustc
::session
::config
::Input
;
45 pub use rustc
::session
::search_paths
::SearchPaths
;
47 pub type ExternalPaths
= FxHashMap
<DefId
, (Vec
<String
>, clean
::TypeKind
)>;
49 pub struct DocContext
<'a
, 'tcx
: 'a
> {
50 pub tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
51 pub populated_all_crate_impls
: Cell
<bool
>,
52 // Note that external items for which `doc(hidden)` applies to are shown as
53 // non-reachable while local items aren't. This is because we're reusing
54 // the access levels from crateanalysis.
55 /// Later on moved into `clean::Crate`
56 pub access_levels
: RefCell
<AccessLevels
<DefId
>>,
57 /// Later on moved into `html::render::CACHE_KEY`
58 pub renderinfo
: RefCell
<RenderInfo
>,
59 /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
60 pub external_traits
: RefCell
<FxHashMap
<DefId
, clean
::Trait
>>,
62 // The current set of type and lifetime substitutions,
63 // for expanding type aliases at the HIR level:
65 /// Table type parameter definition -> substituted type
66 pub ty_substs
: RefCell
<FxHashMap
<Def
, clean
::Type
>>,
67 /// Table node id of lifetime parameter definition -> substituted lifetime
68 pub lt_substs
: RefCell
<FxHashMap
<DefId
, clean
::Lifetime
>>,
71 impl<'a
, 'tcx
> DocContext
<'a
, 'tcx
> {
72 pub fn sess(&self) -> &session
::Session
{
76 /// Call the closure with the given parameters set as
77 /// the substitutions for a type alias' RHS.
78 pub fn enter_alias
<F
, R
>(&self,
79 ty_substs
: FxHashMap
<Def
, clean
::Type
>,
80 lt_substs
: FxHashMap
<DefId
, clean
::Lifetime
>,
82 where F
: FnOnce() -> R
{
83 let (old_tys
, old_lts
) =
84 (mem
::replace(&mut *self.ty_substs
.borrow_mut(), ty_substs
),
85 mem
::replace(&mut *self.lt_substs
.borrow_mut(), lt_substs
));
87 *self.ty_substs
.borrow_mut() = old_tys
;
88 *self.lt_substs
.borrow_mut() = old_lts
;
93 pub trait DocAccessLevels
{
94 fn is_doc_reachable(&self, did
: DefId
) -> bool
;
97 impl DocAccessLevels
for AccessLevels
<DefId
> {
98 fn is_doc_reachable(&self, did
: DefId
) -> bool
{
104 pub fn run_core(search_paths
: SearchPaths
,
106 externs
: config
::Externs
,
108 triple
: Option
<String
>,
109 maybe_sysroot
: Option
<PathBuf
>,
110 allow_warnings
: bool
,
111 force_unstable_if_unmarked
: bool
) -> (clean
::Crate
, RenderInfo
)
113 // Parse, resolve, and typecheck the given crate.
115 let cpath
= match input
{
116 Input
::File(ref p
) => Some(p
.clone()),
120 let warning_lint
= lint
::builtin
::WARNINGS
.name_lower();
122 let sessopts
= config
::Options
{
125 crate_types
: vec
![config
::CrateTypeRlib
],
126 lint_opts
: if !allow_warnings { vec![(warning_lint, lint::Allow)] }
else { vec![] }
,
127 lint_cap
: Some(lint
::Allow
),
129 target_triple
: triple
.unwrap_or(config
::host_triple().to_string()),
130 // Ensure that rustdoc works even if rustc is feature-staged
131 unstable_features
: UnstableFeatures
::Allow
,
132 actually_rustdoc
: true,
133 debugging_opts
: config
::DebuggingOptions
{
134 force_unstable_if_unmarked
,
135 ..config
::basic_debugging_options()
137 ..config
::basic_options().clone()
140 let codemap
= Rc
::new(codemap
::CodeMap
::new(sessopts
.file_path_mapping()));
141 let diagnostic_handler
= errors
::Handler
::with_tty_emitter(ColorConfig
::Auto
,
144 Some(codemap
.clone()));
146 let cstore
= Rc
::new(CStore
::new(box rustc_trans
::LlvmMetadataLoader
));
147 let mut sess
= session
::build_session_(
148 sessopts
, cpath
, diagnostic_handler
, codemap
,
150 rustc_trans
::init(&sess
);
151 rustc_lint
::register_builtins(&mut sess
.lint_store
.borrow_mut(), Some(&sess
));
153 let mut cfg
= config
::build_configuration(&sess
, config
::parse_cfgspecs(cfgs
));
154 target_features
::add_configuration(&mut cfg
, &sess
);
155 sess
.parse_sess
.config
= cfg
;
157 let control
= &driver
::CompileController
::basic();
159 let krate
= panictry
!(driver
::phase_1_parse_input(control
, &sess
, &input
));
160 let krate
= ReplaceBodyWithLoop
::new().fold_crate(krate
);
162 let name
= link
::find_crate_name(Some(&sess
), &krate
.attrs
, &input
);
164 let driver
::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. }
= {
165 let result
= driver
::phase_2_configure_and_expand(&sess
,
171 resolve
::MakeGlobMap
::No
,
173 abort_on_err(result
, &sess
)
176 let arena
= DroplessArena
::new();
177 let arenas
= GlobalArenas
::new();
178 let hir_map
= hir_map
::map_crate(&sess
, &*cstore
, &mut hir_forest
, &defs
);
179 let output_filenames
= driver
::build_output_filenames(&input
,
185 abort_on_err(driver
::phase_3_run_analysis_passes(control
,
195 |tcx
, analysis
, _
, result
| {
196 if let Err(_
) = result
{
197 sess
.fatal("Compilation failed, aborting rustdoc");
200 let ty
::CrateAnalysis { access_levels, .. }
= analysis
;
202 // Convert from a NodeId set to a DefId set since we don't always have easy access
203 // to the map from defid -> nodeid
204 let access_levels
= AccessLevels
{
205 map
: access_levels
.map
.iter()
206 .map(|(&k
, &v
)| (tcx
.hir
.local_def_id(k
), v
))
210 let ctxt
= DocContext
{
212 populated_all_crate_impls
: Cell
::new(false),
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: {:?}", tcx
.hir
.krate());
222 let mut v
= RustdocVisitor
::new(&*cstore
, &ctxt
);
223 v
.visit(tcx
.hir
.krate());
227 (krate
, ctxt
.renderinfo
.into_inner())