Skip to content

Commit

Permalink
Rustdoc: remove ListAttributesIter and use impl Iterator instead
Browse files Browse the repository at this point in the history
  • Loading branch information
Kobzol committed Dec 28, 2021
1 parent e91ad5f commit 5470e2a
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 75 deletions.
8 changes: 4 additions & 4 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,15 +729,14 @@ fn clean_fn_or_proc_macro(
match macro_kind {
Some(kind) => {
if kind == MacroKind::Derive {
*name = attrs
.lists(sym::proc_macro_derive)
*name = attr_items(attrs, sym::proc_macro_derive)
.find_map(|mi| mi.ident())
.expect("proc-macro derives require a name")
.name;
}

let mut helpers = Vec::new();
for mi in attrs.lists(sym::proc_macro_derive) {
for mi in attr_items(attrs, sym::proc_macro_derive) {
if !mi.has_name(sym::attributes) {
continue;
}
Expand Down Expand Up @@ -1955,7 +1954,8 @@ fn clean_use_statement(

let visibility = cx.tcx.visibility(import.def_id);
let attrs = cx.tcx.hir().attrs(import.hir_id());
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
let inline_attr =
attr_items(attrs, sym::doc).find(|attr| attr.is_word() && attr.has_name(sym::inline));
let pub_underscore = visibility.is_public() && name == kw::Underscore;
let current_mod = cx.tcx.parent_module_from_def_id(import.def_id);

Expand Down
77 changes: 18 additions & 59 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::lazy::SyncOnceCell as OnceCell;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::{slice, vec};
use std::vec;

use arrayvec::ArrayVec;

Expand Down Expand Up @@ -215,8 +215,7 @@ impl ExternalCrate {
// Failing that, see if there's an attribute specifying where to find this
// external crate
let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
tcx.get_attrs(did)
.lists(sym::doc)
attr_items(tcx.get_attrs(did), sym::doc)
.filter(|a| a.has_name(sym::html_root_url))
.filter_map(|a| a.value_str())
.map(to_remote)
Expand All @@ -232,7 +231,7 @@ impl ExternalCrate {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = tcx.get_attrs(def_id);
let mut keyword = None;
for attr in attrs.lists(sym::doc) {
for attr in attr_items(attrs, sym::doc) {
if attr.has_name(sym::keyword) {
if let Some(v) = attr.value_str() {
keyword = Some(v);
Expand Down Expand Up @@ -294,7 +293,7 @@ impl ExternalCrate {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = tcx.get_attrs(def_id);
let mut prim = None;
for attr in attrs.lists(sym::doc) {
for attr in attr_items(attrs, sym::doc) {
if let Some(v) = attr.value_str() {
if attr.has_name(sym::primitive) {
prim = PrimitiveType::from_symbol(v);
Expand Down Expand Up @@ -725,44 +724,19 @@ crate struct Module {
crate span: Span,
}

crate struct ListAttributesIter<'a> {
attrs: slice::Iter<'a, ast::Attribute>,
current_list: vec::IntoIter<ast::NestedMetaItem>,
/// Finds attributes with the given name and returns their nested items.
crate fn attr_items(
attrs: &[ast::Attribute],
name: Symbol,
}

impl<'a> Iterator for ListAttributesIter<'a> {
type Item = ast::NestedMetaItem;

fn next(&mut self) -> Option<Self::Item> {
if let Some(nested) = self.current_list.next() {
return Some(nested);
}

for attr in &mut self.attrs {
if let Some(list) = attr.meta_item_list() {
if attr.has_name(self.name) {
self.current_list = list.into_iter();
if let Some(nested) = self.current_list.next() {
return Some(nested);
}
}
}
}

None
}

fn size_hint(&self) -> (usize, Option<usize>) {
let lower = self.current_list.len();
(lower, None)
}
) -> impl Iterator<Item = ast::NestedMetaItem> + '_ {
attrs
.iter()
.filter(move |attr| attr.has_name(name))
.filter_map(ast::Attribute::meta_item_list)
.flatten()
}

crate trait AttributesExt {
/// Finds an attribute as List and returns the list of attributes nested inside.
fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;

fn span(&self) -> Option<rustc_span::Span>;

fn inner_docs(&self) -> bool;
Expand All @@ -773,10 +747,6 @@ crate trait AttributesExt {
}

impl AttributesExt for [ast::Attribute] {
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
}

/// Return the span of the first doc-comment, if it exists.
fn span(&self) -> Option<rustc_span::Span> {
self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
Expand Down Expand Up @@ -860,7 +830,7 @@ impl AttributesExt for [ast::Attribute] {

// treat #[target_feature(enable = "feat")] attributes as if they were
// #[doc(cfg(target_feature = "feat"))] attributes as well
for attr in self.lists(sym::target_feature) {
for attr in attr_items(self, sym::target_feature) {
if attr.has_name(sym::enable) {
if let Some(feat) = attr.value_str() {
let meta = attr::mk_name_value_item_str(
Expand All @@ -882,18 +852,11 @@ impl AttributesExt for [ast::Attribute] {
crate trait NestedAttributesExt {
/// Returns `true` if the attribute list contains a specific `Word`
fn has_word(self, word: Symbol) -> bool;
fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
}

impl<I: Iterator<Item = ast::NestedMetaItem> + IntoIterator<Item = ast::NestedMetaItem>>
NestedAttributesExt for I
{
fn has_word(self, word: Symbol) -> bool {
self.into_iter().any(|attr| attr.is_word() && attr.has_name(word))
}

fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
self.find(|attr| attr.is_word() && attr.has_name(word))
impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
fn has_word(mut self, word: Symbol) -> bool {
self.any(|attr| attr.is_word() && attr.has_name(word))
}
}

Expand Down Expand Up @@ -1001,10 +964,6 @@ crate struct Attributes {
}

impl Attributes {
crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
self.other_attrs.lists(name)
}

crate fn has_doc_flag(&self, flag: Symbol) -> bool {
for attr in &self.other_attrs {
if !attr.has_name(sym::doc) {
Expand Down Expand Up @@ -1110,7 +1069,7 @@ impl Attributes {
crate fn get_doc_aliases(&self) -> Box<[Symbol]> {
let mut aliases = FxHashSet::default();

for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
for attr in attr_items(&self.other_attrs, sym::doc).filter(|a| a.has_name(sym::alias)) {
if let Some(values) = attr.meta_item_list() {
for l in values {
match l.literal().unwrap().kind {
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::mem;
use std::rc::Rc;

use crate::clean::inline::build_external_trait;
use crate::clean::{self, ItemId, TraitWithExtraInfo};
use crate::clean::{self, attr_items, ItemId, TraitWithExtraInfo};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
use crate::passes::{self, Condition::*};
Expand Down Expand Up @@ -435,7 +435,7 @@ crate fn run_global_ctxt(

// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.attrs.lists(sym::doc) {
for attr in attr_items(&krate.module.attrs.other_attrs, sym::doc) {
let diag = ctxt.sess().diagnostic();

let name = attr.name_or_empty();
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::{
BASIC_KEYWORDS,
};

use crate::clean::{self, ExternalCrate};
use crate::clean::{self, attr_items, ExternalCrate};
use crate::config::RenderOptions;
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
Expand Down Expand Up @@ -430,7 +430,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {

// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
for attr in krate.module.attrs.lists(sym::doc) {
for attr in attr_items(&krate.module.attrs.other_attrs, sym::doc) {
match (attr.name_or_empty(), attr.value_str()) {
(sym::html_favicon_url, Some(s)) => {
layout.favicon = s.to_string();
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/passes/check_doc_test_visibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
}
}

if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
if attr_items(&cx.tcx.hir().attrs(hir_id), sym::doc).has_word(sym::hidden)
|| inherits_doc_hidden(cx.tcx, hir_id)
|| cx.tcx.hir().span(hir_id).in_derive_expansion()
{
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/passes/strip_hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_span::symbol::sym;
use std::mem;

use crate::clean;
use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
use crate::clean::{attr_items, Item, ItemIdSet, NestedAttributesExt};
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
Expand Down Expand Up @@ -36,7 +36,7 @@ struct Stripper<'a> {

impl<'a> DocFolder for Stripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
if i.attrs.lists(sym::doc).has_word(sym::hidden) {
if attr_items(&i.attrs.other_attrs, sym::doc).has_word(sym::hidden) {
debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
// use a dedicated hidden item for given item type if any
match *i.kind {
Expand Down
11 changes: 6 additions & 5 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_span::Span;

use std::mem;

use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt};
use crate::clean::{self, attr_items, cfg::Cfg, NestedAttributesExt};
use crate::core;

/// This module is used to store stuff from Rust's AST in a more convenient
Expand Down Expand Up @@ -55,7 +55,7 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
crate fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool {
while let Some(id) = tcx.hir().get_enclosing_scope(node) {
node = id;
if tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
if attr_items(tcx.hir().attrs(node), sym::doc).has_word(sym::hidden) {
return true;
}
}
Expand Down Expand Up @@ -199,16 +199,17 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {

let use_attrs = tcx.hir().attrs(id);
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
|| use_attrs.lists(sym::doc).has_word(sym::hidden);
let is_no_inline = attr_items(&use_attrs, sym::doc).any(|attr| {
attr.is_word() && (attr.has_name(sym::no_inline) || attr.has_name(sym::hidden))
});

// For cross-crate impl inlining we need to know whether items are
// reachable in documentation -- a previously unreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront).
if !res_did.is_local() && !is_no_inline {
let attrs = clean::inline::load_attrs(self.cx, res_did);
let self_is_hidden = attrs.lists(sym::doc).has_word(sym::hidden);
let self_is_hidden = attr_items(attrs, sym::doc).has_word(sym::hidden);
if !self_is_hidden {
if let Res::Def(kind, did) = res {
if kind == DefKind::Mod {
Expand Down

0 comments on commit 5470e2a

Please sign in to comment.