Refactor rustdocs attribute handling
This commit is contained in:
parent
8f6e09a956
commit
2a28b69948
|
@ -26,7 +26,7 @@ use rustc::middle::const_eval;
|
||||||
|
|
||||||
use core::DocContext;
|
use core::DocContext;
|
||||||
use doctree;
|
use doctree;
|
||||||
use clean;
|
use clean::{self, Attributes};
|
||||||
|
|
||||||
use super::{Clean, ToSource};
|
use super::{Clean, ToSource};
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
|
||||||
cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
|
cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
|
||||||
cstore::DlDef(Def::Mod(did)) => {
|
cstore::DlDef(Def::Mod(did)) => {
|
||||||
// Don't recurse if this is a #[doc(hidden)] module
|
// Don't recurse if this is a #[doc(hidden)] module
|
||||||
if load_attrs(cx, tcx, did).iter().any(|a| is_doc_hidden(a)) {
|
if load_attrs(cx, tcx, did).list_def("doc").has_word("hidden") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
if let Some(ref t) = associated_trait {
|
if let Some(ref t) = associated_trait {
|
||||||
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
|
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
|
||||||
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
let trait_attrs = load_attrs(cx, tcx, t.def_id);
|
||||||
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
|
if trait_attrs.list_def("doc").has_word("hidden") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,20 +422,6 @@ pub fn build_impl(cx: &DocContext,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_doc_hidden(a: &clean::Attribute) -> bool {
|
|
||||||
match *a {
|
|
||||||
clean::List(ref name, ref inner) if *name == "doc" => {
|
|
||||||
inner.iter().any(|a| {
|
|
||||||
match *a {
|
|
||||||
clean::Word(ref s) => *s == "hidden",
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_module(cx: &DocContext, tcx: &TyCtxt,
|
fn build_module(cx: &DocContext, tcx: &TyCtxt,
|
||||||
did: DefId) -> clean::Module {
|
did: DefId) -> clean::Module {
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
|
@ -258,7 +258,7 @@ pub struct Item {
|
||||||
pub source: Span,
|
pub source: Span,
|
||||||
/// Not everything has a name. E.g., impls
|
/// Not everything has a name. E.g., impls
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub attrs: Vec<Attribute> ,
|
pub attrs: Vec<Attribute>,
|
||||||
pub inner: ItemEnum,
|
pub inner: ItemEnum,
|
||||||
pub visibility: Option<Visibility>,
|
pub visibility: Option<Visibility>,
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
|
@ -267,49 +267,10 @@ pub struct Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item {
|
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 {
|
|
||||||
match *attr {
|
|
||||||
List(ref x, ref list) if "doc" == *x => {
|
|
||||||
return Some(list);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||||
/// value found.
|
/// value found.
|
||||||
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
|
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
|
||||||
for attr in &self.attrs {
|
self.attrs.value("doc")
|
||||||
match *attr {
|
|
||||||
NameValue(ref x, ref v) if "doc" == *x => {
|
|
||||||
return Some(v);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_hidden_from_doc(&self) -> bool {
|
|
||||||
match self.doc_list() {
|
|
||||||
Some(l) => {
|
|
||||||
for innerattr in l {
|
|
||||||
match *innerattr {
|
|
||||||
Word(ref s) if "hidden" == *s => {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => ()
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mod(&self) -> bool {
|
pub fn is_mod(&self) -> bool {
|
||||||
|
@ -438,10 +399,54 @@ impl Clean<Item> for doctree::Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Attributes {
|
||||||
|
fn has_word(&self, &str) -> bool;
|
||||||
|
fn value<'a>(&'a self, &str) -> Option<&'a str>;
|
||||||
|
fn list_def<'a>(&'a self, &str) -> &'a [Attribute];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Attributes for [Attribute] {
|
||||||
|
/// Returns whether the attribute list contains a specific `Word`
|
||||||
|
fn has_word(&self, word: &str) -> bool {
|
||||||
|
for attr in self {
|
||||||
|
if let Word(ref w) = *attr {
|
||||||
|
if word == *w {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds an attribute as NameValue and returns the corresponding value found.
|
||||||
|
fn value<'a>(&'a self, name: &str) -> Option<&'a str> {
|
||||||
|
for attr in self {
|
||||||
|
if let NameValue(ref x, ref v) = *attr {
|
||||||
|
if name == *x {
|
||||||
|
return Some(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds an attribute as List and returns the list of attributes nested inside.
|
||||||
|
fn list_def<'a>(&'a self, name: &str) -> &'a [Attribute] {
|
||||||
|
for attr in self {
|
||||||
|
if let List(ref x, ref list) = *attr {
|
||||||
|
if name == *x {
|
||||||
|
return &list[..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||||
pub enum Attribute {
|
pub enum Attribute {
|
||||||
Word(String),
|
Word(String),
|
||||||
List(String, Vec<Attribute> ),
|
List(String, Vec<Attribute>),
|
||||||
NameValue(String, String)
|
NameValue(String, String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1513,24 +1518,16 @@ impl PrimitiveType {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
|
fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
|
||||||
for attr in attrs {
|
for attr in attrs.list_def("doc") {
|
||||||
let list = match *attr {
|
if let NameValue(ref k, ref v) = *attr {
|
||||||
List(ref k, ref l) if *k == "doc" => l,
|
if "primitive" == *k {
|
||||||
_ => continue,
|
if let ret@Some(..) = PrimitiveType::from_str(v) {
|
||||||
};
|
return ret;
|
||||||
for sub_attr in list {
|
|
||||||
let value = match *sub_attr {
|
|
||||||
NameValue(ref k, ref v)
|
|
||||||
if *k == "primitive" => v,
|
|
||||||
_ => continue,
|
|
||||||
};
|
|
||||||
match PrimitiveType::from_str(value) {
|
|
||||||
Some(p) => return Some(p),
|
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> &'static str {
|
pub fn to_string(&self) -> &'static str {
|
||||||
|
|
|
@ -62,7 +62,7 @@ use rustc::middle::stability;
|
||||||
use rustc::session::config::get_unstable_features_setting;
|
use rustc::session::config::get_unstable_features_setting;
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
|
||||||
use clean::{self, SelfTy};
|
use clean::{self, SelfTy, Attributes};
|
||||||
use doctree;
|
use doctree;
|
||||||
use fold::DocFolder;
|
use fold::DocFolder;
|
||||||
use html::escape::Escape;
|
use html::escape::Escape;
|
||||||
|
@ -432,8 +432,7 @@ pub fn run(mut krate: clean::Crate,
|
||||||
|
|
||||||
// Crawl the crate attributes looking for attributes which control how we're
|
// Crawl the crate attributes looking for attributes which control how we're
|
||||||
// going to emit HTML
|
// going to emit HTML
|
||||||
let default: &[_] = &[];
|
if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list_def("doc")) {
|
||||||
if let Some(attrs) = krate.module.as_ref().map(|m| m.doc_list().unwrap_or(default)) {
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
match *attr {
|
match *attr {
|
||||||
clean::NameValue(ref x, ref s)
|
clean::NameValue(ref x, ref s)
|
||||||
|
@ -833,28 +832,13 @@ fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
|
||||||
|
|
||||||
// Failing that, see if there's an attribute specifying where to find this
|
// Failing that, see if there's an attribute specifying where to find this
|
||||||
// external crate
|
// external crate
|
||||||
for attr in &e.attrs {
|
e.attrs.list_def("doc").value("html_root_url").map(|url| {
|
||||||
match *attr {
|
let mut url = url.to_owned();
|
||||||
clean::List(ref x, ref list) if "doc" == *x => {
|
if !url.ends_with("/") {
|
||||||
for attr in list {
|
url.push('/')
|
||||||
match *attr {
|
|
||||||
clean::NameValue(ref x, ref s)
|
|
||||||
if "html_root_url" == *x => {
|
|
||||||
if s.ends_with("/") {
|
|
||||||
return Remote(s.to_string());
|
|
||||||
}
|
}
|
||||||
return Remote(format!("{}/", s));
|
Remote(url)
|
||||||
}
|
}).unwrap_or(Unknown) // Well, at least we tried.
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Well, at least we tried.
|
|
||||||
return Unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocFolder for SourceCollector<'a> {
|
impl<'a> DocFolder for SourceCollector<'a> {
|
||||||
|
@ -1153,19 +1137,6 @@ impl DocFolder for Cache {
|
||||||
// implementations elsewhere
|
// implementations elsewhere
|
||||||
let ret = self.fold_item_recur(item).and_then(|item| {
|
let ret = self.fold_item_recur(item).and_then(|item| {
|
||||||
if let clean::Item { attrs, inner: clean::ImplItem(i), .. } = item {
|
if let clean::Item { attrs, inner: clean::ImplItem(i), .. } = item {
|
||||||
// extract relevant documentation for this impl
|
|
||||||
let dox = match attrs.into_iter().find(|a| {
|
|
||||||
match *a {
|
|
||||||
clean::NameValue(ref x, _)
|
|
||||||
if "doc" == *x => {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Some(clean::NameValue(_, dox)) => Some(dox),
|
|
||||||
Some(..) | None => None,
|
|
||||||
};
|
|
||||||
// Figure out the id of this impl. This may map to a
|
// Figure out the id of this impl. This may map to a
|
||||||
// primitive rather than always to a struct/enum.
|
// primitive rather than always to a struct/enum.
|
||||||
let did = match i.for_ {
|
let did = match i.for_ {
|
||||||
|
@ -1189,7 +1160,7 @@ impl DocFolder for Cache {
|
||||||
if let Some(did) = did {
|
if let Some(did) = did {
|
||||||
self.impls.entry(did).or_insert(vec![]).push(Impl {
|
self.impls.entry(did).or_insert(vec![]).push(Impl {
|
||||||
impl_: i,
|
impl_: i,
|
||||||
dox: dox,
|
dox: attrs.value("doc").map(|s|s.to_owned()),
|
||||||
stability: item.stability.clone(),
|
stability: item.stability.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,8 @@ pub mod visit_ast;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
mod flock;
|
mod flock;
|
||||||
|
|
||||||
|
use clean::Attributes;
|
||||||
|
|
||||||
type Pass = (&'static str, // name
|
type Pass = (&'static str, // name
|
||||||
fn(clean::Crate) -> plugins::PluginResult, // fn
|
fn(clean::Crate) -> plugins::PluginResult, // fn
|
||||||
&'static str); // description
|
&'static str); // description
|
||||||
|
@ -379,32 +381,25 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
|
||||||
|
|
||||||
// Process all of the crate attributes, extracting plugin metadata along
|
// Process all of the crate attributes, extracting plugin metadata along
|
||||||
// with the passes which we are supposed to run.
|
// with the passes which we are supposed to run.
|
||||||
match krate.module.as_ref().unwrap().doc_list() {
|
for attr in krate.module.as_ref().unwrap().attrs.list_def("doc") {
|
||||||
Some(nested) => {
|
match *attr {
|
||||||
for inner in nested {
|
clean::Word(ref w) if "no_default_passes" == *w => {
|
||||||
match *inner {
|
|
||||||
clean::Word(ref x)
|
|
||||||
if "no_default_passes" == *x => {
|
|
||||||
default_passes = false;
|
default_passes = false;
|
||||||
}
|
},
|
||||||
clean::NameValue(ref x, ref value)
|
clean::NameValue(ref name, ref value) => {
|
||||||
if "passes" == *x => {
|
let sink = match &name[..] {
|
||||||
for pass in value.split_whitespace() {
|
"passes" => &mut passes,
|
||||||
passes.push(pass.to_string());
|
"plugins" => &mut plugins,
|
||||||
}
|
_ => continue,
|
||||||
}
|
};
|
||||||
clean::NameValue(ref x, ref value)
|
|
||||||
if "plugins" == *x => {
|
|
||||||
for p in value.split_whitespace() {
|
for p in value.split_whitespace() {
|
||||||
plugins.push(p.to_string());
|
sink.push(p.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
if default_passes {
|
if default_passes {
|
||||||
for name in DEFAULT_PASSES.iter().rev() {
|
for name in DEFAULT_PASSES.iter().rev() {
|
||||||
passes.insert(0, name.to_string());
|
passes.insert(0, name.to_string());
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::string::String;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
|
||||||
use clean;
|
use clean::{self, Attributes};
|
||||||
use clean::Item;
|
use clean::Item;
|
||||||
use plugins;
|
use plugins;
|
||||||
use fold;
|
use fold;
|
||||||
|
@ -33,7 +33,7 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
|
||||||
}
|
}
|
||||||
impl<'a> fold::DocFolder for Stripper<'a> {
|
impl<'a> fold::DocFolder for Stripper<'a> {
|
||||||
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||||
if i.is_hidden_from_doc() {
|
if i.attrs.list_def("doc").has_word("hidden") {
|
||||||
debug!("found one in strip_hidden; removing");
|
debug!("found one in strip_hidden; removing");
|
||||||
self.stripped.insert(i.def_id);
|
self.stripped.insert(i.def_id);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue