]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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. | |
4 | // | |
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. | |
1a4d82fc | 10 | |
c34b1796 | 11 | use rustc_lint; |
7453a54e SL |
12 | use rustc_driver::{driver, target_features, abort_on_err}; |
13 | use rustc::dep_graph::DepGraph; | |
1a4d82fc | 14 | use rustc::session::{self, config}; |
54a0048b | 15 | use rustc::hir::def_id::DefId; |
cc61c64b | 16 | use rustc::hir::def::Def; |
92a42be0 | 17 | use rustc::middle::privacy::AccessLevels; |
8bb4bdeb | 18 | use rustc::ty::{self, TyCtxt, GlobalArenas}; |
54a0048b | 19 | use rustc::hir::map as hir_map; |
1a4d82fc | 20 | use rustc::lint; |
8bb4bdeb | 21 | use rustc::util::nodemap::FxHashMap; |
7cac9316 | 22 | use rustc_trans; |
1a4d82fc | 23 | use rustc_trans::back::link; |
85aaf69f | 24 | use rustc_resolve as resolve; |
92a42be0 | 25 | use rustc_metadata::cstore::CStore; |
1a4d82fc | 26 | |
3157f602 | 27 | use syntax::{ast, codemap}; |
62682a34 | 28 | use syntax::feature_gate::UnstableFeatures; |
3157f602 XL |
29 | use errors; |
30 | use errors::emitter::ColorConfig; | |
1a4d82fc | 31 | |
d9579d0f | 32 | use std::cell::{RefCell, Cell}; |
9e0c209e | 33 | use std::mem; |
92a42be0 | 34 | use std::rc::Rc; |
9e0c209e | 35 | use std::path::PathBuf; |
1a4d82fc JJ |
36 | |
37 | use visit_ast::RustdocVisitor; | |
38 | use clean; | |
39 | use clean::Clean; | |
a7813a04 | 40 | use html::render::RenderInfo; |
32a655c1 | 41 | use arena::DroplessArena; |
1a4d82fc | 42 | |
85aaf69f SL |
43 | pub use rustc::session::config::Input; |
44 | pub use rustc::session::search_paths::SearchPaths; | |
45 | ||
476ff2be | 46 | pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>; |
1a4d82fc | 47 | |
62682a34 | 48 | pub struct DocContext<'a, 'tcx: 'a> { |
476ff2be | 49 | pub tcx: TyCtxt<'a, 'tcx, 'tcx>, |
9e0c209e | 50 | pub populated_all_crate_impls: Cell<bool>, |
a7813a04 XL |
51 | // Note that external items for which `doc(hidden)` applies to are shown as |
52 | // non-reachable while local items aren't. This is because we're reusing | |
53 | // the access levels from crateanalysis. | |
54 | /// Later on moved into `clean::Crate` | |
55 | pub access_levels: RefCell<AccessLevels<DefId>>, | |
56 | /// Later on moved into `html::render::CACHE_KEY` | |
57 | pub renderinfo: RefCell<RenderInfo>, | |
58 | /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` | |
476ff2be | 59 | pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>, |
9e0c209e SL |
60 | |
61 | // The current set of type and lifetime substitutions, | |
62 | // for expanding type aliases at the HIR level: | |
63 | ||
64 | /// Table type parameter definition -> substituted type | |
476ff2be | 65 | pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>, |
9e0c209e | 66 | /// Table node id of lifetime parameter definition -> substituted lifetime |
476ff2be | 67 | pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>, |
476ff2be | 68 | } |
1a4d82fc | 69 | |
476ff2be SL |
70 | impl<'a, 'tcx> DocContext<'a, 'tcx> { |
71 | pub fn sess(&self) -> &session::Session { | |
72 | &self.tcx.sess | |
1a4d82fc | 73 | } |
9e0c209e SL |
74 | |
75 | /// Call the closure with the given parameters set as | |
76 | /// the substitutions for a type alias' RHS. | |
77 | pub fn enter_alias<F, R>(&self, | |
476ff2be SL |
78 | ty_substs: FxHashMap<Def, clean::Type>, |
79 | lt_substs: FxHashMap<ast::NodeId, clean::Lifetime>, | |
9e0c209e SL |
80 | f: F) -> R |
81 | where F: FnOnce() -> R { | |
82 | let (old_tys, old_lts) = | |
83 | (mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs), | |
84 | mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs)); | |
85 | let r = f(); | |
86 | *self.ty_substs.borrow_mut() = old_tys; | |
87 | *self.lt_substs.borrow_mut() = old_lts; | |
88 | r | |
89 | } | |
1a4d82fc JJ |
90 | } |
91 | ||
a7813a04 | 92 | pub trait DocAccessLevels { |
7cac9316 | 93 | fn is_doc_reachable(&self, did: DefId) -> bool; |
1a4d82fc JJ |
94 | } |
95 | ||
a7813a04 XL |
96 | impl DocAccessLevels for AccessLevels<DefId> { |
97 | fn is_doc_reachable(&self, did: DefId) -> bool { | |
98 | self.is_public(did) | |
99 | } | |
100 | } | |
1a4d82fc | 101 | |
1a4d82fc | 102 | |
a7813a04 XL |
103 | pub fn run_core(search_paths: SearchPaths, |
104 | cfgs: Vec<String>, | |
5bcae85e | 105 | externs: config::Externs, |
a7813a04 | 106 | input: Input, |
9e0c209e | 107 | triple: Option<String>, |
7cac9316 | 108 | maybe_sysroot: Option<PathBuf>, |
041b39d2 XL |
109 | allow_warnings: bool, |
110 | force_unstable_if_unmarked: bool) -> (clean::Crate, RenderInfo) | |
a7813a04 | 111 | { |
1a4d82fc JJ |
112 | // Parse, resolve, and typecheck the given crate. |
113 | ||
85aaf69f SL |
114 | let cpath = match input { |
115 | Input::File(ref p) => Some(p.clone()), | |
116 | _ => None | |
117 | }; | |
1a4d82fc JJ |
118 | |
119 | let warning_lint = lint::builtin::WARNINGS.name_lower(); | |
120 | ||
121 | let sessopts = config::Options { | |
9e0c209e | 122 | maybe_sysroot: maybe_sysroot, |
1a4d82fc | 123 | search_paths: search_paths, |
c30ab7b3 | 124 | crate_types: vec![config::CrateTypeRlib], |
7cac9316 | 125 | lint_opts: if !allow_warnings { vec![(warning_lint, lint::Allow)] } else { vec![] }, |
92a42be0 | 126 | lint_cap: Some(lint::Allow), |
1a4d82fc JJ |
127 | externs: externs, |
128 | target_triple: triple.unwrap_or(config::host_triple().to_string()), | |
1a4d82fc | 129 | // Ensure that rustdoc works even if rustc is feature-staged |
62682a34 | 130 | unstable_features: UnstableFeatures::Allow, |
c30ab7b3 | 131 | actually_rustdoc: true, |
041b39d2 XL |
132 | debugging_opts: config::DebuggingOptions { |
133 | force_unstable_if_unmarked: force_unstable_if_unmarked, | |
134 | ..config::basic_debugging_options() | |
135 | }, | |
1a4d82fc JJ |
136 | ..config::basic_options().clone() |
137 | }; | |
138 | ||
7cac9316 | 139 | let codemap = Rc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); |
9cc50fc6 | 140 | let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto, |
9cc50fc6 SL |
141 | true, |
142 | false, | |
5bcae85e | 143 | Some(codemap.clone())); |
1a4d82fc | 144 | |
a7813a04 XL |
145 | let dep_graph = DepGraph::new(false); |
146 | let _ignore = dep_graph.in_ignore(); | |
7cac9316 | 147 | let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader)); |
c30ab7b3 SL |
148 | let mut sess = session::build_session_( |
149 | sessopts, &dep_graph, cpath, diagnostic_handler, codemap, cstore.clone() | |
150 | ); | |
7cac9316 | 151 | rustc_trans::init(&sess); |
c34b1796 | 152 | rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); |
1a4d82fc | 153 | |
5bcae85e | 154 | let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs)); |
e9174d1e | 155 | target_features::add_configuration(&mut cfg, &sess); |
c30ab7b3 | 156 | sess.parse_sess.config = cfg; |
1a4d82fc | 157 | |
c30ab7b3 | 158 | let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); |
1a4d82fc | 159 | |
3157f602 | 160 | let name = link::find_crate_name(Some(&sess), &krate.attrs, &input); |
1a4d82fc | 161 | |
3157f602 | 162 | let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = { |
32a655c1 SL |
163 | let result = driver::phase_2_configure_and_expand(&sess, |
164 | &cstore, | |
165 | krate, | |
166 | None, | |
167 | &name, | |
168 | None, | |
169 | resolve::MakeGlobMap::No, | |
170 | |_| Ok(())); | |
171 | abort_on_err(result, &sess) | |
a7813a04 XL |
172 | }; |
173 | ||
32a655c1 SL |
174 | let arena = DroplessArena::new(); |
175 | let arenas = GlobalArenas::new(); | |
a7813a04 | 176 | let hir_map = hir_map::map_crate(&mut hir_forest, defs); |
1a4d82fc | 177 | |
a7813a04 | 178 | abort_on_err(driver::phase_3_run_analysis_passes(&sess, |
7453a54e | 179 | hir_map, |
a7813a04 XL |
180 | analysis, |
181 | resolutions, | |
32a655c1 | 182 | &arena, |
7453a54e SL |
183 | &arenas, |
184 | &name, | |
c30ab7b3 | 185 | |tcx, analysis, _, result| { |
7453a54e | 186 | if let Err(_) = result { |
a7813a04 | 187 | sess.fatal("Compilation failed, aborting rustdoc"); |
7453a54e SL |
188 | } |
189 | ||
cc61c64b | 190 | let ty::CrateAnalysis { access_levels, .. } = analysis; |
62682a34 | 191 | |
b039eaaf SL |
192 | // Convert from a NodeId set to a DefId set since we don't always have easy access |
193 | // to the map from defid -> nodeid | |
92a42be0 | 194 | let access_levels = AccessLevels { |
cc61c64b XL |
195 | map: access_levels.map.iter() |
196 | .map(|(&k, &v)| (tcx.hir.local_def_id(k), v)) | |
92a42be0 SL |
197 | .collect() |
198 | }; | |
b039eaaf | 199 | |
62682a34 | 200 | let ctxt = DocContext { |
476ff2be | 201 | tcx: tcx, |
9e0c209e | 202 | populated_all_crate_impls: Cell::new(false), |
a7813a04 | 203 | access_levels: RefCell::new(access_levels), |
9e0c209e SL |
204 | external_traits: Default::default(), |
205 | renderinfo: Default::default(), | |
206 | ty_substs: Default::default(), | |
207 | lt_substs: Default::default(), | |
62682a34 | 208 | }; |
32a655c1 | 209 | debug!("crate: {:?}", tcx.hir.krate()); |
62682a34 | 210 | |
62682a34 | 211 | let krate = { |
a7813a04 | 212 | let mut v = RustdocVisitor::new(&ctxt); |
32a655c1 | 213 | v.visit(tcx.hir.krate()); |
62682a34 SL |
214 | v.clean(&ctxt) |
215 | }; | |
216 | ||
a7813a04 XL |
217 | (krate, ctxt.renderinfo.into_inner()) |
218 | }), &sess) | |
1a4d82fc | 219 | } |