General MetaItem encapsulation rewrites.
This commit is contained in:
parent
9316ae515e
commit
a5e5ea1646
14 changed files with 231 additions and 170 deletions
|
@ -366,19 +366,19 @@ 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)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
out
|
out
|
||||||
|
|
|
@ -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,15 +393,13 @@ 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);
|
||||||
}
|
|
||||||
_ => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,20 +648,19 @@ 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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,13 +110,13 @@ 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 {
|
||||||
self.tcx.sess.span_err(
|
// FIXME better-encapsulate meta_item (don't directly access `node`)
|
||||||
meta_item.span,
|
self.tcx.sess.span_err(
|
||||||
&format!("unexpected meta-item {:?}", meta_item.node));
|
meta_item.span(),
|
||||||
}
|
&format!("unexpected meta-item {:?}", meta_item.node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let id = id.unwrap_or(InternedString::new(ID));
|
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 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 {
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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![],
|
||||||
|
|
|
@ -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,31 +1431,28 @@ 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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,7 +1461,7 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
|
||||||
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();
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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,21 +267,43 @@ 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)
|
||||||
id: id,
|
|
||||||
style: ast::AttrStyle::Inner,
|
|
||||||
value: item,
|
|
||||||
is_sugared_doc: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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.
|
/// 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 {
|
||||||
|
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_ {
|
dummy_spanned(Attribute_ {
|
||||||
id: id,
|
id: id,
|
||||||
style: ast::AttrStyle::Outer,
|
style: ast::AttrStyle::Outer,
|
||||||
value: item,
|
value: item,
|
||||||
is_sugared_doc: false,
|
is_sugared_doc: is_sugared_doc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1108,14 +1108,13 @@ 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) {
|
||||||
*(setter(&mut features)) = true;
|
*(setter(&mut features)) = true;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue