mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Add ProcMacroClient
This commit is contained in:
parent
a617f24eae
commit
d0b6ed4441
17 changed files with 222 additions and 43 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -926,6 +926,7 @@ name = "ra_db"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ra_cfg",
|
"ra_cfg",
|
||||||
|
"ra_proc_macro",
|
||||||
"ra_prof",
|
"ra_prof",
|
||||||
"ra_syntax",
|
"ra_syntax",
|
||||||
"relative-path",
|
"relative-path",
|
||||||
|
@ -1110,6 +1111,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",
|
||||||
|
|
|
@ -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_proc_macro = { path = "../ra_proc_macro" }
|
||||||
test_utils = { path = "../test_utils" }
|
test_utils = { path = "../test_utils" }
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -19,6 +19,7 @@ use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{RelativePath, RelativePathBuf};
|
use crate::{RelativePath, RelativePathBuf};
|
||||||
use fmt::Display;
|
use fmt::Display;
|
||||||
|
use ra_proc_macro::ProcMacro;
|
||||||
|
|
||||||
/// `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 +116,9 @@ impl Display for CrateName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ProcMacroId(pub usize);
|
||||||
|
|
||||||
#[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 +131,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,6 +171,7 @@ impl CrateGraph {
|
||||||
cfg_options: CfgOptions,
|
cfg_options: CfgOptions,
|
||||||
env: Env,
|
env: Env,
|
||||||
extern_source: ExternSource,
|
extern_source: ExternSource,
|
||||||
|
proc_macro: Vec<ProcMacro>,
|
||||||
) -> CrateId {
|
) -> CrateId {
|
||||||
let data = CrateData {
|
let data = CrateData {
|
||||||
root_file_id: file_id,
|
root_file_id: file_id,
|
||||||
|
@ -174,6 +180,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 +352,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 +361,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 +370,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 +387,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 +396,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 +405,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 +421,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 +430,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)
|
||||||
|
|
|
@ -12,9 +12,10 @@ 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 ra_proc_macro::ProcMacro;
|
||||||
pub use relative_path::{RelativePath, RelativePathBuf};
|
pub use relative_path::{RelativePath, RelativePathBuf};
|
||||||
pub use salsa;
|
pub use salsa;
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ 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, SmolStr};
|
||||||
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: SmolStr::new(&it.name()), id: tt::TokenId::unspecified() };
|
||||||
|
(name.as_name(), ProcMacroExpander::new(def_map.krate, ProcMacroId(idx)))
|
||||||
|
})
|
||||||
|
.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()
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
//! 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)
|
||||||
};
|
.clone()
|
||||||
|
.ok_or_else(|| mbe::ExpandError::ConversionError)?;
|
||||||
log::debug!("Proc-macro-expanding name = {}", name);
|
proc_macro.custom_derive(tt)
|
||||||
|
|
||||||
// Return nothing for now
|
|
||||||
return Ok(tt::Subtree::default());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -1,7 +1,78 @@
|
||||||
#[cfg(test)]
|
//! Client-side Proc-Macro crate
|
||||||
mod tests {
|
//!
|
||||||
#[test]
|
//! We separate proc-macro expanding logic to an extern program to allow
|
||||||
fn it_works() {
|
//! different implementations (e.g. wasm or dylib loading). And this crate
|
||||||
assert_eq!(2 + 2, 4);
|
//! is used for provide basic infra-structure for commnicate between two
|
||||||
|
//! process: Client (RA itself), Server (the external program)
|
||||||
|
|
||||||
|
use ra_mbe::ExpandError;
|
||||||
|
use ra_tt::Subtree;
|
||||||
|
use std::{
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
trait ProcMacroExpander: std::fmt::Debug + Send + Sync + std::panic::RefUnwindSafe {
|
||||||
|
fn custom_derive(&self, subtree: &Subtree, derive_name: &str) -> Result<Subtree, ExpandError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ProcMacroProcessExpander {
|
||||||
|
process_path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcMacroExpander for ProcMacroProcessExpander {
|
||||||
|
fn custom_derive(
|
||||||
|
&self,
|
||||||
|
_subtree: &Subtree,
|
||||||
|
_derive_name: &str,
|
||||||
|
) -> Result<Subtree, ExpandError> {
|
||||||
|
// FIXME: do nothing for now
|
||||||
|
Ok(Subtree::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ProcMacro {
|
||||||
|
expander: Arc<Box<dyn ProcMacroExpander>>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcMacro {
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn custom_derive(&self, subtree: &Subtree) -> Result<Subtree, ExpandError> {
|
||||||
|
self.expander.custom_derive(subtree, &self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ProcMacroClient {
|
||||||
|
Process { expander: Arc<ProcMacroProcessExpander> },
|
||||||
|
Dummy,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcMacroClient {
|
||||||
|
pub fn extern_process(process_path: &Path) -> ProcMacroClient {
|
||||||
|
let expander = ProcMacroProcessExpander { process_path: process_path.into() };
|
||||||
|
ProcMacroClient::Process { expander: Arc::new(expander) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dummy() -> ProcMacroClient {
|
||||||
|
ProcMacroClient::Dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn by_dylib_path(&self, _dylib_path: &Path) -> Vec<ProcMacro> {
|
||||||
|
// FIXME: return empty for now
|
||||||
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue