rust/src/librustdoc/clean.rs

1266 lines
34 KiB
Rust
Raw Normal View History

// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
2013-08-15 16:28:54 -04:00
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.
use syntax;
use syntax::ast;
use syntax::ast_util;
use syntax::attr;
use syntax::attr::AttributeMethods;
use syntax::codemap::Pos;
use syntax::parse::token::InternedString;
use syntax::parse::token;
2013-08-15 16:28:54 -04:00
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
use rustc::metadata::cstore;
use rustc::metadata::csearch;
use rustc::metadata::decoder;
2013-08-15 16:28:54 -04:00
use std;
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
use std::hashmap::HashMap;
2013-08-15 16:28:54 -04:00
use doctree;
use visit_ast;
use std::local_data;
pub trait Clean<T> {
fn clean(&self) -> T;
}
impl<T: Clean<U>, U> Clean<~[U]> for ~[T] {
fn clean(&self) -> ~[U] {
self.iter().map(|x| x.clean()).collect()
}
}
impl<T: Clean<U>, U> Clean<U> for @T {
fn clean(&self) -> U {
(**self).clean()
}
}
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
fn clean(&self) -> Option<U> {
match self {
&None => None,
&Some(ref v) => Some(v.clean())
}
}
}
impl<T: Clean<U>, U> Clean<~[U]> for syntax::opt_vec::OptVec<T> {
fn clean(&self) -> ~[U] {
match self {
&syntax::opt_vec::Empty => ~[],
&syntax::opt_vec::Vec(ref v) => v.clean()
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Crate {
name: ~str,
module: Option<Item>,
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
externs: HashMap<ast::CrateNum, ExternalCrate>,
2013-08-15 16:28:54 -04:00
}
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Crate {
2013-12-27 19:14:01 -05:00
use syntax::attr::find_crateid;
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let mut externs = HashMap::new();
2013-12-25 13:08:04 -07:00
cx.sess.cstore.iter_crate_data(|n, meta| {
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
externs.insert(n, meta.clean());
});
2013-08-15 16:28:54 -04:00
Crate {
2013-12-27 19:14:01 -05:00
name: match find_crateid(self.attrs) {
Some(n) => n.name,
2013-12-19 10:18:37 -05:00
None => fail!("rustdoc requires a `crate_id` crate attribute"),
2013-08-15 16:28:54 -04:00
},
module: Some(self.module.clean()),
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
externs: externs,
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct ExternalCrate {
name: ~str,
attrs: ~[Attribute],
}
impl Clean<ExternalCrate> for cstore::crate_metadata {
fn clean(&self) -> ExternalCrate {
ExternalCrate {
name: self.name.to_owned(),
attrs: decoder::get_crate_attributes(self.data()).clean()
2013-08-15 16:28:54 -04:00
}
}
}
/// Anything with a source location and set of attributes and, optionally, a
/// name. That is, anything that can be documented. This doesn't correspond
/// directly to the AST's concept of an item; it's a strict superset.
#[deriving(Clone, Encodable, Decodable)]
pub struct Item {
/// Stringified span
source: Span,
2013-08-15 16:28:54 -04:00
/// Not everything has a name. E.g., impls
name: Option<~str>,
attrs: ~[Attribute],
inner: ItemEnum,
visibility: Option<Visibility>,
id: ast::NodeId,
}
impl Item {
/// Finds the `doc` attribute as a List and returns the list of attributes
/// nested inside.
pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
for attr in self.attrs.iter() {
match *attr {
List(~"doc", ref list) => { return Some(list.as_slice()); }
_ => {}
}
}
return None;
}
/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
for attr in self.attrs.iter() {
match *attr {
NameValue(~"doc", ref v) => { return Some(v.as_slice()); }
_ => {}
}
}
return None;
}
pub fn is_mod(&self) -> bool {
2013-11-28 12:22:53 -08:00
match self.inner { ModuleItem(..) => true, _ => false }
}
pub fn is_trait(&self) -> bool {
2013-11-28 12:22:53 -08:00
match self.inner { TraitItem(..) => true, _ => false }
}
pub fn is_struct(&self) -> bool {
2013-11-28 12:22:53 -08:00
match self.inner { StructItem(..) => true, _ => false }
}
pub fn is_enum(&self) -> bool {
2013-11-28 12:22:53 -08:00
match self.inner { EnumItem(..) => true, _ => false }
}
pub fn is_fn(&self) -> bool {
2013-11-28 12:22:53 -08:00
match self.inner { FunctionItem(..) => true, _ => false }
}
}
2013-08-15 16:28:54 -04:00
#[deriving(Clone, Encodable, Decodable)]
pub enum ItemEnum {
StructItem(Struct),
EnumItem(Enum),
FunctionItem(Function),
ModuleItem(Module),
TypedefItem(Typedef),
StaticItem(Static),
TraitItem(Trait),
ImplItem(Impl),
ViewItemItem(ViewItem),
TyMethodItem(TyMethod),
MethodItem(Method),
StructFieldItem(StructField),
VariantItem(Variant),
ForeignFunctionItem(Function),
ForeignStaticItem(Static),
2013-08-15 16:28:54 -04:00
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Module {
items: ~[Item],
}
impl Clean<Item> for doctree::Module {
fn clean(&self) -> Item {
let name = if self.name.is_some() {
self.name.unwrap().clean()
} else {
~""
};
Item {
name: Some(name),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
id: self.id,
inner: ModuleItem(Module {
items: [self.structs.clean(), self.enums.clean(),
self.fns.clean(), self.foreigns.clean().concat_vec(),
self.mods.clean(), self.typedefs.clean(),
self.statics.clean(), self.traits.clean(),
self.impls.clean(), self.view_items.clean()].concat_vec()
2013-08-15 16:28:54 -04:00
})
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum Attribute {
Word(~str),
List(~str, ~[Attribute]),
NameValue(~str, ~str)
}
impl Clean<Attribute> for ast::MetaItem {
fn clean(&self) -> Attribute {
match self.node {
ast::MetaWord(ref s) => Word(s.get().to_owned()),
ast::MetaList(ref s, ref l) => {
List(s.get().to_owned(), l.clean())
}
ast::MetaNameValue(ref s, ref v) => {
NameValue(s.get().to_owned(), lit_to_str(v))
}
2013-08-15 16:28:54 -04:00
}
}
}
impl Clean<Attribute> for ast::Attribute {
fn clean(&self) -> Attribute {
self.desugar_doc().node.value.clean()
2013-08-15 16:28:54 -04:00
}
}
// This is a rough approximation that gets us what we want.
impl<'a> attr::AttrMetaMethods for &'a Attribute {
fn name(&self) -> InternedString {
match **self {
Word(ref n) | List(ref n, _) | NameValue(ref n, _) => {
token::intern_and_get_ident(*n)
}
}
}
fn value_str(&self) -> Option<InternedString> {
match **self {
NameValue(_, ref v) => Some(token::intern_and_get_ident(*v)),
_ => None,
}
}
fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
None
}
}
2013-08-15 16:28:54 -04:00
#[deriving(Clone, Encodable, Decodable)]
pub struct TyParam {
name: ~str,
id: ast::NodeId,
bounds: ~[TyParamBound]
}
impl Clean<TyParam> for ast::TyParam {
fn clean(&self) -> TyParam {
TyParam {
name: self.ident.clean(),
id: self.id,
bounds: self.bounds.clean(),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum TyParamBound {
RegionBound,
TraitBound(Type)
}
impl Clean<TyParamBound> for ast::TyParamBound {
fn clean(&self) -> TyParamBound {
match *self {
ast::RegionTyParamBound => RegionBound,
ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Lifetime(~str);
impl Lifetime {
pub fn get_ref<'a>(&'a self) -> &'a str {
let Lifetime(ref s) = *self;
let s: &'a str = *s;
return s;
}
}
2013-08-15 16:28:54 -04:00
impl Clean<Lifetime> for ast::Lifetime {
fn clean(&self) -> Lifetime {
Lifetime(self.ident.clean())
}
}
// maybe use a Generic enum and use ~[Generic]?
#[deriving(Clone, Encodable, Decodable)]
pub struct Generics {
lifetimes: ~[Lifetime],
type_params: ~[TyParam]
}
impl Clean<Generics> for ast::Generics {
fn clean(&self) -> Generics {
Generics {
lifetimes: self.lifetimes.clean(),
type_params: self.ty_params.clean(),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Method {
generics: Generics,
self_: SelfTy,
purity: ast::Purity,
2013-08-15 16:28:54 -04:00
decl: FnDecl,
}
impl Clean<Item> for ast::Method {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Item {
let inputs = match self.explicit_self.node {
ast::SelfStatic => self.decl.inputs.as_slice(),
_ => self.decl.inputs.slice_from(1)
};
let decl = FnDecl {
inputs: Arguments {
values: inputs.iter().map(|x| x.clean()).collect(),
},
output: (self.decl.output.clean()),
cf: self.decl.cf.clean(),
attrs: ~[]
};
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
source: self.span.clean(),
id: self.id.clone(),
visibility: self.vis.clean(),
2013-08-15 16:28:54 -04:00
inner: MethodItem(Method {
generics: self.generics.clean(),
self_: self.explicit_self.clean(),
purity: self.purity.clone(),
decl: decl,
2013-08-15 16:28:54 -04:00
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct TyMethod {
purity: ast::Purity,
2013-08-15 16:28:54 -04:00
decl: FnDecl,
generics: Generics,
self_: SelfTy,
}
impl Clean<Item> for ast::TypeMethod {
fn clean(&self) -> Item {
let inputs = match self.explicit_self.node {
ast::SelfStatic => self.decl.inputs.as_slice(),
_ => self.decl.inputs.slice_from(1)
};
let decl = FnDecl {
inputs: Arguments {
values: inputs.iter().map(|x| x.clean()).collect(),
},
output: (self.decl.output.clean()),
cf: self.decl.cf.clean(),
attrs: ~[]
};
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
source: self.span.clean(),
id: self.id,
visibility: None,
inner: TyMethodItem(TyMethod {
purity: self.purity.clone(),
decl: decl,
2013-08-15 16:28:54 -04:00
self_: self.explicit_self.clean(),
generics: self.generics.clean(),
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum SelfTy {
SelfStatic,
SelfValue,
SelfBorrowed(Option<Lifetime>, Mutability),
SelfOwned,
}
impl Clean<SelfTy> for ast::ExplicitSelf {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> SelfTy {
match self.node {
ast::SelfStatic => SelfStatic,
ast::SelfValue => SelfValue,
ast::SelfUniq => SelfOwned,
ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Function {
decl: FnDecl,
generics: Generics,
purity: ast::Purity,
2013-08-15 16:28:54 -04:00
}
impl Clean<Item> for doctree::Function {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
id: self.id,
inner: FunctionItem(Function {
decl: self.decl.clean(),
generics: self.generics.clean(),
purity: self.purity,
2013-08-15 16:28:54 -04:00
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct ClosureDecl {
sigil: ast::Sigil,
region: Option<Lifetime>,
lifetimes: ~[Lifetime],
decl: FnDecl,
onceness: ast::Onceness,
purity: ast::Purity,
2013-08-15 16:28:54 -04:00
bounds: ~[TyParamBound]
}
impl Clean<ClosureDecl> for ast::ClosureTy {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> ClosureDecl {
ClosureDecl {
sigil: self.sigil,
region: self.region.clean(),
lifetimes: self.lifetimes.clean(),
decl: self.decl.clean(),
onceness: self.onceness,
purity: self.purity,
bounds: match self.bounds {
Some(ref x) => x.clean(),
None => ~[]
},
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct FnDecl {
inputs: Arguments,
2013-08-15 16:28:54 -04:00
output: Type,
cf: RetStyle,
attrs: ~[Attribute]
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Arguments {
values: ~[Argument],
}
impl Clean<FnDecl> for ast::FnDecl {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> FnDecl {
FnDecl {
inputs: Arguments {
values: self.inputs.iter().map(|x| x.clean()).collect(),
},
2013-08-15 16:28:54 -04:00
output: (self.output.clean()),
cf: self.cf.clean(),
attrs: ~[]
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Argument {
type_: Type,
name: ~str,
id: ast::NodeId
}
impl Clean<Argument> for ast::Arg {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Argument {
Argument {
name: name_from_pat(self.pat),
type_: (self.ty.clean()),
id: self.id
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum RetStyle {
NoReturn,
Return
}
impl Clean<RetStyle> for ast::RetStyle {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> RetStyle {
match *self {
ast::Return => Return,
ast::NoReturn => NoReturn
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Trait {
methods: ~[TraitMethod],
generics: Generics,
parents: ~[Type],
}
impl Clean<Item> for doctree::Trait {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: TraitItem(Trait {
methods: self.methods.clean(),
generics: self.generics.clean(),
parents: self.parents.clean(),
}),
}
}
}
impl Clean<Type> for ast::TraitRef {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Type {
resolve_type(self.path.clean(), None, self.ref_id)
2013-08-15 16:28:54 -04:00
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum TraitMethod {
Required(Item),
Provided(Item),
}
impl TraitMethod {
pub fn is_req(&self) -> bool {
2013-08-15 16:28:54 -04:00
match self {
2013-11-28 12:22:53 -08:00
&Required(..) => true,
2013-08-15 16:28:54 -04:00
_ => false,
}
}
pub fn is_def(&self) -> bool {
2013-08-15 16:28:54 -04:00
match self {
2013-11-28 12:22:53 -08:00
&Provided(..) => true,
2013-08-15 16:28:54 -04:00
_ => false,
}
}
pub fn item<'a>(&'a self) -> &'a Item {
match *self {
Required(ref item) => item,
Provided(ref item) => item,
}
}
2013-08-15 16:28:54 -04:00
}
impl Clean<TraitMethod> for ast::TraitMethod {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> TraitMethod {
match self {
&ast::Required(ref t) => Required(t.clean()),
&ast::Provided(ref t) => Provided(t.clean()),
2013-08-15 16:28:54 -04:00
}
}
}
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
/// it does not preserve mutability or boxes.
#[deriving(Clone, Encodable, Decodable)]
pub enum Type {
/// structs/enums/traits (anything that'd be an ast::TyPath)
ResolvedPath {
path: Path,
typarams: Option<~[TyParamBound]>,
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
id: ast::NodeId,
},
/// Same as above, but only external variants
ExternalPath {
path: Path,
typarams: Option<~[TyParamBound]>,
fqn: ~[~str],
kind: TypeKind,
krate: ast::CrateNum,
},
2013-08-15 16:28:54 -04:00
// I have no idea how to usefully use this.
TyParamBinder(ast::NodeId),
/// For parameterized types, so the consumer of the JSON don't go looking
/// for types which don't exist anywhere.
Generic(ast::NodeId),
/// For references to self
Self(ast::NodeId),
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
Primitive(ast::PrimTy),
2013-08-15 16:28:54 -04:00
Closure(~ClosureDecl),
/// extern "ABI" fn
BareFunction(~BareFunctionDecl),
Tuple(~[Type]),
Vector(~Type),
FixedVector(~Type, ~str),
String,
Bool,
/// aka TyNil
2013-08-15 16:28:54 -04:00
Unit,
/// aka TyBot
2013-08-15 16:28:54 -04:00
Bottom,
Unique(~Type),
Managed(~Type),
2013-08-15 16:28:54 -04:00
RawPointer(Mutability, ~Type),
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: ~Type},
// region, raw, other boxes, mutable
}
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
#[deriving(Clone, Encodable, Decodable)]
pub enum TypeKind {
TypeStruct,
TypeEnum,
TypeTrait,
TypeFunction,
}
2013-08-15 16:28:54 -04:00
impl Clean<Type> for ast::Ty {
fn clean(&self) -> Type {
use syntax::ast::*;
debug!("cleaning type `{:?}`", self);
2013-08-15 16:28:54 -04:00
let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess.codemap;
debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
match self.node {
TyNil => Unit,
TyPtr(ref m) => RawPointer(m.mutbl.clean(), ~m.ty.clean()),
TyRptr(ref l, ref m) =>
2013-08-15 16:28:54 -04:00
BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
type_: ~m.ty.clean()},
TyBox(ty) => Managed(~ty.clean()),
TyUniq(ty) => Unique(~ty.clean()),
TyVec(ty) => Vector(~ty.clean()),
TyFixedLengthVec(ty, ref e) => FixedVector(~ty.clean(),
e.span.to_src()),
TyTup(ref tys) => Tuple(tys.iter().map(|x| x.clean()).collect()),
TyPath(ref p, ref tpbs, id) =>
resolve_type(p.clean(), tpbs.clean(), id),
TyClosure(ref c) => Closure(~c.clean()),
TyBareFn(ref barefn) => BareFunction(~barefn.clean()),
TyBot => Bottom,
ref x => fail!("Unimplemented type {:?}", x),
}
2013-08-15 16:28:54 -04:00
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct StructField {
type_: Type,
}
impl Clean<Item> for ast::StructField {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Item {
let (name, vis) = match self.node.kind {
ast::NamedField(id, vis) => (Some(id), Some(vis)),
2013-08-15 16:28:54 -04:00
_ => (None, None)
};
Item {
name: name.clean(),
attrs: self.node.attrs.clean(),
source: self.span.clean(),
visibility: vis,
id: self.node.id,
inner: StructFieldItem(StructField {
type_: self.node.ty.clean(),
}),
}
}
}
pub type Visibility = ast::Visibility;
2013-08-15 16:28:54 -04:00
impl Clean<Option<Visibility>> for ast::Visibility {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Option<Visibility> {
Some(*self)
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Struct {
struct_type: doctree::StructType,
generics: Generics,
fields: ~[Item],
fields_stripped: bool,
2013-08-15 16:28:54 -04:00
}
impl Clean<Item> for doctree::Struct {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: StructItem(Struct {
struct_type: self.struct_type,
generics: self.generics.clean(),
fields: self.fields.clean(),
fields_stripped: false,
2013-08-15 16:28:54 -04:00
}),
}
}
}
/// This is a more limited form of the standard Struct, different in that it
/// it lacks the things most items have (name, id, parameterization). Found
/// only as a variant in an enum.
#[deriving(Clone, Encodable, Decodable)]
pub struct VariantStruct {
struct_type: doctree::StructType,
fields: ~[Item],
fields_stripped: bool,
2013-08-15 16:28:54 -04:00
}
impl Clean<VariantStruct> for syntax::ast::StructDef {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> VariantStruct {
VariantStruct {
struct_type: doctree::struct_type_from_def(self),
fields: self.fields.clean(),
fields_stripped: false,
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Enum {
variants: ~[Item],
generics: Generics,
variants_stripped: bool,
2013-08-15 16:28:54 -04:00
}
impl Clean<Item> for doctree::Enum {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: EnumItem(Enum {
variants: self.variants.clean(),
generics: self.generics.clean(),
variants_stripped: false,
2013-08-15 16:28:54 -04:00
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Variant {
kind: VariantKind,
}
impl Clean<Item> for doctree::Variant {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
id: self.id,
inner: VariantItem(Variant {
kind: self.kind.clean(),
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum VariantKind {
CLikeVariant,
TupleVariant(~[Type]),
StructVariant(VariantStruct),
}
impl Clean<VariantKind> for ast::VariantKind {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> VariantKind {
match self {
&ast::TupleVariantKind(ref args) => {
2013-08-15 16:28:54 -04:00
if args.len() == 0 {
CLikeVariant
} else {
TupleVariant(args.iter().map(|x| x.ty.clean()).collect())
}
},
&ast::StructVariantKind(ref sd) => StructVariant(sd.clean()),
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Span {
filename: ~str,
loline: uint,
locol: uint,
hiline: uint,
hicol: uint,
}
impl Clean<Span> for syntax::codemap::Span {
fn clean(&self) -> Span {
let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess.codemap;
let filename = cm.span_to_filename(*self);
let lo = cm.lookup_char_pos(self.lo);
let hi = cm.lookup_char_pos(self.hi);
Span {
filename: filename.to_owned(),
loline: lo.line,
locol: lo.col.to_uint(),
hiline: hi.line,
hicol: hi.col.to_uint(),
}
2013-08-15 16:28:54 -04:00
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Path {
global: bool,
segments: ~[PathSegment],
2013-08-15 16:28:54 -04:00
}
impl Clean<Path> for ast::Path {
fn clean(&self) -> Path {
Path {
global: self.global,
segments: self.segments.clean()
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct PathSegment {
name: ~str,
lifetimes: ~[Lifetime],
types: ~[Type],
}
impl Clean<PathSegment> for ast::PathSegment {
fn clean(&self) -> PathSegment {
PathSegment {
name: self.identifier.clean(),
lifetimes: self.lifetimes.clean(),
types: self.types.clean()
2013-08-15 16:28:54 -04:00
}
}
}
fn path_to_str(p: &ast::Path) -> ~str {
use syntax::parse::token;
2013-08-15 16:28:54 -04:00
let mut s = ~"";
let mut first = true;
for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
2013-08-15 16:28:54 -04:00
if !first || p.global {
s.push_str("::");
} else {
first = false;
}
s.push_str(i.get());
2013-08-15 16:28:54 -04:00
}
s
}
2013-09-05 10:14:35 -04:00
impl Clean<~str> for ast::Ident {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> ~str {
token::get_ident(*self).get().to_owned()
2013-08-15 16:28:54 -04:00
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Typedef {
type_: Type,
generics: Generics,
}
impl Clean<Item> for doctree::Typedef {
fn clean(&self) -> Item {
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id.clone(),
visibility: self.vis.clean(),
inner: TypedefItem(Typedef {
type_: self.ty.clean(),
generics: self.gen.clean(),
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct BareFunctionDecl {
purity: ast::Purity,
2013-08-15 16:28:54 -04:00
generics: Generics,
decl: FnDecl,
abi: ~str
}
impl Clean<BareFunctionDecl> for ast::BareFnTy {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> BareFunctionDecl {
BareFunctionDecl {
purity: self.purity,
generics: Generics {
lifetimes: self.lifetimes.clean(),
type_params: ~[],
},
decl: self.decl.clean(),
abi: self.abis.to_str(),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Static {
type_: Type,
mutability: Mutability,
/// It's useful to have the value of a static documented, but I have no
/// desire to represent expressions (that'd basically be all of the AST,
/// which is huge!). So, have a string.
expr: ~str,
}
impl Clean<Item> for doctree::Static {
fn clean(&self) -> Item {
debug!("claning static {}: {:?}", self.name.clean(), self);
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: StaticItem(Static {
type_: self.type_.clean(),
mutability: self.mutability.clean(),
expr: self.expr.span.to_src(),
}),
}
}
}
#[deriving(ToStr, Clone, Encodable, Decodable)]
pub enum Mutability {
Mutable,
Immutable,
}
2013-09-05 10:14:35 -04:00
impl Clean<Mutability> for ast::Mutability {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Mutability {
match self {
2013-09-05 10:14:35 -04:00
&ast::MutMutable => Mutable,
&ast::MutImmutable => Immutable,
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct Impl {
generics: Generics,
trait_: Option<Type>,
for_: Type,
methods: ~[Item],
}
impl Clean<Item> for doctree::Impl {
fn clean(&self) -> Item {
Item {
name: None,
attrs: self.attrs.clean(),
source: self.where.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: ImplItem(Impl {
generics: self.generics.clean(),
trait_: self.trait_.clean(),
for_: self.for_.clean(),
methods: self.methods.clean(),
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct ViewItem {
inner: ViewItemInner
}
impl Clean<Item> for ast::ViewItem {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> Item {
Item {
name: None,
attrs: self.attrs.clean(),
source: self.span.clean(),
id: 0,
visibility: self.vis.clean(),
inner: ViewItemItem(ViewItem {
inner: self.node.clean()
}),
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum ViewItemInner {
ExternMod(~str, Option<~str>, ast::NodeId),
2013-08-15 16:28:54 -04:00
Import(~[ViewPath])
}
impl Clean<ViewItemInner> for ast::ViewItem_ {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> ViewItemInner {
match self {
2014-01-21 10:08:10 -08:00
&ast::ViewItemExternMod(ref i, ref p, ref id) => {
let string = match *p {
None => None,
Some((ref x, _)) => Some(x.get().to_owned()),
};
ExternMod(i.clean(), string, *id)
}
&ast::ViewItemUse(ref vp) => Import(vp.clean())
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub enum ViewPath {
// use str = source;
SimpleImport(~str, ImportSource),
// use source::*;
GlobImport(ImportSource),
// use source::{a, b, c};
ImportList(ImportSource, ~[ViewListIdent]),
}
#[deriving(Clone, Encodable, Decodable)]
pub struct ImportSource {
path: Path,
did: Option<ast::DefId>,
2013-08-15 16:28:54 -04:00
}
impl Clean<ViewPath> for ast::ViewPath {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> ViewPath {
match self.node {
ast::ViewPathSimple(ref i, ref p, id) =>
SimpleImport(i.clean(), resolve_use_source(p.clean(), id)),
ast::ViewPathGlob(ref p, id) =>
GlobImport(resolve_use_source(p.clean(), id)),
ast::ViewPathList(ref p, ref pl, id) =>
ImportList(resolve_use_source(p.clean(), id), pl.clean()),
2013-08-15 16:28:54 -04:00
}
}
}
#[deriving(Clone, Encodable, Decodable)]
pub struct ViewListIdent {
name: ~str,
source: Option<ast::DefId>,
}
2013-08-15 16:28:54 -04:00
impl Clean<ViewListIdent> for ast::PathListIdent {
2013-08-15 16:28:54 -04:00
fn clean(&self) -> ViewListIdent {
ViewListIdent {
name: self.node.name.clean(),
source: resolve_def(self.node.id),
}
2013-08-15 16:28:54 -04:00
}
}
impl Clean<~[Item]> for ast::ForeignMod {
fn clean(&self) -> ~[Item] {
self.items.clean()
}
}
impl Clean<Item> for ast::ForeignItem {
fn clean(&self) -> Item {
let inner = match self.node {
ast::ForeignItemFn(ref decl, ref generics) => {
ForeignFunctionItem(Function {
decl: decl.clean(),
generics: generics.clean(),
purity: ast::ExternFn,
})
}
ast::ForeignItemStatic(ref ty, mutbl) => {
ForeignStaticItem(Static {
type_: ty.clean(),
mutability: if mutbl {Mutable} else {Immutable},
expr: ~"",
})
}
};
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
source: self.span.clean(),
id: self.id,
visibility: self.vis.clean(),
inner: inner,
}
}
}
2013-08-15 16:28:54 -04:00
// Utilities
trait ToSource {
fn to_src(&self) -> ~str;
}
2013-09-05 10:14:35 -04:00
impl ToSource for syntax::codemap::Span {
2013-08-15 16:28:54 -04:00
fn to_src(&self) -> ~str {
debug!("converting span {:?} to snippet", self.clean());
2013-08-15 16:28:54 -04:00
let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess.codemap.clone();
let sn = match cm.span_to_snippet(*self) {
Some(x) => x,
None => ~""
};
debug!("got snippet {}", sn);
2013-08-15 16:28:54 -04:00
sn
}
}
fn lit_to_str(lit: &ast::Lit) -> ~str {
2013-08-15 16:28:54 -04:00
match lit.node {
ast::LitStr(ref st, _) => st.get().to_owned(),
ast::LitBinary(ref data) => format!("{:?}", data.borrow().as_slice()),
ast::LitChar(c) => ~"'" + std::char::from_u32(c).unwrap().to_str() + "'",
ast::LitInt(i, _t) => i.to_str(),
ast::LitUint(u, _t) => u.to_str(),
ast::LitIntUnsuffixed(i) => i.to_str(),
ast::LitFloat(ref f, _t) => f.get().to_str(),
ast::LitFloatUnsuffixed(ref f) => f.get().to_str(),
ast::LitBool(b) => b.to_str(),
ast::LitNil => ~"",
2013-08-15 16:28:54 -04:00
}
}
2013-09-05 10:14:35 -04:00
fn name_from_pat(p: &ast::Pat) -> ~str {
2013-08-15 16:28:54 -04:00
use syntax::ast::*;
2013-12-29 00:13:29 -05:00
debug!("Trying to get a name from pattern: {:?}", p);
2013-08-15 16:28:54 -04:00
match p.node {
2013-09-05 10:14:35 -04:00
PatWild => ~"_",
2013-11-07 19:25:39 -08:00
PatWildMulti => ~"..",
2013-09-05 10:14:35 -04:00
PatIdent(_, ref p, _) => path_to_str(p),
PatEnum(ref p, _) => path_to_str(p),
2013-11-28 12:22:53 -08:00
PatStruct(..) => fail!("tried to get argument name from pat_struct, \
2013-09-05 10:14:35 -04:00
which is not allowed in function arguments"),
2013-11-28 12:22:53 -08:00
PatTup(..) => ~"(tuple arg NYI)",
2013-09-05 10:14:35 -04:00
PatUniq(p) => name_from_pat(p),
PatRegion(p) => name_from_pat(p),
2013-12-29 00:13:29 -05:00
PatLit(..) => {
warn!("tried to get argument name from PatLit, \
which is silly in function arguments");
~"()"
},
PatRange(..) => fail!("tried to get argument name from PatRange, \
2013-09-05 10:14:35 -04:00
which is not allowed in function arguments"),
2013-11-28 12:22:53 -08:00
PatVec(..) => fail!("tried to get argument name from pat_vec, \
2013-08-15 16:28:54 -04:00
which is not allowed in function arguments")
}
}
/// Given a Type, resolve it using the def_map
fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
id: ast::NodeId) -> Type {
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let tycx = match cx.tycx {
Some(tycx) => tycx,
// If we're extracting tests, this return value doesn't matter.
None => return Bool
};
debug!("searching for {:?} in defmap", id);
let def_map = tycx.def_map.borrow();
let d = match def_map.get().find(&id) {
2013-08-15 16:28:54 -04:00
Some(k) => k,
None => {
debug!("could not find {:?} in defmap (`{}`)", id, tycx.map.node_to_str(id));
fail!("Unexpected failure: unresolved id not in defmap (this is a bug!)")
2013-08-15 16:28:54 -04:00
}
};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
let (def_id, kind) = match *d {
ast::DefFn(i, _) => (i, TypeFunction),
ast::DefSelfTy(i) => return Self(i),
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => {
debug!("saw DefTrait in def_to_id");
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
(i, TypeTrait)
2013-08-15 16:28:54 -04:00
},
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
ast::DefPrimTy(p) => match p {
ast::TyStr => return String,
ast::TyBool => return Bool,
2013-08-15 16:28:54 -04:00
_ => return Primitive(p)
},
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
ast::DefTyParam(i, _) => return Generic(i.node),
ast::DefStruct(i) => (i, TypeStruct),
ast::DefTyParamBinder(i) => {
debug!("found a typaram_binder, what is it? {}", i);
2013-08-15 16:28:54 -04:00
return TyParamBinder(i);
},
x => fail!("resolved type maps to a weird def {:?}", x),
2013-08-15 16:28:54 -04:00
};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
if ast_util::is_local(def_id) {
ResolvedPath{ path: path, typarams: tpbs, id: def_id.node }
} else {
let fqn = csearch::get_item_path(tycx, def_id);
let fqn = fqn.move_iter().map(|i| i.to_str()).to_owned_vec();
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
ExternalPath{ path: path, typarams: tpbs, fqn: fqn, kind: kind,
krate: def_id.krate }
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
}
2013-08-15 16:28:54 -04:00
}
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
ImportSource {
path: path,
did: resolve_def(id),
}
}
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
match cx.tycx {
Some(tcx) => {
let def_map = tcx.def_map.borrow();
def_map.get().find(&id).map(|&d| ast_util::def_id_of_def(d))
}
None => None
}
}