Add ProcMacroClient

This commit is contained in:
Edwin Cheng 2020-03-18 20:56:46 +08:00
parent a617f24eae
commit d0b6ed4441
17 changed files with 222 additions and 43 deletions

View file

@ -83,6 +83,7 @@ pub struct PackageData {
pub edition: Edition,
pub features: Vec<String>,
pub out_dir: Option<PathBuf>,
pub proc_macro_dylib_path: Option<PathBuf>,
}
#[derive(Debug, Clone)]
@ -158,8 +159,11 @@ impl CargoWorkspace {
})?;
let mut out_dir_by_id = FxHashMap::default();
let mut proc_macro_dylib_paths = FxHashMap::default();
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();
@ -183,6 +187,7 @@ impl CargoWorkspace {
dependencies: Vec::new(),
features: Vec::new(),
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];
pkg_by_id.insert(id, pkg);
@ -246,10 +251,13 @@ impl CargoWorkspace {
}
}
pub fn load_out_dirs(
cargo_toml: &Path,
cargo_features: &CargoFeatures,
) -> FxHashMap<PackageId, PathBuf> {
#[derive(Debug, Clone, Default)]
pub struct ExternResources {
out_dirs: 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![
"check".to_string(),
"--message-format=json".to_string(),
@ -267,14 +275,21 @@ pub fn load_out_dirs(
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| {
match message {
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::Unknown => (),
}

View file

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

View file

@ -23,6 +23,7 @@ pub use crate::{
json_project::JsonProject,
sysroot::Sysroot,
};
pub use ra_proc_macro::ProcMacroClient;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
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 {
match self {
ProjectWorkspace::Json { project } => project.crates.len(),
@ -186,6 +210,7 @@ impl ProjectWorkspace {
&self,
default_cfg_options: &CfgOptions,
extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>,
proc_macro_client: &ProcMacroClient,
load: &mut dyn FnMut(&Path) -> Option<FileId>,
) -> CrateGraph {
let mut crate_graph = CrateGraph::default();
@ -219,7 +244,10 @@ impl ProjectWorkspace {
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
crates.insert(
crate_id,
@ -231,6 +259,7 @@ impl ProjectWorkspace {
cfg_options,
env,
extern_source,
proc_macro.unwrap_or_default(),
),
);
}
@ -270,6 +299,8 @@ impl ProjectWorkspace {
let env = Env::default();
let extern_source = ExternSource::default();
let proc_macro = vec![];
let crate_id = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
@ -280,6 +311,7 @@ impl ProjectWorkspace {
cfg_options,
env,
extern_source,
proc_macro,
);
sysroot_crates.insert(krate, crate_id);
}
@ -327,6 +359,12 @@ impl ProjectWorkspace {
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(
file_id,
edition,
@ -334,6 +372,7 @@ impl ProjectWorkspace {
cfg_options,
env,
extern_source,
proc_macro.clone(),
);
if cargo[tgt].kind == TargetKind::Lib {
lib_tgt = Some((crate_id, cargo[tgt].name.clone()));