3727: Introduce ra_proc_macro r=matklad a=edwin0cheng

This PR implemented:

1.  Reading dylib path of proc-macro crate from cargo check , similar to how `OUTDIR` is obtained.
2.  Added a new crate `ra_proc_macro` and implement the foot-work for reading result from external proc-macro expander. 
3. Added a struct `ProcMacroClient` , which will be responsible to the client side communication to the External process.



Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-03-26 17:09:32 +00:00 committed by GitHub
commit b1594f1080
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 259 additions and 38 deletions

9
Cargo.lock generated
View file

@ -928,6 +928,7 @@ dependencies = [
"ra_cfg", "ra_cfg",
"ra_prof", "ra_prof",
"ra_syntax", "ra_syntax",
"ra_tt",
"relative-path", "relative-path",
"rustc-hash", "rustc-hash",
"salsa", "salsa",
@ -1081,6 +1082,13 @@ dependencies = [
"drop_bomb", "drop_bomb",
] ]
[[package]]
name = "ra_proc_macro"
version = "0.1.0"
dependencies = [
"ra_tt",
]
[[package]] [[package]]
name = "ra_prof" name = "ra_prof"
version = "0.1.0" version = "0.1.0"
@ -1102,6 +1110,7 @@ dependencies = [
"ra_cargo_watch", "ra_cargo_watch",
"ra_cfg", "ra_cfg",
"ra_db", "ra_db",
"ra_proc_macro",
"rustc-hash", "rustc-hash",
"serde", "serde",
"serde_json", "serde_json",

View file

@ -15,4 +15,5 @@ rustc-hash = "1.1.0"
ra_syntax = { path = "../ra_syntax" } ra_syntax = { path = "../ra_syntax" }
ra_cfg = { path = "../ra_cfg" } ra_cfg = { path = "../ra_cfg" }
ra_prof = { path = "../ra_prof" } ra_prof = { path = "../ra_prof" }
ra_tt = { path = "../ra_tt" }
test_utils = { path = "../test_utils" } test_utils = { path = "../test_utils" }

View file

@ -70,6 +70,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
meta.cfg, meta.cfg,
meta.env, meta.env,
Default::default(), Default::default(),
Default::default(),
); );
crate_graph crate_graph
} else { } else {
@ -81,6 +82,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
crate_graph crate_graph
}; };
@ -130,6 +132,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
meta.cfg, meta.cfg,
meta.env, meta.env,
Default::default(), Default::default(),
Default::default(),
); );
let prev = crates.insert(krate.clone(), crate_id); let prev = crates.insert(krate.clone(), crate_id);
assert!(prev.is_none()); assert!(prev.is_none());
@ -167,6 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
} else { } else {
for (from, to) in crate_deps { for (from, to) in crate_deps {

View file

@ -10,6 +10,7 @@ use std::{
fmt, ops, fmt, ops,
path::{Path, PathBuf}, path::{Path, PathBuf},
str::FromStr, str::FromStr,
sync::Arc,
}; };
use ra_cfg::CfgOptions; use ra_cfg::CfgOptions;
@ -19,6 +20,7 @@ use rustc_hash::FxHashSet;
use crate::{RelativePath, RelativePathBuf}; use crate::{RelativePath, RelativePathBuf};
use fmt::Display; use fmt::Display;
use ra_tt::TokenExpander;
/// `FileId` is an integer which uniquely identifies a file. File paths are /// `FileId` is an integer which uniquely identifies a file. File paths are
/// messy and system-dependent, so most of the code should work directly with /// messy and system-dependent, so most of the code should work directly with
@ -115,6 +117,22 @@ impl Display for CrateName {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ProcMacroId(pub u32);
#[derive(Debug, Clone)]
pub struct ProcMacro {
pub name: SmolStr,
pub expander: Arc<dyn TokenExpander>,
}
impl Eq for ProcMacro {}
impl PartialEq for ProcMacro {
fn eq(&self, other: &ProcMacro) -> bool {
self.name == other.name && Arc::ptr_eq(&self.expander, &other.expander)
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct CrateData { pub struct CrateData {
pub root_file_id: FileId, pub root_file_id: FileId,
@ -127,6 +145,7 @@ pub struct CrateData {
pub env: Env, pub env: Env,
pub extern_source: ExternSource, pub extern_source: ExternSource,
pub dependencies: Vec<Dependency>, pub dependencies: Vec<Dependency>,
pub proc_macro: Vec<ProcMacro>,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -166,7 +185,11 @@ impl CrateGraph {
cfg_options: CfgOptions, cfg_options: CfgOptions,
env: Env, env: Env,
extern_source: ExternSource, extern_source: ExternSource,
proc_macro: Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)>,
) -> CrateId { ) -> CrateId {
let proc_macro =
proc_macro.into_iter().map(|(name, it)| ProcMacro { name, expander: it }).collect();
let data = CrateData { let data = CrateData {
root_file_id: file_id, root_file_id: file_id,
edition, edition,
@ -174,6 +197,7 @@ impl CrateGraph {
cfg_options, cfg_options,
env, env,
extern_source, extern_source,
proc_macro,
dependencies: Vec::new(), dependencies: Vec::new(),
}; };
let crate_id = CrateId(self.arena.len() as u32); let crate_id = CrateId(self.arena.len() as u32);
@ -345,6 +369,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId(2u32), FileId(2u32),
@ -353,6 +378,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let crate3 = graph.add_crate_root( let crate3 = graph.add_crate_root(
FileId(3u32), FileId(3u32),
@ -361,6 +387,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@ -377,6 +404,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId(2u32), FileId(2u32),
@ -385,6 +413,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let crate3 = graph.add_crate_root( let crate3 = graph.add_crate_root(
FileId(3u32), FileId(3u32),
@ -393,6 +422,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@ -408,6 +438,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId(2u32), FileId(2u32),
@ -416,6 +447,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
assert!(graph assert!(graph
.add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2)

View file

@ -12,7 +12,7 @@ pub use crate::{
cancellation::Canceled, cancellation::Canceled,
input::{ input::{
CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId,
FileId, SourceRoot, SourceRootId, FileId, ProcMacroId, SourceRoot, SourceRootId,
}, },
}; };
pub use relative_path::{RelativePath, RelativePathBuf}; pub use relative_path::{RelativePath, RelativePathBuf};

View file

@ -11,7 +11,7 @@ use hir_expand::{
HirFileId, MacroCallId, MacroDefId, MacroDefKind, HirFileId, MacroCallId, MacroDefId, MacroDefKind,
}; };
use ra_cfg::CfgOptions; use ra_cfg::CfgOptions;
use ra_db::{CrateId, FileId}; use ra_db::{CrateId, FileId, ProcMacroId};
use ra_syntax::ast; use ra_syntax::ast;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use test_utils::tested_by; use test_utils::tested_by;
@ -53,6 +53,16 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
} }
let cfg_options = &crate_graph[def_map.krate].cfg_options; let cfg_options = &crate_graph[def_map.krate].cfg_options;
let proc_macros = &crate_graph[def_map.krate].proc_macro;
let proc_macros = proc_macros
.iter()
.enumerate()
.map(|(idx, it)| {
// FIXME: a hacky way to create a Name from string.
let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
(name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx as u32)))
})
.collect();
let mut collector = DefCollector { let mut collector = DefCollector {
db, db,
@ -65,9 +75,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
unexpanded_attribute_macros: Vec::new(), unexpanded_attribute_macros: Vec::new(),
mod_dirs: FxHashMap::default(), mod_dirs: FxHashMap::default(),
cfg_options, cfg_options,
proc_macros,
// FIXME: pass proc-macro from crate-graph
proc_macros: Default::default(),
}; };
collector.collect(); collector.collect();
collector.finish() collector.finish()

View file

@ -1,33 +1,32 @@
//! Proc Macro Expander stub //! Proc Macro Expander stub
use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc}; use crate::{db::AstDatabase, LazyMacroId};
use ra_db::CrateId; use ra_db::{CrateId, ProcMacroId};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct ProcMacroExpander { pub struct ProcMacroExpander {
krate: CrateId, krate: CrateId,
proc_macro_id: ProcMacroId,
} }
impl ProcMacroExpander { impl ProcMacroExpander {
pub fn new(krate: CrateId) -> ProcMacroExpander { pub fn new(krate: CrateId, proc_macro_id: ProcMacroId) -> ProcMacroExpander {
ProcMacroExpander { krate } ProcMacroExpander { krate, proc_macro_id }
} }
pub fn expand( pub fn expand(
&self, &self,
db: &dyn AstDatabase, db: &dyn AstDatabase,
id: LazyMacroId, _id: LazyMacroId,
_tt: &tt::Subtree, tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> { ) -> Result<tt::Subtree, mbe::ExpandError> {
let loc: MacroCallLoc = db.lookup_intern_macro(id); let krate_graph = db.crate_graph();
let name = match loc.kind { let proc_macro = krate_graph[self.krate]
MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError), .proc_macro
MacroCallKind::Attr(_, name) => name, .get(self.proc_macro_id.0 as usize)
}; .clone()
.ok_or_else(|| mbe::ExpandError::ConversionError)?;
log::debug!("Proc-macro-expanding name = {}", name); proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from)
// Return nothing for now
return Ok(tt::Subtree::default());
} }
} }

View file

@ -213,6 +213,7 @@ impl Analysis {
cfg_options, cfg_options,
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
change.set_crate_graph(crate_graph); change.set_crate_graph(crate_graph);

View file

@ -103,6 +103,7 @@ impl MockAnalysis {
cfg_options, cfg_options,
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
)); ));
} else if path.ends_with("/lib.rs") { } else if path.ends_with("/lib.rs") {
let crate_name = path.parent().unwrap().file_name().unwrap(); let crate_name = path.parent().unwrap().file_name().unwrap();
@ -113,6 +114,7 @@ impl MockAnalysis {
cfg_options, cfg_options,
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
if let Some(root_crate) = root_crate { if let Some(root_crate) = root_crate {
crate_graph crate_graph

View file

@ -137,6 +137,7 @@ mod tests {
CfgOptions::default(), CfgOptions::default(),
Env::default(), Env::default(),
Default::default(), Default::default(),
Default::default(),
); );
let mut change = AnalysisChange::new(); let mut change = AnalysisChange::new();
change.set_crate_graph(crate_graph); change.set_crate_graph(crate_graph);

View file

@ -28,6 +28,13 @@ pub enum ExpandError {
BindingError(String), BindingError(String),
ConversionError, ConversionError,
InvalidRepeat, InvalidRepeat,
ProcMacroError(tt::ExpansionError),
}
impl From<tt::ExpansionError> for ExpandError {
fn from(it: tt::ExpansionError) -> Self {
ExpandError::ProcMacroError(it)
}
} }
pub use crate::syntax_bridge::{ pub use crate::syntax_bridge::{

View file

@ -0,0 +1,12 @@
[package]
edition = "2018"
name = "ra_proc_macro"
version = "0.1.0"
authors = ["rust-analyzer developers"]
publish = false
[lib]
doctest = false
[dependencies]
ra_tt = { path = "../ra_tt" }

View file

@ -0,0 +1,59 @@
//! Client-side Proc-Macro crate
//!
//! We separate proc-macro expanding logic to an extern program to allow
//! different implementations (e.g. wasm or dylib loading). And this crate
//! is used to provide basic infrastructure for communication between two
//! processes: Client (RA itself), Server (the external program)
use ra_tt::{SmolStr, Subtree};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProcMacroProcessExpander {
process: Arc<ProcMacroProcessSrv>,
name: SmolStr,
}
impl ra_tt::TokenExpander for ProcMacroProcessExpander {
fn expand(
&self,
_subtree: &Subtree,
_attr: Option<&Subtree>,
) -> Result<Subtree, ra_tt::ExpansionError> {
// FIXME: do nothing for now
Ok(Subtree::default())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProcMacroProcessSrv {
path: PathBuf,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProcMacroClient {
Process { process: Arc<ProcMacroProcessSrv> },
Dummy,
}
impl ProcMacroClient {
pub fn extern_process(process_path: &Path) -> ProcMacroClient {
let process = ProcMacroProcessSrv { path: process_path.into() };
ProcMacroClient::Process { process: Arc::new(process) }
}
pub fn dummy() -> ProcMacroClient {
ProcMacroClient::Dummy
}
pub fn by_dylib_path(
&self,
_dylib_path: &Path,
) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> {
// FIXME: return empty for now
vec![]
}
}

View file

@ -17,6 +17,7 @@ ra_arena = { path = "../ra_arena" }
ra_db = { path = "../ra_db" } ra_db = { path = "../ra_db" }
ra_cfg = { path = "../ra_cfg" } ra_cfg = { path = "../ra_cfg" }
ra_cargo_watch = { path = "../ra_cargo_watch" } ra_cargo_watch = { path = "../ra_cargo_watch" }
ra_proc_macro = { path = "../ra_proc_macro" }
serde = { version = "1.0.104", features = ["derive"] } serde = { version = "1.0.104", features = ["derive"] }
serde_json = "1.0.48" serde_json = "1.0.48"

View file

@ -83,6 +83,7 @@ pub struct PackageData {
pub edition: Edition, pub edition: Edition,
pub features: Vec<String>, pub features: Vec<String>,
pub out_dir: Option<PathBuf>, pub out_dir: Option<PathBuf>,
pub proc_macro_dylib_path: Option<PathBuf>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -158,8 +159,11 @@ impl CargoWorkspace {
})?; })?;
let mut out_dir_by_id = FxHashMap::default(); let mut out_dir_by_id = FxHashMap::default();
let mut proc_macro_dylib_paths = FxHashMap::default();
if cargo_features.load_out_dirs_from_check { if cargo_features.load_out_dirs_from_check {
out_dir_by_id = load_out_dirs(cargo_toml, cargo_features); let resources = load_extern_resources(cargo_toml, cargo_features);
out_dir_by_id = resources.out_dirs;
proc_macro_dylib_paths = resources.proc_dylib_paths;
} }
let mut pkg_by_id = FxHashMap::default(); let mut pkg_by_id = FxHashMap::default();
@ -183,6 +187,7 @@ impl CargoWorkspace {
dependencies: Vec::new(), dependencies: Vec::new(),
features: Vec::new(), features: Vec::new(),
out_dir: out_dir_by_id.get(&id).cloned(), out_dir: out_dir_by_id.get(&id).cloned(),
proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
}); });
let pkg_data = &mut packages[pkg]; let pkg_data = &mut packages[pkg];
pkg_by_id.insert(id, pkg); pkg_by_id.insert(id, pkg);
@ -246,10 +251,13 @@ impl CargoWorkspace {
} }
} }
pub fn load_out_dirs( #[derive(Debug, Clone, Default)]
cargo_toml: &Path, pub struct ExternResources {
cargo_features: &CargoFeatures, out_dirs: FxHashMap<PackageId, PathBuf>,
) -> FxHashMap<PackageId, PathBuf> { proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
}
pub fn load_extern_resources(cargo_toml: &Path, cargo_features: &CargoFeatures) -> ExternResources {
let mut args: Vec<String> = vec![ let mut args: Vec<String> = vec![
"check".to_string(), "check".to_string(),
"--message-format=json".to_string(), "--message-format=json".to_string(),
@ -267,14 +275,21 @@ pub fn load_out_dirs(
args.extend(cargo_features.features.iter().cloned()); args.extend(cargo_features.features.iter().cloned());
} }
let mut acc = FxHashMap::default(); let mut acc = ExternResources::default();
let res = run_cargo(&args, cargo_toml.parent(), &mut |message| { let res = run_cargo(&args, cargo_toml.parent(), &mut |message| {
match message { match message {
Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => {
acc.insert(package_id, out_dir); acc.out_dirs.insert(package_id, out_dir);
} }
Message::CompilerArtifact(_) => (), Message::CompilerArtifact(message) => {
if message.target.kind.contains(&"proc-macro".to_string()) {
let package_id = message.package_id;
if let Some(filename) = message.filenames.get(0) {
acc.proc_dylib_paths.insert(package_id, filename.clone());
}
}
}
Message::CompilerMessage(_) => (), Message::CompilerMessage(_) => (),
Message::Unknown => (), Message::Unknown => (),
} }

View file

@ -23,6 +23,7 @@ pub struct Crate {
pub(crate) atom_cfgs: FxHashSet<String>, pub(crate) atom_cfgs: FxHashSet<String>,
pub(crate) key_value_cfgs: FxHashMap<String, String>, pub(crate) key_value_cfgs: FxHashMap<String, String>,
pub(crate) out_dir: Option<PathBuf>, pub(crate) out_dir: Option<PathBuf>,
pub(crate) proc_macro_dylib_path: Option<PathBuf>,
} }
#[derive(Clone, Copy, Debug, Deserialize)] #[derive(Clone, Copy, Debug, Deserialize)]

View file

@ -23,6 +23,7 @@ pub use crate::{
json_project::JsonProject, json_project::JsonProject,
sysroot::Sysroot, sysroot::Sysroot,
}; };
pub use ra_proc_macro::ProcMacroClient;
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CargoTomlNotFoundError { pub struct CargoTomlNotFoundError {
@ -173,6 +174,29 @@ impl ProjectWorkspace {
} }
} }
pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
match self {
ProjectWorkspace::Json { project } => {
let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len());
for krate in &project.crates {
if let Some(out_dir) = &krate.proc_macro_dylib_path {
proc_macro_dylib_paths.push(out_dir.to_path_buf());
}
}
proc_macro_dylib_paths
}
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len());
for pkg in cargo.packages() {
if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path {
proc_macro_dylib_paths.push(dylib_path.to_path_buf());
}
}
proc_macro_dylib_paths
}
}
}
pub fn n_packages(&self) -> usize { pub fn n_packages(&self) -> usize {
match self { match self {
ProjectWorkspace::Json { project } => project.crates.len(), ProjectWorkspace::Json { project } => project.crates.len(),
@ -186,6 +210,7 @@ impl ProjectWorkspace {
&self, &self,
default_cfg_options: &CfgOptions, default_cfg_options: &CfgOptions,
extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>,
proc_macro_client: &ProcMacroClient,
load: &mut dyn FnMut(&Path) -> Option<FileId>, load: &mut dyn FnMut(&Path) -> Option<FileId>,
) -> CrateGraph { ) -> CrateGraph {
let mut crate_graph = CrateGraph::default(); let mut crate_graph = CrateGraph::default();
@ -219,7 +244,10 @@ impl ProjectWorkspace {
extern_source.set_extern_path(&out_dir, extern_source_id); extern_source.set_extern_path(&out_dir, extern_source_id);
} }
} }
let proc_macro = krate
.proc_macro_dylib_path
.clone()
.map(|it| proc_macro_client.by_dylib_path(&it));
// FIXME: No crate name in json definition such that we cannot add OUT_DIR to env // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
crates.insert( crates.insert(
crate_id, crate_id,
@ -231,6 +259,7 @@ impl ProjectWorkspace {
cfg_options, cfg_options,
env, env,
extern_source, extern_source,
proc_macro.unwrap_or_default(),
), ),
); );
} }
@ -270,6 +299,8 @@ impl ProjectWorkspace {
let env = Env::default(); let env = Env::default();
let extern_source = ExternSource::default(); let extern_source = ExternSource::default();
let proc_macro = vec![];
let crate_id = crate_graph.add_crate_root( let crate_id = crate_graph.add_crate_root(
file_id, file_id,
Edition::Edition2018, Edition::Edition2018,
@ -280,6 +311,7 @@ impl ProjectWorkspace {
cfg_options, cfg_options,
env, env,
extern_source, extern_source,
proc_macro,
); );
sysroot_crates.insert(krate, crate_id); sysroot_crates.insert(krate, crate_id);
} }
@ -327,6 +359,12 @@ impl ProjectWorkspace {
extern_source.set_extern_path(&out_dir, extern_source_id); extern_source.set_extern_path(&out_dir, extern_source_id);
} }
} }
let proc_macro = cargo[pkg]
.proc_macro_dylib_path
.as_ref()
.map(|it| proc_macro_client.by_dylib_path(&it))
.unwrap_or_default();
let crate_id = crate_graph.add_crate_root( let crate_id = crate_graph.add_crate_root(
file_id, file_id,
edition, edition,
@ -334,6 +372,7 @@ impl ProjectWorkspace {
cfg_options, cfg_options,
env, env,
extern_source, extern_source,
proc_macro.clone(),
); );
if cargo[tgt].kind == TargetKind::Lib { if cargo[tgt].kind == TargetKind::Lib {
lib_tgt = Some((crate_id, cargo[tgt].name.clone())); lib_tgt = Some((crate_id, cargo[tgt].name.clone()));

View file

@ -14,9 +14,12 @@ macro_rules! impl_froms {
} }
} }
use std::fmt; use std::{
fmt::{self, Debug},
panic::RefUnwindSafe,
};
use smol_str::SmolStr; pub use smol_str::SmolStr;
/// Represents identity of the token. /// Represents identity of the token.
/// ///
@ -184,3 +187,11 @@ impl Subtree {
} }
pub mod buffer; pub mod buffer;
#[derive(Debug, PartialEq, Eq)]
pub enum ExpansionError {}
pub trait TokenExpander: Debug + Send + Sync + RefUnwindSafe {
fn expand(&self, subtree: &Subtree, attrs: Option<&Subtree>)
-> Result<Subtree, ExpansionError>;
}

