Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/test-fixture/src/lib.rs')
-rw-r--r--crates/test-fixture/src/lib.rs175
1 files changed, 130 insertions, 45 deletions
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 889a7d10ad..0e72d79687 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -13,16 +13,18 @@ use hir_expand::{
proc_macro::{
ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacrosBuilder,
},
- quote, FileRange,
+ quote,
+ tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter},
+ FileRange,
};
use intern::Symbol;
use rustc_hash::FxHashMap;
use span::{Edition, EditionedFileId, FileId, Span};
+use stdx::itertools::Itertools;
use test_utils::{
extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
ESCAPED_CURSOR_MARKER,
};
-use tt::{Leaf, Subtree, TokenTree};
pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0);
@@ -374,7 +376,7 @@ impl ChangeFixture {
}
}
-fn default_test_proc_macros() -> [(String, ProcMacro); 6] {
+fn default_test_proc_macros() -> [(String, ProcMacro); 8] {
[
(
r#"
@@ -466,6 +468,36 @@ pub fn issue_18089(_attr: TokenStream, _item: TokenStream) -> TokenStream {
disabled: false,
},
),
+ (
+ r#"
+#[proc_macro_attribute]
+pub fn issue_18840(_attr: TokenStream, _item: TokenStream) -> TokenStream {
+ loop {}
+}
+"#
+ .into(),
+ ProcMacro {
+ name: Symbol::intern("issue_18840"),
+ kind: ProcMacroKind::Attr,
+ expander: sync::Arc::new(Issue18840ProcMacroExpander),
+ disabled: false,
+ },
+ ),
+ (
+ r#"
+#[proc_macro]
+pub fn issue_17479(input: TokenStream) -> TokenStream {
+ input
+}
+"#
+ .into(),
+ ProcMacro {
+ name: Symbol::intern("issue_17479"),
+ kind: ProcMacroKind::Bang,
+ expander: sync::Arc::new(Issue17479ProcMacroExpander),
+ disabled: false,
+ },
+ ),
]
}
@@ -580,14 +612,14 @@ struct IdentityProcMacroExpander;
impl ProcMacroExpander for IdentityProcMacroExpander {
fn expand(
&self,
- subtree: &Subtree<Span>,
- _: Option<&Subtree<Span>>,
+ subtree: &TopSubtree,
+ _: Option<&TopSubtree>,
_: &Env,
_: Span,
_: Span,
_: Span,
_: Option<String>,
- ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
Ok(subtree.clone())
}
}
@@ -598,15 +630,17 @@ struct Issue18089ProcMacroExpander;
impl ProcMacroExpander for Issue18089ProcMacroExpander {
fn expand(
&self,
- subtree: &Subtree<Span>,
- _: Option<&Subtree<Span>>,
+ subtree: &TopSubtree,
+ _: Option<&TopSubtree>,
_: &Env,
_: Span,
call_site: Span,
_: Span,
_: Option<String>,
- ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
- let macro_name = &subtree.token_trees[1];
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
+ let tt::TokenTree::Leaf(macro_name) = &subtree.0[2] else {
+ return Err(ProcMacroExpansionError::Panic("incorrect input".to_owned()));
+ };
Ok(quote! { call_site =>
#[macro_export]
macro_rules! my_macro___ {
@@ -627,14 +661,14 @@ struct AttributeInputReplaceProcMacroExpander;
impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
fn expand(
&self,
- _: &Subtree<Span>,
- attrs: Option<&Subtree<Span>>,
+ _: &TopSubtree,
+ attrs: Option<&TopSubtree>,
_: &Env,
_: Span,
_: Span,
_: Span,
_: Option<String>,
- ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
attrs
.cloned()
.ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into()))
@@ -642,30 +676,64 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
}
#[derive(Debug)]
+struct Issue18840ProcMacroExpander;
+impl ProcMacroExpander for Issue18840ProcMacroExpander {
+ fn expand(
+ &self,
+ fn_: &TopSubtree,
+ _: Option<&TopSubtree>,
+ _: &Env,
+ def_site: Span,
+ _: Span,
+ _: Span,
+ _: Option<String>,
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
+ // Input:
+ // ```
+ // #[issue_18840]
+ // fn foo() { let loop {} }
+ // ```
+
+ // The span that was created by the fixup infra.
+ let fixed_up_span = fn_.token_trees().flat_tokens()[5].first_span();
+ let mut result =
+ quote! {fixed_up_span => ::core::compile_error! { "my cool compile_error!" } };
+ // Make it so we won't remove the top subtree when reversing fixups.
+ let top_subtree_delimiter_mut = result.top_subtree_delimiter_mut();
+ top_subtree_delimiter_mut.open = def_site;
+ top_subtree_delimiter_mut.close = def_site;
+ Ok(result)
+ }
+}
+
+#[derive(Debug)]
struct MirrorProcMacroExpander;
impl ProcMacroExpander for MirrorProcMacroExpander {
fn expand(
&self,
- input: &Subtree<Span>,
- _: Option<&Subtree<Span>>,
+ input: &TopSubtree,
+ _: Option<&TopSubtree>,
_: &Env,
_: Span,
_: Span,
_: Span,
_: Option<String>,
- ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
- fn traverse(input: &Subtree<Span>) -> Subtree<Span> {
- let mut token_trees = vec![];
- for tt in input.token_trees.iter().rev() {
- let tt = match tt {
- tt::TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(leaf.clone()),
- tt::TokenTree::Subtree(sub) => tt::TokenTree::Subtree(traverse(sub)),
- };
- token_trees.push(tt);
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
+ fn traverse(builder: &mut TopSubtreeBuilder, iter: TtIter<'_>) {
+ for tt in iter.collect_vec().into_iter().rev() {
+ match tt {
+ TtElement::Leaf(leaf) => builder.push(leaf.clone()),
+ TtElement::Subtree(subtree, subtree_iter) => {
+ builder.open(subtree.delimiter.kind, subtree.delimiter.open);
+ traverse(builder, subtree_iter);
+ builder.close(subtree.delimiter.close);
+ }
+ }
}
- Subtree { delimiter: input.delimiter, token_trees: token_trees.into_boxed_slice() }
}
- Ok(traverse(input))
+ let mut builder = TopSubtreeBuilder::new(input.top_subtree().delimiter);
+ traverse(&mut builder, input.iter());
+ Ok(builder.build())
}
}
@@ -677,31 +745,24 @@ struct ShortenProcMacroExpander;
impl ProcMacroExpander for ShortenProcMacroExpander {
fn expand(
&self,
- input: &Subtree<Span>,
- _: Option<&Subtree<Span>>,
+ input: &TopSubtree,
+ _: Option<&TopSubtree>,
_: &Env,
_: Span,
_: Span,
_: Span,
_: Option<String>,
- ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
- return Ok(traverse(input));
-
- fn traverse(input: &Subtree<Span>) -> Subtree<Span> {
- let token_trees = input
- .token_trees
- .iter()
- .map(|it| match it {
- TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(modify_leaf(leaf)),
- TokenTree::Subtree(subtree) => tt::TokenTree::Subtree(traverse(subtree)),
- })
- .collect();
- Subtree { delimiter: input.delimiter, token_trees }
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
+ let mut result = input.0.clone();
+ for it in &mut result {
+ if let TokenTree::Leaf(leaf) = it {
+ modify_leaf(leaf)
+ }
}
+ return Ok(tt::TopSubtree(result));
- fn modify_leaf(leaf: &Leaf<Span>) -> Leaf<Span> {
- let mut leaf = leaf.clone();
- match &mut leaf {
+ fn modify_leaf(leaf: &mut Leaf) {
+ match leaf {
Leaf::Literal(it) => {
// XXX Currently replaces any literals with an empty string, but supporting
// "shortening" other literals would be nice.
@@ -712,7 +773,31 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
it.sym = Symbol::intern(&it.sym.as_str().chars().take(1).collect::<String>());
}
}
- leaf
}
}
}
+
+// Reads ident type within string quotes, for issue #17479.
+#[derive(Debug)]
+struct Issue17479ProcMacroExpander;
+impl ProcMacroExpander for Issue17479ProcMacroExpander {
+ fn expand(
+ &self,
+ subtree: &TopSubtree,
+ _: Option<&TopSubtree>,
+ _: &Env,
+ _: Span,
+ _: Span,
+ _: Span,
+ _: Option<String>,
+ ) -> Result<TopSubtree, ProcMacroExpansionError> {
+ let TokenTree::Leaf(Leaf::Literal(lit)) = &subtree.0[1] else {
+ return Err(ProcMacroExpansionError::Panic("incorrect Input".into()));
+ };
+ let symbol = &lit.symbol;
+ let span = lit.span;
+ Ok(quote! { span =>
+ #symbol()
+ })
+ }
+}