mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Auto merge of #16586 - Veykril:crate-graph-side-table, r=Veykril
fix: Remove cargo knowledge from `CrateData` Fixes https://github.com/rust-lang/rust-analyzer/issues/16170, Fixes https://github.com/rust-lang/rust-analyzer/issues/15656
This commit is contained in:
commit
25d12673db
@ -11,7 +11,6 @@ use std::{fmt, mem, ops, str::FromStr};
|
||||
use cfg::CfgOptions;
|
||||
use la_arena::{Arena, Idx, RawIdx};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use semver::Version;
|
||||
use syntax::SmolStr;
|
||||
use triomphe::Arc;
|
||||
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
|
||||
@ -292,71 +291,6 @@ pub struct CrateData {
|
||||
pub dependencies: Vec<Dependency>,
|
||||
pub origin: CrateOrigin,
|
||||
pub is_proc_macro: bool,
|
||||
// FIXME: These things should not be per crate! These are more per workspace crate graph level
|
||||
// things. This info does need to be somewhat present though as to prevent deduplication from
|
||||
// happening across different workspaces with different layouts.
|
||||
pub target_layout: TargetLayoutLoadResult,
|
||||
pub toolchain: Option<Version>,
|
||||
}
|
||||
|
||||
impl CrateData {
|
||||
/// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value.
|
||||
pub fn eq_ignoring_origin_and_deps(&self, other: &CrateData, ignore_dev_deps: bool) -> bool {
|
||||
// This method has some obscure bits. These are mostly there to be compliant with
|
||||
// some patches. References to the patches are given.
|
||||
if self.root_file_id != other.root_file_id {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.display_name != other.display_name {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.is_proc_macro != other.is_proc_macro {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.edition != other.edition {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.version != other.version {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut opts = self.cfg_options.difference(&other.cfg_options);
|
||||
if let Some(it) = opts.next() {
|
||||
// Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
|
||||
// https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
|
||||
if it.to_string() != "rust_analyzer" {
|
||||
return false;
|
||||
}
|
||||
|
||||
if opts.next().is_some() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if self.env != other.env {
|
||||
return false;
|
||||
}
|
||||
|
||||
let slf_deps = self.dependencies.iter();
|
||||
let other_deps = other.dependencies.iter();
|
||||
|
||||
if ignore_dev_deps {
|
||||
return slf_deps
|
||||
.clone()
|
||||
.filter(|it| it.kind != DependencyKind::Dev)
|
||||
.eq(other_deps.clone().filter(|it| it.kind != DependencyKind::Dev));
|
||||
}
|
||||
|
||||
slf_deps.eq(other_deps)
|
||||
}
|
||||
|
||||
pub fn channel(&self) -> Option<ReleaseChannel> {
|
||||
self.toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
@ -399,32 +333,22 @@ pub enum DependencyKind {
|
||||
pub struct Dependency {
|
||||
pub crate_id: CrateId,
|
||||
pub name: CrateName,
|
||||
kind: DependencyKind,
|
||||
prelude: bool,
|
||||
}
|
||||
|
||||
impl Dependency {
|
||||
pub fn new(name: CrateName, crate_id: CrateId, kind: DependencyKind) -> Self {
|
||||
Self { name, crate_id, prelude: true, kind }
|
||||
pub fn new(name: CrateName, crate_id: CrateId) -> Self {
|
||||
Self { name, crate_id, prelude: true }
|
||||
}
|
||||
|
||||
pub fn with_prelude(
|
||||
name: CrateName,
|
||||
crate_id: CrateId,
|
||||
prelude: bool,
|
||||
kind: DependencyKind,
|
||||
) -> Self {
|
||||
Self { name, crate_id, prelude, kind }
|
||||
pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self {
|
||||
Self { name, crate_id, prelude }
|
||||
}
|
||||
|
||||
/// Whether this dependency is to be added to the depending crate's extern prelude.
|
||||
pub fn is_prelude(&self) -> bool {
|
||||
self.prelude
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> DependencyKind {
|
||||
self.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl CrateGraph {
|
||||
@ -439,8 +363,6 @@ impl CrateGraph {
|
||||
env: Env,
|
||||
is_proc_macro: bool,
|
||||
origin: CrateOrigin,
|
||||
target_layout: Result<Arc<str>, Arc<str>>,
|
||||
toolchain: Option<Version>,
|
||||
) -> CrateId {
|
||||
let data = CrateData {
|
||||
root_file_id,
|
||||
@ -452,9 +374,7 @@ impl CrateGraph {
|
||||
env,
|
||||
dependencies: Vec::new(),
|
||||
origin,
|
||||
target_layout,
|
||||
is_proc_macro,
|
||||
toolchain,
|
||||
};
|
||||
self.arena.alloc(data)
|
||||
}
|
||||
@ -524,6 +444,10 @@ impl CrateGraph {
|
||||
self.arena.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.arena.len()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = CrateId> + '_ {
|
||||
self.arena.iter().map(|(idx, _)| idx)
|
||||
}
|
||||
@ -624,13 +548,17 @@ impl CrateGraph {
|
||||
///
|
||||
/// This will deduplicate the crates of the graph where possible.
|
||||
/// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
|
||||
/// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
|
||||
/// If the crate dependencies were sorted, the resulting graph from this `extend` call will also
|
||||
/// have the crate dependencies sorted.
|
||||
///
|
||||
/// Returns a mapping from `other`'s crate ids to the new crate ids in `self`.
|
||||
pub fn extend(
|
||||
&mut self,
|
||||
mut other: CrateGraph,
|
||||
proc_macros: &mut ProcMacroPaths,
|
||||
on_finished: impl FnOnce(&FxHashMap<CrateId, CrateId>),
|
||||
) {
|
||||
merge: impl Fn((CrateId, &mut CrateData), (CrateId, &CrateData)) -> bool,
|
||||
) -> FxHashMap<CrateId, CrateId> {
|
||||
let m = self.len();
|
||||
let topo = other.crates_in_topological_order();
|
||||
let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
|
||||
for topo in topo {
|
||||
@ -638,51 +566,21 @@ impl CrateGraph {
|
||||
|
||||
crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
|
||||
crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
|
||||
let res = self.arena.iter().find_map(|(id, data)| {
|
||||
match (&data.origin, &crate_data.origin) {
|
||||
(a, b) if a == b => {
|
||||
if data.eq_ignoring_origin_and_deps(crate_data, false) {
|
||||
return Some((id, false));
|
||||
}
|
||||
}
|
||||
(a @ CrateOrigin::Local { .. }, CrateOrigin::Library { .. })
|
||||
| (a @ CrateOrigin::Library { .. }, CrateOrigin::Local { .. }) => {
|
||||
// If the origins differ, check if the two crates are equal without
|
||||
// considering the dev dependencies, if they are, they most likely are in
|
||||
// different loaded workspaces which may cause issues. We keep the local
|
||||
// version and discard the library one as the local version may have
|
||||
// dev-dependencies that we want to keep resolving. See #15656 for more
|
||||
// information.
|
||||
if data.eq_ignoring_origin_and_deps(crate_data, true) {
|
||||
return Some((id, !a.is_local()));
|
||||
}
|
||||
}
|
||||
(_, _) => return None,
|
||||
}
|
||||
let res = self
|
||||
.arena
|
||||
.iter_mut()
|
||||
.take(m)
|
||||
.find_map(|(id, data)| merge((id, data), (topo, &crate_data)).then_some(id));
|
||||
|
||||
None
|
||||
});
|
||||
|
||||
if let Some((res, should_update_lib_to_local)) = res {
|
||||
id_map.insert(topo, res);
|
||||
if should_update_lib_to_local {
|
||||
assert!(self.arena[res].origin.is_lib());
|
||||
assert!(crate_data.origin.is_local());
|
||||
self.arena[res].origin = crate_data.origin.clone();
|
||||
|
||||
// Move local's dev dependencies into the newly-local-formerly-lib crate.
|
||||
self.arena[res].dependencies = crate_data.dependencies.clone();
|
||||
}
|
||||
} else {
|
||||
let id = self.arena.alloc(crate_data.clone());
|
||||
id_map.insert(topo, id);
|
||||
}
|
||||
let new_id =
|
||||
if let Some(res) = res { res } else { self.arena.alloc(crate_data.clone()) };
|
||||
id_map.insert(topo, new_id);
|
||||
}
|
||||
|
||||
*proc_macros =
|
||||
mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect();
|
||||
|
||||
on_finished(&id_map);
|
||||
id_map
|
||||
}
|
||||
|
||||
fn find_path(
|
||||
@ -720,11 +618,9 @@ impl CrateGraph {
|
||||
match (cfg_if, std) {
|
||||
(Some(cfg_if), Some(std)) => {
|
||||
self.arena[cfg_if].dependencies.clear();
|
||||
self.arena[std].dependencies.push(Dependency::new(
|
||||
CrateName::new("cfg_if").unwrap(),
|
||||
cfg_if,
|
||||
DependencyKind::Normal,
|
||||
));
|
||||
self.arena[std]
|
||||
.dependencies
|
||||
.push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@ -872,7 +768,7 @@ impl fmt::Display for CyclicDependenciesError {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{CrateOrigin, DependencyKind};
|
||||
use crate::CrateOrigin;
|
||||
|
||||
use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
|
||||
|
||||
@ -889,8 +785,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId::from_raw(2u32),
|
||||
@ -902,8 +796,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate3 = graph.add_crate_root(
|
||||
FileId::from_raw(3u32),
|
||||
@ -915,26 +807,15 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate1,
|
||||
Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
|
||||
.is_ok());
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate2,
|
||||
Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
|
||||
.is_ok());
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate3,
|
||||
Dependency::new(CrateName::new("crate1").unwrap(), crate1, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1,))
|
||||
.is_err());
|
||||
}
|
||||
|
||||
@ -951,8 +832,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId::from_raw(2u32),
|
||||
@ -964,20 +843,12 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate1,
|
||||
Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
|
||||
.is_ok());
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate2,
|
||||
Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
|
||||
.is_err());
|
||||
}
|
||||
|
||||
@ -994,8 +865,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId::from_raw(2u32),
|
||||
@ -1007,8 +876,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate3 = graph.add_crate_root(
|
||||
FileId::from_raw(3u32),
|
||||
@ -1020,20 +887,12 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate1,
|
||||
Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
|
||||
.is_ok());
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate2,
|
||||
Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
|
||||
)
|
||||
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
@ -1050,8 +909,6 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
let crate2 = graph.add_crate_root(
|
||||
FileId::from_raw(2u32),
|
||||
@ -1063,26 +920,16 @@ mod tests {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("".into()),
|
||||
None,
|
||||
);
|
||||
assert!(graph
|
||||
.add_dep(
|
||||
crate1,
|
||||
Dependency::new(
|
||||
CrateName::normalize_dashes("crate-name-with-dashes"),
|
||||
crate2,
|
||||
DependencyKind::Normal
|
||||
)
|
||||
Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2,)
|
||||
)
|
||||
.is_ok());
|
||||
assert_eq!(
|
||||
graph[crate1].dependencies,
|
||||
vec![Dependency::new(
|
||||
CrateName::new("crate_name_with_dashes").unwrap(),
|
||||
crate2,
|
||||
DependencyKind::Normal
|
||||
)]
|
||||
vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,20 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
||||
/// The crate graph.
|
||||
#[salsa::input]
|
||||
fn crate_graph(&self) -> Arc<CrateGraph>;
|
||||
|
||||
// FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
|
||||
#[salsa::input]
|
||||
fn data_layout(&self, krate: CrateId) -> TargetLayoutLoadResult;
|
||||
|
||||
#[salsa::input]
|
||||
fn toolchain(&self, krate: CrateId) -> Option<Version>;
|
||||
|
||||
#[salsa::transparent]
|
||||
fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
|
||||
}
|
||||
|
||||
fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option<ReleaseChannel> {
|
||||
db.toolchain(krate).as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
|
||||
}
|
||||
|
||||
fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
|
||||
|
@ -1,6 +1,10 @@
|
||||
//! Defines a unit of change that can applied to the database to get the next
|
||||
//! state. Changes are transactional.
|
||||
use base_db::{salsa::Durability, CrateGraph, FileChange, SourceDatabaseExt, SourceRoot};
|
||||
use base_db::{
|
||||
salsa::Durability, CrateGraph, CrateId, FileChange, SourceDatabaseExt, SourceRoot,
|
||||
TargetLayoutLoadResult, Version,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
use span::FileId;
|
||||
use triomphe::Arc;
|
||||
|
||||
@ -10,6 +14,8 @@ use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
|
||||
pub struct Change {
|
||||
pub source_change: FileChange,
|
||||
pub proc_macros: Option<ProcMacros>,
|
||||
pub toolchains: Option<Vec<Option<Version>>>,
|
||||
pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
|
||||
}
|
||||
|
||||
impl Change {
|
||||
@ -22,6 +28,24 @@ impl Change {
|
||||
if let Some(proc_macros) = self.proc_macros {
|
||||
db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
|
||||
}
|
||||
if let Some(target_data_layouts) = self.target_data_layouts {
|
||||
for (id, val) in target_data_layouts.into_iter().enumerate() {
|
||||
db.set_data_layout_with_durability(
|
||||
CrateId::from_raw(RawIdx::from(id as u32)),
|
||||
val,
|
||||
Durability::HIGH,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(toolchains) = self.toolchains {
|
||||
for (id, val) in toolchains.into_iter().enumerate() {
|
||||
db.set_toolchain_with_durability(
|
||||
CrateId::from_raw(RawIdx::from(id as u32)),
|
||||
val,
|
||||
Durability::HIGH,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<str>>) {
|
||||
@ -36,6 +60,14 @@ impl Change {
|
||||
self.proc_macros = Some(proc_macros);
|
||||
}
|
||||
|
||||
pub fn set_toolchains(&mut self, toolchains: Vec<Option<Version>>) {
|
||||
self.toolchains = Some(toolchains);
|
||||
}
|
||||
|
||||
pub fn set_target_data_layouts(&mut self, target_data_layouts: Vec<TargetLayoutLoadResult>) {
|
||||
self.target_data_layouts = Some(target_data_layouts);
|
||||
}
|
||||
|
||||
pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
|
||||
self.source_change.set_roots(roots)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl DeclarativeMacroExpander {
|
||||
call_id: MacroCallId,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let loc = db.lookup_intern_macro_call(call_id);
|
||||
let toolchain = &db.crate_graph()[loc.def.krate].toolchain;
|
||||
let toolchain = db.toolchain(loc.def.krate);
|
||||
let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
|
||||
REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
|
||||
&base_db::Version {
|
||||
@ -67,7 +67,7 @@ impl DeclarativeMacroExpander {
|
||||
krate: CrateId,
|
||||
call_site: Span,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let toolchain = &db.crate_graph()[krate].toolchain;
|
||||
let toolchain = db.toolchain(krate);
|
||||
let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
|
||||
REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
|
||||
&base_db::Version {
|
||||
@ -119,7 +119,7 @@ impl DeclarativeMacroExpander {
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
let toolchain = crate_data.toolchain.as_ref();
|
||||
let toolchain = db.toolchain(def_crate);
|
||||
let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
|
||||
REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
|
||||
&base_db::Version {
|
||||
|
@ -11,10 +11,8 @@ pub fn target_data_layout_query(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
||||
let crate_graph = db.crate_graph();
|
||||
let res = crate_graph[krate].target_layout.as_deref();
|
||||
match res {
|
||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
|
||||
match db.data_layout(krate) {
|
||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(&it) {
|
||||
Ok(it) => Ok(Arc::new(it)),
|
||||
Err(e) => {
|
||||
Err(match e {
|
||||
@ -44,6 +42,6 @@ pub fn target_data_layout_query(
|
||||
}.into())
|
||||
}
|
||||
},
|
||||
Err(e) => Err(Arc::from(&**e)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ fn current_machine_data_layout() -> String {
|
||||
fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
|
||||
let target_data_layout = current_machine_data_layout();
|
||||
let ra_fixture = format!(
|
||||
"{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\n{ra_fixture}",
|
||||
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
|
||||
);
|
||||
|
||||
let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
|
||||
@ -76,7 +76,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
|
||||
fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
|
||||
let target_data_layout = current_machine_data_layout();
|
||||
let ra_fixture = format!(
|
||||
"{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\nfn main(){{let goal = {{{ra_fixture}}};}}",
|
||||
"//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
|
||||
);
|
||||
|
||||
let (db, file_id) = TestDB::with_single_file(&ra_fixture);
|
||||
|
@ -717,7 +717,7 @@ impl<'a> CompletionContext<'a> {
|
||||
let krate = scope.krate();
|
||||
let module = scope.module();
|
||||
|
||||
let toolchain = db.crate_graph()[krate.into()].channel();
|
||||
let toolchain = db.toolchain_channel(krate.into());
|
||||
// `toolchain == None` means we're in some detached files. Since we have no information on
|
||||
// the toolchain being used, let's just allow unstable items to be listed.
|
||||
let is_nightly = matches!(toolchain, Some(base_db::ReleaseChannel::Nightly) | None);
|
||||
|
@ -71,7 +71,6 @@ impl Definition {
|
||||
&self,
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
new_name: &str,
|
||||
rename_external: bool,
|
||||
) -> Result<SourceChange> {
|
||||
// self.krate() returns None if
|
||||
// self is a built-in attr, built-in type or tool module.
|
||||
@ -80,8 +79,8 @@ impl Definition {
|
||||
if let Some(krate) = self.krate(sema.db) {
|
||||
// Can we not rename non-local items?
|
||||
// Then bail if non-local
|
||||
if !rename_external && !krate.origin(sema.db).is_local() {
|
||||
bail!("Cannot rename a non-local definition as the config for it is disabled")
|
||||
if !krate.origin(sema.db).is_local() {
|
||||
bail!("Cannot rename a non-local definition")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Ass
|
||||
let label = format!("Rename to {}", d.suggested_text);
|
||||
let mut res = unresolved_fix("change_case", &label, frange.range);
|
||||
if ctx.resolve.should_resolve(&res.id) {
|
||||
let source_change = def.rename(&ctx.sema, &d.suggested_text, true);
|
||||
let source_change = def.rename(&ctx.sema, &d.suggested_text);
|
||||
res.source_change = Some(source_change.ok().unwrap_or_default());
|
||||
}
|
||||
|
||||
|
@ -501,7 +501,7 @@ fn get_doc_base_urls(
|
||||
let Some(krate) = def.krate(db) else { return Default::default() };
|
||||
let Some(display_name) = krate.display_name(db) else { return Default::default() };
|
||||
let crate_data = &db.crate_graph()[krate.into()];
|
||||
let channel = crate_data.channel().unwrap_or(ReleaseChannel::Nightly).as_str();
|
||||
let channel = db.toolchain_channel(krate.into()).unwrap_or(ReleaseChannel::Nightly).as_str();
|
||||
|
||||
let (web_base, local_base) = match &crate_data.origin {
|
||||
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
|
||||
|
@ -253,11 +253,11 @@ impl Analysis {
|
||||
Env::default(),
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
Err("Analysis::from_single_file has no target layout".into()),
|
||||
None,
|
||||
);
|
||||
change.change_file(file_id, Some(Arc::from(text)));
|
||||
change.set_crate_graph(crate_graph);
|
||||
change.set_target_data_layouts(vec![Err("fixture has no layout".into())]);
|
||||
change.set_toolchains(vec![None]);
|
||||
host.apply_change(change);
|
||||
(host.analysis(), file_id)
|
||||
}
|
||||
@ -675,9 +675,8 @@ impl Analysis {
|
||||
&self,
|
||||
position: FilePosition,
|
||||
new_name: &str,
|
||||
rename_external: bool,
|
||||
) -> Cancellable<Result<SourceChange, RenameError>> {
|
||||
self.with_db(|db| rename::rename(db, position, new_name, rename_external))
|
||||
self.with_db(|db| rename::rename(db, position, new_name))
|
||||
}
|
||||
|
||||
pub fn prepare_rename(
|
||||
|
@ -84,7 +84,6 @@ pub(crate) fn rename(
|
||||
db: &RootDatabase,
|
||||
position: FilePosition,
|
||||
new_name: &str,
|
||||
rename_external: bool,
|
||||
) -> RenameResult<SourceChange> {
|
||||
let sema = Semantics::new(db);
|
||||
let source_file = sema.parse(position.file_id);
|
||||
@ -104,7 +103,7 @@ pub(crate) fn rename(
|
||||
return rename_to_self(&sema, local);
|
||||
}
|
||||
}
|
||||
def.rename(&sema, new_name, rename_external)
|
||||
def.rename(&sema, new_name)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -123,9 +122,9 @@ pub(crate) fn will_rename_file(
|
||||
let module = sema.to_module_def(file_id)?;
|
||||
let def = Definition::Module(module);
|
||||
let mut change = if is_raw_identifier(new_name_stem) {
|
||||
def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem]), true).ok()?
|
||||
def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
|
||||
} else {
|
||||
def.rename(&sema, new_name_stem, true).ok()?
|
||||
def.rename(&sema, new_name_stem).ok()?
|
||||
};
|
||||
change.file_system_edits.clear();
|
||||
Some(change)
|
||||
@ -377,16 +376,11 @@ mod tests {
|
||||
use super::{RangeInfo, RenameError};
|
||||
|
||||
fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
|
||||
check_with_rename_config(new_name, ra_fixture_before, ra_fixture_after, true);
|
||||
check_with_rename_config(new_name, ra_fixture_before, ra_fixture_after);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_with_rename_config(
|
||||
new_name: &str,
|
||||
ra_fixture_before: &str,
|
||||
ra_fixture_after: &str,
|
||||
rename_external: bool,
|
||||
) {
|
||||
fn check_with_rename_config(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
|
||||
let ra_fixture_after = &trim_indent(ra_fixture_after);
|
||||
let (analysis, position) = fixture::position(ra_fixture_before);
|
||||
if !ra_fixture_after.starts_with("error: ") {
|
||||
@ -395,7 +389,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
let rename_result = analysis
|
||||
.rename(position, new_name, rename_external)
|
||||
.rename(position, new_name)
|
||||
.unwrap_or_else(|err| panic!("Rename to '{new_name}' was cancelled: {err}"));
|
||||
match rename_result {
|
||||
Ok(source_change) => {
|
||||
@ -426,10 +420,8 @@ mod tests {
|
||||
|
||||
fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
|
||||
let (analysis, position) = fixture::position(ra_fixture);
|
||||
let source_change = analysis
|
||||
.rename(position, new_name, true)
|
||||
.unwrap()
|
||||
.expect("Expect returned a RenameError");
|
||||
let source_change =
|
||||
analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError");
|
||||
expect.assert_eq(&filter_expect(source_change))
|
||||
}
|
||||
|
||||
@ -2636,19 +2628,7 @@ pub struct S;
|
||||
//- /main.rs crate:main deps:lib new_source_root:local
|
||||
use lib::S$0;
|
||||
"#,
|
||||
"error: Cannot rename a non-local definition as the config for it is disabled",
|
||||
false,
|
||||
);
|
||||
|
||||
check(
|
||||
"Baz",
|
||||
r#"
|
||||
//- /lib.rs crate:lib new_source_root:library
|
||||
pub struct S;
|
||||
//- /main.rs crate:main deps:lib new_source_root:local
|
||||
use lib::S$0;
|
||||
"#,
|
||||
"use lib::Baz;\n",
|
||||
"error: Cannot rename a non-local definition",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2663,8 +2643,7 @@ use core::hash::Hash;
|
||||
#[derive(H$0ash)]
|
||||
struct A;
|
||||
"#,
|
||||
"error: Cannot rename a non-local definition as the config for it is disabled",
|
||||
false,
|
||||
"error: Cannot rename a non-local definition",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,6 @@ pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
|
||||
data.env.clone(),
|
||||
data.is_proc_macro,
|
||||
data.origin.clone(),
|
||||
data.target_layout.clone(),
|
||||
data.toolchain.clone(),
|
||||
);
|
||||
new_proc_macros.insert(new_id, proc_macros[&old_id].clone());
|
||||
map.insert(old_id, new_id);
|
||||
|
@ -72,8 +72,6 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
|
||||
dependencies,
|
||||
origin,
|
||||
is_proc_macro,
|
||||
target_layout,
|
||||
toolchain,
|
||||
} = &crate_graph[crate_id];
|
||||
format_to!(
|
||||
buf,
|
||||
@ -91,12 +89,6 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
|
||||
format_to!(buf, " Env: {:?}\n", env);
|
||||
format_to!(buf, " Origin: {:?}\n", origin);
|
||||
format_to!(buf, " Is a proc macro crate: {}\n", is_proc_macro);
|
||||
format_to!(buf, " Workspace Target Layout: {:?}\n", target_layout);
|
||||
format_to!(
|
||||
buf,
|
||||
" Workspace Toolchain: {}\n",
|
||||
toolchain.as_ref().map_or_else(|| "n/a".into(), |v| v.to_string())
|
||||
);
|
||||
let deps = dependencies
|
||||
.iter()
|
||||
.map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw()))
|
||||
|
@ -2,7 +2,7 @@
|
||||
//! for incorporating changes.
|
||||
// Note, don't remove any public api from this. This API is consumed by external tools
|
||||
// to run rust-analyzer as a library.
|
||||
use std::{collections::hash_map::Entry, mem, path::Path, sync};
|
||||
use std::{collections::hash_map::Entry, iter, mem, path::Path, sync};
|
||||
|
||||
use crossbeam_channel::{unbounded, Receiver};
|
||||
use hir_expand::proc_macro::{
|
||||
@ -106,7 +106,7 @@ pub fn load_workspace(
|
||||
.collect()
|
||||
};
|
||||
|
||||
let project_folders = ProjectFolders::new(&[ws], &[]);
|
||||
let project_folders = ProjectFolders::new(std::slice::from_ref(&ws), &[]);
|
||||
loader.set_config(vfs::loader::Config {
|
||||
load: project_folders.load,
|
||||
watch: vec![],
|
||||
@ -114,6 +114,7 @@ pub fn load_workspace(
|
||||
});
|
||||
|
||||
let host = load_crate_graph(
|
||||
&ws,
|
||||
crate_graph,
|
||||
proc_macros,
|
||||
project_folders.source_root_config,
|
||||
@ -301,6 +302,7 @@ pub fn load_proc_macro(
|
||||
}
|
||||
|
||||
fn load_crate_graph(
|
||||
ws: &ProjectWorkspace,
|
||||
crate_graph: CrateGraph,
|
||||
proc_macros: ProcMacros,
|
||||
source_root_config: SourceRootConfig,
|
||||
@ -339,8 +341,17 @@ fn load_crate_graph(
|
||||
let source_roots = source_root_config.partition(vfs);
|
||||
analysis_change.set_roots(source_roots);
|
||||
|
||||
let num_crates = crate_graph.len();
|
||||
analysis_change.set_crate_graph(crate_graph);
|
||||
analysis_change.set_proc_macros(proc_macros);
|
||||
if let ProjectWorkspace::Cargo { toolchain, target_layout, .. }
|
||||
| ProjectWorkspace::Json { toolchain, target_layout, .. } = ws
|
||||
{
|
||||
analysis_change.set_target_data_layouts(
|
||||
iter::repeat(target_layout.clone()).take(num_crates).collect(),
|
||||
);
|
||||
analysis_change.set_toolchains(iter::repeat(toolchain.clone()).take(num_crates).collect());
|
||||
}
|
||||
|
||||
host.apply_change(analysis_change);
|
||||
host
|
||||
|
@ -49,7 +49,7 @@
|
||||
//! user explores them belongs to that extension (it's totally valid to change
|
||||
//! rust-project.json over time via configuration request!)
|
||||
|
||||
use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, DependencyKind, Edition};
|
||||
use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition};
|
||||
use la_arena::RawIdx;
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use rustc_hash::FxHashMap;
|
||||
@ -135,7 +135,6 @@ impl ProjectJson {
|
||||
Dependency::new(
|
||||
dep_data.name,
|
||||
CrateId::from_raw(RawIdx::from(dep_data.krate as u32)),
|
||||
DependencyKind::Normal,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
|
@ -9,6 +9,7 @@ use expect_test::{expect_file, ExpectFile};
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::de::DeserializeOwned;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
|
||||
@ -76,7 +77,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
|
||||
sysroot,
|
||||
rustc_cfg: Vec::new(),
|
||||
toolchain: None,
|
||||
target_layout: Err("test has no data layout".to_owned()),
|
||||
target_layout: Err(Arc::from("test has no data layout")),
|
||||
};
|
||||
to_crate_graph(project_workspace)
|
||||
}
|
||||
@ -237,7 +238,7 @@ fn crate_graph_dedup_identical() {
|
||||
|
||||
let (d_crate_graph, mut d_proc_macros) = (crate_graph.clone(), proc_macros.clone());
|
||||
|
||||
crate_graph.extend(d_crate_graph.clone(), &mut d_proc_macros, |_| ());
|
||||
crate_graph.extend(d_crate_graph.clone(), &mut d_proc_macros, |(_, a), (_, b)| a == b);
|
||||
assert!(crate_graph.iter().eq(d_crate_graph.iter()));
|
||||
assert_eq!(proc_macros, d_proc_macros);
|
||||
}
|
||||
@ -253,62 +254,10 @@ fn crate_graph_dedup() {
|
||||
load_cargo_with_fake_sysroot(path_map, "regex-metadata.json");
|
||||
assert_eq!(regex_crate_graph.iter().count(), 60);
|
||||
|
||||
crate_graph.extend(regex_crate_graph, &mut regex_proc_macros, |_| ());
|
||||
crate_graph.extend(regex_crate_graph, &mut regex_proc_macros, |(_, a), (_, b)| a == b);
|
||||
assert_eq!(crate_graph.iter().count(), 118);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deduplicate_origin_dev() {
|
||||
let path_map = &mut Default::default();
|
||||
let (mut crate_graph, _proc_macros) =
|
||||
load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_A.json");
|
||||
crate_graph.sort_deps();
|
||||
let (crate_graph_1, mut _proc_macros_2) =
|
||||
load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_B.json");
|
||||
|
||||
crate_graph.extend(crate_graph_1, &mut _proc_macros_2, |_| ());
|
||||
|
||||
let mut crates_named_p2 = vec![];
|
||||
for id in crate_graph.iter() {
|
||||
let krate = &crate_graph[id];
|
||||
if let Some(name) = krate.display_name.as_ref() {
|
||||
if name.to_string() == "p2" {
|
||||
crates_named_p2.push(krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(crates_named_p2.len() == 1);
|
||||
let p2 = crates_named_p2[0];
|
||||
assert!(p2.origin.is_local());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deduplicate_origin_dev_rev() {
|
||||
let path_map = &mut Default::default();
|
||||
let (mut crate_graph, _proc_macros) =
|
||||
load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_B.json");
|
||||
crate_graph.sort_deps();
|
||||
let (crate_graph_1, mut _proc_macros_2) =
|
||||
load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_A.json");
|
||||
|
||||
crate_graph.extend(crate_graph_1, &mut _proc_macros_2, |_| ());
|
||||
|
||||
let mut crates_named_p2 = vec![];
|
||||
for id in crate_graph.iter() {
|
||||
let krate = &crate_graph[id];
|
||||
if let Some(name) = krate.display_name.as_ref() {
|
||||
if name.to_string() == "p2" {
|
||||
crates_named_p2.push(krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(crates_named_p2.len() == 1);
|
||||
let p2 = crates_named_p2[0];
|
||||
assert!(p2.origin.is_local());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoke_test_real_sysroot_cargo() {
|
||||
if std::env::var("SYSROOT_CARGO_METADATA").is_err() {
|
||||
|
@ -6,8 +6,8 @@ use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr,
|
||||
|
||||
use anyhow::{format_err, Context};
|
||||
use base_db::{
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
|
||||
Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
|
||||
FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
|
||||
};
|
||||
use cfg::{CfgAtom, CfgDiff, CfgOptions};
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
@ -71,7 +71,7 @@ pub enum ProjectWorkspace {
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
cfg_overrides: CfgOverrides,
|
||||
toolchain: Option<Version>,
|
||||
target_layout: Result<String, String>,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
cargo_config_extra_env: FxHashMap<String, String>,
|
||||
},
|
||||
/// Project workspace was manually specified using a `rust-project.json` file.
|
||||
@ -82,7 +82,7 @@ pub enum ProjectWorkspace {
|
||||
/// `rustc --print cfg`.
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
toolchain: Option<Version>,
|
||||
target_layout: Result<String, String>,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
},
|
||||
// FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
|
||||
// That's not the end user experience we should strive for.
|
||||
@ -335,7 +335,9 @@ impl ProjectWorkspace {
|
||||
rustc_cfg,
|
||||
cfg_overrides,
|
||||
toolchain,
|
||||
target_layout: data_layout.map_err(|it| it.to_string()),
|
||||
target_layout: data_layout
|
||||
.map(Arc::from)
|
||||
.map_err(|it| Arc::from(it.to_string())),
|
||||
cargo_config_extra_env,
|
||||
}
|
||||
}
|
||||
@ -393,7 +395,7 @@ impl ProjectWorkspace {
|
||||
sysroot,
|
||||
rustc_cfg,
|
||||
toolchain,
|
||||
target_layout: data_layout.map_err(|it| it.to_string()),
|
||||
target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,20 +692,19 @@ impl ProjectWorkspace {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
|
||||
|
||||
let (mut crate_graph, proc_macros) = match self {
|
||||
ProjectWorkspace::Json { project, sysroot, rustc_cfg, toolchain, target_layout } => {
|
||||
project_json_to_crate_graph(
|
||||
rustc_cfg.clone(),
|
||||
load,
|
||||
project,
|
||||
sysroot.as_ref().ok(),
|
||||
extra_env,
|
||||
match target_layout.as_ref() {
|
||||
Ok(it) => Ok(Arc::from(it.as_str())),
|
||||
Err(it) => Err(Arc::from(it.as_str())),
|
||||
},
|
||||
toolchain.clone(),
|
||||
)
|
||||
}
|
||||
ProjectWorkspace::Json {
|
||||
project,
|
||||
sysroot,
|
||||
rustc_cfg,
|
||||
toolchain: _,
|
||||
target_layout: _,
|
||||
} => project_json_to_crate_graph(
|
||||
rustc_cfg.clone(),
|
||||
load,
|
||||
project,
|
||||
sysroot.as_ref().ok(),
|
||||
extra_env,
|
||||
),
|
||||
ProjectWorkspace::Cargo {
|
||||
cargo,
|
||||
sysroot,
|
||||
@ -711,8 +712,8 @@ impl ProjectWorkspace {
|
||||
rustc_cfg,
|
||||
cfg_overrides,
|
||||
build_scripts,
|
||||
toolchain,
|
||||
target_layout,
|
||||
toolchain: _,
|
||||
target_layout: _,
|
||||
cargo_config_extra_env: _,
|
||||
} => cargo_to_crate_graph(
|
||||
load,
|
||||
@ -722,20 +723,9 @@ impl ProjectWorkspace {
|
||||
rustc_cfg.clone(),
|
||||
cfg_overrides,
|
||||
build_scripts,
|
||||
match target_layout.as_ref() {
|
||||
Ok(it) => Ok(Arc::from(it.as_str())),
|
||||
Err(it) => Err(Arc::from(it.as_str())),
|
||||
},
|
||||
toolchain.as_ref(),
|
||||
),
|
||||
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
|
||||
detached_files_to_crate_graph(
|
||||
rustc_cfg.clone(),
|
||||
load,
|
||||
files,
|
||||
sysroot.as_ref().ok(),
|
||||
Err("detached file projects have no target layout set".into()),
|
||||
)
|
||||
detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot.as_ref().ok())
|
||||
}
|
||||
};
|
||||
if crate_graph.patch_cfg_if() {
|
||||
@ -818,21 +808,12 @@ fn project_json_to_crate_graph(
|
||||
project: &ProjectJson,
|
||||
sysroot: Option<&Sysroot>,
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
toolchain: Option<Version>,
|
||||
) -> (CrateGraph, ProcMacroPaths) {
|
||||
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
|
||||
let (crate_graph, proc_macros) = &mut res;
|
||||
let sysroot_deps = sysroot.as_ref().map(|sysroot| {
|
||||
sysroot_to_crate_graph(
|
||||
crate_graph,
|
||||
sysroot,
|
||||
rustc_cfg.clone(),
|
||||
target_layout.clone(),
|
||||
load,
|
||||
toolchain.as_ref(),
|
||||
)
|
||||
});
|
||||
let sysroot_deps = sysroot
|
||||
.as_ref()
|
||||
.map(|sysroot| sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load));
|
||||
|
||||
let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
|
||||
let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
|
||||
@ -887,8 +868,6 @@ fn project_json_to_crate_graph(
|
||||
} else {
|
||||
CrateOrigin::Local { repo: None, name: None }
|
||||
},
|
||||
target_layout.clone(),
|
||||
toolchain.clone(),
|
||||
);
|
||||
if *is_proc_macro {
|
||||
if let Some(path) = proc_macro_dylib_path.clone() {
|
||||
@ -915,7 +894,7 @@ fn project_json_to_crate_graph(
|
||||
|
||||
for dep in &krate.deps {
|
||||
if let Some(&to) = crates.get(&dep.crate_id) {
|
||||
add_dep(crate_graph, from, dep.name.clone(), to, dep.kind().to_owned())
|
||||
add_dep(crate_graph, from, dep.name.clone(), to)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -931,22 +910,13 @@ fn cargo_to_crate_graph(
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
override_cfg: &CfgOverrides,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
toolchain: Option<&Version>,
|
||||
) -> (CrateGraph, ProcMacroPaths) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "cargo_to_crate_graph").entered();
|
||||
let mut res = (CrateGraph::default(), ProcMacroPaths::default());
|
||||
let crate_graph = &mut res.0;
|
||||
let proc_macros = &mut res.1;
|
||||
let (public_deps, libproc_macro) = match sysroot {
|
||||
Some(sysroot) => sysroot_to_crate_graph(
|
||||
crate_graph,
|
||||
sysroot,
|
||||
rustc_cfg.clone(),
|
||||
target_layout.clone(),
|
||||
load,
|
||||
toolchain,
|
||||
),
|
||||
Some(sysroot) => sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load),
|
||||
None => (SysrootPublicDeps::default(), None),
|
||||
};
|
||||
|
||||
@ -968,8 +938,6 @@ fn cargo_to_crate_graph(
|
||||
// Add test cfg for local crates
|
||||
if cargo[pkg].is_local {
|
||||
cfg_options.insert_atom("test".into());
|
||||
}
|
||||
if cargo[pkg].is_member {
|
||||
cfg_options.insert_atom("rust_analyzer".into());
|
||||
}
|
||||
|
||||
@ -1003,18 +971,28 @@ fn cargo_to_crate_graph(
|
||||
|
||||
let Some(file_id) = load(root) else { continue };
|
||||
|
||||
let build_data = build_scripts.get_output(pkg);
|
||||
let pkg_data = &cargo[pkg];
|
||||
let crate_id = add_target_crate_root(
|
||||
crate_graph,
|
||||
proc_macros,
|
||||
&cargo[pkg],
|
||||
build_scripts.get_output(pkg),
|
||||
pkg_data,
|
||||
build_data,
|
||||
cfg_options.clone(),
|
||||
file_id,
|
||||
name,
|
||||
kind,
|
||||
target_layout.clone(),
|
||||
false,
|
||||
toolchain.cloned(),
|
||||
if pkg_data.is_local {
|
||||
CrateOrigin::Local {
|
||||
repo: pkg_data.repository.clone(),
|
||||
name: Some(pkg_data.name.clone()),
|
||||
}
|
||||
} else {
|
||||
CrateOrigin::Library {
|
||||
repo: pkg_data.repository.clone(),
|
||||
name: pkg_data.name.clone(),
|
||||
}
|
||||
},
|
||||
);
|
||||
if let TargetKind::Lib { .. } = kind {
|
||||
lib_tgt = Some((crate_id, name.clone()));
|
||||
@ -1048,7 +1026,7 @@ fn cargo_to_crate_graph(
|
||||
// cargo metadata does not do any normalization,
|
||||
// so we do it ourselves currently
|
||||
let name = CrateName::normalize_dashes(&name);
|
||||
add_dep(crate_graph, from, name, to, DependencyKind::Normal);
|
||||
add_dep(crate_graph, from, name, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1068,17 +1046,7 @@ fn cargo_to_crate_graph(
|
||||
continue;
|
||||
}
|
||||
|
||||
add_dep(
|
||||
crate_graph,
|
||||
from,
|
||||
name.clone(),
|
||||
to,
|
||||
match dep.kind {
|
||||
DepKind::Normal => DependencyKind::Normal,
|
||||
DepKind::Dev => DependencyKind::Dev,
|
||||
DepKind::Build => DependencyKind::Build,
|
||||
},
|
||||
)
|
||||
add_dep(crate_graph, from, name.clone(), to)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1106,8 +1074,6 @@ fn cargo_to_crate_graph(
|
||||
} else {
|
||||
rustc_build_scripts
|
||||
},
|
||||
target_layout,
|
||||
toolchain,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1119,19 +1085,11 @@ fn detached_files_to_crate_graph(
|
||||
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
|
||||
detached_files: &[AbsPathBuf],
|
||||
sysroot: Option<&Sysroot>,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
) -> (CrateGraph, ProcMacroPaths) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered();
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let (public_deps, _libproc_macro) = match sysroot {
|
||||
Some(sysroot) => sysroot_to_crate_graph(
|
||||
&mut crate_graph,
|
||||
sysroot,
|
||||
rustc_cfg.clone(),
|
||||
target_layout.clone(),
|
||||
load,
|
||||
None,
|
||||
),
|
||||
Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
|
||||
None => (SysrootPublicDeps::default(), None),
|
||||
};
|
||||
|
||||
@ -1163,8 +1121,6 @@ fn detached_files_to_crate_graph(
|
||||
repo: None,
|
||||
name: display_name.map(|n| n.canonical_name().to_owned()),
|
||||
},
|
||||
target_layout.clone(),
|
||||
None,
|
||||
);
|
||||
|
||||
public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
|
||||
@ -1185,8 +1141,6 @@ fn handle_rustc_crates(
|
||||
cfg_options: &CfgOptions,
|
||||
override_cfg: &CfgOverrides,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
toolchain: Option<&Version>,
|
||||
) {
|
||||
let mut rustc_pkg_crates = FxHashMap::default();
|
||||
// The root package of the rustc-dev component is rustc_driver, so we match that
|
||||
@ -1239,9 +1193,7 @@ fn handle_rustc_crates(
|
||||
file_id,
|
||||
&rustc_workspace[tgt].name,
|
||||
kind,
|
||||
target_layout.clone(),
|
||||
true,
|
||||
toolchain.cloned(),
|
||||
CrateOrigin::Rustc { name: rustc_workspace[pkg].name.clone() },
|
||||
);
|
||||
pkg_to_lib_crate.insert(pkg, crate_id);
|
||||
// Add dependencies on core / std / alloc for this crate
|
||||
@ -1261,17 +1213,7 @@ fn handle_rustc_crates(
|
||||
let name = CrateName::new(&dep.name).unwrap();
|
||||
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
||||
for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
add_dep(
|
||||
crate_graph,
|
||||
from,
|
||||
name.clone(),
|
||||
to,
|
||||
match dep.kind {
|
||||
DepKind::Normal => DependencyKind::Normal,
|
||||
DepKind::Dev => DependencyKind::Dev,
|
||||
DepKind::Build => DependencyKind::Build,
|
||||
},
|
||||
);
|
||||
add_dep(crate_graph, from, name.clone(), to);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1293,7 +1235,7 @@ fn handle_rustc_crates(
|
||||
// `rust_analyzer` thinks that it should use the one from the `rustc_source`
|
||||
// instead of the one from `crates.io`
|
||||
if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
|
||||
add_dep(crate_graph, *from, name.clone(), to, DependencyKind::Normal);
|
||||
add_dep(crate_graph, *from, name.clone(), to);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1310,9 +1252,7 @@ fn add_target_crate_root(
|
||||
file_id: FileId,
|
||||
cargo_name: &str,
|
||||
kind: TargetKind,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
rustc_crate: bool,
|
||||
toolchain: Option<Version>,
|
||||
origin: CrateOrigin,
|
||||
) -> CrateId {
|
||||
let edition = pkg.edition;
|
||||
let potential_cfg_options = if pkg.features.is_empty() {
|
||||
@ -1360,15 +1300,7 @@ fn add_target_crate_root(
|
||||
potential_cfg_options,
|
||||
env,
|
||||
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
|
||||
if rustc_crate {
|
||||
CrateOrigin::Rustc { name: pkg.name.clone() }
|
||||
} else if pkg.is_member {
|
||||
CrateOrigin::Local { repo: pkg.repository.clone(), name: Some(pkg.name.clone()) }
|
||||
} else {
|
||||
CrateOrigin::Library { repo: pkg.repository.clone(), name: pkg.name.clone() }
|
||||
},
|
||||
target_layout,
|
||||
toolchain,
|
||||
origin,
|
||||
);
|
||||
if let TargetKind::Lib { is_proc_macro: true } = kind {
|
||||
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
|
||||
@ -1392,14 +1324,7 @@ impl SysrootPublicDeps {
|
||||
/// Makes `from` depend on the public sysroot crates.
|
||||
fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
|
||||
for (name, krate, prelude) in &self.deps {
|
||||
add_dep_with_prelude(
|
||||
crate_graph,
|
||||
from,
|
||||
name.clone(),
|
||||
*krate,
|
||||
*prelude,
|
||||
DependencyKind::Normal,
|
||||
);
|
||||
add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1408,9 +1333,7 @@ fn sysroot_to_crate_graph(
|
||||
crate_graph: &mut CrateGraph,
|
||||
sysroot: &Sysroot,
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
target_layout: TargetLayoutLoadResult,
|
||||
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
|
||||
toolchain: Option<&Version>,
|
||||
) -> (SysrootPublicDeps, Option<CrateId>) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "sysroot_to_crate_graph").entered();
|
||||
match sysroot.mode() {
|
||||
@ -1423,8 +1346,6 @@ fn sysroot_to_crate_graph(
|
||||
rustc_cfg,
|
||||
&CfgOverrides::default(),
|
||||
&WorkspaceBuildScripts::default(),
|
||||
target_layout,
|
||||
toolchain,
|
||||
);
|
||||
|
||||
let mut pub_deps = vec![];
|
||||
@ -1467,17 +1388,16 @@ fn sysroot_to_crate_graph(
|
||||
|
||||
// Remove all crates except the ones we are interested in to keep the sysroot graph small.
|
||||
let removed_mapping = cg.remove_crates_except(&marker_set);
|
||||
let mapping = crate_graph.extend(cg, &mut pm, |(_, a), (_, b)| a == b);
|
||||
|
||||
crate_graph.extend(cg, &mut pm, |mapping| {
|
||||
// Map the id through the removal mapping first, then through the crate graph extension mapping.
|
||||
pub_deps.iter_mut().for_each(|(_, cid, _)| {
|
||||
*cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
|
||||
});
|
||||
if let Some(libproc_macro) = &mut libproc_macro {
|
||||
*libproc_macro = mapping
|
||||
[&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
|
||||
}
|
||||
// Map the id through the removal mapping first, then through the crate graph extension mapping.
|
||||
pub_deps.iter_mut().for_each(|(_, cid, _)| {
|
||||
*cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
|
||||
});
|
||||
if let Some(libproc_macro) = &mut libproc_macro {
|
||||
*libproc_macro = mapping
|
||||
[&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
|
||||
}
|
||||
|
||||
(SysrootPublicDeps { deps: pub_deps }, libproc_macro)
|
||||
}
|
||||
@ -1501,8 +1421,6 @@ fn sysroot_to_crate_graph(
|
||||
env,
|
||||
false,
|
||||
CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
|
||||
target_layout.clone(),
|
||||
toolchain.cloned(),
|
||||
);
|
||||
Some((krate, crate_id))
|
||||
})
|
||||
@ -1514,7 +1432,7 @@ fn sysroot_to_crate_graph(
|
||||
if let (Some(&from), Some(&to)) =
|
||||
(sysroot_crates.get(&from), sysroot_crates.get(&to))
|
||||
{
|
||||
add_dep(crate_graph, from, name, to, DependencyKind::Normal);
|
||||
add_dep(crate_graph, from, name, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1535,14 +1453,8 @@ fn sysroot_to_crate_graph(
|
||||
}
|
||||
}
|
||||
|
||||
fn add_dep(
|
||||
graph: &mut CrateGraph,
|
||||
from: CrateId,
|
||||
name: CrateName,
|
||||
to: CrateId,
|
||||
kind: DependencyKind,
|
||||
) {
|
||||
add_dep_inner(graph, from, Dependency::new(name, to, kind))
|
||||
fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
|
||||
add_dep_inner(graph, from, Dependency::new(name, to))
|
||||
}
|
||||
|
||||
fn add_dep_with_prelude(
|
||||
@ -1551,20 +1463,12 @@ fn add_dep_with_prelude(
|
||||
name: CrateName,
|
||||
to: CrateId,
|
||||
prelude: bool,
|
||||
kind: DependencyKind,
|
||||
) {
|
||||
add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, kind))
|
||||
add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude))
|
||||
}
|
||||
|
||||
fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) {
|
||||
add_dep_with_prelude(
|
||||
crate_graph,
|
||||
from,
|
||||
CrateName::new("proc_macro").unwrap(),
|
||||
to,
|
||||
prelude,
|
||||
DependencyKind::Normal,
|
||||
);
|
||||
add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude);
|
||||
}
|
||||
|
||||
fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
|
||||
|
@ -48,7 +48,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -59,10 +58,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
1: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -113,7 +108,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -121,7 +115,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -132,10 +125,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
2: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -186,7 +175,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -194,7 +182,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -205,10 +192,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
3: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -259,7 +242,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -267,7 +249,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -278,10 +259,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
4: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -347,9 +324,5 @@
|
||||
name: "libc",
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
}
|
@ -48,7 +48,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -59,10 +58,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
1: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -113,7 +108,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -121,7 +115,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -132,10 +125,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
2: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -186,7 +175,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -194,7 +182,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -205,10 +192,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
3: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -259,7 +242,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -267,7 +249,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -278,10 +259,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
4: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -347,9 +324,5 @@
|
||||
name: "libc",
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
}
|
@ -47,7 +47,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -58,10 +57,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
1: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -111,7 +106,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -119,7 +113,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -130,10 +123,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
2: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -183,7 +172,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -191,7 +179,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -202,10 +189,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
3: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -255,7 +238,6 @@
|
||||
name: CrateName(
|
||||
"hello_world",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -263,7 +245,6 @@
|
||||
name: CrateName(
|
||||
"libc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -274,10 +255,6 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
4: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -343,9 +320,5 @@
|
||||
name: "libc",
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"target_data_layout not loaded",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
}
|
@ -28,7 +28,6 @@
|
||||
name: CrateName(
|
||||
"core",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -36,10 +35,6 @@
|
||||
Alloc,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
1: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -69,10 +64,6 @@
|
||||
Core,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
2: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -102,10 +93,6 @@
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
3: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -135,10 +122,6 @@
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
4: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -169,7 +152,6 @@
|
||||
name: CrateName(
|
||||
"std",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -177,7 +159,6 @@
|
||||
name: CrateName(
|
||||
"core",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -185,10 +166,6 @@
|
||||
ProcMacro,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
5: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -218,10 +195,6 @@
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
6: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -252,7 +225,6 @@
|
||||
name: CrateName(
|
||||
"alloc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -260,7 +232,6 @@
|
||||
name: CrateName(
|
||||
"panic_unwind",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -268,7 +239,6 @@
|
||||
name: CrateName(
|
||||
"panic_abort",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -276,7 +246,6 @@
|
||||
name: CrateName(
|
||||
"core",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -284,7 +253,6 @@
|
||||
name: CrateName(
|
||||
"profiler_builtins",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -292,7 +260,6 @@
|
||||
name: CrateName(
|
||||
"unwind",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -300,7 +267,6 @@
|
||||
name: CrateName(
|
||||
"std_detect",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -308,7 +274,6 @@
|
||||
name: CrateName(
|
||||
"test",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
@ -316,10 +281,6 @@
|
||||
Std,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
7: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -349,10 +310,6 @@
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
8: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -382,10 +339,6 @@
|
||||
Test,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
9: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -415,10 +368,6 @@
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
10: CrateData {
|
||||
root_file_id: FileId(
|
||||
@ -449,7 +398,6 @@
|
||||
name: CrateName(
|
||||
"core",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -457,7 +405,6 @@
|
||||
name: CrateName(
|
||||
"alloc",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -465,7 +412,6 @@
|
||||
name: CrateName(
|
||||
"std",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
@ -473,7 +419,6 @@
|
||||
name: CrateName(
|
||||
"test",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: false,
|
||||
},
|
||||
Dependency {
|
||||
@ -481,7 +426,6 @@
|
||||
name: CrateName(
|
||||
"proc_macro",
|
||||
),
|
||||
kind: Normal,
|
||||
prelude: false,
|
||||
},
|
||||
],
|
||||
@ -492,9 +436,5 @@
|
||||
),
|
||||
},
|
||||
is_proc_macro: false,
|
||||
target_layout: Err(
|
||||
"test has no data layout",
|
||||
),
|
||||
toolchain: None,
|
||||
},
|
||||
}
|
@ -511,9 +511,6 @@ config_data! {
|
||||
/// Exclude tests from find-all-references.
|
||||
references_excludeTests: bool = "false",
|
||||
|
||||
/// Allow renaming of items not belonging to the loaded workspaces.
|
||||
rename_allowExternalItems: bool = "false",
|
||||
|
||||
|
||||
/// Command to be executed instead of 'cargo' for runnables.
|
||||
runnables_command: Option<String> = "null",
|
||||
@ -1774,10 +1771,6 @@ impl Config {
|
||||
self.data.typing_autoClosingAngleBrackets_enable
|
||||
}
|
||||
|
||||
pub fn rename(&self) -> bool {
|
||||
self.data.rename_allowExternalItems
|
||||
}
|
||||
|
||||
// FIXME: VSCode seems to work wrong sometimes, see https://github.com/microsoft/vscode/issues/193124
|
||||
// hence, distinguish it for now.
|
||||
pub fn is_visual_studio_code(&self) -> bool {
|
||||
|
@ -1017,10 +1017,8 @@ pub(crate) fn handle_rename(
|
||||
let _p = tracing::span!(tracing::Level::INFO, "handle_rename").entered();
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
|
||||
let mut change = snap
|
||||
.analysis
|
||||
.rename(position, ¶ms.new_name, snap.config.rename())?
|
||||
.map_err(to_proto::rename_error)?;
|
||||
let mut change =
|
||||
snap.analysis.rename(position, ¶ms.new_name)?.map_err(to_proto::rename_error)?;
|
||||
|
||||
// this is kind of a hack to prevent double edits from happening when moving files
|
||||
// When a module gets renamed by renaming the mod declaration this causes the file to move
|
||||
|
@ -47,7 +47,9 @@ mod integrated_benchmarks;
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub use crate::{caps::server_capabilities, main_loop::main_loop, version::version};
|
||||
pub use crate::{
|
||||
caps::server_capabilities, main_loop::main_loop, reload::ws_to_crate_graph, version::version,
|
||||
};
|
||||
|
||||
pub fn from_json<T: DeserializeOwned>(
|
||||
what: &'static str,
|
||||
|
@ -17,8 +17,9 @@ use std::{iter, mem};
|
||||
|
||||
use flycheck::{FlycheckConfig, FlycheckHandle};
|
||||
use hir::{db::DefDatabase, Change, ProcMacros};
|
||||
use ide::CrateId;
|
||||
use ide_db::{
|
||||
base_db::{salsa::Durability, CrateGraph, ProcMacroPaths},
|
||||
base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
|
||||
FxHashMap,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
@ -28,7 +29,7 @@ use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
|
||||
use rustc_hash::FxHashSet;
|
||||
use stdx::{format_to, thread::ThreadIntent};
|
||||
use triomphe::Arc;
|
||||
use vfs::{AbsPath, ChangeKind};
|
||||
use vfs::{AbsPath, AbsPathBuf, ChangeKind};
|
||||
|
||||
use crate::{
|
||||
config::{Config, FilesWatcher, LinkedProject},
|
||||
@ -524,15 +525,15 @@ impl GlobalState {
|
||||
}
|
||||
|
||||
fn recreate_crate_graph(&mut self, cause: String) {
|
||||
// Create crate graph from all the workspaces
|
||||
let (crate_graph, proc_macro_paths, crate_graph_file_dependencies) = {
|
||||
{
|
||||
// Create crate graph from all the workspaces
|
||||
let vfs = &mut self.vfs.write().0;
|
||||
let loader = &mut self.loader;
|
||||
// crate graph construction relies on these paths, record them so when one of them gets
|
||||
// deleted or created we trigger a reconstruction of the crate graph
|
||||
let mut crate_graph_file_dependencies = FxHashSet::default();
|
||||
|
||||
let mut load = |path: &AbsPath| {
|
||||
let load = |path: &AbsPath| {
|
||||
let _p = tracing::span!(tracing::Level::DEBUG, "switch_workspaces::load").entered();
|
||||
let vfs_path = vfs::VfsPath::from(path.to_path_buf());
|
||||
crate_graph_file_dependencies.insert(vfs_path.clone());
|
||||
@ -547,32 +548,26 @@ impl GlobalState {
|
||||
}
|
||||
};
|
||||
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let mut proc_macros = Vec::default();
|
||||
for ws in &**self.workspaces {
|
||||
let (other, mut crate_proc_macros) =
|
||||
ws.to_crate_graph(&mut load, self.config.extra_env());
|
||||
crate_graph.extend(other, &mut crate_proc_macros, |_| {});
|
||||
proc_macros.push(crate_proc_macros);
|
||||
let (crate_graph, proc_macro_paths, layouts, toolchains) =
|
||||
ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load);
|
||||
|
||||
let mut change = Change::new();
|
||||
if self.config.expand_proc_macros() {
|
||||
change.set_proc_macros(
|
||||
crate_graph
|
||||
.iter()
|
||||
.map(|id| (id, Err("Proc-macros have not been built yet".to_owned())))
|
||||
.collect(),
|
||||
);
|
||||
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
|
||||
}
|
||||
(crate_graph, proc_macros, crate_graph_file_dependencies)
|
||||
};
|
||||
|
||||
let mut change = Change::new();
|
||||
if self.config.expand_proc_macros() {
|
||||
change.set_proc_macros(
|
||||
crate_graph
|
||||
.iter()
|
||||
.map(|id| (id, Err("Proc-macros have not been built yet".to_owned())))
|
||||
.collect(),
|
||||
);
|
||||
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
|
||||
change.set_crate_graph(crate_graph);
|
||||
change.set_target_data_layouts(layouts);
|
||||
change.set_toolchains(toolchains);
|
||||
self.analysis_host.apply_change(change);
|
||||
self.crate_graph_file_dependencies = crate_graph_file_dependencies;
|
||||
}
|
||||
change.set_crate_graph(crate_graph);
|
||||
self.analysis_host.apply_change(change);
|
||||
self.crate_graph_file_dependencies = crate_graph_file_dependencies;
|
||||
self.process_changes();
|
||||
|
||||
self.reload_flycheck();
|
||||
}
|
||||
|
||||
@ -679,6 +674,69 @@ impl GlobalState {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Move this into load-cargo?
|
||||
pub fn ws_to_crate_graph(
|
||||
workspaces: &[ProjectWorkspace],
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
mut load: impl FnMut(&AbsPath) -> Option<vfs::FileId>,
|
||||
) -> (
|
||||
CrateGraph,
|
||||
Vec<FxHashMap<CrateId, Result<(Option<String>, AbsPathBuf), String>>>,
|
||||
Vec<Result<Arc<str>, Arc<str>>>,
|
||||
Vec<Option<Version>>,
|
||||
) {
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let mut proc_macro_paths = Vec::default();
|
||||
let mut layouts = Vec::default();
|
||||
let mut toolchains = Vec::default();
|
||||
let e = Err(Arc::from("missing layout"));
|
||||
for ws in workspaces {
|
||||
let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env);
|
||||
let num_layouts = layouts.len();
|
||||
let num_toolchains = toolchains.len();
|
||||
let (toolchain, layout) = match ws {
|
||||
ProjectWorkspace::Cargo { toolchain, target_layout, .. }
|
||||
| ProjectWorkspace::Json { toolchain, target_layout, .. } => {
|
||||
(toolchain.clone(), target_layout.clone())
|
||||
}
|
||||
ProjectWorkspace::DetachedFiles { .. } => {
|
||||
(None, Err("detached files have no layout".into()))
|
||||
}
|
||||
};
|
||||
|
||||
let mapping = crate_graph.extend(
|
||||
other,
|
||||
&mut crate_proc_macros,
|
||||
|(cg_id, cg_data), (_o_id, o_data)| {
|
||||
// if the newly created crate graph's layout is equal to the crate of the merged graph, then
|
||||
// we can merge the crates.
|
||||
let id = cg_id.into_raw().into_u32() as usize;
|
||||
layouts[id] == layout && toolchains[id] == toolchain && cg_data == o_data
|
||||
},
|
||||
);
|
||||
// Populate the side tables for the newly merged crates
|
||||
mapping.values().for_each(|val| {
|
||||
let idx = val.into_raw().into_u32() as usize;
|
||||
// we only need to consider crates that were not merged and remapped, as the
|
||||
// ones that were remapped already have the correct layout and toolchain
|
||||
if idx >= num_layouts {
|
||||
if layouts.len() <= idx {
|
||||
layouts.resize(idx + 1, e.clone());
|
||||
}
|
||||
layouts[idx] = layout.clone();
|
||||
}
|
||||
if idx >= num_toolchains {
|
||||
if toolchains.len() <= idx {
|
||||
toolchains.resize(idx + 1, None);
|
||||
}
|
||||
toolchains[idx] = toolchain.clone();
|
||||
}
|
||||
});
|
||||
proc_macro_paths.push(crate_proc_macros);
|
||||
}
|
||||
(crate_graph, proc_macro_paths, layouts, toolchains)
|
||||
}
|
||||
|
||||
pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {
|
||||
const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
|
||||
const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
|
||||
|
118
crates/rust-analyzer/tests/crate_graph.rs
Normal file
118
crates/rust-analyzer/tests/crate_graph.rs
Normal file
@ -0,0 +1,118 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use project_model::{CargoWorkspace, ProjectWorkspace, Sysroot, WorkspaceBuildScripts};
|
||||
use rust_analyzer::ws_to_crate_graph;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::de::DeserializeOwned;
|
||||
use vfs::{AbsPathBuf, FileId};
|
||||
|
||||
fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
|
||||
let meta = get_test_json_file(file);
|
||||
let cargo_workspace = CargoWorkspace::new(meta);
|
||||
ProjectWorkspace::Cargo {
|
||||
cargo: cargo_workspace,
|
||||
build_scripts: WorkspaceBuildScripts::default(),
|
||||
sysroot: Ok(get_fake_sysroot()),
|
||||
rustc: Err(None),
|
||||
rustc_cfg: Vec::new(),
|
||||
cfg_overrides: Default::default(),
|
||||
toolchain: None,
|
||||
target_layout: Err("target_data_layout not loaded".into()),
|
||||
cargo_config_extra_env: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_test_json_file<T: DeserializeOwned>(file: &str) -> T {
|
||||
let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let file = base.join("tests/test_data").join(file);
|
||||
let data = std::fs::read_to_string(file).unwrap();
|
||||
let mut json = data.parse::<serde_json::Value>().unwrap();
|
||||
fixup_paths(&mut json);
|
||||
return serde_json::from_value(json).unwrap();
|
||||
|
||||
fn fixup_paths(val: &mut serde_json::Value) {
|
||||
match val {
|
||||
serde_json::Value::String(s) => replace_root(s, true),
|
||||
serde_json::Value::Array(vals) => vals.iter_mut().for_each(fixup_paths),
|
||||
serde_json::Value::Object(kvals) => kvals.values_mut().for_each(fixup_paths),
|
||||
serde_json::Value::Null | serde_json::Value::Bool(_) | serde_json::Value::Number(_) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_root(s: &mut String, direction: bool) {
|
||||
if direction {
|
||||
let root = if cfg!(windows) { r#"C:\\ROOT\"# } else { "/ROOT/" };
|
||||
*s = s.replace("$ROOT$", root)
|
||||
} else {
|
||||
let root = if cfg!(windows) { r#"C:\\\\ROOT\\"# } else { "/ROOT/" };
|
||||
*s = s.replace(root, "$ROOT$")
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fake_sysroot_path() -> PathBuf {
|
||||
let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
base.join("../project-model/test_data/fake-sysroot")
|
||||
}
|
||||
|
||||
fn get_fake_sysroot() -> Sysroot {
|
||||
let sysroot_path = get_fake_sysroot_path();
|
||||
// there's no `libexec/` directory with a `proc-macro-srv` binary in that
|
||||
// fake sysroot, so we give them both the same path:
|
||||
let sysroot_dir = AbsPathBuf::assert(sysroot_path);
|
||||
let sysroot_src_dir = sysroot_dir.clone();
|
||||
Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deduplicate_origin_dev() {
|
||||
let path_map = &mut FxHashMap::default();
|
||||
let ws = load_cargo_with_fake_sysroot("deduplication_crate_graph_A.json");
|
||||
let ws2 = load_cargo_with_fake_sysroot("deduplication_crate_graph_B.json");
|
||||
|
||||
let (crate_graph, ..) = ws_to_crate_graph(&[ws, ws2], &Default::default(), |path| {
|
||||
let len = path_map.len();
|
||||
Some(*path_map.entry(path.to_path_buf()).or_insert(FileId::from_raw(len as u32)))
|
||||
});
|
||||
|
||||
let mut crates_named_p2 = vec![];
|
||||
for id in crate_graph.iter() {
|
||||
let krate = &crate_graph[id];
|
||||
if let Some(name) = krate.display_name.as_ref() {
|
||||
if name.to_string() == "p2" {
|
||||
crates_named_p2.push(krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(crates_named_p2.len() == 1);
|
||||
let p2 = crates_named_p2[0];
|
||||
assert!(p2.origin.is_local());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deduplicate_origin_dev_rev() {
|
||||
let path_map = &mut FxHashMap::default();
|
||||
let ws = load_cargo_with_fake_sysroot("deduplication_crate_graph_B.json");
|
||||
let ws2 = load_cargo_with_fake_sysroot("deduplication_crate_graph_A.json");
|
||||
|
||||
let (crate_graph, ..) = ws_to_crate_graph(&[ws, ws2], &Default::default(), |path| {
|
||||
let len = path_map.len();
|
||||
Some(*path_map.entry(path.to_path_buf()).or_insert(FileId::from_raw(len as u32)))
|
||||
});
|
||||
|
||||
let mut crates_named_p2 = vec![];
|
||||
for id in crate_graph.iter() {
|
||||
let krate = &crate_graph[id];
|
||||
if let Some(name) = krate.display_name.as_ref() {
|
||||
if name.to_string() == "p2" {
|
||||
crates_named_p2.push(krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(crates_named_p2.len() == 1);
|
||||
let p2 = crates_named_p2[0];
|
||||
assert!(p2.origin.is_local());
|
||||
}
|
@ -101,8 +101,13 @@ impl Project<'_> {
|
||||
};
|
||||
});
|
||||
|
||||
let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } =
|
||||
FixtureWithProjectMeta::parse(self.fixture);
|
||||
let FixtureWithProjectMeta {
|
||||
fixture,
|
||||
mini_core,
|
||||
proc_macro_names,
|
||||
toolchain,
|
||||
target_data_layout: _,
|
||||
} = FixtureWithProjectMeta::parse(self.fixture);
|
||||
assert!(proc_macro_names.is_empty());
|
||||
assert!(mini_core.is_none());
|
||||
assert!(toolchain.is_none());
|
||||
|
@ -1,10 +1,9 @@
|
||||
//! A set of high-level utility fixture methods to use in tests.
|
||||
use std::{mem, ops::Not, str::FromStr, sync};
|
||||
use std::{iter, mem, ops::Not, str::FromStr, sync};
|
||||
|
||||
use base_db::{
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
|
||||
Edition, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version,
|
||||
VfsPath,
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
|
||||
FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version, VfsPath,
|
||||
};
|
||||
use cfg::CfgOptions;
|
||||
use hir_expand::{
|
||||
@ -118,8 +117,14 @@ impl ChangeFixture {
|
||||
ra_fixture: &str,
|
||||
mut proc_macro_defs: Vec<(String, ProcMacro)>,
|
||||
) -> ChangeFixture {
|
||||
let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } =
|
||||
FixtureWithProjectMeta::parse(ra_fixture);
|
||||
let FixtureWithProjectMeta {
|
||||
fixture,
|
||||
mini_core,
|
||||
proc_macro_names,
|
||||
toolchain,
|
||||
target_data_layout,
|
||||
} = FixtureWithProjectMeta::parse(ra_fixture);
|
||||
let target_data_layout = Ok(target_data_layout.into());
|
||||
let toolchain = Some({
|
||||
let channel = toolchain.as_deref().unwrap_or("stable");
|
||||
Version::parse(&format!("1.76.0-{channel}")).unwrap()
|
||||
@ -131,7 +136,6 @@ impl ChangeFixture {
|
||||
let mut crates = FxHashMap::default();
|
||||
let mut crate_deps = Vec::new();
|
||||
let mut default_crate_root: Option<FileId> = None;
|
||||
let mut default_target_data_layout: Option<String> = None;
|
||||
let mut default_cfg = CfgOptions::default();
|
||||
let mut default_env = Env::new_for_test_fixture();
|
||||
|
||||
@ -187,11 +191,6 @@ impl ChangeFixture {
|
||||
meta.env,
|
||||
false,
|
||||
origin,
|
||||
meta.target_data_layout
|
||||
.as_deref()
|
||||
.map(From::from)
|
||||
.ok_or_else(|| "target_data_layout unset".into()),
|
||||
toolchain.clone(),
|
||||
);
|
||||
let prev = crates.insert(crate_name.clone(), crate_id);
|
||||
assert!(prev.is_none(), "multiple crates with same name: {}", crate_name);
|
||||
@ -205,7 +204,6 @@ impl ChangeFixture {
|
||||
default_crate_root = Some(file_id);
|
||||
default_cfg.extend(meta.cfg.into_iter());
|
||||
default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
|
||||
default_target_data_layout = meta.target_data_layout;
|
||||
}
|
||||
|
||||
source_change.change_file(file_id, Some(text.into()));
|
||||
@ -228,10 +226,6 @@ impl ChangeFixture {
|
||||
default_env,
|
||||
false,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
default_target_data_layout
|
||||
.map(|it| it.into())
|
||||
.ok_or_else(|| "target_data_layout unset".into()),
|
||||
toolchain.clone(),
|
||||
);
|
||||
} else {
|
||||
for (from, to, prelude) in crate_deps {
|
||||
@ -240,20 +234,11 @@ impl ChangeFixture {
|
||||
crate_graph
|
||||
.add_dep(
|
||||
from_id,
|
||||
Dependency::with_prelude(
|
||||
CrateName::new(&to).unwrap(),
|
||||
to_id,
|
||||
prelude,
|
||||
DependencyKind::Normal,
|
||||
),
|
||||
Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
let target_layout = crate_graph.iter().next().map_or_else(
|
||||
|| Err("target_data_layout unset".into()),
|
||||
|it| crate_graph[it].target_layout.clone(),
|
||||
);
|
||||
|
||||
if let Some(mini_core) = mini_core {
|
||||
let core_file = file_id;
|
||||
@ -277,20 +262,11 @@ impl ChangeFixture {
|
||||
Env::new_for_test_fixture(),
|
||||
false,
|
||||
CrateOrigin::Lang(LangCrateOrigin::Core),
|
||||
target_layout.clone(),
|
||||
toolchain.clone(),
|
||||
);
|
||||
|
||||
for krate in all_crates {
|
||||
crate_graph
|
||||
.add_dep(
|
||||
krate,
|
||||
Dependency::new(
|
||||
CrateName::new("core").unwrap(),
|
||||
core_crate,
|
||||
DependencyKind::Normal,
|
||||
),
|
||||
)
|
||||
.add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@ -322,8 +298,6 @@ impl ChangeFixture {
|
||||
Env::new_for_test_fixture(),
|
||||
true,
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
target_layout,
|
||||
toolchain,
|
||||
);
|
||||
proc_macros.insert(proc_macros_crate, Ok(proc_macro));
|
||||
|
||||
@ -331,11 +305,7 @@ impl ChangeFixture {
|
||||
crate_graph
|
||||
.add_dep(
|
||||
krate,
|
||||
Dependency::new(
|
||||
CrateName::new("proc_macros").unwrap(),
|
||||
proc_macros_crate,
|
||||
DependencyKind::Normal,
|
||||
),
|
||||
Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
@ -346,17 +316,20 @@ impl ChangeFixture {
|
||||
SourceRootKind::Library => SourceRoot::new_library(mem::take(&mut file_set)),
|
||||
};
|
||||
roots.push(root);
|
||||
source_change.set_roots(roots);
|
||||
source_change.set_crate_graph(crate_graph);
|
||||
|
||||
ChangeFixture {
|
||||
file_position,
|
||||
files,
|
||||
change: Change {
|
||||
source_change,
|
||||
proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
|
||||
},
|
||||
}
|
||||
let mut change = Change {
|
||||
source_change,
|
||||
proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
|
||||
toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
|
||||
target_data_layouts: Some(
|
||||
iter::repeat(target_data_layout).take(crate_graph.len()).collect(),
|
||||
),
|
||||
};
|
||||
|
||||
change.source_change.set_roots(roots);
|
||||
change.source_change.set_crate_graph(crate_graph);
|
||||
|
||||
ChangeFixture { file_position, files, change }
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,7 +448,6 @@ struct FileMeta {
|
||||
edition: Edition,
|
||||
env: Env,
|
||||
introduce_new_source_root: Option<SourceRootKind>,
|
||||
target_data_layout: Option<String>,
|
||||
}
|
||||
|
||||
impl FileMeta {
|
||||
@ -507,7 +479,6 @@ impl FileMeta {
|
||||
edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()),
|
||||
env: f.env.into_iter().collect(),
|
||||
introduce_new_source_root,
|
||||
target_data_layout: f.target_data_layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,11 +126,6 @@ pub struct Fixture {
|
||||
///
|
||||
/// Syntax: `library`
|
||||
pub library: bool,
|
||||
/// Specifies LLVM data layout to be used.
|
||||
///
|
||||
/// You probably don't want to manually specify this. See LLVM manual for the
|
||||
/// syntax, if you must: https://llvm.org/docs/LangRef.html#data-layout
|
||||
pub target_data_layout: Option<String>,
|
||||
/// Actual file contents. All meta comments are stripped.
|
||||
pub text: String,
|
||||
}
|
||||
@ -145,6 +140,11 @@ pub struct FixtureWithProjectMeta {
|
||||
pub mini_core: Option<MiniCore>,
|
||||
pub proc_macro_names: Vec<String>,
|
||||
pub toolchain: Option<String>,
|
||||
/// Specifies LLVM data layout to be used.
|
||||
///
|
||||
/// You probably don't want to manually specify this. See LLVM manual for the
|
||||
/// syntax, if you must: https://llvm.org/docs/LangRef.html#data-layout
|
||||
pub target_data_layout: String,
|
||||
}
|
||||
|
||||
impl FixtureWithProjectMeta {
|
||||
@ -172,6 +172,8 @@ impl FixtureWithProjectMeta {
|
||||
let fixture = trim_indent(ra_fixture);
|
||||
let mut fixture = fixture.as_str();
|
||||
let mut toolchain = None;
|
||||
let mut target_data_layout =
|
||||
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned();
|
||||
let mut mini_core = None;
|
||||
let mut res: Vec<Fixture> = Vec::new();
|
||||
let mut proc_macro_names = vec![];
|
||||
@ -182,6 +184,12 @@ impl FixtureWithProjectMeta {
|
||||
fixture = remain;
|
||||
}
|
||||
|
||||
if let Some(meta) = fixture.strip_prefix("//- target_data_layout:") {
|
||||
let (meta, remain) = meta.split_once('\n').unwrap();
|
||||
target_data_layout = meta.trim().to_owned();
|
||||
fixture = remain;
|
||||
}
|
||||
|
||||
if let Some(meta) = fixture.strip_prefix("//- proc_macros:") {
|
||||
let (meta, remain) = meta.split_once('\n').unwrap();
|
||||
proc_macro_names = meta.split(',').map(|it| it.trim().to_owned()).collect();
|
||||
@ -225,7 +233,7 @@ impl FixtureWithProjectMeta {
|
||||
}
|
||||
}
|
||||
|
||||
Self { fixture: res, mini_core, proc_macro_names, toolchain }
|
||||
Self { fixture: res, mini_core, proc_macro_names, toolchain, target_data_layout }
|
||||
}
|
||||
|
||||
//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
|
||||
@ -245,9 +253,6 @@ impl FixtureWithProjectMeta {
|
||||
let mut env = FxHashMap::default();
|
||||
let mut introduce_new_source_root = None;
|
||||
let mut library = false;
|
||||
let mut target_data_layout = Some(
|
||||
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned(),
|
||||
);
|
||||
for component in components {
|
||||
if component == "library" {
|
||||
library = true;
|
||||
@ -284,7 +289,6 @@ impl FixtureWithProjectMeta {
|
||||
}
|
||||
}
|
||||
"new_source_root" => introduce_new_source_root = Some(value.to_owned()),
|
||||
"target_data_layout" => target_data_layout = Some(value.to_owned()),
|
||||
_ => panic!("bad component: {component:?}"),
|
||||
}
|
||||
}
|
||||
@ -307,7 +311,6 @@ impl FixtureWithProjectMeta {
|
||||
env,
|
||||
introduce_new_source_root,
|
||||
library,
|
||||
target_data_layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,16 +479,21 @@ fn parse_fixture_checks_further_indented_metadata() {
|
||||
|
||||
#[test]
|
||||
fn parse_fixture_gets_full_meta() {
|
||||
let FixtureWithProjectMeta { fixture: parsed, mini_core, proc_macro_names, toolchain } =
|
||||
FixtureWithProjectMeta::parse(
|
||||
r#"
|
||||
let FixtureWithProjectMeta {
|
||||
fixture: parsed,
|
||||
mini_core,
|
||||
proc_macro_names,
|
||||
toolchain,
|
||||
target_data_layout: _,
|
||||
} = FixtureWithProjectMeta::parse(
|
||||
r#"
|
||||
//- toolchain: nightly
|
||||
//- 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!(toolchain, Some("nightly".to_owned()));
|
||||
assert_eq!(proc_macro_names, vec!["identity".to_owned()]);
|
||||
assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_owned()]);
|
||||
|
@ -803,11 +803,6 @@ Exclude imports from find-all-references.
|
||||
--
|
||||
Exclude tests from find-all-references.
|
||||
--
|
||||
[[rust-analyzer.rename.allowExternalItems]]rust-analyzer.rename.allowExternalItems (default: `false`)::
|
||||
+
|
||||
--
|
||||
Allow renaming of items not belonging to the loaded workspaces.
|
||||
--
|
||||
[[rust-analyzer.runnables.command]]rust-analyzer.runnables.command (default: `null`)::
|
||||
+
|
||||
--
|
||||
|
@ -1527,11 +1527,6 @@
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.rename.allowExternalItems": {
|
||||
"markdownDescription": "Allow renaming of items not belonging to the loaded workspaces.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.runnables.command": {
|
||||
"markdownDescription": "Command to be executed instead of 'cargo' for runnables.",
|
||||
"default": null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user