]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/record_exports.rs
Add verbose option to rustdoc in order to fix problem with --version
[rust.git] / src / librustc_resolve / record_exports.rs
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.
10
11
12 // Export recording
13 //
14 // This pass simply determines what all "export" keywords refer to and
15 // writes the results into the export map.
16 //
17 // FIXME #4953 This pass will be removed once exports change to per-item.
18 // Then this operation can simply be performed as part of item (or import)
19 // processing.
20
21 use {Module, NameBindings, Resolver};
22 use Namespace::{mod, TypeNS, ValueNS};
23
24 use rustc::middle::def::Export;
25 use syntax::ast;
26 use syntax::parse::token;
27
28 use std::rc::Rc;
29
30 struct ExportRecorder<'a, 'b:'a, 'tcx:'b> {
31     resolver: &'a mut Resolver<'b, 'tcx>
32 }
33
34 // Deref and DerefMut impls allow treating ExportRecorder as Resolver.
35 impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
36     fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
37         &*self.resolver
38     }
39 }
40
41 impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
42     fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
43         &mut *self.resolver
44     }
45 }
46
47 impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
48     fn record_exports_for_module_subtree(&mut self,
49                                          module_: Rc<Module>) {
50         // If this isn't a local krate, then bail out. We don't need to record
51         // exports for nonlocal crates.
52
53         match module_.def_id.get() {
54             Some(def_id) if def_id.krate == ast::LOCAL_CRATE => {
55                 // OK. Continue.
56                 debug!("(recording exports for module subtree) recording \
57                         exports for local module `{}`",
58                        self.module_to_string(&*module_));
59             }
60             None => {
61                 // Record exports for the root module.
62                 debug!("(recording exports for module subtree) recording \
63                         exports for root module `{}`",
64                        self.module_to_string(&*module_));
65             }
66             Some(_) => {
67                 // Bail out.
68                 debug!("(recording exports for module subtree) not recording \
69                         exports for `{}`",
70                        self.module_to_string(&*module_));
71                 return;
72             }
73         }
74
75         self.record_exports_for_module(&*module_);
76         self.populate_module_if_necessary(&module_);
77
78         for (_, child_name_bindings) in module_.children.borrow().iter() {
79             match child_name_bindings.get_module_if_available() {
80                 None => {
81                     // Nothing to do.
82                 }
83                 Some(child_module) => {
84                     self.record_exports_for_module_subtree(child_module);
85                 }
86             }
87         }
88
89         for (_, child_module) in module_.anonymous_children.borrow().iter() {
90             self.record_exports_for_module_subtree(child_module.clone());
91         }
92     }
93
94     fn record_exports_for_module(&mut self, module_: &Module) {
95         let mut exports = Vec::new();
96
97         self.add_exports_for_module(&mut exports, module_);
98         match module_.def_id.get() {
99             Some(def_id) => {
100                 self.export_map.insert(def_id.node, exports);
101                 debug!("(computing exports) writing exports for {} (some)",
102                        def_id.node);
103             }
104             None => {}
105         }
106     }
107
108     fn add_exports_of_namebindings(&mut self,
109                                    exports: &mut Vec<Export>,
110                                    name: ast::Name,
111                                    namebindings: &NameBindings,
112                                    ns: Namespace) {
113         match namebindings.def_for_namespace(ns) {
114             Some(d) => {
115                 debug!("(computing exports) YES: export '{}' => {}",
116                        name, d.def_id());
117                 exports.push(Export {
118                     name: name,
119                     def_id: d.def_id()
120                 });
121             }
122             d_opt => {
123                 debug!("(computing exports) NO: {}", d_opt);
124             }
125         }
126     }
127
128     fn add_exports_for_module(&mut self,
129                               exports: &mut Vec<Export>,
130                               module_: &Module) {
131         for (name, importresolution) in module_.import_resolutions.borrow().iter() {
132             if !importresolution.is_public {
133                 continue
134             }
135             let xs = [TypeNS, ValueNS];
136             for &ns in xs.iter() {
137                 match importresolution.target_for_namespace(ns) {
138                     Some(target) => {
139                         debug!("(computing exports) maybe export '{}'",
140                                token::get_name(*name));
141                         self.add_exports_of_namebindings(exports,
142                                                          *name,
143                                                          &*target.bindings,
144                                                          ns)
145                     }
146                     _ => ()
147                 }
148             }
149         }
150     }
151 }
152
153 pub fn record(resolver: &mut Resolver) {
154     let mut recorder = ExportRecorder { resolver: resolver };
155     let root_module = recorder.graph_root.get_module();
156     recorder.record_exports_for_module_subtree(root_module);
157 }