Inline reexports in rustdoc
If a reexport comes from a non-public module, then the documentation for the reexport will be inlined into the module that exports it, but if the reexport is targeted at a public type (like the prelude), then it is not inlined but rather hyperlinked.
This commit is contained in:
parent
4329fc6730
commit
3425901d93
|
@ -209,6 +209,7 @@ pub fn phase_2_configure_and_expand(sess: Session,
|
||||||
pub struct CrateAnalysis {
|
pub struct CrateAnalysis {
|
||||||
exp_map2: middle::resolve::ExportMap2,
|
exp_map2: middle::resolve::ExportMap2,
|
||||||
exported_items: middle::privacy::ExportedItems,
|
exported_items: middle::privacy::ExportedItems,
|
||||||
|
public_items: middle::privacy::PublicItems,
|
||||||
ty_cx: ty::ctxt,
|
ty_cx: ty::ctxt,
|
||||||
maps: astencode::Maps,
|
maps: astencode::Maps,
|
||||||
reachable: @RefCell<HashSet<ast::NodeId>>
|
reachable: @RefCell<HashSet<ast::NodeId>>
|
||||||
|
@ -268,9 +269,10 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
||||||
method_map, ty_cx));
|
method_map, ty_cx));
|
||||||
|
|
||||||
let maps = (external_exports, last_private_map);
|
let maps = (external_exports, last_private_map);
|
||||||
let exported_items = time(time_passes, "privacy checking", maps, |(a, b)|
|
let (exported_items, public_items) =
|
||||||
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
|
time(time_passes, "privacy checking", maps, |(a, b)|
|
||||||
a, b, crate));
|
middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
|
||||||
|
a, b, crate));
|
||||||
|
|
||||||
time(time_passes, "effect checking", (), |_|
|
time(time_passes, "effect checking", (), |_|
|
||||||
middle::effect::check_crate(ty_cx, method_map, crate));
|
middle::effect::check_crate(ty_cx, method_map, crate));
|
||||||
|
@ -322,6 +324,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
||||||
exp_map2: exp_map2,
|
exp_map2: exp_map2,
|
||||||
ty_cx: ty_cx,
|
ty_cx: ty_cx,
|
||||||
exported_items: exported_items,
|
exported_items: exported_items,
|
||||||
|
public_items: public_items,
|
||||||
maps: astencode::Maps {
|
maps: astencode::Maps {
|
||||||
root_map: root_map,
|
root_map: root_map,
|
||||||
method_map: method_map,
|
method_map: method_map,
|
||||||
|
|
|
@ -35,6 +35,11 @@ type Context<'a> = (&'a method_map, &'a resolve::ExportMap2);
|
||||||
/// A set of AST nodes exported by the crate.
|
/// A set of AST nodes exported by the crate.
|
||||||
pub type ExportedItems = HashSet<ast::NodeId>;
|
pub type ExportedItems = HashSet<ast::NodeId>;
|
||||||
|
|
||||||
|
/// A set of AST nodes that are fully public in the crate. This map is used for
|
||||||
|
/// documentation purposes (reexporting a private struct inlines the doc,
|
||||||
|
/// reexporting a public struct doesn't inline the doc).
|
||||||
|
pub type PublicItems = HashSet<ast::NodeId>;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// The parent visitor, used to determine what's the parent of what (node-wise)
|
/// The parent visitor, used to determine what's the parent of what (node-wise)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -165,6 +170,12 @@ struct EmbargoVisitor<'a> {
|
||||||
// means that the destination of the reexport is exported, and hence the
|
// means that the destination of the reexport is exported, and hence the
|
||||||
// destination must also be exported.
|
// destination must also be exported.
|
||||||
reexports: HashSet<ast::NodeId>,
|
reexports: HashSet<ast::NodeId>,
|
||||||
|
|
||||||
|
// These two fields are closely related to one another in that they are only
|
||||||
|
// used for generation of the 'PublicItems' set, not for privacy checking at
|
||||||
|
// all
|
||||||
|
public_items: PublicItems,
|
||||||
|
prev_public: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EmbargoVisitor<'a> {
|
impl<'a> EmbargoVisitor<'a> {
|
||||||
|
@ -186,7 +197,13 @@ impl<'a> EmbargoVisitor<'a> {
|
||||||
|
|
||||||
impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||||
fn visit_item(&mut self, item: &ast::item, _: ()) {
|
fn visit_item(&mut self, item: &ast::item, _: ()) {
|
||||||
let orig_all_pub = self.prev_exported;
|
let orig_all_pub = self.prev_public;
|
||||||
|
self.prev_public = orig_all_pub && item.vis == ast::public;
|
||||||
|
if self.prev_public {
|
||||||
|
self.public_items.insert(item.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let orig_all_exported = self.prev_exported;
|
||||||
match item.node {
|
match item.node {
|
||||||
// impls/extern blocks do not break the "public chain" because they
|
// impls/extern blocks do not break the "public chain" because they
|
||||||
// cannot have visibility qualifiers on them anyway
|
// cannot have visibility qualifiers on them anyway
|
||||||
|
@ -202,7 +219,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||||
// `pub` is explicitly listed.
|
// `pub` is explicitly listed.
|
||||||
_ => {
|
_ => {
|
||||||
self.prev_exported =
|
self.prev_exported =
|
||||||
(orig_all_pub && item.vis == ast::public) ||
|
(orig_all_exported && item.vis == ast::public) ||
|
||||||
self.reexports.contains(&item.id);
|
self.reexports.contains(&item.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +321,8 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
|
||||||
|
|
||||||
visit::walk_item(self, item, ());
|
visit::walk_item(self, item, ());
|
||||||
|
|
||||||
self.prev_exported = orig_all_pub;
|
self.prev_exported = orig_all_exported;
|
||||||
|
self.prev_public = orig_all_pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, a: &ast::foreign_item, _: ()) {
|
fn visit_foreign_item(&mut self, a: &ast::foreign_item, _: ()) {
|
||||||
|
@ -1002,7 +1020,7 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||||
exp_map2: &resolve::ExportMap2,
|
exp_map2: &resolve::ExportMap2,
|
||||||
external_exports: resolve::ExternalExports,
|
external_exports: resolve::ExternalExports,
|
||||||
last_private_map: resolve::LastPrivateMap,
|
last_private_map: resolve::LastPrivateMap,
|
||||||
crate: &ast::Crate) -> ExportedItems {
|
crate: &ast::Crate) -> (ExportedItems, PublicItems) {
|
||||||
// Figure out who everyone's parent is
|
// Figure out who everyone's parent is
|
||||||
let mut visitor = ParentVisitor {
|
let mut visitor = ParentVisitor {
|
||||||
parents: HashMap::new(),
|
parents: HashMap::new(),
|
||||||
|
@ -1038,9 +1056,11 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||||
let mut visitor = EmbargoVisitor {
|
let mut visitor = EmbargoVisitor {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
exported_items: HashSet::new(),
|
exported_items: HashSet::new(),
|
||||||
|
public_items: HashSet::new(),
|
||||||
reexports: HashSet::new(),
|
reexports: HashSet::new(),
|
||||||
exp_map2: exp_map2,
|
exp_map2: exp_map2,
|
||||||
prev_exported: true,
|
prev_exported: true,
|
||||||
|
prev_public: true,
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
let before = visitor.exported_items.len();
|
let before = visitor.exported_items.len();
|
||||||
|
@ -1050,5 +1070,6 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return visitor.exported_items;
|
let EmbargoVisitor { exported_items, public_items, .. } = visitor;
|
||||||
|
return (exported_items, public_items);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ pub struct Crate {
|
||||||
externs: HashMap<ast::CrateNum, ExternalCrate>,
|
externs: HashMap<ast::CrateNum, ExternalCrate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<Crate> for visit_ast::RustdocVisitor {
|
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
|
||||||
fn clean(&self) -> Crate {
|
fn clean(&self) -> Crate {
|
||||||
use syntax::attr::find_crateid;
|
use syntax::attr::find_crateid;
|
||||||
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub struct DocContext {
|
||||||
|
|
||||||
pub struct CrateAnalysis {
|
pub struct CrateAnalysis {
|
||||||
exported_items: privacy::ExportedItems,
|
exported_items: privacy::ExportedItems,
|
||||||
|
public_items: privacy::PublicItems,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses, resolves, and typechecks the given crate
|
/// Parses, resolves, and typechecks the given crate
|
||||||
|
@ -75,12 +76,15 @@ fn get_ast_and_resolve(cpath: &Path,
|
||||||
let crate = phase_1_parse_input(sess, cfg.clone(), &input);
|
let crate = phase_1_parse_input(sess, cfg.clone(), &input);
|
||||||
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
|
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
|
||||||
let driver::driver::CrateAnalysis {
|
let driver::driver::CrateAnalysis {
|
||||||
exported_items, ty_cx, ..
|
exported_items, public_items, ty_cx, ..
|
||||||
} = phase_3_run_analysis_passes(sess, &crate, ast_map);
|
} = phase_3_run_analysis_passes(sess, &crate, ast_map);
|
||||||
|
|
||||||
debug!("crate: {:?}", crate);
|
debug!("crate: {:?}", crate);
|
||||||
return (DocContext { crate: crate, tycx: Some(ty_cx), sess: sess },
|
return (DocContext { crate: crate, tycx: Some(ty_cx), sess: sess },
|
||||||
CrateAnalysis { exported_items: exported_items });
|
CrateAnalysis {
|
||||||
|
exported_items: exported_items,
|
||||||
|
public_items: public_items,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Crate, CrateAnalysis) {
|
pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Crate, CrateAnalysis) {
|
||||||
|
@ -88,8 +92,11 @@ pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Cra
|
||||||
let ctxt = @ctxt;
|
let ctxt = @ctxt;
|
||||||
local_data::set(super::ctxtkey, ctxt);
|
local_data::set(super::ctxtkey, ctxt);
|
||||||
|
|
||||||
let mut v = RustdocVisitor::new();
|
let crate = {
|
||||||
v.visit(&ctxt.crate);
|
let mut v = RustdocVisitor::new(ctxt, Some(&analysis));
|
||||||
|
v.visit(&ctxt.crate);
|
||||||
|
v.clean()
|
||||||
|
};
|
||||||
|
|
||||||
(v.clean(), analysis)
|
(crate, analysis)
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
|
||||||
};
|
};
|
||||||
local_data::set(super::ctxtkey, ctx);
|
local_data::set(super::ctxtkey, ctx);
|
||||||
|
|
||||||
let mut v = RustdocVisitor::new();
|
let mut v = RustdocVisitor::new(ctx, None);
|
||||||
v.visit(&ctx.crate);
|
v.visit(&ctx.crate);
|
||||||
let crate = v.clean();
|
let crate = v.clean();
|
||||||
let (crate, _) = passes::unindent_comments(crate);
|
let (crate, _) = passes::unindent_comments(crate);
|
||||||
|
|
|
@ -13,169 +13,278 @@
|
||||||
|
|
||||||
use syntax::abi::AbiSet;
|
use syntax::abi::AbiSet;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use syntax::ast_util;
|
||||||
|
use syntax::ast_map;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
|
||||||
|
use core;
|
||||||
use doctree::*;
|
use doctree::*;
|
||||||
|
|
||||||
pub struct RustdocVisitor {
|
pub struct RustdocVisitor<'a> {
|
||||||
module: Module,
|
module: Module,
|
||||||
attrs: ~[ast::Attribute],
|
attrs: ~[ast::Attribute],
|
||||||
|
cx: &'a core::DocContext,
|
||||||
|
analysis: Option<&'a core::CrateAnalysis>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RustdocVisitor {
|
impl<'a> RustdocVisitor<'a> {
|
||||||
pub fn new() -> RustdocVisitor {
|
pub fn new<'b>(cx: &'b core::DocContext,
|
||||||
|
analysis: Option<&'b core::CrateAnalysis>) -> RustdocVisitor<'b> {
|
||||||
RustdocVisitor {
|
RustdocVisitor {
|
||||||
module: Module::new(None),
|
module: Module::new(None),
|
||||||
attrs: ~[],
|
attrs: ~[],
|
||||||
|
cx: cx,
|
||||||
|
analysis: analysis,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl RustdocVisitor {
|
|
||||||
pub fn visit(&mut self, crate: &ast::Crate) {
|
pub fn visit(&mut self, crate: &ast::Crate) {
|
||||||
self.attrs = crate.attrs.clone();
|
self.attrs = crate.attrs.clone();
|
||||||
fn visit_struct_def(item: &ast::item, sd: @ast::struct_def, generics:
|
|
||||||
&ast::Generics) -> Struct {
|
|
||||||
debug!("Visiting struct");
|
|
||||||
let struct_type = struct_type_from_def(sd);
|
|
||||||
Struct {
|
|
||||||
id: item.id,
|
|
||||||
struct_type: struct_type,
|
|
||||||
name: item.ident,
|
|
||||||
vis: item.vis,
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
generics: generics.clone(),
|
|
||||||
fields: sd.fields.clone(),
|
|
||||||
where: item.span
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_enum_def(it: &ast::item, def: &ast::enum_def, params: &ast::Generics) -> Enum {
|
self.module = self.visit_mod_contents(crate.span, crate.attrs.clone(),
|
||||||
debug!("Visiting enum");
|
ast::public, ast::CRATE_NODE_ID,
|
||||||
let mut vars: ~[Variant] = ~[];
|
&crate.module, None);
|
||||||
for x in def.variants.iter() {
|
}
|
||||||
vars.push(Variant {
|
|
||||||
name: x.node.name,
|
|
||||||
attrs: x.node.attrs.clone(),
|
|
||||||
vis: x.node.vis,
|
|
||||||
id: x.node.id,
|
|
||||||
kind: x.node.kind.clone(),
|
|
||||||
where: x.span,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Enum {
|
|
||||||
name: it.ident,
|
|
||||||
variants: vars,
|
|
||||||
vis: it.vis,
|
|
||||||
generics: params.clone(),
|
|
||||||
attrs: it.attrs.clone(),
|
|
||||||
id: it.id,
|
|
||||||
where: it.span,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_fn(item: &ast::item, fd: &ast::fn_decl, purity: &ast::purity,
|
pub fn visit_struct_def(&mut self, item: &ast::item, sd: @ast::struct_def,
|
||||||
_abi: &AbiSet, gen: &ast::Generics) -> Function {
|
|
||||||
debug!("Visiting fn");
|
|
||||||
Function {
|
|
||||||
id: item.id,
|
|
||||||
vis: item.vis,
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
decl: fd.clone(),
|
|
||||||
name: item.ident,
|
|
||||||
where: item.span,
|
|
||||||
generics: gen.clone(),
|
|
||||||
purity: *purity,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_mod_contents(span: Span, attrs: ~[ast::Attribute], vis:
|
generics: &ast::Generics) -> Struct {
|
||||||
ast::visibility, id: ast::NodeId, m: &ast::_mod,
|
debug!("Visiting struct");
|
||||||
|
let struct_type = struct_type_from_def(sd);
|
||||||
|
Struct {
|
||||||
|
id: item.id,
|
||||||
|
struct_type: struct_type,
|
||||||
|
name: item.ident,
|
||||||
|
vis: item.vis,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
generics: generics.clone(),
|
||||||
|
fields: sd.fields.clone(),
|
||||||
|
where: item.span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_enum_def(&mut self, it: &ast::item, def: &ast::enum_def,
|
||||||
|
params: &ast::Generics) -> Enum {
|
||||||
|
debug!("Visiting enum");
|
||||||
|
let mut vars: ~[Variant] = ~[];
|
||||||
|
for x in def.variants.iter() {
|
||||||
|
vars.push(Variant {
|
||||||
|
name: x.node.name,
|
||||||
|
attrs: x.node.attrs.clone(),
|
||||||
|
vis: x.node.vis,
|
||||||
|
id: x.node.id,
|
||||||
|
kind: x.node.kind.clone(),
|
||||||
|
where: x.span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Enum {
|
||||||
|
name: it.ident,
|
||||||
|
variants: vars,
|
||||||
|
vis: it.vis,
|
||||||
|
generics: params.clone(),
|
||||||
|
attrs: it.attrs.clone(),
|
||||||
|
id: it.id,
|
||||||
|
where: it.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_fn(&mut self, item: &ast::item, fd: &ast::fn_decl,
|
||||||
|
purity: &ast::purity, _abi: &AbiSet,
|
||||||
|
gen: &ast::Generics) -> Function {
|
||||||
|
debug!("Visiting fn");
|
||||||
|
Function {
|
||||||
|
id: item.id,
|
||||||
|
vis: item.vis,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
decl: fd.clone(),
|
||||||
|
name: item.ident,
|
||||||
|
where: item.span,
|
||||||
|
generics: gen.clone(),
|
||||||
|
purity: *purity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_mod_contents(&mut self, span: Span, attrs: ~[ast::Attribute],
|
||||||
|
vis: ast::visibility, id: ast::NodeId,
|
||||||
|
m: &ast::_mod,
|
||||||
name: Option<ast::Ident>) -> Module {
|
name: Option<ast::Ident>) -> Module {
|
||||||
let mut om = Module::new(name);
|
let mut om = Module::new(name);
|
||||||
om.view_items = m.view_items.clone();
|
for item in m.view_items.iter() {
|
||||||
om.where = span;
|
self.visit_view_item(item, &mut om);
|
||||||
om.attrs = attrs;
|
|
||||||
om.vis = vis;
|
|
||||||
om.id = id;
|
|
||||||
for i in m.items.iter() {
|
|
||||||
visit_item(*i, &mut om);
|
|
||||||
}
|
|
||||||
om
|
|
||||||
}
|
}
|
||||||
|
om.where = span;
|
||||||
|
om.attrs = attrs;
|
||||||
|
om.vis = vis;
|
||||||
|
om.id = id;
|
||||||
|
for i in m.items.iter() {
|
||||||
|
self.visit_item(*i, &mut om);
|
||||||
|
}
|
||||||
|
om
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item(item: &ast::item, om: &mut Module) {
|
pub fn visit_view_item(&mut self, item: &ast::view_item, om: &mut Module) {
|
||||||
debug!("Visiting item {:?}", item);
|
if item.vis != ast::public {
|
||||||
match item.node {
|
return om.view_items.push(item.clone());
|
||||||
ast::item_mod(ref m) => {
|
}
|
||||||
om.mods.push(visit_mod_contents(item.span, item.attrs.clone(),
|
let item = match item.node {
|
||||||
item.vis, item.id, m,
|
ast::view_item_use(ref paths) => {
|
||||||
Some(item.ident)));
|
// rustc no longer supports "use foo, bar;"
|
||||||
},
|
assert_eq!(paths.len(), 1);
|
||||||
ast::item_enum(ref ed, ref gen) => om.enums.push(visit_enum_def(item, ed, gen)),
|
match self.visit_view_path(paths[0], om) {
|
||||||
ast::item_struct(sd, ref gen) => om.structs.push(visit_struct_def(item, sd, gen)),
|
None => return,
|
||||||
ast::item_fn(fd, ref pur, ref abi, ref gen, _) =>
|
Some(path) => {
|
||||||
om.fns.push(visit_fn(item, fd, pur, abi, gen)),
|
ast::view_item {
|
||||||
ast::item_ty(ty, ref gen) => {
|
node: ast::view_item_use(~[path]),
|
||||||
let t = Typedef {
|
.. item.clone()
|
||||||
ty: ty,
|
}
|
||||||
gen: gen.clone(),
|
}
|
||||||
name: item.ident,
|
|
||||||
id: item.id,
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
where: item.span,
|
|
||||||
vis: item.vis,
|
|
||||||
};
|
|
||||||
om.typedefs.push(t);
|
|
||||||
},
|
|
||||||
ast::item_static(ty, ref mut_, ref exp) => {
|
|
||||||
let s = Static {
|
|
||||||
type_: ty,
|
|
||||||
mutability: mut_.clone(),
|
|
||||||
expr: exp.clone(),
|
|
||||||
id: item.id,
|
|
||||||
name: item.ident,
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
where: item.span,
|
|
||||||
vis: item.vis,
|
|
||||||
};
|
|
||||||
om.statics.push(s);
|
|
||||||
},
|
|
||||||
ast::item_trait(ref gen, ref tr, ref met) => {
|
|
||||||
let t = Trait {
|
|
||||||
name: item.ident,
|
|
||||||
methods: met.clone(),
|
|
||||||
generics: gen.clone(),
|
|
||||||
parents: tr.clone(),
|
|
||||||
id: item.id,
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
where: item.span,
|
|
||||||
vis: item.vis,
|
|
||||||
};
|
|
||||||
om.traits.push(t);
|
|
||||||
},
|
|
||||||
ast::item_impl(ref gen, ref tr, ty, ref meths) => {
|
|
||||||
let i = Impl {
|
|
||||||
generics: gen.clone(),
|
|
||||||
trait_: tr.clone(),
|
|
||||||
for_: ty,
|
|
||||||
methods: meths.clone(),
|
|
||||||
attrs: item.attrs.clone(),
|
|
||||||
id: item.id,
|
|
||||||
where: item.span,
|
|
||||||
vis: item.vis,
|
|
||||||
};
|
|
||||||
om.impls.push(i);
|
|
||||||
},
|
|
||||||
ast::item_foreign_mod(ref fm) => {
|
|
||||||
om.foreigns.push(fm.clone());
|
|
||||||
}
|
}
|
||||||
_ => (),
|
}
|
||||||
|
ast::view_item_extern_mod(..) => item.clone()
|
||||||
|
};
|
||||||
|
om.view_items.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_view_path(&mut self, path: @ast::view_path,
|
||||||
|
om: &mut Module) -> Option<@ast::view_path> {
|
||||||
|
match path.node {
|
||||||
|
ast::view_path_simple(_, _, id) => {
|
||||||
|
if self.resolve_id(id, false, om) { return None }
|
||||||
|
}
|
||||||
|
ast::view_path_list(ref p, ref paths, ref b) => {
|
||||||
|
let mut mine = ~[];
|
||||||
|
for path in paths.iter() {
|
||||||
|
if !self.resolve_id(path.node.id, false, om) {
|
||||||
|
mine.push(path.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mine.len() == 0 { return None }
|
||||||
|
return Some(@::syntax::codemap::Spanned {
|
||||||
|
node: ast::view_path_list(p.clone(), mine, b.clone()),
|
||||||
|
span: path.span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are feature gated anyway
|
||||||
|
ast::view_path_glob(_, id) => {
|
||||||
|
if self.resolve_id(id, true, om) { return None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
|
||||||
self.module = visit_mod_contents(crate.span, crate.attrs.clone(),
|
fn resolve_id(&mut self, id: ast::NodeId, glob: bool,
|
||||||
ast::public, ast::CRATE_NODE_ID,
|
om: &mut Module) -> bool {
|
||||||
&crate.module, None);
|
let def = {
|
||||||
|
let dm = match self.cx.tycx {
|
||||||
|
Some(tcx) => tcx.def_map.borrow(),
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
ast_util::def_id_of_def(*dm.get().get(&id))
|
||||||
|
};
|
||||||
|
if !ast_util::is_local(def) { return false }
|
||||||
|
let analysis = match self.analysis {
|
||||||
|
Some(analysis) => analysis, None => return false
|
||||||
|
};
|
||||||
|
if analysis.public_items.contains(&def.node) { return false }
|
||||||
|
|
||||||
|
let item = {
|
||||||
|
let items = self.cx.tycx.unwrap().items.borrow();
|
||||||
|
*items.get().get(&def.node)
|
||||||
|
};
|
||||||
|
match item {
|
||||||
|
ast_map::node_item(it, _) => {
|
||||||
|
if glob {
|
||||||
|
match it.node {
|
||||||
|
ast::item_mod(ref m) => {
|
||||||
|
for vi in m.view_items.iter() {
|
||||||
|
self.visit_view_item(vi, om);
|
||||||
|
}
|
||||||
|
for i in m.items.iter() {
|
||||||
|
self.visit_item(*i, om);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => { fail!("glob not mapped to a module"); }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.visit_item(it, om);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn visit_item(&mut self, item: &ast::item, om: &mut Module) {
|
||||||
|
debug!("Visiting item {:?}", item);
|
||||||
|
match item.node {
|
||||||
|
ast::item_mod(ref m) => {
|
||||||
|
om.mods.push(self.visit_mod_contents(item.span, item.attrs.clone(),
|
||||||
|
item.vis, item.id, m,
|
||||||
|
Some(item.ident)));
|
||||||
|
},
|
||||||
|
ast::item_enum(ref ed, ref gen) =>
|
||||||
|
om.enums.push(self.visit_enum_def(item, ed, gen)),
|
||||||
|
ast::item_struct(sd, ref gen) =>
|
||||||
|
om.structs.push(self.visit_struct_def(item, sd, gen)),
|
||||||
|
ast::item_fn(fd, ref pur, ref abi, ref gen, _) =>
|
||||||
|
om.fns.push(self.visit_fn(item, fd, pur, abi, gen)),
|
||||||
|
ast::item_ty(ty, ref gen) => {
|
||||||
|
let t = Typedef {
|
||||||
|
ty: ty,
|
||||||
|
gen: gen.clone(),
|
||||||
|
name: item.ident,
|
||||||
|
id: item.id,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.typedefs.push(t);
|
||||||
|
},
|
||||||
|
ast::item_static(ty, ref mut_, ref exp) => {
|
||||||
|
let s = Static {
|
||||||
|
type_: ty,
|
||||||
|
mutability: mut_.clone(),
|
||||||
|
expr: exp.clone(),
|
||||||
|
id: item.id,
|
||||||
|
name: item.ident,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.statics.push(s);
|
||||||
|
},
|
||||||
|
ast::item_trait(ref gen, ref tr, ref met) => {
|
||||||
|
let t = Trait {
|
||||||
|
name: item.ident,
|
||||||
|
methods: met.clone(),
|
||||||
|
generics: gen.clone(),
|
||||||
|
parents: tr.clone(),
|
||||||
|
id: item.id,
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.traits.push(t);
|
||||||
|
},
|
||||||
|
ast::item_impl(ref gen, ref tr, ty, ref meths) => {
|
||||||
|
let i = Impl {
|
||||||
|
generics: gen.clone(),
|
||||||
|
trait_: tr.clone(),
|
||||||
|
for_: ty,
|
||||||
|
methods: meths.clone(),
|
||||||
|
attrs: item.attrs.clone(),
|
||||||
|
id: item.id,
|
||||||
|
where: item.span,
|
||||||
|
vis: item.vis,
|
||||||
|
};
|
||||||
|
om.impls.push(i);
|
||||||
|
},
|
||||||
|
ast::item_foreign_mod(ref fm) => {
|
||||||
|
om.foreigns.push(fm.clone());
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue