Skip to content

Commit 2a28b69

Browse files
committed
Refactor rustdocs attribute handling
1 parent 8f6e09a commit 2a28b69

File tree

5 files changed

+85
-136
lines changed

5 files changed

+85
-136
lines changed

src/librustdoc/clean/inline.rs

+3-17
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc::middle::const_eval;
2626

2727
use core::DocContext;
2828
use doctree;
29-
use clean;
29+
use clean::{self, Attributes};
3030

3131
use super::{Clean, ToSource};
3232

@@ -253,7 +253,7 @@ pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
253253
cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
254254
cstore::DlDef(Def::Mod(did)) => {
255255
// Don't recurse if this is a #[doc(hidden)] module
256-
if load_attrs(cx, tcx, did).iter().any(|a| is_doc_hidden(a)) {
256+
if load_attrs(cx, tcx, did).list_def("doc").has_word("hidden") {
257257
return;
258258
}
259259

@@ -282,7 +282,7 @@ pub fn build_impl(cx: &DocContext,
282282
if let Some(ref t) = associated_trait {
283283
// If this is an impl for a #[doc(hidden)] trait, be sure to not inline
284284
let trait_attrs = load_attrs(cx, tcx, t.def_id);
285-
if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
285+
if trait_attrs.list_def("doc").has_word("hidden") {
286286
return
287287
}
288288
}
@@ -422,20 +422,6 @@ pub fn build_impl(cx: &DocContext,
422422
});
423423
}
424424

425-
fn is_doc_hidden(a: &clean::Attribute) -> bool {
426-
match *a {
427-
clean::List(ref name, ref inner) if *name == "doc" => {
428-
inner.iter().any(|a| {
429-
match *a {
430-
clean::Word(ref s) => *s == "hidden",
431-
_ => false,
432-
}
433-
})
434-
}
435-
_ => false
436-
}
437-
}
438-
439425
fn build_module(cx: &DocContext, tcx: &TyCtxt,
440426
did: DefId) -> clean::Module {
441427
let mut items = Vec::new();

src/librustdoc/clean/mod.rs

+54-57
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ pub struct Item {
258258
pub source: Span,
259259
/// Not everything has a name. E.g., impls
260260
pub name: Option<String>,
261-
pub attrs: Vec<Attribute> ,
261+
pub attrs: Vec<Attribute>,
262262
pub inner: ItemEnum,
263263
pub visibility: Option<Visibility>,
264264
pub def_id: DefId,
@@ -267,49 +267,10 @@ pub struct Item {
267267
}
268268

269269
impl Item {
270-
/// Finds the `doc` attribute as a List and returns the list of attributes
271-
/// nested inside.
272-
pub fn doc_list<'a>(&'a self) -> Option<&'a [Attribute]> {
273-
for attr in &self.attrs {
274-
match *attr {
275-
List(ref x, ref list) if "doc" == *x => {
276-
return Some(list);
277-
}
278-
_ => {}
279-
}
280-
}
281-
return None;
282-
}
283-
284270
/// Finds the `doc` attribute as a NameValue and returns the corresponding
285271
/// value found.
286272
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
287-
for attr in &self.attrs {
288-
match *attr {
289-
NameValue(ref x, ref v) if "doc" == *x => {
290-
return Some(v);
291-
}
292-
_ => {}
293-
}
294-
}
295-
return None;
296-
}
297-
298-
pub fn is_hidden_from_doc(&self) -> bool {
299-
match self.doc_list() {
300-
Some(l) => {
301-
for innerattr in l {
302-
match *innerattr {
303-
Word(ref s) if "hidden" == *s => {
304-
return true
305-
}
306-
_ => (),
307-
}
308-
}
309-
},
310-
None => ()
311-
}
312-
return false;
273+
self.attrs.value("doc")
313274
}
314275

315276
pub fn is_mod(&self) -> bool {
@@ -438,10 +399,54 @@ impl Clean<Item> for doctree::Module {
438399
}
439400
}
440401

402+
pub trait Attributes {
403+
fn has_word(&self, &str) -> bool;
404+
fn value<'a>(&'a self, &str) -> Option<&'a str>;
405+
fn list_def<'a>(&'a self, &str) -> &'a [Attribute];
406+
}
407+
408+
impl Attributes for [Attribute] {
409+
/// Returns whether the attribute list contains a specific `Word`
410+
fn has_word(&self, word: &str) -> bool {
411+
for attr in self {
412+
if let Word(ref w) = *attr {
413+
if word == *w {
414+
return true;
415+
}
416+
}
417+
}
418+
false
419+
}
420+
421+
/// Finds an attribute as NameValue and returns the corresponding value found.
422+
fn value<'a>(&'a self, name: &str) -> Option<&'a str> {
423+
for attr in self {
424+
if let NameValue(ref x, ref v) = *attr {
425+
if name == *x {
426+
return Some(v);
427+
}
428+
}
429+
}
430+
None
431+
}
432+
433+
/// Finds an attribute as List and returns the list of attributes nested inside.
434+
fn list_def<'a>(&'a self, name: &str) -> &'a [Attribute] {
435+
for attr in self {
436+
if let List(ref x, ref list) = *attr {
437+
if name == *x {
438+
return &list[..];
439+
}
440+
}
441+
}
442+
&[]
443+
}
444+
}
445+
441446
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
442447
pub enum Attribute {
443448
Word(String),
444-
List(String, Vec<Attribute> ),
449+
List(String, Vec<Attribute>),
445450
NameValue(String, String)
446451
}
447452

@@ -1513,24 +1518,16 @@ impl PrimitiveType {
15131518
}
15141519

15151520
fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
1516-
for attr in attrs {
1517-
let list = match *attr {
1518-
List(ref k, ref l) if *k == "doc" => l,
1519-
_ => continue,
1520-
};
1521-
for sub_attr in list {
1522-
let value = match *sub_attr {
1523-
NameValue(ref k, ref v)
1524-
if *k == "primitive" => v,
1525-
_ => continue,
1526-
};
1527-
match PrimitiveType::from_str(value) {
1528-
Some(p) => return Some(p),
1529-
None => {}
1521+
for attr in attrs.list_def("doc") {
1522+
if let NameValue(ref k, ref v) = *attr {
1523+
if "primitive" == *k {
1524+
if let ret@Some(..) = PrimitiveType::from_str(v) {
1525+
return ret;
1526+
}
15301527
}
15311528
}
15321529
}
1533-
return None
1530+
None
15341531
}
15351532

15361533
pub fn to_string(&self) -> &'static str {

src/librustdoc/html/render.rs

+9-38
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use rustc::middle::stability;
6262
use rustc::session::config::get_unstable_features_setting;
6363
use rustc_front::hir;
6464

65-
use clean::{self, SelfTy};
65+
use clean::{self, SelfTy, Attributes};
6666
use doctree;
6767
use fold::DocFolder;
6868
use html::escape::Escape;
@@ -432,8 +432,7 @@ pub fn run(mut krate: clean::Crate,
432432

433433
// Crawl the crate attributes looking for attributes which control how we're
434434
// going to emit HTML
435-
let default: &[_] = &[];
436-
if let Some(attrs) = krate.module.as_ref().map(|m| m.doc_list().unwrap_or(default)) {
435+
if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list_def("doc")) {
437436
for attr in attrs {
438437
match *attr {
439438
clean::NameValue(ref x, ref s)
@@ -833,28 +832,13 @@ fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
833832

834833
// Failing that, see if there's an attribute specifying where to find this
835834
// external crate
836-
for attr in &e.attrs {
837-
match *attr {
838-
clean::List(ref x, ref list) if "doc" == *x => {
839-
for attr in list {
840-
match *attr {
841-
clean::NameValue(ref x, ref s)
842-
if "html_root_url" == *x => {
843-
if s.ends_with("/") {
844-
return Remote(s.to_string());
845-
}
846-
return Remote(format!("{}/", s));
847-
}
848-
_ => {}
849-
}
850-
}
851-
}
852-
_ => {}
835+
e.attrs.list_def("doc").value("html_root_url").map(|url| {
836+
let mut url = url.to_owned();
837+
if !url.ends_with("/") {
838+
url.push('/')
853839
}
854-
}
855-
856-
// Well, at least we tried.
857-
return Unknown;
840+
Remote(url)
841+
}).unwrap_or(Unknown) // Well, at least we tried.
858842
}
859843

860844
impl<'a> DocFolder for SourceCollector<'a> {
@@ -1153,19 +1137,6 @@ impl DocFolder for Cache {
11531137
// implementations elsewhere
11541138
let ret = self.fold_item_recur(item).and_then(|item| {
11551139
if let clean::Item { attrs, inner: clean::ImplItem(i), .. } = item {
1156-
// extract relevant documentation for this impl
1157-
let dox = match attrs.into_iter().find(|a| {
1158-
match *a {
1159-
clean::NameValue(ref x, _)
1160-
if "doc" == *x => {
1161-
true
1162-
}
1163-
_ => false
1164-
}
1165-
}) {
1166-
Some(clean::NameValue(_, dox)) => Some(dox),
1167-
Some(..) | None => None,
1168-
};
11691140
// Figure out the id of this impl. This may map to a
11701141
// primitive rather than always to a struct/enum.
11711142
let did = match i.for_ {
@@ -1189,7 +1160,7 @@ impl DocFolder for Cache {
11891160
if let Some(did) = did {
11901161
self.impls.entry(did).or_insert(vec![]).push(Impl {
11911162
impl_: i,
1192-
dox: dox,
1163+
dox: attrs.value("doc").map(|s|s.to_owned()),
11931164
stability: item.stability.clone(),
11941165
});
11951166
}

src/librustdoc/lib.rs

+17-22
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ pub mod visit_ast;
9494
pub mod test;
9595
mod flock;
9696

97+
use clean::Attributes;
98+
9799
type Pass = (&'static str, // name
98100
fn(clean::Crate) -> plugins::PluginResult, // fn
99101
&'static str); // description
@@ -379,32 +381,25 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
379381

380382
// Process all of the crate attributes, extracting plugin metadata along
381383
// with the passes which we are supposed to run.
382-
match krate.module.as_ref().unwrap().doc_list() {
383-
Some(nested) => {
384-
for inner in nested {
385-
match *inner {
386-
clean::Word(ref x)
387-
if "no_default_passes" == *x => {
388-
default_passes = false;
389-
}
390-
clean::NameValue(ref x, ref value)
391-
if "passes" == *x => {
392-
for pass in value.split_whitespace() {
393-
passes.push(pass.to_string());
394-
}
395-
}
396-
clean::NameValue(ref x, ref value)
397-
if "plugins" == *x => {
398-
for p in value.split_whitespace() {
399-
plugins.push(p.to_string());
400-
}
401-
}
402-
_ => {}
384+
for attr in krate.module.as_ref().unwrap().attrs.list_def("doc") {
385+
match *attr {
386+
clean::Word(ref w) if "no_default_passes" == *w => {
387+
default_passes = false;
388+
},
389+
clean::NameValue(ref name, ref value) => {
390+
let sink = match &name[..] {
391+
"passes" => &mut passes,
392+
"plugins" => &mut plugins,
393+
_ => continue,
394+
};
395+
for p in value.split_whitespace() {
396+
sink.push(p.to_string());
403397
}
404398
}
399+
_ => (),
405400
}
406-
None => {}
407401
}
402+
408403
if default_passes {
409404
for name in DEFAULT_PASSES.iter().rev() {
410405
passes.insert(0, name.to_string());

src/librustdoc/passes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::string::String;
1616
use std::usize;
1717
use rustc_front::hir;
1818

19-
use clean;
19+
use clean::{self, Attributes};
2020
use clean::Item;
2121
use plugins;
2222
use fold;
@@ -33,7 +33,7 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
3333
}
3434
impl<'a> fold::DocFolder for Stripper<'a> {
3535
fn fold_item(&mut self, i: Item) -> Option<Item> {
36-
if i.is_hidden_from_doc() {
36+
if i.attrs.list_def("doc").has_word("hidden") {
3737
debug!("found one in strip_hidden; removing");
3838
self.stripped.insert(i.def_id);
3939

0 commit comments

Comments
 (0)