syntax: Do not accidentally treat multi-segment meta-items as single-segment

This commit is contained in:
Vadim Petrochenkov 2019-02-28 09:17:24 +03:00
parent e2009ea5ff
commit 8371caf5ee
29 changed files with 236 additions and 213 deletions

View file

@ -58,7 +58,13 @@ impl Cfg {
/// If the content is not properly formatted, it will return an error indicating what and where
/// the error is.
pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
let name = cfg.name();
let name = match cfg.ident() {
Some(ident) => ident.name,
None => return Err(InvalidCfgError {
msg: "expected a single identifier",
span: cfg.span
}),
};
match cfg.node {
MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
MetaItemKind::NameValue(ref lit) => match lit.node {

View file

@ -492,7 +492,7 @@ impl Item {
pub fn is_non_exhaustive(&self) -> bool {
self.attrs.other_attrs.iter()
.any(|a| a.name().as_str() == "non_exhaustive")
.any(|a| a.check_name("non_exhaustive"))
}
/// Returns a documentation-level item type from the item.
@ -3683,7 +3683,7 @@ impl Clean<Vec<Item>> for doctree::ExternCrate {
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
a.name() == "doc" && match a.meta_item_list() {
a.check_name("doc") && match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, "inline"),
None => false,
}
@ -3722,7 +3722,7 @@ impl Clean<Vec<Item>> for doctree::Import {
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
a.name() == "doc" && match a.meta_item_list() {
a.check_name("doc") && match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, "no_inline") ||
attr::list_contains_name(&l, "hidden"),
None => false,

View file

@ -521,8 +521,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
let diag = ctxt.sess().diagnostic();
let name = attr.name().map(|s| s.as_str());
let name = name.as_ref().map(|s| &s[..]);
let name = attr.ident_str();
if attr.is_word() {
if name == Some("no_default_passes") {
report_deprecated_attr("no_default_passes", diag);

View file

@ -562,8 +562,7 @@ pub fn run(mut krate: clean::Crate,
// going to emit HTML
if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
for attr in attrs.lists("doc") {
let name = attr.name().map(|s| s.as_str());
match (name.as_ref().map(|s| &s[..]), attr.value_str()) {
match (attr.ident_str(), attr.value_str()) {
(Some("html_favicon_url"), Some(s)) => {
scx.layout.favicon = s.to_string();
}
@ -3714,19 +3713,19 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
}
fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
let name = attr.name();
let path = attr.ident.to_string();
if attr.is_word() {
Some(name.to_string())
Some(path)
} else if let Some(v) = attr.value_str() {
Some(format!("{} = {:?}", name, v.as_str()))
Some(format!("{} = {:?}", path, v.as_str()))
} else if let Some(values) = attr.meta_item_list() {
let display: Vec<_> = values.iter().filter_map(|attr| {
attr.meta_item().and_then(|mi| render_attribute(mi))
}).collect();
if display.len() > 0 {
Some(format!("{}({})", name, display.join(", ")))
Some(format!("{}({})", path, display.join(", ")))
} else {
None
}
@ -3750,8 +3749,7 @@ fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Resul
let mut attrs = String::new();
for attr in &it.attrs.other_attrs {
let name = attr.name();
if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
continue;
}
if let Some(s) = render_attribute(&attr.meta().unwrap()) {

View file

@ -178,9 +178,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
Some(kind) => {
let name = if kind == MacroKind::Derive {
item.attrs.lists("proc_macro_derive")
.filter_map(|mi| mi.name())
.filter_map(|mi| mi.ident())
.next()
.expect("proc-macro derives require a name")
.name
} else {
name
};
@ -193,8 +194,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
if let Some(list) = mi.meta_item_list() {
for inner_mi in list {
if let Some(name) = inner_mi.name() {
helpers.push(name);
if let Some(ident) = inner_mi.ident() {
helpers.push(ident.name);
}
}
}