mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Merge #3727
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:
commit
b1594f1080
20 changed files with 259 additions and 38 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -928,6 +928,7 @@ dependencies = [
|
|||
"ra_cfg",
|
||||
"ra_prof",
|
||||
"ra_syntax",
|
||||
"ra_tt",
|
||||
"relative-path",
|
||||
"rustc-hash",
|
||||
"salsa",
|
||||
|
@ -1081,6 +1082,13 @@ dependencies = [
|
|||
"drop_bomb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra_proc_macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ra_tt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ra_prof"
|
||||
version = "0.1.0"
|
||||
|
@ -1102,6 +1110,7 @@ dependencies = [
|
|||
"ra_cargo_watch",
|
||||
"ra_cfg",
|
||||
"ra_db",
|
||||
"ra_proc_macro",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -15,4 +15,5 @@ rustc-hash = "1.1.0"
|
|||
ra_syntax = { path = "../ra_syntax" }
|
||||
ra_cfg = { path = "../ra_cfg" }
|
||||
ra_prof = { path = "../ra_prof" }
|
||||
ra_tt = { path = "../ra_tt" }
|
||||
test_utils = { path = "../test_utils" }
|
||||
|
|
|
@ -70,6 +70,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
|
|||
meta.cfg,
|
||||
meta.env,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
crate_graph
|
||||
} else {
|
||||
|
@ -81,6 +82,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
crate_graph
|
||||
};
|
||||
|
@ -130,6 +132,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
|
|||
meta.cfg,
|
||||
meta.env,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let prev = crates.insert(krate.clone(), crate_id);
|
||||
assert!(prev.is_none());
|
||||
|
@ -167,6 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
} else {
|
||||
for (from, to) in crate_deps {
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::{
|
|||
fmt, ops,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use ra_cfg::CfgOptions;
|
||||
|
@ -19,6 +20,7 @@ use rustc_hash::FxHashSet;
|
|||
|
||||
use crate::{RelativePath, RelativePathBuf};
|
||||
use fmt::Display;
|
||||
use ra_tt::TokenExpander;
|
||||
|
||||
/// `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
|
||||
|
@ -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)]
|
||||
pub struct CrateData {
|
||||
pub root_file_id: FileId,
|
||||
|
@ -127,6 +145,7 @@ pub struct CrateData {
|
|||
pub env: Env,
|
||||
pub extern_source: ExternSource,
|
||||
pub dependencies: Vec<Dependency>,
|
||||
pub proc_macro: Vec<ProcMacro>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -166,7 +185,11 @@ impl CrateGraph {
|
|||
cfg_options: CfgOptions,
|
||||
env: Env,
|
||||
extern_source: ExternSource,
|
||||
proc_macro: Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)>,
|
||||
) -> CrateId {
|
||||
let proc_macro =
|
||||
proc_macro.into_iter().map(|(name, it)| ProcMacro { name, expander: it }).collect();
|
||||
|
||||
let data = CrateData {
|
||||
root_file_id: file_id,
|
||||
edition,
|
||||
|
@ -174,6 +197,7 @@ impl CrateGraph {
|
|||
cfg_options,
|
||||
env,
|
||||
extern_source,
|
||||
proc_macro,
|
||||
dependencies: Vec::new(),
|
||||
};
|
||||
let crate_id = CrateId(self.arena.len() as u32);
|
||||
|
@ -345,6 +369,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId(2u32),
|
||||
|
@ -353,6 +378,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let crate3 = graph.add_crate_root(
|
||||
FileId(3u32),
|
||||
|
@ -361,6 +387,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
|
||||
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
|
||||
|
@ -377,6 +404,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId(2u32),
|
||||
|
@ -385,6 +413,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let crate3 = graph.add_crate_root(
|
||||
FileId(3u32),
|
||||
|
@ -393,6 +422,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
|
||||
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
|
||||
|
@ -408,6 +438,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId(2u32),
|
||||
|
@ -416,6 +447,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
assert!(graph
|
||||
.add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
|
||||
|
|
|
@ -12,7 +12,7 @@ pub use crate::{
|
|||
cancellation::Canceled,
|
||||
input::{
|
||||
CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId,
|
||||
FileId, SourceRoot, SourceRootId,
|
||||
FileId, ProcMacroId, SourceRoot, SourceRootId,
|
||||
},
|
||||
};
|
||||
pub use relative_path::{RelativePath, RelativePathBuf};
|
||||
|
|
|
@ -11,7 +11,7 @@ use hir_expand::{
|
|||
HirFileId, MacroCallId, MacroDefId, MacroDefKind,
|
||||
};
|
||||
use ra_cfg::CfgOptions;
|
||||
use ra_db::{CrateId, FileId};
|
||||
use ra_db::{CrateId, FileId, ProcMacroId};
|
||||
use ra_syntax::ast;
|
||||
use rustc_hash::FxHashMap;
|
||||
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 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 {
|
||||
db,
|
||||
|
@ -65,9 +75,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
|
|||
unexpanded_attribute_macros: Vec::new(),
|
||||
mod_dirs: FxHashMap::default(),
|
||||
cfg_options,
|
||||
|
||||
// FIXME: pass proc-macro from crate-graph
|
||||
proc_macros: Default::default(),
|
||||
proc_macros,
|
||||
};
|
||||
collector.collect();
|
||||
collector.finish()
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
//! Proc Macro Expander stub
|
||||
|
||||
use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc};
|
||||
use ra_db::CrateId;
|
||||
use crate::{db::AstDatabase, LazyMacroId};
|
||||
use ra_db::{CrateId, ProcMacroId};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct ProcMacroExpander {
|
||||
krate: CrateId,
|
||||
proc_macro_id: ProcMacroId,
|
||||
}
|
||||
|
||||
impl ProcMacroExpander {
|
||||
pub fn new(krate: CrateId) -> ProcMacroExpander {
|
||||
ProcMacroExpander { krate }
|
||||
pub fn new(krate: CrateId, proc_macro_id: ProcMacroId) -> ProcMacroExpander {
|
||||
ProcMacroExpander { krate, proc_macro_id }
|
||||
}
|
||||
|
||||
pub fn expand(
|
||||
&self,
|
||||
db: &dyn AstDatabase,
|
||||
id: LazyMacroId,
|
||||
_tt: &tt::Subtree,
|
||||
_id: LazyMacroId,
|
||||
tt: &tt::Subtree,
|
||||
) -> Result<tt::Subtree, mbe::ExpandError> {
|
||||
let loc: MacroCallLoc = db.lookup_intern_macro(id);
|
||||
let name = match loc.kind {
|
||||
MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError),
|
||||
MacroCallKind::Attr(_, name) => name,
|
||||
};
|
||||
let krate_graph = db.crate_graph();
|
||||
let proc_macro = krate_graph[self.krate]
|
||||
.proc_macro
|
||||
.get(self.proc_macro_id.0 as usize)
|
||||
.clone()
|
||||
.ok_or_else(|| mbe::ExpandError::ConversionError)?;
|
||||
|
||||
log::debug!("Proc-macro-expanding name = {}", name);
|
||||
|
||||
// Return nothing for now
|
||||
return Ok(tt::Subtree::default());
|
||||
proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,6 +213,7 @@ impl Analysis {
|
|||
cfg_options,
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
|
|
@ -103,6 +103,7 @@ impl MockAnalysis {
|
|||
cfg_options,
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
));
|
||||
} else if path.ends_with("/lib.rs") {
|
||||
let crate_name = path.parent().unwrap().file_name().unwrap();
|
||||
|
@ -113,6 +114,7 @@ impl MockAnalysis {
|
|||
cfg_options,
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
if let Some(root_crate) = root_crate {
|
||||
crate_graph
|
||||
|
|
|
@ -137,6 +137,7 @@ mod tests {
|
|||
CfgOptions::default(),
|
||||
Env::default(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let mut change = AnalysisChange::new();
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
|
|
@ -28,6 +28,13 @@ pub enum ExpandError {
|
|||
BindingError(String),
|
||||
ConversionError,
|
||||
InvalidRepeat,
|
||||
ProcMacroError(tt::ExpansionError),
|
||||
}
|
||||
|
||||
impl From<tt::ExpansionError> for ExpandError {
|
||||
fn from(it: tt::ExpansionError) -> Self {
|
||||
ExpandError::ProcMacroError(it)
|
||||
}
|
||||
}
|
||||
|
||||
pub use crate::syntax_bridge::{
|
||||
|
|
12
crates/ra_proc_macro/Cargo.toml
Normal file
12
crates/ra_proc_macro/Cargo.toml
Normal 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" }
|
59
crates/ra_proc_macro/src/lib.rs
Normal file
59
crates/ra_proc_macro/src/lib.rs
Normal 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![]
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ ra_arena = { path = "../ra_arena" }
|
|||
ra_db = { path = "../ra_db" }
|
||||
ra_cfg = { path = "../ra_cfg" }
|
||||
ra_cargo_watch = { path = "../ra_cargo_watch" }
|
||||
ra_proc_macro = { path = "../ra_proc_macro" }
|
||||
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
serde_json = "1.0.48"
|
||||
|
|
|
@ -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 => (),
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
@ -184,3 +187,11 @@ impl Subtree {
|
|||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@ use anyhow::Result;
|
|||
use crossbeam_channel::{unbounded, Receiver};
|
||||
use ra_db::{ExternSourceId, FileId, SourceRootId};
|
||||
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 rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
|
@ -67,7 +69,9 @@ pub(crate) fn load_cargo(
|
|||
(source_root_id, project_root)
|
||||
})
|
||||
.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))
|
||||
}
|
||||
|
||||
|
@ -77,6 +81,7 @@ pub(crate) fn load(
|
|||
vfs: &mut Vfs,
|
||||
receiver: Receiver<VfsTask>,
|
||||
extern_dirs: FxHashSet<PathBuf>,
|
||||
proc_macro_client: &ProcMacroClient,
|
||||
) -> AnalysisHost {
|
||||
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
|
||||
let mut host = AnalysisHost::new(lru_cap);
|
||||
|
@ -143,12 +148,16 @@ pub(crate) fn load(
|
|||
opts
|
||||
};
|
||||
|
||||
let crate_graph =
|
||||
ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut |path: &Path| {
|
||||
let crate_graph = ws.to_crate_graph(
|
||||
&default_cfg_options,
|
||||
&extern_source_roots,
|
||||
proc_macro_client,
|
||||
&mut |path: &Path| {
|
||||
let vfs_file = vfs.load(path);
|
||||
log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
|
||||
vfs_file.map(vfs_file_to_id)
|
||||
});
|
||||
},
|
||||
);
|
||||
log::debug!("crate graph: {:?}", crate_graph);
|
||||
analysis_change.set_crate_graph(crate_graph);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use ra_ide::{
|
|||
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayHintsOptions, LibraryData,
|
||||
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 relative_path::RelativePathBuf;
|
||||
|
||||
|
@ -150,9 +150,19 @@ impl WorldState {
|
|||
vfs_file.map(|f| FileId(f.0))
|
||||
};
|
||||
|
||||
let proc_macro_client =
|
||||
ProcMacroClient::extern_process(std::path::Path::new("ra_proc_macro_srv"));
|
||||
|
||||
workspaces
|
||||
.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| {
|
||||
crate_graph.extend(graph);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue