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
::middle
::privacy
::AccessLevels
;
18 use rustc
::ty
::{self, TyCtxt}
;
19 use rustc
::hir
::map
as hir_map
;
21 use rustc_trans
::back
::link
;
22 use rustc_resolve
as resolve
;
23 use rustc
::hir
::lowering
::{lower_crate, LoweringContext}
;
24 use rustc_metadata
::cstore
::CStore
;
26 use syntax
::{ast, codemap, errors}
;
27 use syntax
::errors
::emitter
::ColorConfig
;
28 use syntax
::feature_gate
::UnstableFeatures
;
29 use syntax
::parse
::token
;
31 use std
::cell
::{RefCell, Cell}
;
32 use std
::collections
::{HashMap, HashSet}
;
35 use visit_ast
::RustdocVisitor
;
39 pub use rustc
::session
::config
::Input
;
40 pub use rustc
::session
::search_paths
::SearchPaths
;
42 /// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
43 pub enum MaybeTyped
<'a
, 'tcx
: 'a
> {
44 Typed(&'a TyCtxt
<'tcx
>),
45 NotTyped(&'a session
::Session
)
48 pub type ExternalPaths
= RefCell
<Option
<HashMap
<DefId
,
49 (Vec
<String
>, clean
::TypeKind
)>>>;
51 pub struct DocContext
<'a
, 'tcx
: 'a
> {
52 pub map
: &'a hir_map
::Map
<'tcx
>,
53 pub maybe_typed
: MaybeTyped
<'a
, 'tcx
>,
55 pub external_paths
: ExternalPaths
,
56 pub external_traits
: RefCell
<Option
<HashMap
<DefId
, clean
::Trait
>>>,
57 pub external_typarams
: RefCell
<Option
<HashMap
<DefId
, String
>>>,
58 pub inlined
: RefCell
<Option
<HashSet
<DefId
>>>,
59 pub all_crate_impls
: RefCell
<HashMap
<ast
::CrateNum
, Vec
<clean
::Item
>>>,
60 pub deref_trait_did
: Cell
<Option
<DefId
>>,
63 impl<'b
, 'tcx
> DocContext
<'b
, 'tcx
> {
64 pub fn sess
<'a
>(&'a
self) -> &'a session
::Session
{
65 match self.maybe_typed
{
66 Typed(tcx
) => &tcx
.sess
,
67 NotTyped(ref sess
) => sess
71 pub fn tcx_opt
<'a
>(&'a
self) -> Option
<&'a TyCtxt
<'tcx
>> {
72 match self.maybe_typed
{
73 Typed(tcx
) => Some(tcx
),
78 pub fn tcx
<'a
>(&'a
self) -> &'a TyCtxt
<'tcx
> {
79 let tcx_opt
= self.tcx_opt();
80 tcx_opt
.expect("tcx not present")
84 pub struct CrateAnalysis
{
85 pub access_levels
: AccessLevels
<DefId
>,
86 pub external_paths
: ExternalPaths
,
87 pub external_typarams
: RefCell
<Option
<HashMap
<DefId
, String
>>>,
88 pub inlined
: RefCell
<Option
<HashSet
<DefId
>>>,
89 pub deref_trait_did
: Option
<DefId
>,
92 pub type Externs
= HashMap
<String
, Vec
<String
>>;
94 pub fn run_core(search_paths
: SearchPaths
, cfgs
: Vec
<String
>, externs
: Externs
,
95 input
: Input
, triple
: Option
<String
>)
96 -> (clean
::Crate
, CrateAnalysis
) {
98 // Parse, resolve, and typecheck the given crate.
100 let cpath
= match input
{
101 Input
::File(ref p
) => Some(p
.clone()),
105 let warning_lint
= lint
::builtin
::WARNINGS
.name_lower();
107 let sessopts
= config
::Options
{
109 search_paths
: search_paths
,
110 crate_types
: vec
!(config
::CrateTypeRlib
),
111 lint_opts
: vec
!((warning_lint
, lint
::Allow
)),
112 lint_cap
: Some(lint
::Allow
),
114 target_triple
: triple
.unwrap_or(config
::host_triple().to_string()),
115 cfg
: config
::parse_cfgspecs(cfgs
),
116 // Ensure that rustdoc works even if rustc is feature-staged
117 unstable_features
: UnstableFeatures
::Allow
,
118 ..config
::basic_options().clone()
121 let codemap
= Rc
::new(codemap
::CodeMap
::new());
122 let diagnostic_handler
= errors
::Handler
::with_tty_emitter(ColorConfig
::Auto
,
128 let cstore
= Rc
::new(CStore
::new(token
::get_ident_interner()));
129 let sess
= session
::build_session_(sessopts
, cpath
, diagnostic_handler
,
130 codemap
, cstore
.clone());
131 rustc_lint
::register_builtins(&mut sess
.lint_store
.borrow_mut(), Some(&sess
));
133 let mut cfg
= config
::build_configuration(&sess
);
134 target_features
::add_configuration(&mut cfg
, &sess
);
136 let krate
= panictry
!(driver
::phase_1_parse_input(&sess
, cfg
, &input
));
138 let name
= link
::find_crate_name(Some(&sess
), &krate
.attrs
,
141 let krate
= driver
::phase_2_configure_and_expand(&sess
, &cstore
, krate
, &name
, None
)
142 .expect("phase_2_configure_and_expand aborted in rustdoc!");
144 let krate
= driver
::assign_node_ids(&sess
, krate
);
146 let lcx
= LoweringContext
::new(&sess
, Some(&krate
));
147 let mut hir_forest
= hir_map
::Forest
::new(lower_crate(&lcx
, &krate
), DepGraph
::new(false));
148 let arenas
= ty
::CtxtArenas
::new();
149 let hir_map
= driver
::make_map(&sess
, &mut hir_forest
);
151 let krate_and_analysis
= abort_on_err(driver
::phase_3_run_analysis_passes(&sess
,
156 resolve
::MakeGlobMap
::No
,
157 |tcx
, _
, analysis
, result
| {
158 // Return if the driver hit an err (in `result`)
159 if let Err(_
) = result
{
163 let _ignore
= tcx
.dep_graph
.in_ignore();
164 let ty
::CrateAnalysis { access_levels, .. }
= analysis
;
166 // Convert from a NodeId set to a DefId set since we don't always have easy access
167 // to the map from defid -> nodeid
168 let access_levels
= AccessLevels
{
169 map
: access_levels
.map
.into_iter()
170 .map(|(k
, v
)| (tcx
.map
.local_def_id(k
), v
))
174 let ctxt
= DocContext
{
176 maybe_typed
: Typed(tcx
),
178 external_traits
: RefCell
::new(Some(HashMap
::new())),
179 external_typarams
: RefCell
::new(Some(HashMap
::new())),
180 external_paths
: RefCell
::new(Some(HashMap
::new())),
181 inlined
: RefCell
::new(Some(HashSet
::new())),
182 all_crate_impls
: RefCell
::new(HashMap
::new()),
183 deref_trait_did
: Cell
::new(None
),
185 debug
!("crate: {:?}", ctxt
.map
.krate());
187 let mut analysis
= CrateAnalysis
{
188 access_levels
: access_levels
,
189 external_paths
: RefCell
::new(None
),
190 external_typarams
: RefCell
::new(None
),
191 inlined
: RefCell
::new(None
),
192 deref_trait_did
: None
,
196 let mut v
= RustdocVisitor
::new(&ctxt
, Some(&analysis
));
197 v
.visit(ctxt
.map
.krate());
201 let external_paths
= ctxt
.external_paths
.borrow_mut().take();
202 *analysis
.external_paths
.borrow_mut() = external_paths
;
204 let map
= ctxt
.external_typarams
.borrow_mut().take();
205 *analysis
.external_typarams
.borrow_mut() = map
;
207 let map
= ctxt
.inlined
.borrow_mut().take();
208 *analysis
.inlined
.borrow_mut() = map
;
210 analysis
.deref_trait_did
= ctxt
.deref_trait_did
.get();
212 Some((krate
, analysis
))
215 krate_and_analysis
.unwrap()