View file

@ -7,7 +7,9 @@ use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver}; use crossbeam_channel::{unbounded, Receiver};
use ra_db::{ExternSourceId, FileId, SourceRootId}; use ra_db::{ExternSourceId, FileId, SourceRootId};
use ra_ide::{AnalysisChange, AnalysisHost}; use ra_ide::{AnalysisChange, AnalysisHost};
use ra_project_model::{get_rustc_cfg_options, CargoFeatures, PackageRoot, ProjectWorkspace}; use ra_project_model::{
get_rustc_cfg_options, CargoFeatures, PackageRoot, ProcMacroClient, ProjectWorkspace,
};
use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -67,7 +69,9 @@ pub(crate) fn load_cargo(
(source_root_id, project_root) (source_root_id, project_root)
}) })
.collect::<FxHashMap<_, _>>(); .collect::<FxHashMap<_, _>>();
let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs);
let proc_macro_client = ProcMacroClient::dummy();
let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client);
Ok((host, source_roots)) Ok((host, source_roots))
} }
@ -77,6 +81,7 @@ pub(crate) fn load(
vfs: &mut Vfs, vfs: &mut Vfs,
receiver: Receiver<VfsTask>, receiver: Receiver<VfsTask>,
extern_dirs: FxHashSet<PathBuf>, extern_dirs: FxHashSet<PathBuf>,
proc_macro_client: &ProcMacroClient,
) -> AnalysisHost { ) -> AnalysisHost {
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
let mut host = AnalysisHost::new(lru_cap); let mut host = AnalysisHost::new(lru_cap);
@ -143,12 +148,16 @@ pub(crate) fn load(
opts opts
}; };
let crate_graph = let crate_graph = ws.to_crate_graph(
ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut |path: &Path| { &default_cfg_options,
&extern_source_roots,
proc_macro_client,
&mut |path: &Path| {
let vfs_file = vfs.load(path); let vfs_file = vfs.load(path);
log::debug!("vfs file {:?} -> {:?}", path, vfs_file); log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
vfs_file.map(vfs_file_to_id) vfs_file.map(vfs_file_to_id)
}); },
);
log::debug!("crate graph: {:?}", crate_graph); log::debug!("crate graph: {:?}", crate_graph);
analysis_change.set_crate_graph(crate_graph); analysis_change.set_crate_graph(crate_graph);

View file

@ -16,7 +16,7 @@ use ra_ide::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData, Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData,
SourceRootId, SourceRootId,
}; };
use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace};
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
@ -150,9 +150,19 @@ impl WorldState {
vfs_file.map(|f| FileId(f.0)) vfs_file.map(|f| FileId(f.0))
}; };
let proc_macro_client =
ProcMacroClient::extern_process(std::path::Path::new("ra_proc_macro_srv"));
workspaces workspaces
.iter() .iter()
.map(|ws| ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut load)) .map(|ws| {
ws.to_crate_graph(
&default_cfg_options,
&extern_source_roots,
&proc_macro_client,
&mut load,
)
})
.for_each(|graph| { .for_each(|graph| {
crate_graph.extend(graph); crate_graph.extend(graph);
}); });