Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement tool_attributes feature (RFC 2103) #50030

Merged
merged 9 commits into from
May 3, 2018
Prev Previous commit
Next Next commit
Allow Path for name of MetaItem
  • Loading branch information
topecongiro authored and flip1995 committed May 2, 2018
commit 759bd01e039452a1a357d347aea51348f9ffc443
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