diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5c88576acb7b4..c0f62cddb98bf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -121,6 +121,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt, inner: inner, visibility: Some(hir::Public), stability: stability::lookup_stability(tcx, did).clean(cx), + deprecation: stability::lookup_deprecation(tcx, did).clean(cx), def_id: did, }); Some(ret) @@ -304,6 +305,7 @@ pub fn build_impl(cx: &DocContext, attrs: attrs, visibility: Some(hir::Inherited), stability: stability::lookup_stability(tcx, did).clean(cx), + deprecation: stability::lookup_deprecation(tcx, did).clean(cx), def_id: did, }); } @@ -334,6 +336,7 @@ pub fn build_impl(cx: &DocContext, attrs: vec![], visibility: None, stability: stability::lookup_stability(tcx, did).clean(cx), + deprecation: stability::lookup_deprecation(tcx, did).clean(cx), def_id: did }) } @@ -382,6 +385,7 @@ pub fn build_impl(cx: &DocContext, attrs: vec![], visibility: None, stability: stability::lookup_stability(tcx, did).clean(cx), + deprecation: stability::lookup_deprecation(tcx, did).clean(cx), def_id: did }) } @@ -415,6 +419,7 @@ pub fn build_impl(cx: &DocContext, attrs: attrs, visibility: Some(hir::Inherited), stability: stability::lookup_stability(tcx, did).clean(cx), + deprecation: stability::lookup_deprecation(tcx, did).clean(cx), def_id: did, }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 942cc135aa8f5..52eeb781b31cc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -65,6 +65,10 @@ fn get_stability(cx: &DocContext, def_id: DefId) -> Option { cx.tcx_opt().and_then(|tcx| stability::lookup_stability(tcx, def_id)).clean(cx) } +fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option { + cx.tcx_opt().and_then(|tcx| stability::lookup_deprecation(tcx, def_id)).clean(cx) +} + pub trait Clean { fn clean(&self, cx: &DocContext) -> T; } @@ -188,6 +192,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { attrs: child.attrs.clone(), visibility: Some(hir::Public), stability: None, + deprecation: None, def_id: DefId::local(prim.to_def_index()), inner: PrimitiveItem(prim), }); @@ -254,6 +259,7 @@ pub struct Item { pub visibility: Option, pub def_id: DefId, pub stability: Option, + pub deprecation: Option, } impl Item { @@ -417,6 +423,7 @@ impl Clean for doctree::Module { source: whence.clean(cx), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), def_id: cx.map.local_def_id(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, @@ -1078,6 +1085,7 @@ impl Clean for doctree::Function { source: self.whence.clean(cx), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), def_id: cx.map.local_def_id(self.id), inner: FunctionItem(Function { decl: self.decl.clean(cx), @@ -1204,6 +1212,7 @@ impl Clean for doctree::Trait { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: TraitItem(Trait { unsafety: self.unsafety, items: self.items.clean(cx), @@ -1254,6 +1263,7 @@ impl Clean for hir::TraitItem { def_id: cx.map.local_def_id(self.id), visibility: None, stability: get_stability(cx, cx.map.local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), inner: inner } } @@ -1287,6 +1297,7 @@ impl Clean for hir::ImplItem { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: get_stability(cx, cx.map.local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), inner: inner } } @@ -1357,6 +1368,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { name: Some(self.name.clean(cx)), visibility: Some(hir::Inherited), stability: get_stability(cx, self.def_id), + deprecation: get_deprecation(cx, self.def_id), def_id: self.def_id, attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), source: Span::empty(), @@ -1715,6 +1727,7 @@ impl Clean for hir::StructField { source: self.span.clean(cx), visibility: Some(vis), stability: get_stability(cx, cx.map.local_def_id(self.node.id)), + deprecation: get_deprecation(cx, cx.map.local_def_id(self.node.id)), def_id: cx.map.local_def_id(self.node.id), inner: StructFieldItem(TypedStructField(self.node.ty.clean(cx))), } @@ -1740,6 +1753,7 @@ impl<'tcx> Clean for ty::FieldDefData<'tcx, 'static> { source: Span::empty(), visibility: Some(self.vis), stability: get_stability(cx, self.did), + deprecation: get_deprecation(cx, self.did), def_id: self.did, inner: StructFieldItem(TypedStructField(self.unsubst_ty().clean(cx))), } @@ -1771,6 +1785,7 @@ impl Clean for doctree::Struct { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: StructItem(Struct { struct_type: self.struct_type, generics: self.generics.clean(cx), @@ -1817,6 +1832,7 @@ impl Clean for doctree::Enum { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: EnumItem(Enum { variants: self.variants.clean(cx), generics: self.generics.clean(cx), @@ -1839,6 +1855,7 @@ impl Clean for doctree::Variant { source: self.whence.clean(cx), visibility: None, stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), def_id: cx.map.local_def_id(self.def.id()), inner: VariantItem(Variant { kind: struct_def_to_variant_kind(&self.def, cx), @@ -1876,6 +1893,7 @@ impl<'tcx> Clean for ty::VariantDefData<'tcx, 'static> { // at the needed information here. def_id: self.did, stability: get_stability(cx, self.did), + deprecation: get_deprecation(cx, self.did), inner: StructFieldItem( TypedStructField(field.unsubst_ty().clean(cx)) ) @@ -1892,6 +1910,7 @@ impl<'tcx> Clean for ty::VariantDefData<'tcx, 'static> { def_id: self.did, inner: VariantItem(Variant { kind: kind }), stability: get_stability(cx, self.did), + deprecation: get_deprecation(cx, self.did), } } } @@ -2067,6 +2086,7 @@ impl Clean for doctree::Typedef { def_id: cx.map.local_def_id(self.id.clone()), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: TypedefItem(Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx), @@ -2118,6 +2138,7 @@ impl Clean for doctree::Static { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: StaticItem(Static { type_: self.type_.clean(cx), mutability: self.mutability.clean(cx), @@ -2142,6 +2163,7 @@ impl Clean for doctree::Constant { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: ConstantItem(Constant { type_: self.type_.clean(cx), expr: self.expr.span.to_src(cx), @@ -2216,6 +2238,7 @@ impl Clean> for doctree::Impl { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), inner: ImplItem(Impl { unsafety: self.unsafety, generics: self.generics.clean(cx), @@ -2298,6 +2321,7 @@ impl Clean for doctree::DefaultImpl { def_id: cx.map.local_def_id(self.id), visibility: Some(hir::Public), stability: None, + deprecation: None, inner: DefaultImplItem(DefaultImpl { unsafety: self.unsafety, trait_: self.trait_.clean(cx), @@ -2315,6 +2339,7 @@ impl Clean for doctree::ExternCrate { def_id: cx.map.local_def_id(0), visibility: self.vis.clean(cx), stability: None, + deprecation: None, inner: ExternCrateItem(self.name.clean(cx), self.path.clone()) } } @@ -2380,6 +2405,7 @@ impl Clean> for doctree::Import { def_id: cx.map.local_def_id(0), visibility: self.vis.clean(cx), stability: None, + deprecation: None, inner: ImportItem(inner) }); ret @@ -2466,6 +2492,7 @@ impl Clean for hir::ForeignItem { def_id: cx.map.local_def_id(self.id), visibility: self.vis.clean(cx), stability: get_stability(cx, cx.map.local_def_id(self.id)), + deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), inner: inner, } } @@ -2659,6 +2686,7 @@ impl Clean for doctree::Macro { source: self.whence.clean(cx), visibility: hir::Public.clean(cx), stability: self.stab.clean(cx), + deprecation: self.depr.clean(cx), def_id: cx.map.local_def_id(self.id), inner: MacroItem(Macro { source: format!("macro_rules! {} {{\n{}}}", @@ -2680,6 +2708,12 @@ pub struct Stability { pub issue: Option } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct Deprecation { + pub since: String, + pub note: String, +} + impl Clean for attr::Stability { fn clean(&self, _: &DocContext) -> Stability { Stability { @@ -2716,6 +2750,15 @@ impl<'a> Clean for &'a attr::Stability { } } +impl Clean for attr::Deprecation { + fn clean(&self, _: &DocContext) -> Deprecation { + Deprecation { + since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()), + note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()), + } + } +} + impl<'tcx> Clean for ty::AssociatedConst<'tcx> { fn clean(&self, cx: &DocContext) -> Item { Item { @@ -2726,6 +2769,7 @@ impl<'tcx> Clean for ty::AssociatedConst<'tcx> { visibility: None, def_id: self.def_id, stability: None, + deprecation: None, } } } @@ -2783,6 +2827,7 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { visibility: self.vis.clean(cx), def_id: self.def_id, stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx), + deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx), } } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 0129ab43cefd8..d1030a6fcb07c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -40,6 +40,7 @@ pub struct Module { pub traits: Vec, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub impls: Vec, pub def_traits: Vec, pub foreigns: Vec, @@ -54,6 +55,7 @@ impl Module { id: 0, vis: hir::Inherited, stab: None, + depr: None, where_outer: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP, attrs : Vec::new(), @@ -96,6 +98,7 @@ pub enum TypeBound { pub struct Struct { pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub id: NodeId, pub struct_type: StructType, pub name: Name, @@ -108,6 +111,7 @@ pub struct Struct { pub struct Enum { pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub variants: Vec, pub generics: hir::Generics, pub attrs: Vec, @@ -121,6 +125,7 @@ pub struct Variant { pub attrs: Vec, pub def: hir::VariantData, pub stab: Option, + pub depr: Option, pub whence: Span, } @@ -131,6 +136,7 @@ pub struct Function { pub name: Name, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub unsafety: hir::Unsafety, pub constness: hir::Constness, pub whence: Span, @@ -147,6 +153,7 @@ pub struct Typedef { pub whence: Span, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, } #[derive(Debug)] @@ -158,6 +165,7 @@ pub struct Static { pub attrs: Vec, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub id: ast::NodeId, pub whence: Span, } @@ -169,6 +177,7 @@ pub struct Constant { pub attrs: Vec, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub id: ast::NodeId, pub whence: Span, } @@ -184,6 +193,7 @@ pub struct Trait { pub whence: Span, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, } pub struct Impl { @@ -197,6 +207,7 @@ pub struct Impl { pub whence: Span, pub vis: hir::Visibility, pub stab: Option, + pub depr: Option, pub id: ast::NodeId, } @@ -215,6 +226,7 @@ pub struct Macro { pub whence: Span, pub matchers: Vec, pub stab: Option, + pub depr: Option, pub imported_from: Option, } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 0a1860c66f273..5a4f95d1a1a5a 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -19,7 +19,7 @@ pub trait DocFolder : Sized { /// don't override! fn fold_item_recur(&mut self, item: Item) -> Option { - let Item { attrs, name, source, visibility, def_id, inner, stability } = item; + let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item; let inner = inner; let inner = match inner { StructItem(mut i) => { @@ -66,7 +66,8 @@ pub trait DocFolder : Sized { }; Some(Item { attrs: attrs, name: name, source: source, inner: inner, - visibility: visibility, stability: stability, def_id: def_id }) + visibility: visibility, stability: stability, deprecation: deprecation, + def_id: def_id }) } fn fold_mod(&mut self, m: Module) -> Module { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 45969ed0c644d..09a2a1b1c0269 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1801,7 +1801,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Option { - item.stability.as_ref().and_then(|stab| { + let mut result = item.stability.as_ref().and_then(|stab| { let reason = if show_reason && !stab.reason.is_empty() { format!(": {}", stab.reason) } else { @@ -1836,7 +1836,27 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio }; Some(format!("{}", item.stability_class(), text)) - }) + }); + + if result.is_none() { + result = item.deprecation.as_ref().and_then(|depr| { + let note = if show_reason && !depr.note.is_empty() { + format!(": {}", depr.note) + } else { + String::new() + }; + let since = if show_reason && !depr.since.is_empty() { + format!(" since {}", Escape(&depr.since)) + } else { + String::new() + }; + + let text = format!("Deprecated{}{}", since, Markdown(¬e)); + Some(format!("{}", text)) + }); + } + + result } struct Initializer<'a>(&'a str); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 89527c54a3851..d95a4553bf1f5 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -69,6 +69,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }) } + fn deprecation(&self, id: ast::NodeId) -> Option { + self.cx.tcx_opt().and_then(|tcx| { + self.cx.map.opt_local_def_id(id) + .and_then(|def_id| stability::lookup_deprecation(tcx, def_id)) + }) + } + pub fn visit(&mut self, krate: &hir::Crate) { self.attrs = krate.attrs.clone(); @@ -95,6 +102,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: name, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), attrs: item.attrs.clone(), generics: generics.clone(), fields: sd.fields().iter().cloned().collect(), @@ -112,11 +120,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: v.node.name, attrs: v.node.attrs.clone(), stab: self.stability(v.node.data.id()), + depr: self.deprecation(v.node.data.id()), def: v.node.data.clone(), whence: v.span, }).collect(), vis: it.vis, stab: self.stability(it.id), + depr: self.deprecation(it.id), generics: params.clone(), attrs: it.attrs.clone(), id: it.id, @@ -135,6 +145,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { id: item.id, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), attrs: item.attrs.clone(), decl: fd.clone(), name: name, @@ -156,6 +167,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.attrs = attrs; om.vis = vis; om.stab = self.stability(id); + om.depr = self.deprecation(id); om.id = id; for i in &m.item_ids { let item = self.cx.map.expect_item(i.id); @@ -314,6 +326,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), }; om.typedefs.push(t); }, @@ -328,6 +341,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), }; om.statics.push(s); }, @@ -341,6 +355,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), }; om.constants.push(s); }, @@ -356,6 +371,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), }; om.traits.push(t); }, @@ -372,6 +388,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + depr: self.deprecation(item.id), }; // Don't duplicate impls when inlining glob imports, we'll pick // them up regardless of where they're located. @@ -410,6 +427,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: def.span, matchers: matchers, stab: self.stability(def.id), + depr: self.deprecation(def.id), imported_from: def.imported_from, } } diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs new file mode 100644 index 0000000000000..744304a62c216 --- /dev/null +++ b/src/test/rustdoc/deprecated.rs @@ -0,0 +1,16 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(deprecated)] + +// @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \ +// 'Deprecated since 1.0.0: text' +#[deprecated(since = "1.0.0", note = "text")] +pub struct S;