use middle::trans::adt; // for `adt::is_ffi_safe`
use middle::typeck::astconv::ast_ty_to_ty;
use middle::typeck::infer;
-use middle::{typeck, ty, def, pat_util};
+use middle::{typeck, ty, def, pat_util, stability};
use util::ppaux::{ty_to_str};
use util::nodemap::NodeSet;
use lint::{Context, LintPass, LintArray};
Some(method) => {
match method.origin {
typeck::MethodStatic(def_id) => {
- // If this implements a trait method, get def_id
- // of the method inside trait definition.
- // Otherwise, use the current def_id (which refers
- // to the method inside impl).
- ty::trait_method_of_method(cx.tcx, def_id).unwrap_or(def_id)
+ def_id
}
typeck::MethodParam(typeck::MethodParam {
trait_id: trait_id,
// check anything for crate-local usage.
if ast_util::is_local(id) { return }
- let stability = cx.tcx.stability.borrow_mut().lookup(&cx.tcx.sess.cstore, id);
-
+ let stability = stability::lookup(cx.tcx, id);
let (lint, label) = match stability {
// no stability attributes == Unstable
None => (UNSTABLE, "unmarked"),
use middle::astencode;
use middle::ty;
use middle::typeck;
+use middle::stability;
use middle;
use util::nodemap::{NodeMap, NodeSet};
encode_visibility(ebml_w, variant.node.vis);
encode_attributes(ebml_w, variant.node.attrs.as_slice());
- let stab = ecx.tcx.stability.borrow().lookup_local(variant.node.id);
+ let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
encode_stability(ebml_w, stab);
match variant.node.kind {
encode_path(ebml_w, path.clone());
encode_visibility(ebml_w, vis);
- encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(id));
+
+ let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
+ encode_stability(ebml_w, stab);
// Encode the reexports of this module, if this module is public.
if vis == Public {
encode_symbol(ecx, ebml_w, ctor_id);
}
- encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(ctor_id));
+ let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
+ encode_stability(ebml_w, stab);
// indicate that this is a tuple struct ctor, because downstream users will normally want
// the tuple struct definition, but without this there is no way for them to tell that
encode_method_ty_fields(ecx, ebml_w, m);
encode_parent_item(ebml_w, local_def(parent_id));
- let stab = ecx.tcx.stability.borrow().lookup_local(m.def_id.node);
+ let stab = stability::lookup(ecx.tcx, m.def_id);
encode_stability(ebml_w, stab);
// The type for methods gets encoded twice, which is unfortunate.
}
debug!("encoding info for item at {}",
- ecx.tcx.sess.codemap().span_to_str(item.span));
+ tcx.sess.codemap().span_to_str(item.span));
let def_id = local_def(item.id);
- let stab = tcx.stability.borrow().lookup_local(item.id);
+ let stab = stability::lookup(tcx, ast_util::local_def(item.id));
match item.node {
ItemStatic(_, m, _) => {
encode_method_ty_fields(ecx, ebml_w, &*method_ty);
encode_parent_item(ebml_w, def_id);
- let stab = tcx.stability.borrow().lookup_local(method_def_id.node);
+ let stab = stability::lookup(tcx, method_def_id);
encode_stability(ebml_w, stab);
let elem = ast_map::PathName(method_ty.ident.name);
use syntax::ast_util::is_local;
use syntax::attr::Stability;
use syntax::visit::{FnKind, FkMethod, Visitor};
-use metadata::{cstore, csearch};
+use middle::ty;
+use metadata::csearch;
/// A stability index, giving the stability level for items and methods.
pub struct Index {
attr::find_stability(krate.attrs.as_slice()));
annotator.index
}
+}
- /// Lookup the stability for a node, loading external crate
- /// metadata as necessary.
- pub fn lookup(&mut self, cstore: &cstore::CStore, id: DefId) -> Option<Stability> {
- if is_local(id) {
- self.lookup_local(id.node)
- } else {
- let stab = csearch::get_stability(cstore, id);
- self.extern_cache.insert(id, stab.clone());
+/// Lookup the stability for a node, loading external crate
+/// metadata as necessary.
+pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
+ // is this definition the implementation of a trait method?
+ match ty::trait_method_of_method(tcx, id) {
+ Some(trait_method_id) if trait_method_id != id => {
+ lookup(tcx, trait_method_id)
+ }
+ _ if is_local(id) => {
+ tcx.stability.borrow().local.find_copy(&id.node)
+ }
+ _ => {
+ let stab = csearch::get_stability(&tcx.sess.cstore, id);
+ let mut index = tcx.stability.borrow_mut();
+ (*index).extern_cache.insert(id, stab.clone());
stab
}
}
-
- /// Lookup the stability for a local node without loading any external crates
- pub fn lookup_local(&self, id: NodeId) -> Option<Stability> {
- self.local.find_copy(&id)
- }
}
use rustc::metadata::decoder;
use rustc::middle::def;
use rustc::middle::ty;
+use rustc::middle::stability;
use core;
use doctree;
attrs: load_attrs(tcx, did),
inner: inner,
visibility: Some(ast::Public),
+ stability: stability::lookup(tcx, did).clean(),
def_id: did,
});
Some(ret)
name: None,
attrs: attrs,
visibility: Some(ast::Inherited),
+ stability: stability::lookup(tcx, did).clean(),
def_id: did,
})
}
use rustc::middle::subst;
use rustc::middle::subst::VecPerParamSpace;
use rustc::middle::ty;
+use rustc::middle::stability;
use std::rc::Rc;
use std::u32;
mod inline;
+// load the current DocContext from TLD
+fn get_cx() -> Gc<core::DocContext> {
+ *super::ctxtkey.get().unwrap()
+}
+
+// extract the stability index for a node from TLD, if possible
+fn get_stability(def_id: ast::DefId) -> Option<Stability> {
+ get_cx().tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id))
+ .map(|stab| stab.clean())
+}
+
pub trait Clean<T> {
fn clean(&self) -> T;
}
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
fn clean(&self) -> Crate {
- let cx = super::ctxtkey.get().unwrap();
+ let cx = get_cx();
let mut externs = Vec::new();
cx.sess().cstore.iter_crate_data(|n, meta| {
name: Some(prim.to_url_str().to_string()),
attrs: Vec::new(),
visibility: None,
+ stability: None,
def_id: ast_util::local_def(prim.to_node_id()),
inner: PrimitiveItem(prim),
};
impl Clean<ExternalCrate> for cstore::crate_metadata {
fn clean(&self) -> ExternalCrate {
let mut primitives = Vec::new();
- let cx = super::ctxtkey.get().unwrap();
- match cx.maybe_typed {
- core::Typed(ref tcx) => {
- csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
- self.cnum,
- |def, _, _| {
- let did = match def {
- decoder::DlDef(def::DefMod(did)) => did,
- _ => return
- };
- let attrs = inline::load_attrs(tcx, did);
- match Primitive::find(attrs.as_slice()) {
- Some(prim) => primitives.push(prim),
- None => {}
- }
- });
- }
- core::NotTyped(..) => {}
- }
+ get_cx().tcx_opt().map(|tcx| {
+ csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
+ self.cnum,
+ |def, _, _| {
+ let did = match def {
+ decoder::DlDef(def::DefMod(did)) => did,
+ _ => return
+ };
+ let attrs = inline::load_attrs(tcx, did);
+ Primitive::find(attrs.as_slice()).map(|prim| primitives.push(prim));
+ })
+ });
ExternalCrate {
name: self.name.to_string(),
attrs: decoder::get_crate_attributes(self.data()).clean(),
pub inner: ItemEnum,
pub visibility: Option<Visibility>,
pub def_id: ast::DefId,
+ pub stability: Option<Stability>,
}
impl Item {
attrs: self.attrs.clean(),
source: where.clean(),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
impl Clean<TyParam> for ty::TypeParameterDef {
fn clean(&self) -> TyParam {
- let cx = super::ctxtkey.get().unwrap();
- cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id,
- self.ident.clean());
+ get_cx().external_typarams.borrow_mut().get_mut_ref()
+ .insert(self.def_id, self.ident.clean());
TyParam {
name: self.ident.clean(),
did: self.def_id,
impl Clean<TyParamBound> for ty::BuiltinBound {
fn clean(&self) -> TyParamBound {
- let cx = super::ctxtkey.get().unwrap();
+ let cx = get_cx();
let tcx = match cx.maybe_typed {
core::Typed(ref tcx) => tcx,
core::NotTyped(_) => return RegionBound,
impl Clean<TyParamBound> for ty::TraitRef {
fn clean(&self) -> TyParamBound {
- let cx = super::ctxtkey.get().unwrap();
+ let cx = get_cx();
let tcx = match cx.maybe_typed {
core::Typed(ref tcx) => tcx,
core::NotTyped(_) => return RegionBound,
name: Some(self.ident.clean()),
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
- def_id: ast_util::local_def(self.id.clone()),
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: get_stability(ast_util::local_def(self.id)),
inner: MethodItem(Method {
generics: self.generics.clean(),
self_: self.explicit_self.node.clean(),
source: self.span.clean(),
def_id: ast_util::local_def(self.id),
visibility: None,
+ stability: get_stability(ast_util::local_def(self.id)),
inner: TyMethodItem(TyMethod {
fn_style: self.fn_style.clone(),
decl: decl,
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
inner: FunctionItem(Function {
decl: self.decl.clean(),
impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
fn clean(&self) -> FnDecl {
- let cx = super::ctxtkey.get().unwrap();
- let tcx = match cx.maybe_typed {
- core::Typed(ref tcx) => tcx,
- core::NotTyped(_) => unreachable!(),
- };
+ let cx = get_cx();
let (did, sig) = *self;
let mut names = if did.node != 0 {
- csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter()
+ csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).move_iter()
} else {
Vec::new().move_iter()
}.peekable();
source: self.where.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: TraitItem(Trait {
methods: self.methods.clean(),
generics: self.generics.clean(),
impl Clean<Item> for ty::Method {
fn clean(&self) -> Item {
- let cx = super::ctxtkey.get().unwrap();
- let tcx = match cx.maybe_typed {
- core::Typed(ref tcx) => tcx,
- core::NotTyped(_) => unreachable!(),
- };
+ let cx = get_cx();
let (self_, sig) = match self.explicit_self {
ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
s => {
Item {
name: Some(self.ident.clean()),
visibility: Some(ast::Inherited),
+ stability: get_stability(self.def_id),
def_id: self.def_id,
- attrs: inline::load_attrs(tcx, self.def_id),
+ attrs: inline::load_attrs(cx.tcx(), self.def_id),
source: Span::empty(),
inner: TyMethodItem(TyMethod {
fn_style: self.fty.fn_style,
ty::ty_struct(did, ref substs) |
ty::ty_enum(did, ref substs) |
ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
- let cx = super::ctxtkey.get().unwrap();
- let tcx = match cx.maybe_typed {
- core::Typed(ref tycx) => tycx,
- core::NotTyped(_) => unreachable!(),
- };
- let fqn = csearch::get_item_path(tcx, did);
+ let fqn = csearch::get_item_path(get_cx().tcx(), did);
let fqn: Vec<String> = fqn.move_iter().map(|i| {
i.to_str()
}).collect();
};
let path = external_path(fqn.last().unwrap().to_str().as_slice(),
substs);
- cx.external_paths.borrow_mut().get_mut_ref().insert(did,
- (fqn, kind));
+ get_cx().external_paths.borrow_mut().get_mut_ref()
+ .insert(did, (fqn, kind));
ResolvedPath {
path: path,
typarams: None,
attrs: self.node.attrs.clean().move_iter().collect(),
source: self.span.clean(),
visibility: Some(vis),
+ stability: get_stability(ast_util::local_def(self.node.id)),
def_id: ast_util::local_def(self.node.id),
inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
}
} else {
Some(self.name)
};
- let cx = super::ctxtkey.get().unwrap();
- let tcx = match cx.maybe_typed {
- core::Typed(ref tycx) => tycx,
- core::NotTyped(_) => unreachable!(),
- };
- let ty = ty::lookup_item_type(tcx, self.id);
+ let cx = get_cx();
+ let ty = ty::lookup_item_type(cx.tcx(), self.id);
Item {
name: name.clean(),
- attrs: inline::load_attrs(tcx, self.id),
+ attrs: inline::load_attrs(cx.tcx(), self.id),
source: Span::empty(),
visibility: Some(self.vis),
+ stability: get_stability(self.id),
def_id: self.id,
inner: StructFieldItem(TypedStructField(ty.ty.clean())),
}
source: self.where.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: StructItem(Struct {
struct_type: self.struct_type,
generics: self.generics.clean(),
source: self.where.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: EnumItem(Enum {
variants: self.variants.clean(),
generics: self.generics.clean(),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
inner: VariantItem(Variant {
kind: self.kind.clean(),
impl Clean<Item> for ty::VariantInfo {
fn clean(&self) -> Item {
// use syntax::parse::token::special_idents::unnamed_field;
- let cx = super::ctxtkey.get().unwrap();
- let tcx = match cx.maybe_typed {
- core::Typed(ref tycx) => tycx,
- core::NotTyped(_) => fail!("tcx not present"),
- };
+ let cx = get_cx();
let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) {
None | Some([]) if self.args.len() == 0 => CLikeVariant,
None | Some([]) => {
name: Some(name.clean()),
attrs: Vec::new(),
visibility: Some(ast::Public),
+ stability: get_stability(self.id),
// FIXME: this is not accurate, we need an id for
// the specific field but we're using the id
// for the whole variant. Nothing currently
};
Item {
name: Some(self.name.clean()),
- attrs: inline::load_attrs(tcx, self.id),
+ attrs: inline::load_attrs(cx.tcx(), self.id),
source: Span::empty(),
visibility: Some(ast::Public),
def_id: self.id,
inner: VariantItem(Variant { kind: kind }),
+ stability: None,
}
}
}
source: self.where.clean(),
def_id: ast_util::local_def(self.id.clone()),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: TypedefItem(Typedef {
type_: self.ty.clean(),
generics: self.gen.clean(),
source: self.where.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: StaticItem(Static {
type_: self.type_.clean(),
mutability: self.mutability.clean(),
source: self.where.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: self.stab.clean(),
inner: ImplItem(Impl {
generics: self.generics.clean(),
trait_: self.trait_.clean(),
source: self.span.clean(),
def_id: ast_util::local_def(0),
visibility: self.vis.clean(),
+ stability: None,
inner: ViewItemItem(ViewItem { inner: node.clean() }),
}
};
source: self.span.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
+ stability: None,
inner: inner,
}
}
/// Given a Type, resolve it using the def_map
fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
id: ast::NodeId) -> Type {
- let cx = super::ctxtkey.get().unwrap();
+ let cx = get_cx();
let tycx = match cx.maybe_typed {
core::Typed(ref tycx) => tycx,
// If we're extracting tests, this return value doesn't matter.
def::DefTyParamBinder(i) => return TyParamBinder(i),
_ => {}
};
- let did = register_def(&**cx, def);
+ let did = register_def(&*cx, def);
ResolvedPath { path: path, typarams: tpbs, did: did }
}
}
fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
- let cx = super::ctxtkey.get().unwrap();
- match cx.maybe_typed {
- core::Typed(ref tcx) => {
- tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def))
- }
- core::NotTyped(_) => None
- }
+ get_cx().tcx_opt().and_then(|tcx| {
+ tcx.def_map.borrow().find(&id).map(|&def| register_def(&*get_cx(), def))
+ })
}
#[deriving(Clone, Encodable, Decodable)]
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: ast::Public.clean(),
+ stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
inner: MacroItem(Macro {
source: self.where.to_src(),
}
}
}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub struct Stability {
+ pub level: attr::StabilityLevel,
+ pub text: String
+}
+
+impl Clean<Stability> for attr::Stability {
+ fn clean(&self) -> Stability {
+ Stability {
+ level: self.level,
+ text: self.text.as_ref().map_or("".to_string(),
+ |interned| interned.get().to_string()),
+ }
+ }
+}
use rustc;
use rustc::{driver, middle};
-use rustc::middle::privacy;
+use rustc::middle::{privacy, ty};
use rustc::lint;
use syntax::ast;
use clean;
use clean::Clean;
+/// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
pub enum MaybeTyped {
Typed(middle::ty::ctxt),
NotTyped(driver::session::Session)
NotTyped(ref sess) => sess
}
}
+
+ pub fn tcx_opt<'a>(&'a self) -> Option<&'a ty::ctxt> {
+ match self.maybe_typed {
+ Typed(ref tcx) => Some(tcx),
+ NotTyped(_) => None
+ }
+ }
+
+ pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
+ let tcx_opt = self.tcx_opt();
+ tcx_opt.expect("tcx not present")
+ }
}
pub struct CrateAnalysis {
use syntax;
use syntax::codemap::Span;
use syntax::ast;
+use syntax::attr;
use syntax::ast::{Ident, NodeId};
use std::gc::Gc;
pub statics: Vec<Static>,
pub traits: Vec<Trait>,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub impls: Vec<Impl>,
pub foreigns: Vec<ast::ForeignMod>,
pub view_items: Vec<ast::ViewItem>,
name : name,
id: 0,
vis: ast::Inherited,
+ stab: None,
where_outer: syntax::codemap::DUMMY_SP,
where_inner: syntax::codemap::DUMMY_SP,
attrs : Vec::new(),
pub struct Struct {
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub id: NodeId,
pub struct_type: StructType,
pub name: Ident,
pub struct Enum {
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub variants: Vec<Variant>,
pub generics: ast::Generics,
pub attrs: Vec<ast::Attribute>,
pub kind: ast::VariantKind,
pub id: ast::NodeId,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub where: Span,
}
pub id: NodeId,
pub name: Ident,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub fn_style: ast::FnStyle,
pub where: Span,
pub generics: ast::Generics,
pub attrs: Vec<ast::Attribute>,
pub where: Span,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
}
pub struct Static {
pub name: Ident,
pub attrs: Vec<ast::Attribute>,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub id: ast::NodeId,
pub where: Span,
}
pub id: ast::NodeId,
pub where: Span,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
}
pub struct Impl {
pub attrs: Vec<ast::Attribute>,
pub where: Span,
pub vis: ast::Visibility,
+ pub stab: Option<attr::Stability>,
pub id: ast::NodeId,
}
pub id: ast::NodeId,
pub attrs: Vec<ast::Attribute>,
pub where: Span,
+ pub stab: Option<attr::Stability>,
}
pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType {
/// don't override!
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
- let Item { attrs, name, source, visibility, def_id, inner } = item;
+ let Item { attrs, name, source, visibility, def_id, inner, stability } = item;
let inner = inner;
let inner = match inner {
StructItem(mut i) => {
};
Some(Item { attrs: attrs, name: name, source: source, inner: inner,
- visibility: visibility, def_id: def_id })
+ visibility: visibility, stability: stability, def_id: def_id })
}
fn fold_mod(&mut self, m: Module) -> Module {
pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
/// Similar to VisSpace, but used for mutability
pub struct MutableSpace(pub clean::Mutability);
+/// Wrapper struct for properly emitting the stability level.
+pub struct Stability<'a>(pub &'a Option<clean::Stability>);
+/// Wrapper struct for emitting the stability level concisely.
+pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
impl VisSpace {
pub fn get(&self) -> Option<ast::Visibility> {
}
}
}
+
+impl<'a> fmt::Show for Stability<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let Stability(stab) = *self;
+ match *stab {
+ Some(ref stability) => {
+ write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
+ lvl = stability.level.to_str(),
+ reason = stability.text)
+ }
+ None => Ok(())
+ }
+ }
+}
+
+impl<'a> fmt::Show for ConciseStability<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let ConciseStability(stab) = *self;
+ match *stab {
+ Some(ref stability) => {
+ write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
+ lvl = stability.level.to_str(),
+ colon = if stability.text.len() > 0 { ": " } else { "" },
+ reason = stability.text)
+ }
+ None => {
+ write!(f, "<a class='stability Unmarked' title='No stability level'></a>")
+ }
+ }
+ }
+}
use serialize::json::ToJson;
use syntax::ast;
use syntax::ast_util;
-use syntax::attr;
-use syntax::parse::token::InternedString;
use rustc::util::nodemap::NodeSet;
use clean;
use doctree;
use fold::DocFolder;
-use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace};
+use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability};
+use html::format::{ConciseStability};
use html::highlight;
use html::item_type::{ItemType, shortty};
use html::item_type;
generics: clean::Generics,
trait_: clean::Type,
for_: clean::Type,
+ stability: Option<clean::Stability>,
+}
+
+/// Metadata about implementations for a type.
+#[deriving(Clone)]
+pub struct Impl {
+ impl_: clean::Impl,
+ dox: Option<String>,
+ stability: Option<clean::Stability>,
}
/// This cache is used to store information about the `clean::Crate` being
///
/// The values of the map are a list of implementations and documentation
/// found on that implementation.
- pub impls: HashMap<ast::DefId, Vec<(clean::Impl, Option<String>)>>,
+ pub impls: HashMap<ast::DefId, Vec<Impl>>,
/// Maintains a mapping of local crate node ids to the fully qualified name
/// and "short type description" of that node. This is used when generating
// going on). If they're in different crates then the crate defining
// the trait will be interested in our implementation.
if imp.def_id.krate == did.krate { continue }
- try!(write!(&mut f, r#""impl{} {} for {}","#,
+ try!(write!(&mut f, r#""{}impl{} {} for {}","#,
+ ConciseStability(&imp.stability),
imp.generics, imp.trait_, imp.for_));
}
try!(writeln!(&mut f, r"];"));
generics: i.generics.clone(),
trait_: i.trait_.get_ref().clone(),
for_: i.for_.clone(),
+ stability: item.stability.clone(),
});
}
Some(..) | None => {}
let v = self.impls.find_or_insert_with(did, |_| {
Vec::new()
});
- v.push((i, dox));
+ v.push(Impl {
+ impl_: i,
+ dox: dox,
+ stability: item.stability.clone(),
+ });
}
None => {}
}
try!(write!(fmt, "<a class='{}' href=''>{}</a>",
shortty(self.item), self.item.name.get_ref().as_slice()));
- // Write stability attributes
- match attr::find_stability_generic(self.item.attrs.iter()) {
- Some((ref stability, _)) => {
- try!(write!(fmt,
- "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
- lvl = stability.level.to_str(),
- reason = match stability.text {
- Some(ref s) => (*s).clone(),
- None => InternedString::new(""),
- }));
- }
- None => {}
- }
+ // Write stability level
+ try!(write!(fmt, "{}", Stability(&self.item.stability)));
// Write `src` tag
//
try!(write!(w, "
<tr>
- <td><code>{}static {}{}: {}</code>{}</td>
+ <td>{}<code>{}static {}{}: {}</code>{}</td>
<td class='docblock'>{} </td>
</tr>
",
+ ConciseStability(&myitem.stability),
VisSpace(myitem.visibility),
MutableSpace(s.mutability),
*myitem.name.get_ref(),
if myitem.name.is_none() { continue }
try!(write!(w, "
<tr>
- <td><a class='{class}' href='{href}'
+ <td>{stab}<a class='{class}' href='{href}'
title='{title}'>{}</a></td>
<td class='docblock short'>{}</td>
</tr>
Markdown(shorter(myitem.doc_value())),
class = shortty(myitem),
href = item_path(myitem),
- title = full_path(cx, myitem)));
+ title = full_path(cx, myitem),
+ stab = ConciseStability(&myitem.stability)));
}
}
}
try!(document(w, it));
fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
- try!(write!(w, "<h3 id='{}.{}' class='method'><code>",
- shortty(m.item()),
- *m.item().name.get_ref()));
+ try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
+ shortty(m.item()),
+ *m.item().name.get_ref(),
+ ConciseStability(&m.item().stability)));
try!(render_method(w, m.item()));
try!(write!(w, "</code></h3>"));
try!(document(w, m.item()));
match cache.implementors.find(&it.def_id) {
Some(implementors) => {
for i in implementors.iter() {
- try!(writeln!(w, "<li><code>impl{} {} for {}</code></li>",
+ try!(writeln!(w, "<li>{}<code>impl{} {} for {}</code></li>",
+ ConciseStability(&i.stability),
i.generics, i.trait_, i.for_));
}
}
try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
for field in fields {
try!(write!(w, "<tr><td id='structfield.{name}'>\
- <code>{name}</code></td><td>",
+ {stab}<code>{name}</code></td><td>",
+ stab = ConciseStability(&field.stability),
name = field.name.get_ref().as_slice()));
try!(document(w, field));
try!(write!(w, "</td></tr>"));
if e.variants.len() > 0 {
try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table>"));
for variant in e.variants.iter() {
- try!(write!(w, "<tr><td id='variant.{name}'><code>{name}</code></td><td>",
+ try!(write!(w, "<tr><td id='variant.{name}'>{stab}<code>{name}</code></td><td>",
+ stab = ConciseStability(&variant.stability),
name = variant.name.get_ref().as_slice()));
try!(document(w, variant));
match variant.inner {
fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
match cache_key.get().unwrap().impls.find(&it.def_id) {
Some(v) => {
- let mut non_trait = v.iter().filter(|p| {
- p.ref0().trait_.is_none()
- });
- let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<String>)>>();
- let mut traits = v.iter().filter(|p| {
- p.ref0().trait_.is_some()
- });
- let traits = traits.collect::<Vec<&(clean::Impl, Option<String>)>>();
-
+ let (non_trait, traits) = v.partitioned(|i| i.impl_.trait_.is_none());
if non_trait.len() > 0 {
try!(write!(w, "<h2 id='methods'>Methods</h2>"));
- for &(ref i, ref dox) in non_trait.move_iter() {
- try!(render_impl(w, i, dox));
+ for i in non_trait.iter() {
+ try!(render_impl(w, i));
}
}
if traits.len() > 0 {
try!(write!(w, "<h2 id='implementations'>Trait \
Implementations</h2>"));
- let mut any_derived = false;
- for & &(ref i, ref dox) in traits.iter() {
- if !i.derived {
- try!(render_impl(w, i, dox));
- } else {
- any_derived = true;
- }
+ let (derived, manual) = traits.partition(|i| i.impl_.derived);
+ for i in manual.iter() {
+ try!(render_impl(w, i));
}
- if any_derived {
+ if derived.len() > 0 {
try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
</h3>"));
- for &(ref i, ref dox) in traits.move_iter() {
- if i.derived {
- try!(render_impl(w, i, dox));
- }
+ for i in derived.iter() {
+ try!(render_impl(w, i));
}
}
}
Ok(())
}
-fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl,
- dox: &Option<String>) -> fmt::Result {
- try!(write!(w, "<h3 class='impl'><code>impl{} ", i.generics));
- match i.trait_ {
+fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
+ try!(write!(w, "<h3 class='impl'>{}<code>impl{} ",
+ ConciseStability(&i.stability),
+ i.impl_.generics));
+ match i.impl_.trait_ {
Some(ref ty) => try!(write!(w, "{} for ", *ty)),
None => {}
}
- try!(write!(w, "{}</code></h3>", i.for_));
- match *dox {
+ try!(write!(w, "{}</code></h3>", i.impl_.for_));
+ match i.dox {
Some(ref dox) => {
try!(write!(w, "<div class='docblock'>{}</div>",
Markdown(dox.as_slice())));
fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
dox: bool) -> fmt::Result {
- try!(write!(w, "<h4 id='method.{}' class='method'><code>",
- *item.name.get_ref()));
+ try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
+ *item.name.get_ref(),
+ ConciseStability(&item.stability)));
try!(render_method(w, item));
try!(write!(w, "</code></h4>\n"));
match item.doc_value() {
}
}
- try!(write!(w, "<div class='methods'>"));
- for meth in i.methods.iter() {
+ try!(write!(w, "<div class='impl-methods'>"));
+ for meth in i.impl_.methods.iter() {
try!(docmeth(w, meth, true));
}
// If we've implemented a trait, then also emit documentation for all
// default methods which weren't overridden in the implementation block.
- match i.trait_ {
+ match i.impl_.trait_ {
Some(clean::ResolvedPath { did, .. }) => {
try!({
match cache_key.get().unwrap().traits.find(&did) {
- Some(t) => try!(render_default_methods(w, t, i)),
+ Some(t) => try!(render_default_methods(w, t, &i.impl_)),
None => {}
}
Ok(())
.content .multi-column li { width: 100%; display: inline-block; }
.content .method { font-size: 1em; }
-.content .methods { margin-left: 20px; }
-.content .methods .docblock { margin-left: 20px; }
+.content .methods .docblock { margin-left: 40px; }
+
+.content .impl-methods .docblock { margin-left: 40px; }
nav {
border-bottom: 1px solid #e0e0e0;
}
.stability {
- border-left: 6px solid #000;
+ border-left: 6px solid;
+ padding: 3px 6px;
border-radius: 3px;
- font-weight: 400;
- padding: 4px 10px;
+}
+
+h1 .stability {
text-transform: lowercase;
+ font-weight: 400;
margin-left: 14px;
+ padding: 4px 10px;
+}
+
+.impl-methods .stability {
+ margin-right: 20px;
}
-.stability.Deprecated { border-color: #D60027; color: #880017; }
-.stability.Experimental { border-color: #EC5315; color: #a53c0e; }
-.stability.Unstable { border-color: #FFD700; color: #b39800; }
-.stability.Stable { border-color: #AEC516; color: #7c8b10; }
+.stability.Deprecated { border-color: #A071A8; color: #82478C; }
+.stability.Experimental { border-color: #D46D6A; color: #AA3C39; }
+.stability.Unstable { border-color: #D4B16A; color: #AA8439; }
+.stability.Stable { border-color: #54A759; color: #2D8632; }
.stability.Frozen { border-color: #009431; color: #007726; }
.stability.Locked { border-color: #0084B6; color: #00668c; }
+.stability.Unmarked { border-color: #FFFFFF; }
:target { background: #FDFFD3; }
use syntax::ast;
use syntax::ast_util;
use syntax::ast_map;
+use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
+use rustc::middle::stability;
+
use std::gc::{Gc, GC};
use core;
}
}
+ fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
+ let tcx = match self.cx.maybe_typed {
+ core::Typed(ref tcx) => tcx,
+ core::NotTyped(_) => return None
+ };
+ stability::lookup(tcx, ast_util::local_def(id))
+ }
+
pub fn visit(&mut self, krate: &ast::Crate) {
self.attrs = krate.attrs.iter().map(|x| (*x).clone()).collect();
struct_type: struct_type,
name: item.ident,
vis: item.vis,
+ stab: self.stability(item.id),
attrs: item.attrs.iter().map(|x| *x).collect(),
generics: generics.clone(),
fields: sd.fields.iter().map(|x| (*x).clone()).collect(),
name: x.node.name,
attrs: x.node.attrs.iter().map(|x| *x).collect(),
vis: x.node.vis,
+ stab: self.stability(x.node.id),
id: x.node.id,
kind: x.node.kind.clone(),
where: x.span,
name: it.ident,
variants: vars,
vis: it.vis,
+ stab: self.stability(it.id),
generics: params.clone(),
attrs: it.attrs.iter().map(|x| *x).collect(),
id: it.id,
Function {
id: item.id,
vis: item.vis,
+ stab: self.stability(item.id),
attrs: item.attrs.iter().map(|x| *x).collect(),
decl: fd.clone(),
name: item.ident,
om.where_inner = m.inner;
om.attrs = attrs;
om.vis = vis;
+ om.stab = self.stability(id);
om.id = id;
for i in m.items.iter() {
self.visit_item(&**i, &mut om);
attrs: item.attrs.iter().map(|x| *x).collect(),
where: item.span,
vis: item.vis,
+ stab: self.stability(item.id),
};
om.typedefs.push(t);
},
attrs: item.attrs.iter().map(|x| *x).collect(),
where: item.span,
vis: item.vis,
+ stab: self.stability(item.id),
};
om.statics.push(s);
},
attrs: item.attrs.iter().map(|x| *x).collect(),
where: item.span,
vis: item.vis,
+ stab: self.stability(item.id),
};
om.traits.push(t);
},
id: item.id,
where: item.span,
vis: item.vis,
+ stab: self.stability(item.id),
};
om.impls.push(i);
},
attrs: item.attrs.iter().map(|x| *x).collect(),
name: item.ident,
where: item.span,
+ stab: self.stability(item.id),
})
}
}