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 | 114 |
1 files changed, 70 insertions, 44 deletions
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index a718b96a82..b9c389c769 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -1,11 +1,17 @@ //! A set of high-level utility fixture methods to use in tests. + +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_driver as _; + use std::{any::TypeId, mem, str::FromStr, sync}; use base_db::target::TargetData; use base_db::{ Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData, DependencyBuilder, Env, FileChange, FileSet, FxIndexMap, LangCrateOrigin, SourceDatabase, - SourceRoot, Version, VfsPath, salsa, + SourceRoot, Version, VfsPath, }; use cfg::CfgOptions; use hir_expand::{ @@ -37,10 +43,11 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { #[rust_analyzer::rust_fixture] ra_fixture: &str, ) -> (Self, EditionedFileId) { let mut db = Self::default(); - let fixture = ChangeFixture::parse(&db, ra_fixture); + let fixture = ChangeFixture::parse(ra_fixture); fixture.change.apply(&mut db); assert_eq!(fixture.files.len(), 1, "Multiple file found in the fixture"); - (db, fixture.files[0]) + let file = EditionedFileId::from_span_guess_origin(&db, fixture.files[0]); + (db, file) } #[track_caller] @@ -48,16 +55,21 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { #[rust_analyzer::rust_fixture] ra_fixture: &str, ) -> (Self, Vec<EditionedFileId>) { let mut db = Self::default(); - let fixture = ChangeFixture::parse(&db, ra_fixture); + let fixture = ChangeFixture::parse(ra_fixture); fixture.change.apply(&mut db); assert!(fixture.file_position.is_none()); - (db, fixture.files) + let files = fixture + .files + .into_iter() + .map(|file| EditionedFileId::from_span_guess_origin(&db, file)) + .collect(); + (db, files) } #[track_caller] fn with_files(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Self { let mut db = Self::default(); - let fixture = ChangeFixture::parse(&db, ra_fixture); + let fixture = ChangeFixture::parse(ra_fixture); fixture.change.apply(&mut db); assert!(fixture.file_position.is_none()); db @@ -69,12 +81,8 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { proc_macros: Vec<(String, ProcMacro)>, ) -> Self { let mut db = Self::default(); - let fixture = ChangeFixture::parse_with_proc_macros( - &db, - ra_fixture, - MiniCore::RAW_SOURCE, - proc_macros, - ); + let fixture = + ChangeFixture::parse_with_proc_macros(ra_fixture, MiniCore::RAW_SOURCE, proc_macros); fixture.change.apply(&mut db); assert!(fixture.file_position.is_none()); db @@ -99,12 +107,13 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { #[rust_analyzer::rust_fixture] ra_fixture: &str, ) -> (Self, EditionedFileId, RangeOrOffset) { let mut db = Self::default(); - let fixture = ChangeFixture::parse(&db, ra_fixture); + let fixture = ChangeFixture::parse(ra_fixture); fixture.change.apply(&mut db); let (file_id, range_or_offset) = fixture .file_position .expect("Could not find file position in fixture. Did you forget to add an `$0`?"); + let file_id = EditionedFileId::from_span_guess_origin(&db, file_id); (db, file_id, range_or_offset) } @@ -116,9 +125,9 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static { impl<DB: ExpandDatabase + SourceDatabase + Default + 'static> WithFixture for DB {} pub struct ChangeFixture { - pub file_position: Option<(EditionedFileId, RangeOrOffset)>, + pub file_position: Option<(span::EditionedFileId, RangeOrOffset)>, pub file_lines: Vec<usize>, - pub files: Vec<EditionedFileId>, + pub files: Vec<span::EditionedFileId>, pub change: ChangeWithProcMacros, pub sysroot_files: Vec<FileId>, } @@ -126,15 +135,11 @@ pub struct ChangeFixture { const SOURCE_ROOT_PREFIX: &str = "/"; impl ChangeFixture { - pub fn parse( - db: &dyn salsa::Database, - #[rust_analyzer::rust_fixture] ra_fixture: &str, - ) -> ChangeFixture { - Self::parse_with_proc_macros(db, ra_fixture, MiniCore::RAW_SOURCE, Vec::new()) + pub fn parse(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> ChangeFixture { + Self::parse_with_proc_macros(ra_fixture, MiniCore::RAW_SOURCE, Vec::new()) } pub fn parse_with_proc_macros( - db: &dyn salsa::Database, #[rust_analyzer::rust_fixture] ra_fixture: &str, minicore_raw: &str, mut proc_macro_defs: Vec<(String, ProcMacro)>, @@ -202,7 +207,7 @@ impl ChangeFixture { let meta = FileMeta::from_fixture(entry, current_source_root_kind); if let Some(range_or_offset) = range_or_offset { file_position = - Some((EditionedFileId::new(db, file_id, meta.edition), range_or_offset)); + Some((span::EditionedFileId::new(file_id, meta.edition), range_or_offset)); } assert!(meta.path.starts_with(SOURCE_ROOT_PREFIX)); @@ -234,6 +239,7 @@ impl ChangeFixture { Some(meta.cfg), meta.env, origin, + meta.crate_attrs, false, proc_macro_cwd.clone(), crate_ws_data.clone(), @@ -259,7 +265,7 @@ impl ChangeFixture { source_change.change_file(file_id, Some(text)); let path = VfsPath::new_virtual_path(meta.path); file_set.insert(file_id, path); - files.push(EditionedFileId::new(db, file_id, meta.edition)); + files.push(span::EditionedFileId::new(file_id, meta.edition)); file_id = FileId::from_raw(file_id.index() + 1); } @@ -287,6 +293,7 @@ impl ChangeFixture { String::from("__ra_is_test_fixture"), )]), CrateOrigin::Lang(LangCrateOrigin::Core), + Vec::new(), false, proc_macro_cwd.clone(), crate_ws_data.clone(), @@ -317,6 +324,7 @@ impl ChangeFixture { Some(default_cfg), default_env, CrateOrigin::Local { repo: None, name: None }, + Vec::new(), false, proc_macro_cwd.clone(), crate_ws_data.clone(), @@ -380,6 +388,7 @@ impl ChangeFixture { String::from("__ra_is_test_fixture"), )]), CrateOrigin::Local { repo: None, name: None }, + Vec::new(), true, proc_macro_cwd, crate_ws_data, @@ -630,6 +639,7 @@ struct FileMeta { cfg: CfgOptions, edition: Edition, env: Env, + crate_attrs: Vec<String>, introduce_new_source_root: Option<SourceRootKind>, } @@ -661,6 +671,7 @@ impl FileMeta { cfg, edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()), env: f.env.into_iter().collect(), + crate_attrs: f.crate_attrs, introduce_new_source_root, } } @@ -727,6 +738,7 @@ struct IdentityProcMacroExpander; impl ProcMacroExpander for IdentityProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -749,6 +761,7 @@ struct Issue18089ProcMacroExpander; impl ProcMacroExpander for Issue18089ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -757,7 +770,7 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander { _: Span, _: String, ) -> Result<TopSubtree, ProcMacroExpansionError> { - let tt::TokenTree::Leaf(macro_name) = &subtree.0[2] else { + let Some(tt::TtElement::Leaf(macro_name)) = subtree.iter().nth(1) else { return Err(ProcMacroExpansionError::Panic("incorrect input".to_owned())); }; Ok(quote! { call_site => @@ -784,6 +797,7 @@ struct AttributeInputReplaceProcMacroExpander; impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, _: &TopSubtree, attrs: Option<&TopSubtree>, _: &Env, @@ -807,6 +821,7 @@ struct Issue18840ProcMacroExpander; impl ProcMacroExpander for Issue18840ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, fn_: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -822,13 +837,14 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander { // ``` // The span that was created by the fixup infra. - let fixed_up_span = fn_.token_trees().flat_tokens()[5].first_span(); + let mut iter = fn_.iter(); + iter.nth(2); + let (_, mut fn_body) = iter.expect_subtree().unwrap(); + let fixed_up_span = fn_body.nth(1).unwrap().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; + result.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(def_site)); Ok(result) } @@ -842,6 +858,7 @@ struct MirrorProcMacroExpander; impl ProcMacroExpander for MirrorProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, input: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -880,6 +897,7 @@ struct ShortenProcMacroExpander; impl ProcMacroExpander for ShortenProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, input: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -888,20 +906,22 @@ impl ProcMacroExpander for ShortenProcMacroExpander { _: Span, _: String, ) -> Result<TopSubtree, ProcMacroExpansionError> { - let mut result = input.0.clone(); - for it in &mut result { - if let TokenTree::Leaf(leaf) = it { - modify_leaf(leaf) + let mut result = input.clone(); + for (idx, it) in input.as_token_trees().iter_flat_tokens().enumerate() { + if let TokenTree::Leaf(mut leaf) = it { + modify_leaf(&mut leaf); + result.set_token(idx, leaf); } } - return Ok(tt::TopSubtree(result)); + return Ok(result); 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. - it.symbol = Symbol::empty(); + it.text_and_suffix = Symbol::empty(); + it.suffix_len = 0; } Leaf::Punct(_) => {} Leaf::Ident(it) => { @@ -922,6 +942,7 @@ struct Issue17479ProcMacroExpander; impl ProcMacroExpander for Issue17479ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -930,10 +951,11 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander { _: Span, _: String, ) -> Result<TopSubtree, ProcMacroExpansionError> { - let TokenTree::Leaf(Leaf::Literal(lit)) = &subtree.0[1] else { + let mut iter = subtree.iter(); + let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = iter.next() else { return Err(ProcMacroExpansionError::Panic("incorrect Input".into())); }; - let symbol = &lit.symbol; + let symbol = Symbol::intern(lit.text()); let span = lit.span; Ok(quote! { span => #symbol() @@ -951,6 +973,7 @@ struct Issue18898ProcMacroExpander; impl ProcMacroExpander for Issue18898ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -961,10 +984,8 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander { ) -> Result<TopSubtree, ProcMacroExpansionError> { let span = subtree .token_trees() - .flat_tokens() - .last() - .ok_or_else(|| ProcMacroExpansionError::Panic("malformed input".to_owned()))? - .first_span(); + .last_span() + .ok_or_else(|| ProcMacroExpansionError::Panic("malformed input".to_owned()))?; let overly_long_subtree = quote! {span => { let a = 5; @@ -1006,6 +1027,7 @@ struct DisallowCfgProcMacroExpander; impl ProcMacroExpander for DisallowCfgProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -1014,7 +1036,7 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander { _: Span, _: String, ) -> Result<TopSubtree, ProcMacroExpansionError> { - for tt in subtree.token_trees().flat_tokens() { + for tt in subtree.token_trees().iter_flat_tokens() { if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt && (ident.sym == sym::cfg || ident.sym == sym::cfg_attr) { @@ -1037,6 +1059,7 @@ struct GenerateSuffixedTypeProcMacroExpander; impl ProcMacroExpander for GenerateSuffixedTypeProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _attrs: Option<&TopSubtree>, _env: &Env, @@ -1045,20 +1068,23 @@ impl ProcMacroExpander for GenerateSuffixedTypeProcMacroExpander { _mixed_site: Span, _current_dir: String, ) -> Result<TopSubtree, ProcMacroExpansionError> { - let TokenTree::Leaf(Leaf::Ident(ident)) = &subtree.0[1] else { + let mut iter = subtree.iter(); + let Some(TtElement::Leaf(tt::Leaf::Ident(ident))) = iter.next() else { return Err(ProcMacroExpansionError::Panic("incorrect Input".into())); }; let ident = match ident.sym.as_str() { "struct" => { - let TokenTree::Leaf(Leaf::Ident(ident)) = &subtree.0[2] else { + let Some(TtElement::Leaf(tt::Leaf::Ident(ident))) = iter.next() else { return Err(ProcMacroExpansionError::Panic("incorrect Input".into())); }; ident } "enum" => { - let TokenTree::Leaf(Leaf::Ident(ident)) = &subtree.0[4] else { + iter.next(); + let (_, mut iter) = iter.expect_subtree().unwrap(); + let Some(TtElement::Leaf(tt::Leaf::Ident(ident))) = iter.next() else { return Err(ProcMacroExpansionError::Panic("incorrect Input".into())); }; ident |