Avoid more MetaItem
-to-Attribute
conversions.
There is code for converting `Attribute` (syntactic) to `MetaItem` (semantic). There is also code for the reverse direction. The reverse direction isn't really necessary; it's currently only used when generating attributes, e.g. in `derive` code. This commit adds some new functions for creating `Attributes`s directly, without involving `MetaItem`s: `mk_attr_word`, `mk_attr_name_value_str`, `mk_attr_nested_word`, and `ExtCtxt::attr_{word,name_value_str,nested_word}`. These new methods replace the old functions for creating `Attribute`s: `mk_attr_inner`, `mk_attr_outer`, and `ExtCtxt::attribute`. Those functions took `MetaItem`s as input, and relied on many other functions that created `MetaItems`, which are also removed: `mk_name_value_item`, `mk_list_item`, `mk_word_item`, `mk_nested_word_item`, `{MetaItem,MetaItemKind,NestedMetaItem}::token_trees`, `MetaItemKind::attr_args`, `MetaItemLit::{from_lit_kind,to_token}`, `ExtCtxt::meta_word`. Overall this cuts more than 100 lines of code and makes thing simpler.
This commit is contained in:
parent
d1b61a31c5
commit
ba1751a201
20 changed files with 116 additions and 211 deletions
|
@ -1,10 +1,10 @@
|
|||
//! Functions dealing with attributes and meta items.
|
||||
|
||||
use crate::ast;
|
||||
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
|
||||
use crate::ast::{DelimArgs, LitKind, MetaItemLit};
|
||||
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
|
||||
use crate::ast::{Path, PathSegment};
|
||||
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
|
||||
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
|
||||
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
|
||||
use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Delimiter, Token};
|
||||
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
|
@ -12,7 +12,6 @@ use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
|
|||
use crate::util::comments;
|
||||
use rustc_data_structures::sync::WorkerLocal;
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::source_map::BytePos;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use std::cell::Cell;
|
||||
|
@ -223,11 +222,7 @@ impl AttrItem {
|
|||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem {
|
||||
path: self.path.clone(),
|
||||
kind: MetaItemKind::from_attr_args(&self.args)?,
|
||||
span,
|
||||
})
|
||||
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
|
@ -329,26 +324,13 @@ impl Attribute {
|
|||
/* Constructors */
|
||||
|
||||
pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
|
||||
let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
|
||||
mk_name_value_item(ident, lit_kind, str_span)
|
||||
mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
|
||||
}
|
||||
|
||||
pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
|
||||
let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
|
||||
let span = ident.span.to(lit_span);
|
||||
MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
|
||||
}
|
||||
|
||||
pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
|
||||
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
|
||||
}
|
||||
|
||||
pub fn mk_word_item(ident: Ident) -> MetaItem {
|
||||
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
|
||||
}
|
||||
|
||||
pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
|
||||
NestedMetaItem::MetaItem(mk_word_item(ident))
|
||||
MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
|
||||
}
|
||||
|
||||
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
|
||||
|
@ -406,21 +388,58 @@ pub fn mk_attr_from_item(
|
|||
span: Span,
|
||||
) -> Attribute {
|
||||
Attribute {
|
||||
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
|
||||
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
|
||||
id: g.mk_attr_id(),
|
||||
style,
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an inner attribute with the given value and span.
|
||||
pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||
mk_attr(g, AttrStyle::Inner, item.path, item.kind.attr_args(item.span), item.span)
|
||||
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Empty;
|
||||
mk_attr(g, style, path, args, span)
|
||||
}
|
||||
|
||||
/// Returns an outer attribute with the given value and span.
|
||||
pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
|
||||
mk_attr(g, AttrStyle::Outer, item.path, item.kind.attr_args(item.span), item.span)
|
||||
pub fn mk_attr_name_value_str(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
name: Symbol,
|
||||
val: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
|
||||
let expr = P(Expr {
|
||||
id: DUMMY_NODE_ID,
|
||||
kind: ExprKind::Lit(lit),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||
mk_attr(g, style, path, args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_nested_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
outer: Symbol,
|
||||
inner: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let inner_tokens = TokenStream::new(vec![TokenTree::Token(
|
||||
Token::from_ast_ident(Ident::new(inner, span)),
|
||||
Spacing::Alone,
|
||||
)]);
|
||||
let outer_ident = Ident::new(outer, span);
|
||||
let path = Path::from_ident(outer_ident);
|
||||
let attr_args = AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(span),
|
||||
delim: MacDelimiter::Parenthesis,
|
||||
tokens: inner_tokens,
|
||||
});
|
||||
mk_attr(g, style, path, attr_args, span)
|
||||
}
|
||||
|
||||
pub fn mk_doc_comment(
|
||||
|
@ -438,23 +457,6 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
|||
}
|
||||
|
||||
impl MetaItem {
|
||||
fn token_trees(&self) -> Vec<TokenTree> {
|
||||
let mut idents = vec![];
|
||||
let mut last_pos = BytePos(0_u32);
|
||||
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, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
|
||||
idents.push(TokenTree::token_alone(token::ModSep, mod_sep_span));
|
||||
}
|
||||
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident), Spacing::Alone));
|
||||
last_pos = segment.ident.span.hi();
|
||||
}
|
||||
idents.extend(self.kind.token_trees(self.span));
|
||||
idents
|
||||
}
|
||||
|
||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
|
||||
where
|
||||
I: Iterator<Item = TokenTree>,
|
||||
|
@ -526,62 +528,6 @@ impl MetaItemKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn attr_args(&self, span: Span) -> AttrArgs {
|
||||
match self {
|
||||
MetaItemKind::Word => AttrArgs::Empty,
|
||||
MetaItemKind::NameValue(lit) => {
|
||||
let expr = P(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ExprKind::Lit(lit.token_lit.clone()),
|
||||
span: lit.span,
|
||||
attrs: ast::AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
AttrArgs::Eq(span, AttrArgsEq::Ast(expr))
|
||||
}
|
||||
MetaItemKind::List(list) => {
|
||||
let mut tts = Vec::new();
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tts.push(TokenTree::token_alone(token::Comma, span));
|
||||
}
|
||||
tts.extend(item.token_trees())
|
||||
}
|
||||
AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(span),
|
||||
delim: MacDelimiter::Parenthesis,
|
||||
tokens: TokenStream::new(tts),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn token_trees(&self, span: Span) -> Vec<TokenTree> {
|
||||
match self {
|
||||
MetaItemKind::Word => vec![],
|
||||
MetaItemKind::NameValue(lit) => {
|
||||
vec![
|
||||
TokenTree::token_alone(token::Eq, span),
|
||||
TokenTree::Token(lit.to_token(), Spacing::Alone),
|
||||
]
|
||||
}
|
||||
MetaItemKind::List(list) => {
|
||||
let mut tokens = Vec::new();
|
||||
for (i, item) in list.iter().enumerate() {
|
||||
if i > 0 {
|
||||
tokens.push(TokenTree::token_alone(token::Comma, span));
|
||||
}
|
||||
tokens.extend(item.token_trees())
|
||||
}
|
||||
vec![TokenTree::Delimited(
|
||||
DelimSpan::from_single(span),
|
||||
Delimiter::Parenthesis,
|
||||
TokenStream::new(tokens),
|
||||
)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
|
||||
let mut tokens = tokens.into_trees().peekable();
|
||||
let mut result = Vec::new();
|
||||
|
@ -620,7 +566,7 @@ impl MetaItemKind {
|
|||
}) => MetaItemKind::list_from_tokens(tokens.clone()),
|
||||
AttrArgs::Delimited(..) => None,
|
||||
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
|
||||
ast::ExprKind::Lit(token_lit) => {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
// Turn failures to `None`, we'll get parse errors elsewhere.
|
||||
MetaItemLit::from_token_lit(token_lit, expr.span)
|
||||
.ok()
|
||||
|
@ -659,15 +605,6 @@ impl NestedMetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn token_trees(&self) -> Vec<TokenTree> {
|
||||
match self {
|
||||
NestedMetaItem::MetaItem(item) => item.token_trees(),
|
||||
NestedMetaItem::Lit(lit) => {
|
||||
vec![TokenTree::Token(lit.to_token(), Spacing::Alone)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
|
||||
where
|
||||
I: Iterator<Item = TokenTree>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue