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.rs | 175 |
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() + }) + } +} |