Skip to content

Commit

Permalink
Allow Path for name of MetaItem
Browse files Browse the repository at this point in the history
  • Loading branch information
topecongiro authored and flip1995 committed May 2, 2018
1 parent e27d20a commit 759bd01
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 70 deletions.
16 changes: 12 additions & 4 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,17 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
segment.identifier.name.hash_stable(hcx, hasher);
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
Expand All @@ -229,10 +240,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
} = *self;

style.hash_stable(hcx, hasher);
path.segments.len().hash_stable(hcx, hasher);
for segment in &path.segments {
segment.ident.name.hash_stable(hcx, hasher);
}
path.hash_stable(hcx, hasher);
for tt in tokens.trees() {
tt.hash_stable(hcx, hasher);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ impl RustcDefaultCalls {
let mut cfgs = Vec::new();
for &(name, ref value) in sess.parse_sess.config.iter() {
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
ident: ast::Ident::with_empty_ctxt(name),
name: ast::Path::from_ident(DUMMY_SP, name.to_ident()),
node: ast::MetaItemKind::Word,
span: DUMMY_SP,
});
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ impl<'a> base::Resolver for Resolver<'a> {

if name == "derive" {
let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
parser.parse_path_allowing_meta(PathStyle::Mod)
parser.parse_path(PathStyle::Mod)
});

let mut traits = match result {
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,10 @@ pub enum NestedMetaItemKind {

/// A spanned compile-time attribute item.
///
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MetaItem {
pub ident: Ident,
pub name: Path,
pub node: MetaItemKind,
pub span: Span,
}
Expand Down
139 changes: 99 additions & 40 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl NestedMetaItem {
/// Returns the name of the meta item, e.g. `foo` in `#[foo]`,
/// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
pub fn name(&self) -> Option<Name> {
self.meta_item().and_then(|meta_item| Some(meta_item.ident.name))
self.meta_item().and_then(|meta_item| Some(meta_item.name()))
}

/// Gets the string value if self is a MetaItem and the MetaItem is a
Expand All @@ -154,7 +154,7 @@ impl NestedMetaItem {
if meta_item_list.len() == 1 {
let nested_item = &meta_item_list[0];
if nested_item.is_literal() {
Some((meta_item.ident.name, nested_item.literal().unwrap()))
Some((meta_item.name(), nested_item.literal().unwrap()))
} else {
None
}
Expand Down Expand Up @@ -204,6 +204,10 @@ impl NestedMetaItem {
}
}

fn name_from_path(path: &ast::Path) -> Name {
path.segments.iter().next().unwrap().identifier.name
}

impl Attribute {
pub fn check_name(&self, name: &str) -> bool {
let matches = self.path == name;
Expand All @@ -215,7 +219,7 @@ impl Attribute {

pub fn name(&self) -> Option<Name> {
match self.path.segments.len() {
1 => Some(self.path.segments[0].ident.name),
1 => Some(self.path.segments[0].identifier.name),
_ => None,
}
}
Expand Down Expand Up @@ -250,6 +254,10 @@ impl Attribute {
}

impl MetaItem {
pub fn name(&self) -> Name {
name_from_path(&self.name)
}

pub fn value_str(&self) -> Option<Symbol> {
match self.node {
MetaItemKind::NameValue(ref v) => {
Expand Down Expand Up @@ -279,7 +287,7 @@ impl MetaItem {
pub fn span(&self) -> Span { self.span }

pub fn check_name(&self, name: &str) -> bool {
self.ident.name == name
self.name() == name
}

pub fn is_value_str(&self) -> bool {
Expand All @@ -296,10 +304,7 @@ impl Attribute {
pub fn meta(&self) -> Option<MetaItem> {
let mut tokens = self.tokens.trees().peekable();
Some(MetaItem {
ident: match self.path.segments.len() {
1 => self.path.segments[0].ident,
_ => return None,
},
name: self.path.clone(),
node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
if tokens.peek().is_some() {
return None;
Expand Down Expand Up @@ -344,12 +349,8 @@ impl Attribute {
}

pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
if self.path.segments.len() > 1 {
sess.span_diagnostic.span_err(self.path.span, "expected ident, found path");
}

Ok(MetaItem {
ident: self.path.segments.last().unwrap().ident,
name: self.path.clone(),
node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
span: self.span,
})
Expand Down Expand Up @@ -397,8 +398,31 @@ pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> Met
pub fn mk_word_item(ident: Ident) -> MetaItem {
MetaItem { ident, span: ident.span, node: MetaItemKind::Word }
}
pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident)))

pub fn mk_word_item(name: Name) -> MetaItem {
mk_spanned_word_item(DUMMY_SP, name)
}

macro_rules! mk_spanned_meta_item {
($sp:ident, $name:ident, $node:expr) => {
MetaItem {
span: $sp,
name: ast::Path::from_ident($sp, ast::Ident::with_empty_ctxt($name)),
node: $node,
}
}
}

pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem {
mk_spanned_meta_item!(sp, name, MetaItemKind::NameValue(value))
}

pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
mk_spanned_meta_item!(sp, name, MetaItemKind::List(items))
}

pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem {
mk_spanned_meta_item!(sp, name, MetaItemKind::Word)
}

pub fn mk_attr_id() -> AttrId {
Expand All @@ -422,7 +446,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
Attribute {
id,
style: ast::AttrStyle::Inner,
path: ast::Path::from_ident(item.ident),
path: item.name,
tokens: item.node.tokens(item.span),
is_sugared_doc: false,
span: sp,
Expand All @@ -440,7 +464,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
Attribute {
id,
style: ast::AttrStyle::Outer,
path: ast::Path::from_ident(item.ident),
path: item.name,
tokens: item.node.tokens(item.span),
is_sugared_doc: false,
span: sp,
Expand Down Expand Up @@ -489,7 +513,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
item.check_name("feature") &&
item.meta_item_list().map(|list| {
list.iter().any(|mi| {
mi.word().map(|w| w.ident.name == feature_name)
mi.word().map(|w| w.name() == feature_name)
.unwrap_or(false)
})
}).unwrap_or(false)
Expand Down Expand Up @@ -562,7 +586,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
gated_cfg.check_and_emit(sess, feats);
}
sess.config.contains(&(cfg.ident.name, cfg.value_str()))
sess.config.contains(&(cfg.name(), cfg.value_str()))
})
}

Expand All @@ -583,7 +607,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)

// The unwraps below may look dangerous, but we've already asserted
// that they won't fail with the loop above.
match &*cfg.ident.name.as_str() {
match &*cfg.name().as_str() {
"any" => mis.iter().any(|mi| {
eval_condition(mi.meta_item().unwrap(), sess, eval)
}),
Expand Down Expand Up @@ -676,7 +700,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
let meta = meta.as_ref().unwrap();
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
return false
}
if let Some(v) = meta.value_str() {
Expand All @@ -695,14 +719,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
)+
for meta in metas {
if let Some(mi) = meta.meta_item() {
match &*mi.ident.name.as_str() {
match &*mi.name().as_str() {
$(
stringify!($name)
=> if !get(mi, &mut $name) { continue 'outer },
)+
_ => {
handle_errors(diagnostic, mi.span,
AttrError::UnknownMetaItem(mi.ident.name));
AttrError::UnknownMetaItem(mi.name()));
continue 'outer
}
}
Expand All @@ -714,7 +738,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
}
}

match &*meta.ident.name.as_str() {
match &*meta.name().as_str() {
"rustc_deprecated" => {
if rustc_depr.is_some() {
span_err!(diagnostic, item_sp, E0540,
Expand Down Expand Up @@ -769,13 +793,13 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
let mut issue = None;
for meta in metas {
if let Some(mi) = meta.meta_item() {
match &*mi.ident.name.as_str() {
match &*mi.name().as_str() {
"feature" => if !get(mi, &mut feature) { continue 'outer },
"reason" => if !get(mi, &mut reason) { continue 'outer },
"issue" => if !get(mi, &mut issue) { continue 'outer },
_ => {
handle_errors(diagnostic, meta.span,
AttrError::UnknownMetaItem(mi.ident.name));
AttrError::UnknownMetaItem(mi.name()));
continue 'outer
}
}
Expand Down Expand Up @@ -825,12 +849,12 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
let mut since = None;
for meta in metas {
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
match &*mi.ident.name.as_str() {
match &*mi.name().as_str() {
"feature" => if !get(mi, &mut feature) { continue 'outer },
"since" => if !get(mi, &mut since) { continue 'outer },
_ => {
handle_errors(diagnostic, meta.span,
AttrError::UnknownMetaItem(mi.ident.name));
AttrError::UnknownMetaItem(mi.name()));
continue 'outer
}
}
Expand Down Expand Up @@ -917,7 +941,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
depr = if let Some(metas) = attr.meta_item_list() {
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
return false
}
if let Some(v) = meta.value_str() {
Expand All @@ -933,12 +957,12 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
let mut note = None;
for meta in metas {
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
match &*mi.ident.name.as_str() {
match &*mi.name().as_str() {
"since" => if !get(mi, &mut since) { continue 'outer },
"note" => if !get(mi, &mut note) { continue 'outer },
_ => {
handle_errors(diagnostic, meta.span,
AttrError::UnknownMetaItem(mi.ident.name));
AttrError::UnknownMetaItem(mi.name()));
continue 'outer
}
}
Expand Down Expand Up @@ -990,7 +1014,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>

let mut recognised = false;
if let Some(mi) = item.word() {
let word = &*mi.ident.name.as_str();
let word = &*mi.name().as_str();
let hint = match word {
"C" => Some(ReprC),
"packed" => Some(ReprPacked(1)),
Expand Down Expand Up @@ -1127,18 +1151,52 @@ impl IntType {

impl MetaItem {
fn tokens(&self) -> TokenStream {
let ident = TokenTree::Token(self.span, Token::from_ast_ident(self.ident));
TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)])
let mut idents = vec![];
let mut last_pos = BytePos(0 as u32);
for (i, segment) in self.name.segments.iter().enumerate() {
let is_first = i == 0;
if !is_first {
let mod_sep_span = Span::new(last_pos, segment.span.lo(), segment.span.ctxt());
idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into());
}
idents.push(TokenTree::Token(segment.span, Token::Ident(segment.identifier)).into());
last_pos = segment.span.hi();
}
idents.push(self.node.tokens(self.span));
TokenStream::concat(idents)
}

fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
where I: Iterator<Item = TokenTree>,
{
let (span, ident) = match tokens.next() {
Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident),
let name = match tokens.next() {
Some(TokenTree::Token(span, Token::Ident(ident))) => {
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
tokens.next();
let mut segments = vec![];
loop {
if let Some(TokenTree::Token(span, Token::Ident(ident))) = tokens.next() {
segments.push(ast::PathSegment::from_ident(ident, span));
} else {
return None;
}
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
tokens.next();
} else {
break;
}
}
ast::Path { span, segments }
} else {
ast::Path::from_ident(span, ident)
}
}
Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
token::Nonterminal::NtIdent(ident, _) => (ident.span, ident),
token::Nonterminal::NtIdent(ident) => {
ast::Path::from_ident(ident.span, ident.node)
}
token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
token::Nonterminal::NtPath(ref path) => path.clone(),
_ => return None,
},
_ => return None,
Expand All @@ -1147,10 +1205,11 @@ impl MetaItem {
let node = MetaItemKind::from_tokens(tokens)?;
let hi = match node {
MetaItemKind::NameValue(ref lit) => lit.span.hi(),
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi()),
_ => span.hi(),
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(name.span.hi()),
_ => name.span.hi(),
};
Some(MetaItem { ident, node, span: span.with_hi(hi) })
let span = name.span.with_hi(hi);
Some(MetaItem { name, node, span })
}
}

Expand Down
Loading

0 comments on commit 759bd01

Please sign in to comment.