General MetaItem encapsulation rewrites.

This commit is contained in:
cgswords 2016-07-15 13:13:17 -07:00
parent 9316ae515e
commit a5e5ea1646
14 changed files with 231 additions and 170 deletions

View file

@ -366,18 +366,18 @@ pub fn gather_attr(attr: &ast::Attribute)
attr::mark_used(attr); attr::mark_used(attr);
let meta = &attr.node.value; let meta = &attr.node.value;
let metas = match meta.node { let metas = if let Some(metas) = meta.meta_item_list() {
ast::MetaItemKind::List(_, ref metas) => metas, metas
_ => { } else {
out.push(Err(meta.span)); out.push(Err(meta.span));
return out; return out;
}
}; };
for meta in metas { for meta in metas {
out.push(match meta.node { out.push(if meta.is_word() {
ast::MetaItemKind::Word(ref lint_name) => Ok((lint_name.clone(), level, meta.span)), Ok((meta.name().clone(), level, meta.span))
_ => Err(meta.span), } else {
Err(meta.span)
}); });
} }

View file

@ -95,6 +95,7 @@ use std::thread;
use rustc::session::early_error; use rustc::session::early_error;
use syntax::{ast, json}; use syntax::{ast, json};
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader}; use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::feature_gate::{GatedCfg, UnstableFeatures};
use syntax::parse::{self, PResult}; use syntax::parse::{self, PResult};
@ -392,16 +393,14 @@ fn check_cfg(sopts: &config::Options,
let mut saw_invalid_predicate = false; let mut saw_invalid_predicate = false;
for item in sopts.cfg.iter() { for item in sopts.cfg.iter() {
match item.node { if item.is_meta_item_list() {
ast::MetaItemKind::List(ref pred, _) => { saw_invalid_predicate = true;
saw_invalid_predicate = true; saw_invalid_predicate = true;
handler.emit(&MultiSpan::new(), handler.emit(&MultiSpan::new(),
&format!("invalid predicate in --cfg command line argument: `{}`", &format!("invalid predicate in --cfg command line argument: `{}`",
pred), pred),
errors::Level::Fatal); errors::Level::Fatal);
} }
_ => {},
}
} }
if saw_invalid_predicate { if saw_invalid_predicate {
@ -649,25 +648,24 @@ impl RustcDefaultCalls {
if !allow_unstable_cfg && GatedCfg::gate(&*cfg).is_some() { if !allow_unstable_cfg && GatedCfg::gate(&*cfg).is_some() {
continue; continue;
} }
match cfg.node { if cfg.is_word() {
ast::MetaItemKind::Word(ref word) => println!("{}", word), println!("{}", cfg.name());
ast::MetaItemKind::NameValue(ref name, ref value) => { } else if cfg.is_value_str() {
println!("{}=\"{}\"", name, match value.node { let rhs = cfg.value_str();
ast::LitKind::Str(ref s, _) => s, match rhs {
_ => continue, Some(s) => println!("{}=\"{}\"", cfg.name(), s),
}); None => continue,
} }
} else if cfg.is_meta_item_list() {
// Right now there are not and should not be any // Right now there are not and should not be any
// MetaItemKind::List items in the configuration returned by // MetaItemKind::List items in the configuration returned by
// `build_configuration`. // `build_configuration`.
ast::MetaItemKind::List(..) => {
panic!("MetaItemKind::List encountered in default cfg") panic!("MetaItemKind::List encountered in default cfg")
} }
} }
} }
} }
} }
}
return Compilation::Stop; return Compilation::Stop;
} }
} }

View file

@ -110,15 +110,15 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
if attr.check_name(IF_THIS_CHANGED) { if attr.check_name(IF_THIS_CHANGED) {
let mut id = None; let mut id = None;
for meta_item in attr.meta_item_list().unwrap_or_default() { for meta_item in attr.meta_item_list().unwrap_or_default() {
match meta_item.node { if meta_item.is_word() && id.is_none() {
ast::MetaItemKind::Word(ref s) if id.is_none() => id = Some(s.clone()), id = Some(meta_item.name().clone());
_ => { } else {
// FIXME better-encapsulate meta_item (don't directly access `node`)
self.tcx.sess.span_err( self.tcx.sess.span_err(
meta_item.span, meta_item.span(),
&format!("unexpected meta-item {:?}", meta_item.node)); &format!("unexpected meta-item {:?}", meta_item.node));
} }
} }
}
let id = id.unwrap_or(InternedString::new(ID)); let id = id.unwrap_or(InternedString::new(ID));
self.if_this_changed.entry(id) self.if_this_changed.entry(id)
.or_insert(FnvHashSet()) .or_insert(FnvHashSet())
@ -127,18 +127,17 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
let mut dep_node_interned = None; let mut dep_node_interned = None;
let mut id = None; let mut id = None;
for meta_item in attr.meta_item_list().unwrap_or_default() { for meta_item in attr.meta_item_list().unwrap_or_default() {
match meta_item.node { if meta_item.is_word() && dep_node_interned.is_none() {
ast::MetaItemKind::Word(ref s) if dep_node_interned.is_none() => dep_node_interned = Some(meta_item.name().clone());
dep_node_interned = Some(s.clone()), } else if meta_item.is_word() && id.is_none() {
ast::MetaItemKind::Word(ref s) if id.is_none() => id = Some(meta_item.name().clone());
id = Some(s.clone()), } else {
_ => { // FIXME better-encapsulate meta_item (don't directly access `node`)
self.tcx.sess.span_err( self.tcx.sess.span_err(
meta_item.span, meta_item.span(),
&format!("unexpected meta-item {:?}", meta_item.node)); &format!("unexpected meta-item {:?}", meta_item.node));
} }
} }
}
let dep_node = match dep_node_interned { let dep_node = match dep_node_interned {
Some(ref n) => { Some(ref n) => {
match DepNode::from_label_string(&n[..], def_id) { match DepNode::from_label_string(&n[..], def_id) {

View file

@ -11,6 +11,7 @@
//! Calculation of a Strict Version Hash for crates. For a length //! Calculation of a Strict Version Hash for crates. For a length
//! comment explaining the general idea, see `librustc/middle/svh.rs`. //! comment explaining the general idea, see `librustc/middle/svh.rs`.
use syntax::attr::AttributeMethods;
use std::hash::{Hash, SipHasher, Hasher}; use std::hash::{Hash, SipHasher, Hasher};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::svh::Svh; use rustc::hir::svh::Svh;
@ -69,7 +70,7 @@ impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
// to avoid hashing the AttrId // to avoid hashing the AttrId
for attr in &krate.attrs { for attr in &krate.attrs {
debug!("krate attr {:?}", attr); debug!("krate attr {:?}", attr);
attr.node.value.hash(&mut state); attr.meta().hash(&mut state);
} }
Svh::new(state.finish()) Svh::new(state.finish())

View file

@ -44,7 +44,7 @@ use lint::{LintPass, LateLintPass};
use std::collections::HashSet; use std::collections::HashSet;
use syntax::{ast}; use syntax::{ast};
use syntax::attr::{self, AttrMetaMethods}; use syntax::attr::{self, AttrMetaMethods, AttributeMethods};
use syntax_pos::{self, Span}; use syntax_pos::{self, Span};
use rustc::hir::{self, PatKind}; use rustc::hir::{self, PatKind};
@ -299,9 +299,10 @@ impl MissingDoc {
} }
let has_doc = attrs.iter().any(|a| { let has_doc = attrs.iter().any(|a| {
match a.node.value.node { if a.is_value_str() && a.name() == "doc" {
ast::MetaItemKind::NameValue(ref name, _) if *name == "doc" => true, true
_ => false } else {
false
} }
}); });
if !has_doc { if !has_doc {
@ -1094,10 +1095,10 @@ impl LintPass for UnstableFeatures {
impl LateLintPass for UnstableFeatures { impl LateLintPass for UnstableFeatures {
fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) { fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
if attr::contains_name(&[attr.node.value.clone()], "feature") { if attr::contains_name(&[attr.meta().clone()], "feature") {
if let Some(items) = attr.node.value.meta_item_list() { if let Some(items) = attr.meta().meta_item_list() {
for item in items { for item in items {
ctx.span_lint(UNSTABLE_FEATURES, item.span, "unstable feature"); ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
} }
} }
} }

View file

@ -1160,15 +1160,7 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
// an attribute // an attribute
assert_eq!(meta_items.len(), 1); assert_eq!(meta_items.len(), 1);
let meta_item = meta_items.into_iter().nth(0).unwrap(); let meta_item = meta_items.into_iter().nth(0).unwrap();
codemap::Spanned { attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
node: ast::Attribute_ {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
value: meta_item,
is_sugared_doc: is_sugared_doc,
},
span: syntax_pos::DUMMY_SP
}
}).collect() }).collect()
}, },
None => vec![], None => vec![],

View file

@ -44,7 +44,7 @@ use std::rc::Rc;
use std::u32; use std::u32;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum}; use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
use syntax::attr; use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
use errors::Handler; use errors::Handler;
use syntax; use syntax;
use syntax_pos::BytePos; use syntax_pos::BytePos;
@ -1431,40 +1431,37 @@ fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
} }
fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
match mi.node { if mi.is_word() {
ast::MetaItemKind::Word(ref name) => { let name = mi.name();
rbml_w.start_tag(tag_meta_item_word); rbml_w.start_tag(tag_meta_item_word);
rbml_w.wr_tagged_str(tag_meta_item_name, name); rbml_w.wr_tagged_str(tag_meta_item_name, &name);
rbml_w.end_tag(); rbml_w.end_tag();
} } else if mi.is_value_str() {
ast::MetaItemKind::NameValue(ref name, ref value) => { let name = mi.name();
match value.node { /* FIXME (#623): support other literal kinds */
ast::LitKind::Str(ref value, _) => { let value = mi.value_str().unwrap();
rbml_w.start_tag(tag_meta_item_name_value); rbml_w.start_tag(tag_meta_item_name_value);
rbml_w.wr_tagged_str(tag_meta_item_name, name); rbml_w.wr_tagged_str(tag_meta_item_name, &name);
rbml_w.wr_tagged_str(tag_meta_item_value, value); rbml_w.wr_tagged_str(tag_meta_item_value, &value);
rbml_w.end_tag(); rbml_w.end_tag();
} } else { // it must be a list
_ => {/* FIXME (#623): encode other variants */ } let name = mi.name();
} let items = mi.meta_item_list().unwrap();
}
ast::MetaItemKind::List(ref name, ref items) => {
rbml_w.start_tag(tag_meta_item_list); rbml_w.start_tag(tag_meta_item_list);
rbml_w.wr_tagged_str(tag_meta_item_name, name); rbml_w.wr_tagged_str(tag_meta_item_name, &name);
for inner_item in items { for inner_item in items {
encode_meta_item(rbml_w, &inner_item); encode_meta_item(rbml_w, &inner_item);
} }
rbml_w.end_tag(); rbml_w.end_tag();
} }
} }
}
fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) { fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
rbml_w.start_tag(tag_attributes); rbml_w.start_tag(tag_attributes);
for attr in attrs { for attr in attrs {
rbml_w.start_tag(tag_attribute); rbml_w.start_tag(tag_attribute);
rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8); rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
encode_meta_item(rbml_w, &attr.node.value); encode_meta_item(rbml_w, attr.meta());
rbml_w.end_tag(); rbml_w.end_tag();
} }
rbml_w.end_tag(); rbml_w.end_tag();

View file

@ -60,10 +60,10 @@ impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
} }
if let (Some(sel), Some(names)) = (import.as_mut(), names) { if let (Some(sel), Some(names)) = (import.as_mut(), names) {
for attr in names { for attr in names {
if let ast::MetaItemKind::Word(ref name) = attr.node { if attr.is_word() {
sel.insert(name.clone(), attr.span); sel.insert(attr.name().clone(), attr.span());
} else { } else {
span_err!(self.sess, attr.span, E0466, "bad macro import"); span_err!(self.sess, attr.span(), E0466, "bad macro import");
} }
} }
} }
@ -78,10 +78,10 @@ impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
}; };
for attr in names { for attr in names {
if let ast::MetaItemKind::Word(ref name) = attr.node { if attr.is_word() {
reexport.insert(name.clone(), attr.span); reexport.insert(attr.name().clone(), attr.span());
} else { } else {
call_bad_macro_reexport(self.sess, attr.span); call_bad_macro_reexport(self.sess, attr.span());
} }
} }
} }

View file

@ -498,21 +498,20 @@ pub enum Attribute {
impl Clean<Attribute> for ast::MetaItem { impl Clean<Attribute> for ast::MetaItem {
fn clean(&self, cx: &DocContext) -> Attribute { fn clean(&self, cx: &DocContext) -> Attribute {
match self.node { if self.is_word() {
ast::MetaItemKind::Word(ref s) => Word(s.to_string()), Word(self.name().to_string())
ast::MetaItemKind::List(ref s, ref l) => { } else if let Some(v) = self.value_str() {
List(s.to_string(), l.clean(cx)) NameValue(self.name().to_string(), v.to_string())
} } else { // must be a list
ast::MetaItemKind::NameValue(ref s, ref v) => { let l = self.meta_item_list().unwrap();
NameValue(s.to_string(), lit_to_string(v)) List(self.name().to_string(), l.clean(cx))
}
} }
} }
} }
impl Clean<Attribute> for ast::Attribute { impl Clean<Attribute> for ast::Attribute {
fn clean(&self, cx: &DocContext) -> Attribute { fn clean(&self, cx: &DocContext) -> Attribute {
self.with_desugared_doc(|a| a.node.value.clean(cx)) self.with_desugared_doc(|a| a.meta().clean(cx))
} }
} }
@ -535,6 +534,28 @@ impl attr::AttrMetaMethods for Attribute {
} }
} }
fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None } fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
fn is_word(&self) -> bool {
match *self {
Word(_) => true,
_ => false,
}
}
fn is_value_str(&self) -> bool {
match *self {
NameValue(..) => true,
_ => false,
}
}
fn is_meta_item_list(&self) -> bool {
match *self {
List(..) => true,
_ => false,
}
}
fn span(&self) -> syntax_pos::Span { unimplemented!() } fn span(&self) -> syntax_pos::Span { unimplemented!() }
} }
@ -2568,25 +2589,25 @@ impl ToSource for syntax_pos::Span {
} }
} }
fn lit_to_string(lit: &ast::Lit) -> String { // fn lit_to_string(lit: &ast::Lit) -> String {
match lit.node { // match lit.node {
ast::LitKind::Str(ref st, _) => st.to_string(), // ast::LitKind::Str(ref st, _) => st.to_string(),
ast::LitKind::ByteStr(ref data) => format!("{:?}", data), // ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
ast::LitKind::Byte(b) => { // ast::LitKind::Byte(b) => {
let mut res = String::from("b'"); // let mut res = String::from("b'");
for c in (b as char).escape_default() { // for c in (b as char).escape_default() {
res.push(c); // res.push(c);
} // }
res.push('\''); // res.push('\'');
res // res
}, // },
ast::LitKind::Char(c) => format!("'{}'", c), // ast::LitKind::Char(c) => format!("'{}'", c),
ast::LitKind::Int(i, _t) => i.to_string(), // ast::LitKind::Int(i, _t) => i.to_string(),
ast::LitKind::Float(ref f, _t) => f.to_string(), // ast::LitKind::Float(ref f, _t) => f.to_string(),
ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(), // ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
ast::LitKind::Bool(b) => b.to_string(), // ast::LitKind::Bool(b) => b.to_string(),
} // }
} // }
fn name_from_pat(p: &hir::Pat) -> String { fn name_from_pat(p: &hir::Pat) -> String {
use rustc::hir::*; use rustc::hir::*;

View file

@ -17,8 +17,8 @@ pub use self::IntType::*;
use ast; use ast;
use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind}; use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
use ast::{Expr, Item, Local, Stmt, StmtKind}; use ast::{Expr, Item, Local, Stmt, StmtKind};
use codemap::{spanned, dummy_spanned, Spanned}; use codemap::{respan, spanned, dummy_spanned, Spanned};
use syntax_pos::{Span, BytePos}; use syntax_pos::{Span, BytePos, DUMMY_SP};
use errors::Handler; use errors::Handler;
use feature_gate::{Features, GatedCfg}; use feature_gate::{Features, GatedCfg};
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
@ -92,6 +92,13 @@ pub trait AttrMetaMethods {
/// Gets a list of inner meta items from a list MetaItem type. /// Gets a list of inner meta items from a list MetaItem type.
fn meta_item_list(&self) -> Option<&[P<MetaItem>]>; fn meta_item_list(&self) -> Option<&[P<MetaItem>]>;
/// Indicates if the attribute is a Word.
fn is_word(&self) -> bool;
/// Indicates if the attribute is a Value String.
fn is_value_str(&self) -> bool;
/// Indicates if the attribute is a Meta-Item List.
fn is_meta_item_list(&self) -> bool;
fn span(&self) -> Span; fn span(&self) -> Span;
} }
@ -108,8 +115,14 @@ impl AttrMetaMethods for Attribute {
self.meta().value_str() self.meta().value_str()
} }
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> { fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
self.node.value.meta_item_list() self.meta().meta_item_list()
} }
fn is_word(&self) -> bool { self.meta().is_word() }
fn is_value_str(&self) -> bool { self.meta().is_value_str() }
fn is_meta_item_list(&self) -> bool { self.meta().is_meta_item_list() }
fn span(&self) -> Span { self.meta().span } fn span(&self) -> Span { self.meta().span }
} }
@ -140,6 +153,18 @@ impl AttrMetaMethods for MetaItem {
_ => None _ => None
} }
} }
fn is_word(&self) -> bool {
match self.node {
MetaItemKind::Word(_) => true,
_ => false,
}
}
fn is_value_str(&self) -> bool { self.value_str().is_some() }
fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() }
fn span(&self) -> Span { self.span } fn span(&self) -> Span { self.span }
} }
@ -150,6 +175,9 @@ impl AttrMetaMethods for P<MetaItem> {
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> { fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
(**self).meta_item_list() (**self).meta_item_list()
} }
fn is_word(&self) -> bool { (**self).is_word() }
fn is_value_str(&self) -> bool { (**self).is_value_str() }
fn is_meta_item_list(&self) -> bool { (**self).is_meta_item_list() }
fn span(&self) -> Span { (**self).span() } fn span(&self) -> Span { (**self).span() }
} }
@ -194,22 +222,38 @@ impl AttributeMethods for Attribute {
pub fn mk_name_value_item_str(name: InternedString, value: InternedString) pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
-> P<MetaItem> { -> P<MetaItem> {
let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked)); let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked));
mk_name_value_item(name, value_lit) mk_spanned_name_value_item(DUMMY_SP, name, value_lit)
} }
pub fn mk_name_value_item(name: InternedString, value: ast::Lit) pub fn mk_name_value_item(name: InternedString, value: ast::Lit)
-> P<MetaItem> { -> P<MetaItem> {
P(dummy_spanned(MetaItemKind::NameValue(name, value))) mk_spanned_name_value_item(DUMMY_SP, name, value)
} }
pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> { pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
P(dummy_spanned(MetaItemKind::List(name, items))) mk_spanned_list_item(DUMMY_SP, name, items)
} }
pub fn mk_word_item(name: InternedString) -> P<MetaItem> { pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
P(dummy_spanned(MetaItemKind::Word(name))) mk_spanned_word_item(DUMMY_SP, name)
} }
pub fn mk_spanned_name_value_item(sp: Span, name: InternedString, value: ast::Lit)
-> P<MetaItem> {
P(respan(sp,MetaItemKind::NameValue(name, value)))
}
pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec<P<MetaItem>>)
-> P<MetaItem> {
P(respan(sp, MetaItemKind::List(name, items)))
}
pub fn mk_spanned_word_item(sp: Span, name: InternedString) -> P<MetaItem> {
P(respan(sp,MetaItemKind::Word(name)))
}
thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) } thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
pub fn mk_attr_id() -> AttrId { pub fn mk_attr_id() -> AttrId {
@ -223,7 +267,13 @@ pub fn mk_attr_id() -> AttrId {
/// Returns an inner attribute with the given value. /// Returns an inner attribute with the given value.
pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute { pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
dummy_spanned(Attribute_ { mk_spanned_attr_inner(DUMMY_SP, id, item)
}
/// Returns an innter attribute with the given value and span.
pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
respan(sp,
Attribute_ {
id: id, id: id,
style: ast::AttrStyle::Inner, style: ast::AttrStyle::Inner,
value: item, value: item,
@ -231,9 +281,16 @@ pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
}) })
} }
/// Returns an outer attribute with the given value. /// Returns an outer attribute with the given value.
pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute { pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
dummy_spanned(Attribute_ { mk_spanned_attr_outer(DUMMY_SP, id, item)
}
/// Returns an outer attribute with the given value and span.
pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: P<MetaItem>) -> Attribute {
respan(sp,
Attribute_ {
id: id, id: id,
style: ast::AttrStyle::Outer, style: ast::AttrStyle::Outer,
value: item, value: item,
@ -241,6 +298,15 @@ pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
}) })
} }
pub fn mk_doc_attr_outer(id: AttrId, item: P<MetaItem>, is_sugared_doc: bool) -> Attribute {
dummy_spanned(Attribute_ {
id: id,
style: ast::AttrStyle::Outer,
value: item,
is_sugared_doc: is_sugared_doc,
})
}
pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos, pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos,
hi: BytePos) hi: BytePos)
-> Attribute { -> Attribute {

View file

@ -1135,30 +1135,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} }
fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute { fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
respan(sp, ast::Attribute_ { attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi)
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
value: mi,
is_sugared_doc: false,
})
} }
fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> { fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> {
P(respan(sp, ast::MetaItemKind::Word(w))) attr::mk_spanned_word_item(sp, w)
} }
fn meta_list(&self, fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<P<ast::MetaItem>>)
sp: Span,
name: InternedString,
mis: Vec<P<ast::MetaItem>> )
-> P<ast::MetaItem> { -> P<ast::MetaItem> {
P(respan(sp, ast::MetaItemKind::List(name, mis))) attr::mk_spanned_list_item(sp, name, mis)
} }
fn meta_name_value(&self, fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
sp: Span,
name: InternedString,
value: ast::LitKind)
-> P<ast::MetaItem> { -> P<ast::MetaItem> {
P(respan(sp, ast::MetaItemKind::NameValue(name, respan(sp, value)))) attr::mk_spanned_name_value_item(sp, name, respan(sp, value))
} }
fn item_use(&self, sp: Span, fn item_use(&self, sp: Span,

View file

@ -302,9 +302,8 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
}; };
if is_use { if is_use {
match attr.node.value.node { if !attr.is_word() {
ast::MetaItemKind::Word(..) => (), fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here");
_ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"),
} }
return true; return true;
} }

