mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
Remove MappedSubtree
This commit is contained in:
parent
177c70128c
commit
5fb8c0ddfd
7 changed files with 21 additions and 41 deletions
|
@ -14,7 +14,7 @@ use either::Either;
|
||||||
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
|
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
use mbe::{syntax_node_to_token_tree, DelimiterKind, MappedSubTree};
|
use mbe::{syntax_node_to_token_tree, DelimiterKind};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode, AttrsOwner},
|
ast::{self, AstNode, AttrsOwner},
|
||||||
|
@ -160,18 +160,18 @@ impl RawAttrs {
|
||||||
}
|
}
|
||||||
|
|
||||||
let subtree = match attr.input.as_deref() {
|
let subtree = match attr.input.as_deref() {
|
||||||
Some(AttrInput::TokenTree(it)) => it,
|
Some(AttrInput::TokenTree(it, _)) => it,
|
||||||
_ => return smallvec![attr.clone()],
|
_ => return smallvec![attr.clone()],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Input subtree is: `(cfg, $(attr),+)`
|
// Input subtree is: `(cfg, $(attr),+)`
|
||||||
// Split it up into a `cfg` subtree and the `attr` subtrees.
|
// Split it up into a `cfg` subtree and the `attr` subtrees.
|
||||||
// FIXME: There should be a common API for this.
|
// FIXME: There should be a common API for this.
|
||||||
let mut parts = subtree.tree.token_trees.split(
|
let mut parts = subtree.token_trees.split(
|
||||||
|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','),
|
|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','),
|
||||||
);
|
);
|
||||||
let cfg = parts.next().unwrap();
|
let cfg = parts.next().unwrap();
|
||||||
let cfg = Subtree { delimiter: subtree.tree.delimiter, token_trees: cfg.to_vec() };
|
let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
|
||||||
let cfg = CfgExpr::parse(&cfg);
|
let cfg = CfgExpr::parse(&cfg);
|
||||||
let index = attr.id;
|
let index = attr.id;
|
||||||
let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
|
let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
|
||||||
|
@ -260,7 +260,7 @@ impl Attrs {
|
||||||
pub fn docs(&self) -> Option<Documentation> {
|
pub fn docs(&self) -> Option<Documentation> {
|
||||||
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::Literal(s) => Some(s),
|
AttrInput::Literal(s) => Some(s),
|
||||||
AttrInput::TokenTree(_) => None,
|
AttrInput::TokenTree(..) => None,
|
||||||
});
|
});
|
||||||
let indent = docs
|
let indent = docs
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -465,7 +465,7 @@ impl AttrsWithOwner {
|
||||||
// FIXME: code duplication in `docs` above
|
// FIXME: code duplication in `docs` above
|
||||||
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::Literal(s) => Some((s, attr.id)),
|
AttrInput::Literal(s) => Some((s, attr.id)),
|
||||||
AttrInput::TokenTree(_) => None,
|
AttrInput::TokenTree(..) => None,
|
||||||
});
|
});
|
||||||
let indent = docs
|
let indent = docs
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -654,14 +654,14 @@ pub enum AttrInput {
|
||||||
/// `#[attr = "string"]`
|
/// `#[attr = "string"]`
|
||||||
Literal(SmolStr),
|
Literal(SmolStr),
|
||||||
/// `#[attr(subtree)]`
|
/// `#[attr(subtree)]`
|
||||||
TokenTree(mbe::MappedSubTree),
|
TokenTree(tt::Subtree, mbe::TokenMap),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for AttrInput {
|
impl fmt::Display for AttrInput {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
|
AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
|
||||||
AttrInput::TokenTree(subtree) => subtree.tree.fmt(f),
|
AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,7 +682,7 @@ impl Attr {
|
||||||
Some(Interned::new(AttrInput::Literal(value)))
|
Some(Interned::new(AttrInput::Literal(value)))
|
||||||
} else if let Some(tt) = ast.token_tree() {
|
} else if let Some(tt) = ast.token_tree() {
|
||||||
let (tree, map) = syntax_node_to_token_tree(tt.syntax());
|
let (tree, map) = syntax_node_to_token_tree(tt.syntax());
|
||||||
Some(Interned::new(AttrInput::TokenTree(MappedSubTree { tree, map })))
|
Some(Interned::new(AttrInput::TokenTree(tree, map)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -712,10 +712,9 @@ impl Attr {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.input.as_deref() {
|
match self.input.as_deref() {
|
||||||
Some(AttrInput::TokenTree(args)) => {
|
Some(AttrInput::TokenTree(args, _)) => {
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let paths = args
|
let paths = args
|
||||||
.tree
|
|
||||||
.token_trees
|
.token_trees
|
||||||
.iter()
|
.iter()
|
||||||
.group_by(move |tt| {
|
.group_by(move |tt| {
|
||||||
|
@ -760,7 +759,7 @@ pub struct AttrQuery<'a> {
|
||||||
impl<'a> AttrQuery<'a> {
|
impl<'a> AttrQuery<'a> {
|
||||||
pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
|
pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
|
||||||
self.attrs().filter_map(|attr| match attr.input.as_deref()? {
|
self.attrs().filter_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::TokenTree(it) => Some(&it.tree),
|
AttrInput::TokenTree(it, _) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -787,12 +787,12 @@ fn attr_macro_as_call_id(
|
||||||
let mut arg = match ¯o_attr.input {
|
let mut arg = match ¯o_attr.input {
|
||||||
Some(input) => match &**input {
|
Some(input) => match &**input {
|
||||||
attr::AttrInput::Literal(_) => Default::default(),
|
attr::AttrInput::Literal(_) => Default::default(),
|
||||||
attr::AttrInput::TokenTree(tt) => tt.clone(),
|
attr::AttrInput::TokenTree(tt, map) => (tt.clone(), map.clone()),
|
||||||
},
|
},
|
||||||
None => Default::default(),
|
None => Default::default(),
|
||||||
};
|
};
|
||||||
// The parentheses are always disposed here.
|
// The parentheses are always disposed here.
|
||||||
arg.tree.delimiter = None;
|
arg.0.delimiter = None;
|
||||||
|
|
||||||
let res = def.as_lazy_macro(
|
let res = def.as_lazy_macro(
|
||||||
db.upcast(),
|
db.upcast(),
|
||||||
|
|
|
@ -289,7 +289,7 @@ impl DefCollector<'_> {
|
||||||
|| *attr_name == hir_expand::name![register_tool]
|
|| *attr_name == hir_expand::name![register_tool]
|
||||||
{
|
{
|
||||||
match attr.input.as_deref() {
|
match attr.input.as_deref() {
|
||||||
Some(AttrInput::TokenTree(subtree)) => match &*subtree.tree.token_trees {
|
Some(AttrInput::TokenTree(subtree, _)) => match &*subtree.token_trees {
|
||||||
[tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(),
|
[tt::TokenTree::Leaf(tt::Leaf::Ident(name))] => name.as_name(),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
},
|
},
|
||||||
|
|
|
@ -387,7 +387,7 @@ fn expand_proc_macro(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult<tt::
|
||||||
|
|
||||||
let attr_arg = match &loc.kind {
|
let attr_arg = match &loc.kind {
|
||||||
MacroCallKind::Attr { attr_args, .. } => {
|
MacroCallKind::Attr { attr_args, .. } => {
|
||||||
let mut attr_args = attr_args.tree.clone();
|
let mut attr_args = attr_args.0.clone();
|
||||||
mbe::Shift::new(¯o_arg.0).shift_all(&mut attr_args);
|
mbe::Shift::new(¯o_arg.0).shift_all(&mut attr_args);
|
||||||
Some(attr_args)
|
Some(attr_args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,7 +283,7 @@ pub enum MacroCallKind {
|
||||||
Attr {
|
Attr {
|
||||||
ast_id: AstId<ast::Item>,
|
ast_id: AstId<ast::Item>,
|
||||||
attr_name: String,
|
attr_name: String,
|
||||||
attr_args: mbe::MappedSubTree,
|
attr_args: (tt::Subtree, mbe::TokenMap),
|
||||||
/// Syntactical index of the invoking `#[attribute]`.
|
/// Syntactical index of the invoking `#[attribute]`.
|
||||||
///
|
///
|
||||||
/// Outer attributes are counted first, then inner attributes. This does not support
|
/// Outer attributes are counted first, then inner attributes. This does not support
|
||||||
|
@ -390,7 +390,7 @@ impl ExpansionInfo {
|
||||||
token_tree.left_delimiter_token()?.text_range().start();
|
token_tree.left_delimiter_token()?.text_range().start();
|
||||||
let range = token.value.text_range().checked_sub(attr_input_start)?;
|
let range = token.value.text_range().checked_sub(attr_input_start)?;
|
||||||
let token_id =
|
let token_id =
|
||||||
self.macro_arg_shift.shift(attr_args.map.token_by_range(range)?);
|
self.macro_arg_shift.shift(attr_args.1.token_by_range(range)?);
|
||||||
Some(token_id)
|
Some(token_id)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -437,7 +437,7 @@ impl ExpansionInfo {
|
||||||
MacroCallKind::Attr { attr_args, .. } => match self.macro_arg_shift.unshift(token_id) {
|
MacroCallKind::Attr { attr_args, .. } => match self.macro_arg_shift.unshift(token_id) {
|
||||||
Some(unshifted) => {
|
Some(unshifted) => {
|
||||||
token_id = unshifted;
|
token_id = unshifted;
|
||||||
(&attr_args.map, self.attr_input_or_mac_def.clone()?.syntax().cloned())
|
(&attr_args.1, self.attr_input_or_mac_def.clone()?.syntax().cloned())
|
||||||
}
|
}
|
||||||
None => (&self.macro_arg.1, self.arg.clone()),
|
None => (&self.macro_arg.1, self.arg.clone()),
|
||||||
},
|
},
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub use crate::{
|
||||||
parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
|
parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
|
||||||
token_tree_to_syntax_node,
|
token_tree_to_syntax_node,
|
||||||
},
|
},
|
||||||
token_map::{MappedSubTree, TokenMap},
|
token_map::TokenMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This struct contains AST for a single `macro_rules` definition. What might
|
/// This struct contains AST for a single `macro_rules` definition. What might
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::hash::Hash;
|
||||||
use parser::{SyntaxKind, T};
|
use parser::{SyntaxKind, T};
|
||||||
use syntax::{TextRange, TextSize};
|
use syntax::{TextRange, TextSize};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
enum TokenTextRange {
|
enum TokenTextRange {
|
||||||
Token(TextRange),
|
Token(TextRange),
|
||||||
Delimiter(TextRange),
|
Delimiter(TextRange),
|
||||||
|
@ -26,27 +26,8 @@ impl TokenTextRange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct MappedSubTree {
|
|
||||||
pub tree: tt::Subtree,
|
|
||||||
pub map: TokenMap,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for MappedSubTree {}
|
|
||||||
impl PartialEq for MappedSubTree {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.tree == other.tree && self.map == other.map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for MappedSubTree {
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.tree.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Maps `tt::TokenId` to the relative range of the original token.
|
/// Maps `tt::TokenId` to the relative range of the original token.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
#[derive(Debug, PartialEq, Eq, Clone, Default, Hash)]
|
||||||
pub struct TokenMap {
|
pub struct TokenMap {
|
||||||
/// Maps `tt::TokenId` to the *relative* source range.
|
/// Maps `tt::TokenId` to the *relative* source range.
|
||||||
entries: Vec<(tt::TokenId, TokenTextRange)>,
|
entries: Vec<(tt::TokenId, TokenTextRange)>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue