]>
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. | |
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 | ||
92a42be0 SL |
21 | use {Module, NameBinding, Resolver}; |
22 | use Namespace::{TypeNS, ValueNS}; | |
1a4d82fc JJ |
23 | |
24 | use build_reduced_graph; | |
c34b1796 | 25 | use module_to_string; |
1a4d82fc JJ |
26 | |
27 | use rustc::middle::def::Export; | |
28 | use syntax::ast; | |
1a4d82fc JJ |
29 | |
30 | use std::ops::{Deref, DerefMut}; | |
31 | use std::rc::Rc; | |
32 | ||
92a42be0 SL |
33 | struct ExportRecorder<'a, 'b: 'a, 'tcx: 'b> { |
34 | resolver: &'a mut Resolver<'b, 'tcx>, | |
1a4d82fc JJ |
35 | } |
36 | ||
37 | // Deref and DerefMut impls allow treating ExportRecorder as Resolver. | |
38 | impl<'a, 'b, 'tcx:'b> Deref for ExportRecorder<'a, 'b, 'tcx> { | |
39 | type Target = Resolver<'b, 'tcx>; | |
40 | ||
41 | fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { | |
42 | &*self.resolver | |
43 | } | |
44 | } | |
45 | ||
46 | impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> { | |
47 | fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { | |
48 | &mut *self.resolver | |
49 | } | |
50 | } | |
51 | ||
52 | impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { | |
92a42be0 | 53 | fn record_exports_for_module_subtree(&mut self, module_: Rc<Module>) { |
1a4d82fc JJ |
54 | // If this isn't a local krate, then bail out. We don't need to record |
55 | // exports for nonlocal crates. | |
56 | ||
92a42be0 | 57 | match module_.def_id() { |
e9174d1e | 58 | Some(def_id) if def_id.is_local() => { |
1a4d82fc | 59 | // OK. Continue. |
92a42be0 SL |
60 | debug!("(recording exports for module subtree) recording exports for local \ |
61 | module `{}`", | |
c34b1796 | 62 | module_to_string(&*module_)); |
1a4d82fc JJ |
63 | } |
64 | None => { | |
65 | // Record exports for the root module. | |
92a42be0 SL |
66 | debug!("(recording exports for module subtree) recording exports for root module \ |
67 | `{}`", | |
c34b1796 | 68 | module_to_string(&*module_)); |
1a4d82fc JJ |
69 | } |
70 | Some(_) => { | |
71 | // Bail out. | |
92a42be0 | 72 | debug!("(recording exports for module subtree) not recording exports for `{}`", |
c34b1796 | 73 | module_to_string(&*module_)); |
1a4d82fc JJ |
74 | return; |
75 | } | |
76 | } | |
77 | ||
78 | self.record_exports_for_module(&*module_); | |
79 | build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); | |
80 | ||
62682a34 | 81 | for (_, child_name_bindings) in module_.children.borrow().iter() { |
92a42be0 | 82 | match child_name_bindings.type_ns.module() { |
1a4d82fc JJ |
83 | None => { |
84 | // Nothing to do. | |
85 | } | |
86 | Some(child_module) => { | |
87 | self.record_exports_for_module_subtree(child_module); | |
88 | } | |
89 | } | |
90 | } | |
91 | ||
62682a34 | 92 | for (_, child_module) in module_.anonymous_children.borrow().iter() { |
1a4d82fc JJ |
93 | self.record_exports_for_module_subtree(child_module.clone()); |
94 | } | |
95 | } | |
96 | ||
97 | fn record_exports_for_module(&mut self, module_: &Module) { | |
98 | let mut exports = Vec::new(); | |
99 | ||
100 | self.add_exports_for_module(&mut exports, module_); | |
92a42be0 | 101 | match module_.def_id() { |
1a4d82fc | 102 | Some(def_id) => { |
b039eaaf SL |
103 | let node_id = self.ast_map.as_local_node_id(def_id).unwrap(); |
104 | self.export_map.insert(node_id, exports); | |
105 | debug!("(computing exports) writing exports for {} (some)", node_id); | |
1a4d82fc JJ |
106 | } |
107 | None => {} | |
108 | } | |
109 | } | |
110 | ||
92a42be0 SL |
111 | fn add_export_of_namebinding(&mut self, |
112 | exports: &mut Vec<Export>, | |
113 | name: ast::Name, | |
114 | namebinding: &NameBinding) { | |
115 | match namebinding.def() { | |
1a4d82fc JJ |
116 | Some(d) => { |
117 | debug!("(computing exports) YES: export '{}' => {:?}", | |
92a42be0 SL |
118 | name, |
119 | d.def_id()); | |
1a4d82fc JJ |
120 | exports.push(Export { |
121 | name: name, | |
92a42be0 | 122 | def_id: d.def_id(), |
1a4d82fc JJ |
123 | }); |
124 | } | |
125 | d_opt => { | |
126 | debug!("(computing exports) NO: {:?}", d_opt); | |
127 | } | |
128 | } | |
129 | } | |
130 | ||
92a42be0 | 131 | fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module) { |
62682a34 | 132 | for (name, import_resolution) in module_.import_resolutions.borrow().iter() { |
c34b1796 | 133 | if !import_resolution.is_public { |
92a42be0 | 134 | continue; |
1a4d82fc JJ |
135 | } |
136 | let xs = [TypeNS, ValueNS]; | |
85aaf69f | 137 | for &ns in &xs { |
c34b1796 | 138 | match import_resolution.target_for_namespace(ns) { |
1a4d82fc | 139 | Some(target) => { |
92a42be0 SL |
140 | debug!("(computing exports) maybe export '{}'", name); |
141 | self.add_export_of_namebinding(exports, *name, &target.binding) | |
1a4d82fc | 142 | } |
92a42be0 | 143 | _ => (), |
1a4d82fc JJ |
144 | } |
145 | } | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
150 | pub fn record(resolver: &mut Resolver) { | |
151 | let mut recorder = ExportRecorder { resolver: resolver }; | |
92a42be0 | 152 | let root_module = recorder.graph_root.clone(); |
1a4d82fc JJ |
153 | recorder.record_exports_for_module_subtree(root_module); |
154 | } |