View file

@ -1108,13 +1108,12 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
} }
Some(list) => { Some(list) => {
for mi in list { for mi in list {
let name = match mi.node { let name = if mi.is_word() {
ast::MetaItemKind::Word(ref word) => (*word).clone(), mi.name()
_ => { } else {
span_err!(span_handler, mi.span, E0556, span_err!(span_handler, mi.span, E0556,
"malformed feature, expected just one word"); "malformed feature, expected just one word");
continue continue
}
}; };
if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter() if let Some(&(_, _, _, setter)) = ACTIVE_FEATURES.iter()
.find(|& &(n, _, _, _)| name == n) { .find(|& &(n, _, _, _)| name == n) {

View file

@ -10,7 +10,7 @@
//! The compiler code necessary to implement the `#[derive]` extensions. //! The compiler code necessary to implement the `#[derive]` extensions.
use syntax::ast::{self, MetaItem, MetaItemKind}; use syntax::ast::{MetaItem, self};
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv}; use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier}; use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
@ -98,15 +98,14 @@ fn expand_derive(cx: &mut ExtCtxt,
let mut eq_span = None; let mut eq_span = None;
for titem in traits.iter().rev() { for titem in traits.iter().rev() {
let tname = match titem.node { let tname = if titem.is_word() {
MetaItemKind::Word(ref tname) => tname, titem.name() }
_ => { else {
cx.span_err(titem.span, "malformed `derive` entry"); cx.span_err(titem.span, "malformed `derive` entry");
continue; continue;
}
}; };
if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) { if !(is_builtin_trait(&tname) || cx.ecfg.enable_custom_derive()) {
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
"custom_derive", "custom_derive",
titem.span, titem.span,