use crate::ast;
use crate::ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment};
-use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
-use crate::ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
+use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem};
+use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
use crate::mut_visit::visit_clobber;
-use crate::source_map::{BytePos, Spanned, respan, dummy_spanned};
+use crate::source_map::{BytePos, Spanned, dummy_spanned};
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use crate::parse::parser::Parser;
use crate::parse::{self, ParseSess, PResult};
use crate::parse::token::{self, Token};
use crate::ptr::P;
-use crate::symbol::Symbol;
+use crate::symbol::{keywords, Symbol};
use crate::ThinVec;
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
use crate::GLOBALS;
}
impl NestedMetaItem {
- /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
+ /// Returns the MetaItem if self is a NestedMetaItem::MetaItem.
pub fn meta_item(&self) -> Option<&MetaItem> {
- match self.node {
- NestedMetaItemKind::MetaItem(ref item) => Some(item),
+ match *self {
+ NestedMetaItem::MetaItem(ref item) => Some(item),
_ => None
}
}
- /// Returns the Lit if self is a NestedMetaItemKind::Literal.
+ /// Returns the Lit if self is a NestedMetaItem::Literal.
pub fn literal(&self) -> Option<&Lit> {
- match self.node {
- NestedMetaItemKind::Literal(ref lit) => Some(lit),
+ match *self {
+ NestedMetaItem::Literal(ref lit) => Some(lit),
_ => None
}
}
- /// Returns the Span for `self`.
- pub fn span(&self) -> Span {
- self.span
- }
-
/// Returns `true` if this list item is a MetaItem with a name of `name`.
- pub fn check_name(&self, name: &str) -> bool {
+ pub fn check_name(&self, name: Symbol) -> bool {
self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
}
- /// 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.name()))
+ /// For a single-segment meta-item returns its name, otherwise returns `None`.
+ pub fn ident(&self) -> Option<Ident> {
+ self.meta_item().and_then(|meta_item| meta_item.ident())
+ }
+ pub fn name_or_empty(&self) -> Symbol {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name
}
/// Gets the string value if self is a MetaItem and the MetaItem is a
|meta_item| meta_item.meta_item_list().and_then(
|meta_item_list| {
if meta_item_list.len() == 1 {
- let nested_item = &meta_item_list[0];
- if nested_item.is_literal() {
- Some((meta_item.name(), nested_item.literal().unwrap()))
- } else {
- None
+ if let Some(ident) = meta_item.ident() {
+ if let Some(lit) = meta_item_list[0].literal() {
+ return Some((ident.name, lit));
+ }
}
}
- else {
- None
- }}))
- }
-
- /// Returns a MetaItem if self is a MetaItem with Kind Word.
- pub fn word(&self) -> Option<&MetaItem> {
- self.meta_item().and_then(|meta_item| if meta_item.is_word() {
- Some(meta_item)
- } else {
- None
- })
+ None
+ }))
}
/// Gets a list of inner meta items from a list MetaItem type.
/// Returns `true` if self is a MetaItem and the meta item is a word.
pub fn is_word(&self) -> bool {
- self.word().is_some()
+ self.meta_item().map_or(false, |meta_item| meta_item.is_word())
}
/// Returns `true` if self is a MetaItem and the meta item is a ValueString.
}
}
-fn name_from_path(path: &Path) -> Name {
- path.segments.last().expect("empty path in attribute").ident.name
-}
-
impl Attribute {
/// Returns `true` if the attribute's path matches the argument. If it matches, then the
/// attribute is marked as used.
///
/// To check the attribute name without marking it used, use the `path` field directly.
- pub fn check_name(&self, name: &str) -> bool {
+ pub fn check_name(&self, name: Symbol) -> bool {
let matches = self.path == name;
if matches {
mark_used(self);
matches
}
- /// Returns the **last** segment of the name of this attribute.
- /// e.g., `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`.
- pub fn name(&self) -> Name {
- name_from_path(&self.path)
+ /// For a single-segment attribute returns its name, otherwise returns `None`.
+ pub fn ident(&self) -> Option<Ident> {
+ if self.path.segments.len() == 1 {
+ Some(self.path.segments[0].ident)
+ } else {
+ None
+ }
+ }
+ pub fn name_or_empty(&self) -> Symbol {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name
}
pub fn value_str(&self) -> Option<Symbol> {
}
pub fn is_word(&self) -> bool {
- self.path.segments.len() == 1 && self.tokens.is_empty()
- }
-
- pub fn span(&self) -> Span {
- self.span
+ self.tokens.is_empty()
}
pub fn is_meta_item_list(&self) -> bool {
}
impl MetaItem {
- pub fn name(&self) -> Name {
- name_from_path(&self.ident)
+ /// For a single-segment meta-item returns its name, otherwise returns `None`.
+ pub fn ident(&self) -> Option<Ident> {
+ if self.path.segments.len() == 1 {
+ Some(self.path.segments[0].ident)
+ } else {
+ None
+ }
+ }
+ pub fn name_or_empty(&self) -> Symbol {
+ self.ident().unwrap_or(keywords::Invalid.ident()).name
}
// #[attribute(name = "value")]
}
}
- pub fn span(&self) -> Span { self.span }
-
- pub fn check_name(&self, name: &str) -> bool {
- self.name() == name
+ pub fn check_name(&self, name: Symbol) -> bool {
+ self.path == name
}
pub fn is_value_str(&self) -> bool {
pub fn is_meta_item_list(&self) -> bool {
self.meta_item_list().is_some()
}
-
- pub fn is_scoped(&self) -> Option<Ident> {
- if self.ident.segments.len() > 1 {
- Some(self.ident.segments[0].ident)
- } else {
- None
- }
- }
}
impl Attribute {
pub fn meta(&self) -> Option<MetaItem> {
let mut tokens = self.tokens.trees().peekable();
Some(MetaItem {
- ident: self.path.clone(),
+ path: self.path.clone(),
node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
if tokens.peek().is_some() {
return None;
pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
Ok(MetaItem {
- ident: self.path.clone(),
+ path: self.path.clone(),
node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
span: self.span,
})
/* Constructors */
pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem {
- let value = respan(value.span, LitKind::Str(value.node, ast::StrStyle::Cooked));
- mk_name_value_item(ident.span.to(value.span), ident, value)
+ let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked);
+ mk_name_value_item(ident.span.to(value.span), ident, lit_kind, value.span)
}
-pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem {
- MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) }
+pub fn mk_name_value_item(span: Span, ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem {
+ let lit = Lit::from_lit_kind(lit_kind, lit_span);
+ MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::NameValue(lit) }
}
pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
- MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) }
+ MetaItem { path: Path::from_ident(ident), span, node: MetaItemKind::List(items) }
}
pub fn mk_word_item(ident: Ident) -> MetaItem {
- MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word }
+ MetaItem { path: Path::from_ident(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)))
+ NestedMetaItem::MetaItem(mk_word_item(ident))
}
pub fn mk_attr_id() -> AttrId {
Attribute {
id,
style: ast::AttrStyle::Inner,
- path: item.ident,
+ path: item.path,
tokens: item.node.tokens(item.span),
is_sugared_doc: false,
span: sp,
Attribute {
id,
style: ast::AttrStyle::Outer,
- path: item.ident,
+ path: item.path,
tokens: item.node.tokens(item.span),
is_sugared_doc: false,
span: sp,
pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute {
let style = doc_comment_style(&text.as_str());
- let lit = respan(span, LitKind::Str(text, ast::StrStyle::Cooked));
+ let lit_kind = LitKind::Str(text, ast::StrStyle::Cooked);
+ let lit = Lit::from_lit_kind(lit_kind, span);
Attribute {
id,
style,
}
}
-pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool {
+pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
items.iter().any(|item| {
item.check_name(name)
})
}
-pub fn contains_name(attrs: &[Attribute], name: &str) -> bool {
+pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
attrs.iter().any(|item| {
item.check_name(name)
})
}
-pub fn find_by_name<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a Attribute> {
+pub fn find_by_name<'a>(attrs: &'a [Attribute], name: Symbol) -> Option<&'a Attribute> {
attrs.iter().find(|attr| attr.check_name(name))
}
-pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: &'a str)
+pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: Symbol)
-> impl Iterator<Item = &'a Attribute> {
attrs.iter().filter(move |attr| attr.check_name(name))
}
-pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<Symbol> {
+pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option<Symbol> {
attrs.iter()
.find(|at| at.check_name(name))
.and_then(|at| at.value_str())
fn tokens(&self) -> TokenStream {
let mut idents = vec![];
let mut last_pos = BytePos(0 as u32);
- for (i, segment) in self.ident.segments.iter().enumerate() {
+ for (i, segment) in self.path.segments.iter().enumerate() {
let is_first = i == 0;
if !is_first {
let mod_sep_span = Span::new(last_pos,
where I: Iterator<Item = TokenTree>,
{
// FIXME: Share code with `parse_path`.
- let ident = match tokens.next() {
+ let path = match tokens.next() {
Some(TokenTree::Token(span, token @ Token::Ident(..))) |
Some(TokenTree::Token(span, token @ Token::ModSep)) => 'arm: {
let mut segments = if let Token::Ident(ident, _) = token {
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(ident.span.hi()),
- _ => ident.span.hi(),
+ MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()),
+ _ => path.span.hi(),
};
- let span = ident.span.with_hi(hi);
- Some(MetaItem { ident, node, span })
+ let span = path.span.with_hi(hi);
+ Some(MetaItem { path, node, span })
}
}
if i > 0 {
tokens.push(TokenTree::Token(span, Token::Comma).into());
}
- item.node.tokens().append_to_tree_and_joint_vec(&mut tokens);
+ item.tokens().append_to_tree_and_joint_vec(&mut tokens);
}
TokenTree::Delimited(
DelimSpan::from_single(span),
Some(TokenTree::Token(_, token::Eq)) => {
tokens.next();
return if let Some(TokenTree::Token(span, token)) = tokens.next() {
- LitKind::from_token(token)
- .map(|lit| MetaItemKind::NameValue(Spanned { node: lit, span: span }))
+ Lit::from_token(&token, span, None).map(MetaItemKind::NameValue)
} else {
None
};
let mut tokens = delimited.into_trees().peekable();
let mut result = Vec::new();
while let Some(..) = tokens.peek() {
- let item = NestedMetaItemKind::from_tokens(&mut tokens)?;
- result.push(respan(item.span(), item));
+ let item = NestedMetaItem::from_tokens(&mut tokens)?;
+ result.push(item);
match tokens.next() {
None | Some(TokenTree::Token(_, Token::Comma)) => {}
_ => return None,
}
}
-impl NestedMetaItemKind {
- fn span(&self) -> Span {
+impl NestedMetaItem {
+ pub fn span(&self) -> Span {
match *self {
- NestedMetaItemKind::MetaItem(ref item) => item.span,
- NestedMetaItemKind::Literal(ref lit) => lit.span,
+ NestedMetaItem::MetaItem(ref item) => item.span,
+ NestedMetaItem::Literal(ref lit) => lit.span,
}
}
fn tokens(&self) -> TokenStream {
match *self {
- NestedMetaItemKind::MetaItem(ref item) => item.tokens(),
- NestedMetaItemKind::Literal(ref lit) => lit.tokens(),
+ NestedMetaItem::MetaItem(ref item) => item.tokens(),
+ NestedMetaItem::Literal(ref lit) => lit.tokens(),
}
}
- fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItemKind>
+ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
where I: Iterator<Item = TokenTree>,
{
if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() {
- if let Some(node) = LitKind::from_token(token) {
+ if let Some(lit) = Lit::from_token(&token, span, None) {
tokens.next();
- return Some(NestedMetaItemKind::Literal(respan(span, node)));
+ return Some(NestedMetaItem::Literal(lit));
}
}
- MetaItem::from_tokens(tokens).map(NestedMetaItemKind::MetaItem)
- }
-}
-
-impl Lit {
- crate fn tokens(&self) -> TokenStream {
- TokenTree::Token(self.span, self.node.token()).into()
- }
-}
-
-impl LitKind {
- fn token(&self) -> Token {
- use std::ascii;
-
- match *self {
- LitKind::Str(string, ast::StrStyle::Cooked) => {
- let escaped = string.as_str().escape_default().to_string();
- Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None)
- }
- LitKind::Str(string, ast::StrStyle::Raw(n)) => {
- Token::Literal(token::Lit::StrRaw(string, n), None)
- }
- LitKind::ByteStr(ref bytes) => {
- let string = bytes.iter().cloned().flat_map(ascii::escape_default)
- .map(Into::<char>::into).collect::<String>();
- Token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None)
- }
- LitKind::Byte(byte) => {
- let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
- Token::Literal(token::Lit::Byte(Symbol::intern(&string)), None)
- }
- LitKind::Char(ch) => {
- let string: String = ch.escape_default().map(Into::<char>::into).collect();
- Token::Literal(token::Lit::Char(Symbol::intern(&string)), None)
- }
- LitKind::Int(n, ty) => {
- let suffix = match ty {
- ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())),
- ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())),
- ast::LitIntType::Unsuffixed => None,
- };
- Token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), suffix)
- }
- LitKind::Float(symbol, ty) => {
- Token::Literal(token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string())))
- }
- LitKind::FloatUnsuffixed(symbol) => Token::Literal(token::Lit::Float(symbol), None),
- LitKind::Bool(value) => Token::Ident(Ident::with_empty_ctxt(Symbol::intern(if value {
- "true"
- } else {
- "false"
- })), false),
- LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None),
- }
- }
-
- fn from_token(token: Token) -> Option<LitKind> {
- match token {
- Token::Ident(ident, false) if ident.name == "true" => Some(LitKind::Bool(true)),
- Token::Ident(ident, false) if ident.name == "false" => Some(LitKind::Bool(false)),
- Token::Interpolated(nt) => match *nt {
- token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node {
- ExprKind::Lit(ref lit) => Some(lit.node.clone()),
- _ => None,
- },
- _ => None,
- },
- Token::Literal(lit, suf) => {
- let (suffix_illegal, result) = parse::lit_token(lit, suf, None);
- if suffix_illegal && suf.is_some() {
- return None;
- }
- result
- }
- _ => None,
- }
+ MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
}
}