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

View file

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

View file

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

View file

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

View file

@ -44,7 +44,7 @@ use lint::{LintPass, LateLintPass};
use std::collections::HashSet;
use syntax::{ast};
use syntax::attr::{self, AttrMetaMethods};
use syntax::attr::{self, AttrMetaMethods, AttributeMethods};
use syntax_pos::{self, Span};
use rustc::hir::{self, PatKind};
@ -299,9 +299,10 @@ impl MissingDoc {
}
let has_doc = attrs.iter().any(|a| {
match a.node.value.node {
ast::MetaItemKind::NameValue(ref name, _) if *name == "doc" => true,
_ => false
if a.is_value_str() && a.name() == "doc" {
true
} else {
false
}
});
if !has_doc {
@ -1094,10 +1095,10 @@ impl LintPass for UnstableFeatures {
impl LateLintPass for UnstableFeatures {
fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
if attr::contains_name(&[attr.node.value.clone()], "feature") {
if let Some(items) = attr.node.value.meta_item_list() {
if attr::contains_name(&[attr.meta().clone()], "feature") {
if let Some(items) = attr.meta().meta_item_list() {
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
assert_eq!(meta_items.len(), 1);
let meta_item = meta_items.into_iter().nth(0).unwrap();
codemap::Spanned {
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
}
attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
}).collect()
},
None => vec![],

View file

@ -44,7 +44,7 @@ use std::rc::Rc;
use std::u32;
use syntax::abi::Abi;
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
use syntax::attr;
use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
use errors::Handler;
use syntax;
use syntax_pos::BytePos;
@ -1431,31 +1431,28 @@ fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
}
fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
match mi.node {
ast::MetaItemKind::Word(ref name) => {
if mi.is_word() {
let name = mi.name();
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();
}
ast::MetaItemKind::NameValue(ref name, ref value) => {
match value.node {
ast::LitKind::Str(ref 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_value, value);
rbml_w.end_tag();
}
_ => {/* FIXME (#623): encode other variants */ }
}
}
ast::MetaItemKind::List(ref name, ref items) => {
} else if mi.is_value_str() {
let name = mi.name();
/* FIXME (#623): support other literal kinds */
let value = mi.value_str().unwrap();
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_value, &value);
rbml_w.end_tag();
} else { // it must be a list
let name = mi.name();
let items = mi.meta_item_list().unwrap();
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 {
encode_meta_item(rbml_w, &inner_item);
}
rbml_w.end_tag();
}
}
}
@ -1464,7 +1461,7 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
for attr in attrs {
rbml_w.start_tag(tag_attribute);
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();

View file

@ -60,10 +60,10 @@ impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
}
if let (Some(sel), Some(names)) = (import.as_mut(), names) {
for attr in names {
if let ast::MetaItemKind::Word(ref name) = attr.node {
sel.insert(name.clone(), attr.span);
if attr.is_word() {
sel.insert(attr.name().clone(), attr.span());
} 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 {
if let ast::MetaItemKind::Word(ref name) = attr.node {
reexport.insert(name.clone(), attr.span);
if attr.is_word() {
reexport.insert(attr.name().clone(), attr.span());
} 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 {
fn clean(&self, cx: &DocContext) -> Attribute {
match self.node {
ast::MetaItemKind::Word(ref s) => Word(s.to_string()),
ast::MetaItemKind::List(ref s, ref l) => {
List(s.to_string(), l.clean(cx))
}
ast::MetaItemKind::NameValue(ref s, ref v) => {
NameValue(s.to_string(), lit_to_string(v))
}
}
if self.is_word() {
Word(self.name().to_string())
} else if let Some(v) = self.value_str() {
NameValue(self.name().to_string(), v.to_string())
} else { // must be a list
let l = self.meta_item_list().unwrap();
List(self.name().to_string(), l.clean(cx))
}
}
}
impl Clean<Attribute> for ast::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 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!() }
}
@ -2568,25 +2589,25 @@ impl ToSource for syntax_pos::Span {
}
}
fn lit_to_string(lit: &ast::Lit) -> String {
match lit.node {
ast::LitKind::Str(ref st, _) => st.to_string(),
ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
ast::LitKind::Byte(b) => {
let mut res = String::from("b'");
for c in (b as char).escape_default() {
res.push(c);
}
res.push('\'');
res
},
ast::LitKind::Char(c) => format!("'{}'", c),
ast::LitKind::Int(i, _t) => i.to_string(),
ast::LitKind::Float(ref f, _t) => f.to_string(),
ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
ast::LitKind::Bool(b) => b.to_string(),
}
}
// fn lit_to_string(lit: &ast::Lit) -> String {
// match lit.node {
// ast::LitKind::Str(ref st, _) => st.to_string(),
// ast::LitKind::ByteStr(ref data) => format!("{:?}", data),
// ast::LitKind::Byte(b) => {
// let mut res = String::from("b'");
// for c in (b as char).escape_default() {
// res.push(c);
// }
// res.push('\'');
// res
// },
// ast::LitKind::Char(c) => format!("'{}'", c),
// ast::LitKind::Int(i, _t) => i.to_string(),
// ast::LitKind::Float(ref f, _t) => f.to_string(),
// ast::LitKind::FloatUnsuffixed(ref f) => f.to_string(),
// ast::LitKind::Bool(b) => b.to_string(),
// }
// }
fn name_from_pat(p: &hir::Pat) -> String {
use rustc::hir::*;

View file

@ -17,8 +17,8 @@ pub use self::IntType::*;
use ast;
use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaItemKind};
use ast::{Expr, Item, Local, Stmt, StmtKind};
use codemap::{spanned, dummy_spanned, Spanned};
use syntax_pos::{Span, BytePos};
use codemap::{respan, spanned, dummy_spanned, Spanned};
use syntax_pos::{Span, BytePos, DUMMY_SP};
use errors::Handler;
use feature_gate::{Features, GatedCfg};
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.
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;
}
@ -108,8 +115,14 @@ impl AttrMetaMethods for Attribute {
self.meta().value_str()
}
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 }
}
@ -140,6 +153,18 @@ impl AttrMetaMethods for MetaItem {
_ => 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 }
}
@ -150,6 +175,9 @@ impl AttrMetaMethods for P<MetaItem> {
fn meta_item_list(&self) -> Option<&[P<MetaItem>]> {
(**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() }
}
@ -194,22 +222,38 @@ impl AttributeMethods for Attribute {
pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
-> P<MetaItem> {
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)
-> 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> {
P(dummy_spanned(MetaItemKind::List(name, items)))
mk_spanned_list_item(DUMMY_SP, name, items)
}
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) }
pub fn mk_attr_id() -> AttrId {
@ -223,21 +267,43 @@ pub fn mk_attr_id() -> AttrId {
/// Returns an inner attribute with the given value.
pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
dummy_spanned(Attribute_ {
id: id,
style: ast::AttrStyle::Inner,
value: item,
is_sugared_doc: false,
})
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,
style: ast::AttrStyle::Inner,
value: item,
is_sugared_doc: false,
})
}
/// Returns an outer attribute with the given value.
pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> 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,
style: ast::AttrStyle::Outer,
value: item,
is_sugared_doc: false,
})
}
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: false,
is_sugared_doc: is_sugared_doc,
})
}

View file

@ -1135,30 +1135,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
respan(sp, ast::Attribute_ {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
value: mi,
is_sugared_doc: false,
})
attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi)
}
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,
sp: Span,
name: InternedString,
mis: Vec<P<ast::MetaItem>> )
fn meta_list(&self, sp: Span, name: InternedString, mis: Vec<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,
sp: Span,
name: InternedString,
value: ast::LitKind)
fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
-> 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,

View file

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

View file

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

View file

@ -10,7 +10,7 @@
//! 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::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
@ -98,15 +98,14 @@ fn expand_derive(cx: &mut ExtCtxt,
let mut eq_span = None;
for titem in traits.iter().rev() {
let tname = match titem.node {
MetaItemKind::Word(ref tname) => tname,
_ => {
cx.span_err(titem.span, "malformed `derive` entry");
continue;
}
};
let tname = if titem.is_word() {
titem.name() }
else {
cx.span_err(titem.span, "malformed `derive` entry");
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,
"custom_derive",
titem.span,