Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/base_db/src/fixture.rs62
-rw-r--r--crates/rust-analyzer/tests/slow-tests/support.rs3
-rw-r--r--crates/test_utils/src/fixture.rs25
3 files changed, 82 insertions, 8 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index 8025d6398c..417c081c6b 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -6,11 +6,13 @@ use rustc_hash::FxHashMap;
use test_utils::{
extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER, ESCAPED_CURSOR_MARKER,
};
+use tt::Subtree;
use vfs::{file_set::FileSet, VfsPath};
use crate::{
input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId,
- FilePosition, FileRange, SourceDatabaseExt, SourceRoot, SourceRootId,
+ FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
+ SourceDatabaseExt, SourceRoot, SourceRootId,
};
pub const WORKSPACE: SourceRootId = SourceRootId(0);
@@ -81,7 +83,7 @@ pub struct ChangeFixture {
impl ChangeFixture {
pub fn parse(ra_fixture: &str) -> ChangeFixture {
- let (mini_core, fixture) = Fixture::parse(ra_fixture);
+ let (mini_core, proc_macros, fixture) = Fixture::parse(ra_fixture);
let mut change = Change::new();
let mut files = Vec::new();
@@ -203,6 +205,39 @@ impl ChangeFixture {
crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap();
}
}
+
+ if !proc_macros.is_empty() {
+ let proc_lib_file = file_id;
+ file_id.0 += 1;
+
+ let mut fs = FileSet::default();
+ fs.insert(
+ proc_lib_file,
+ VfsPath::new_virtual_path("/sysroot/proc_macros/lib.rs".to_string()),
+ );
+ roots.push(SourceRoot::new_library(fs));
+
+ change.change_file(proc_lib_file, Some(Arc::new(String::new())));
+
+ let all_crates = crate_graph.crates_in_topological_order();
+
+ let proc_macros_crate = crate_graph.add_crate_root(
+ proc_lib_file,
+ Edition::Edition2021,
+ Some(CrateDisplayName::from_canonical_name("proc_macros".to_string())),
+ CfgOptions::default(),
+ CfgOptions::default(),
+ Env::default(),
+ test_proc_macros(&proc_macros),
+ );
+
+ for krate in all_crates {
+ crate_graph
+ .add_dep(krate, CrateName::new("proc_macros").unwrap(), proc_macros_crate)
+ .unwrap();
+ }
+ }
+
let root = match current_source_root_kind {
SourceRootKind::Local => SourceRoot::new_local(mem::take(&mut file_set)),
SourceRootKind::Library => SourceRoot::new_library(mem::take(&mut file_set)),
@@ -215,6 +250,16 @@ impl ChangeFixture {
}
}
+fn test_proc_macros(proc_macros: &[String]) -> Vec<ProcMacro> {
+ std::array::IntoIter::new([ProcMacro {
+ name: "identity".into(),
+ kind: crate::ProcMacroKind::Attr,
+ expander: Arc::new(IdentityProcMacroExpander),
+ }])
+ .filter(|pm| proc_macros.iter().any(|name| name == &pm.name))
+ .collect()
+}
+
#[derive(Debug, Clone, Copy)]
enum SourceRootKind {
Local,
@@ -253,3 +298,16 @@ impl From<Fixture> for FileMeta {
}
}
}
+
+#[derive(Debug)]
+pub struct IdentityProcMacroExpander;
+impl ProcMacroExpander for IdentityProcMacroExpander {
+ fn expand(
+ &self,
+ subtree: &Subtree,
+ _: Option<&Subtree>,
+ _: &Env,
+ ) -> Result<Subtree, ProcMacroExpansionError> {
+ Ok(subtree.clone())
+ }
+}
diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs
index 5cf9158082..99ae418f7c 100644
--- a/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -78,7 +78,8 @@ impl<'a> Project<'a> {
profile::init_from(crate::PROFILE);
});
- let (mini_core, fixtures) = Fixture::parse(self.fixture);
+ let (mini_core, proc_macros, fixtures) = Fixture::parse(self.fixture);
+ assert!(proc_macros.is_empty());
assert!(mini_core.is_none());
for entry in fixtures {
let path = tmp_dir.path().join(&entry.path['/'.len_utf8()..]);
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs
index 166df3ea01..b66065471d 100644
--- a/crates/test_utils/src/fixture.rs
+++ b/crates/test_utils/src/fixture.rs
@@ -92,19 +92,32 @@ impl Fixture {
/// //- other meta
/// ```
///
- /// Fixture can also start with a minicore declaration:
+ /// Fixture can also start with a proc_macros and minicore declaration(in that order):
///
/// ```
+ /// //- proc_macros: identity
/// //- minicore: sized
/// ```
///
- /// That will include a subset of `libcore` into the fixture, see
+ /// That will include predefined proc macros and a subset of `libcore` into the fixture, see
/// `minicore.rs` for what's available.
- pub fn parse(ra_fixture: &str) -> (Option<MiniCore>, Vec<Fixture>) {
+ pub fn parse(ra_fixture: &str) -> (Option<MiniCore>, Vec<String>, Vec<Fixture>) {
let fixture = trim_indent(ra_fixture);
let mut fixture = fixture.as_str();
let mut mini_core = None;
let mut res: Vec<Fixture> = Vec::new();
+ let mut test_proc_macros = vec![];
+
+ if fixture.starts_with("//- proc_macros:") {
+ let first_line = fixture.split_inclusive('\n').next().unwrap();
+ test_proc_macros = first_line
+ .strip_prefix("//- proc_macros:")
+ .unwrap()
+ .split(',')
+ .map(|it| it.trim().to_string())
+ .collect();
+ fixture = &fixture[first_line.len()..];
+ }
if fixture.starts_with("//- minicore:") {
let first_line = fixture.split_inclusive('\n').next().unwrap();
@@ -144,7 +157,7 @@ impl Fixture {
}
}
- (mini_core, res)
+ (mini_core, test_proc_macros, res)
}
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
@@ -355,13 +368,15 @@ fn parse_fixture_checks_further_indented_metadata() {
#[test]
fn parse_fixture_gets_full_meta() {
- let (mini_core, parsed) = Fixture::parse(
+ let (mini_core, proc_macros, parsed) = Fixture::parse(
r#"
+//- proc_macros: identity
//- minicore: coerce_unsized
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
mod m;
"#,
);
+ assert_eq!(proc_macros, vec!["identity".to_string()]);
assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_string()]);
assert_eq!(1, parsed.len());