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.rs114
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