Lift out workspace related data into a separate query to preserve crategraph deduplication
This commit is contained in:
parent
69ab8c2f26
commit
aa883b421e
@ -3,11 +3,15 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
use salsa::Durability;
|
||||
use triomphe::Arc;
|
||||
use vfs::FileId;
|
||||
|
||||
use crate::{CrateGraph, SourceDatabaseFileInputExt, SourceRoot, SourceRootDatabase, SourceRootId};
|
||||
use crate::{
|
||||
CrateGraph, CrateId, CrateWorkspaceData, SourceDatabaseFileInputExt, SourceRoot,
|
||||
SourceRootDatabase, SourceRootId,
|
||||
};
|
||||
|
||||
/// Encapsulate a bunch of raw `.set` calls on the database.
|
||||
#[derive(Default)]
|
||||
@ -15,6 +19,7 @@ pub struct FileChange {
|
||||
pub roots: Option<Vec<SourceRoot>>,
|
||||
pub files_changed: Vec<(FileId, Option<String>)>,
|
||||
pub crate_graph: Option<CrateGraph>,
|
||||
pub ws_data: Option<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileChange {
|
||||
@ -50,6 +55,10 @@ pub fn set_crate_graph(&mut self, graph: CrateGraph) {
|
||||
self.crate_graph = Some(graph);
|
||||
}
|
||||
|
||||
pub fn set_ws_data(&mut self, data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>) {
|
||||
self.ws_data = Some(data);
|
||||
}
|
||||
|
||||
pub fn apply(self, db: &mut dyn SourceRootDatabase) {
|
||||
let _p = tracing::info_span!("FileChange::apply").entered();
|
||||
if let Some(roots) = self.roots {
|
||||
@ -74,6 +83,9 @@ pub fn apply(self, db: &mut dyn SourceRootDatabase) {
|
||||
if let Some(crate_graph) = self.crate_graph {
|
||||
db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH);
|
||||
}
|
||||
if let Some(data) = self.ws_data {
|
||||
db.set_crate_workspace_data_with_durability(Arc::new(data), Durability::HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,12 @@
|
||||
|
||||
use std::panic;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
use salsa::Durability;
|
||||
use span::EditionedFileId;
|
||||
use syntax::{ast, Parse, SourceFile, SyntaxError};
|
||||
use triomphe::Arc;
|
||||
use vfs::FileId;
|
||||
use vfs::{AbsPathBuf, FileId};
|
||||
|
||||
pub use crate::{
|
||||
change::FileChange,
|
||||
@ -74,19 +75,30 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
||||
#[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>;
|
||||
fn crate_workspace_data(&self) -> Arc<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>;
|
||||
|
||||
#[salsa::transparent]
|
||||
fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
|
||||
}
|
||||
|
||||
/// Crate related data shared by the whole workspace.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct CrateWorkspaceData {
|
||||
/// The working directory to run proc-macros in. This is usually the workspace root of cargo workspaces.
|
||||
pub proc_macro_cwd: Option<AbsPathBuf>,
|
||||
// FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
|
||||
pub data_layout: TargetLayoutLoadResult,
|
||||
/// Toolchain version used to compile the crate.
|
||||
pub toolchain: Option<Version>,
|
||||
}
|
||||
|
||||
fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option<ReleaseChannel> {
|
||||
db.toolchain(krate).as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
|
||||
db.crate_workspace_data()
|
||||
.get(&krate)?
|
||||
.toolchain
|
||||
.as_ref()
|
||||
.and_then(|v| ReleaseChannel::from_str(&v.pre))
|
||||
}
|
||||
|
||||
fn parse(db: &dyn SourceDatabase, file_id: EditionedFileId) -> Parse<ast::SourceFile> {
|
||||
|
@ -117,7 +117,7 @@ pub(crate) fn fields_attrs_query(
|
||||
}
|
||||
|
||||
impl Attrs {
|
||||
pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> {
|
||||
pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> {
|
||||
AttrQuery { attrs: self, key }
|
||||
}
|
||||
|
||||
@ -594,7 +594,7 @@ pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
|
||||
/// #[doc(html_root_url = "url")]
|
||||
/// ^^^^^^^^^^^^^ key
|
||||
/// ```
|
||||
pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> {
|
||||
pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> {
|
||||
self.tt_values().find_map(|tt| {
|
||||
let name = tt.token_trees.iter()
|
||||
.skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
|
||||
|
@ -204,7 +204,7 @@ pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body>
|
||||
pub fn blocks<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn DefDatabase,
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ {
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
|
||||
self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
|
||||
}
|
||||
|
||||
|
@ -1,10 +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, CrateId, FileChange, SourceRoot, SourceRootDatabase,
|
||||
TargetLayoutLoadResult, Version,
|
||||
salsa::Durability, CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot,
|
||||
SourceRootDatabase,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
use rustc_hash::FxHashMap;
|
||||
use span::FileId;
|
||||
use triomphe::Arc;
|
||||
|
||||
@ -14,8 +14,6 @@
|
||||
pub struct ChangeWithProcMacros {
|
||||
pub source_change: FileChange,
|
||||
pub proc_macros: Option<ProcMacros>,
|
||||
pub toolchains: Option<Vec<Option<Version>>>,
|
||||
pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
|
||||
}
|
||||
|
||||
impl ChangeWithProcMacros {
|
||||
@ -28,46 +26,25 @@ pub fn apply(self, db: &mut (impl ExpandDatabase + SourceRootDatabase)) {
|
||||
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<String>) {
|
||||
self.source_change.change_file(file_id, new_text)
|
||||
}
|
||||
|
||||
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
|
||||
self.source_change.set_crate_graph(graph)
|
||||
pub fn set_crate_graph(
|
||||
&mut self,
|
||||
graph: CrateGraph,
|
||||
ws_data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>,
|
||||
) {
|
||||
self.source_change.set_crate_graph(graph);
|
||||
self.source_change.set_ws_data(ws_data);
|
||||
}
|
||||
|
||||
pub fn set_proc_macros(&mut self, proc_macros: ProcMacros) {
|
||||
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)
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ pub fn target_data_layout_query(
|
||||
db: &dyn HirDatabase,
|
||||
krate: CrateId,
|
||||
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
|
||||
match db.data_layout(krate) {
|
||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(&it) {
|
||||
match &db.crate_workspace_data()[&krate].data_layout {
|
||||
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
|
||||
Ok(it) => Ok(Arc::new(it)),
|
||||
Err(e) => {
|
||||
Err(match e {
|
||||
@ -42,6 +42,6 @@ pub fn target_data_layout_query(
|
||||
}.into())
|
||||
}
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
Err(e) => Err(e.clone()),
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@
|
||||
mod view_memory_layout;
|
||||
mod view_mir;
|
||||
|
||||
use std::panic::UnwindSafe;
|
||||
use std::{iter, panic::UnwindSafe};
|
||||
|
||||
use cfg::CfgOptions;
|
||||
use fetch_crates::CrateInfo;
|
||||
@ -65,7 +65,8 @@
|
||||
use ide_db::{
|
||||
base_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, SourceRootDatabase, VfsPath,
|
||||
CrateOrigin, CrateWorkspaceData, Env, FileLoader, FileSet, SourceDatabase,
|
||||
SourceRootDatabase, VfsPath,
|
||||
},
|
||||
prime_caches, symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase,
|
||||
};
|
||||
@ -256,9 +257,16 @@ pub fn from_single_file(text: String) -> (Analysis, FileId) {
|
||||
CrateOrigin::Local { repo: None, name: None },
|
||||
);
|
||||
change.change_file(file_id, Some(text));
|
||||
change.set_crate_graph(crate_graph);
|
||||
change.set_target_data_layouts(vec![Err("fixture has no layout".into())]);
|
||||
change.set_toolchains(vec![None]);
|
||||
let ws_data = crate_graph
|
||||
.iter()
|
||||
.zip(iter::repeat(Arc::new(CrateWorkspaceData {
|
||||
proc_macro_cwd: None,
|
||||
data_layout: Err("fixture has no layout".into()),
|
||||
toolchain: None,
|
||||
})))
|
||||
.collect();
|
||||
change.set_crate_graph(crate_graph, ws_data);
|
||||
|
||||
host.apply_change(change);
|
||||
(host.analysis(), file_id)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
ProcMacros,
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::{CrateGraph, Env, SourceRoot, SourceRootId},
|
||||
base_db::{CrateGraph, CrateWorkspaceData, Env, SourceRoot, SourceRootId},
|
||||
prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
@ -447,12 +447,16 @@ 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);
|
||||
let ws_data = crate_graph
|
||||
.iter()
|
||||
.zip(iter::repeat(From::from(CrateWorkspaceData {
|
||||
proc_macro_cwd: None,
|
||||
data_layout: target_layout.clone(),
|
||||
toolchain: toolchain.clone(),
|
||||
})))
|
||||
.collect();
|
||||
analysis_change.set_crate_graph(crate_graph, ws_data);
|
||||
analysis_change.set_proc_macros(proc_macros);
|
||||
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());
|
||||
|
||||
db.apply_change(analysis_change);
|
||||
db
|
||||
|
@ -16,8 +16,9 @@
|
||||
use std::{iter, mem};
|
||||
|
||||
use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder};
|
||||
use ide::CrateId;
|
||||
use ide_db::{
|
||||
base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
|
||||
base_db::{salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths},
|
||||
FxHashMap,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
@ -692,7 +693,7 @@ fn recreate_crate_graph(&mut self, cause: String) {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let (crate_graph, proc_macro_paths, layouts, toolchains) = {
|
||||
let (crate_graph, proc_macro_paths, ws_data) = {
|
||||
// Create crate graph from all the workspaces
|
||||
let vfs = &mut self.vfs.write().0;
|
||||
|
||||
@ -721,9 +722,7 @@ fn recreate_crate_graph(&mut self, cause: String) {
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
change.set_crate_graph(crate_graph);
|
||||
change.set_target_data_layouts(layouts);
|
||||
change.set_toolchains(toolchains);
|
||||
change.set_crate_graph(crate_graph, ws_data);
|
||||
self.analysis_host.apply_change(change);
|
||||
self.report_progress(
|
||||
"Building CrateGraph",
|
||||
@ -863,42 +862,27 @@ pub fn ws_to_crate_graph(
|
||||
workspaces: &[ProjectWorkspace],
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
mut load: impl FnMut(&AbsPath) -> Option<vfs::FileId>,
|
||||
) -> (CrateGraph, Vec<ProcMacroPaths>, Vec<Result<Arc<str>, Arc<str>>>, Vec<Option<Version>>) {
|
||||
) -> (CrateGraph, Vec<ProcMacroPaths>, FxHashMap<CrateId, Arc<CrateWorkspaceData>>) {
|
||||
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"));
|
||||
let mut ws_data = FxHashMap::default();
|
||||
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 ProjectWorkspace { toolchain, target_layout, .. } = ws;
|
||||
|
||||
let mapping = crate_graph.extend(other, &mut crate_proc_macros);
|
||||
// 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].clone_from(target_layout);
|
||||
}
|
||||
if idx >= num_toolchains {
|
||||
if toolchains.len() <= idx {
|
||||
toolchains.resize(idx + 1, None);
|
||||
}
|
||||
toolchains[idx].clone_from(toolchain);
|
||||
}
|
||||
});
|
||||
ws_data.extend(mapping.values().copied().zip(iter::repeat(Arc::new(CrateWorkspaceData {
|
||||
toolchain: toolchain.clone(),
|
||||
data_layout: target_layout.clone(),
|
||||
proc_macro_cwd: Some(ws.workspace_root().to_owned()),
|
||||
}))));
|
||||
proc_macro_paths.push(crate_proc_macros);
|
||||
}
|
||||
|
||||
crate_graph.shrink_to_fit();
|
||||
proc_macro_paths.shrink_to_fit();
|
||||
(crate_graph, proc_macro_paths, layouts, toolchains)
|
||||
(crate_graph, proc_macro_paths, ws_data)
|
||||
}
|
||||
|
||||
pub(crate) fn should_refresh_for_change(
|
||||
|
@ -2,8 +2,8 @@
|
||||
use std::{iter, mem, str::FromStr, sync};
|
||||
|
||||
use base_db::{
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileChange,
|
||||
FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath,
|
||||
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency,
|
||||
Env, FileChange, FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath,
|
||||
};
|
||||
use cfg::CfgOptions;
|
||||
use hir_expand::{
|
||||
@ -354,16 +354,20 @@ pub fn parse_with_proc_macros(
|
||||
};
|
||||
roots.push(root);
|
||||
|
||||
let mut change = ChangeWithProcMacros {
|
||||
source_change,
|
||||
proc_macros: Some(proc_macros.build()),
|
||||
toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
|
||||
target_data_layouts: Some(
|
||||
iter::repeat(target_data_layout).take(crate_graph.len()).collect(),
|
||||
),
|
||||
};
|
||||
let mut change =
|
||||
ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros.build()) };
|
||||
|
||||
change.source_change.set_roots(roots);
|
||||
change.source_change.set_ws_data(
|
||||
crate_graph
|
||||
.iter()
|
||||
.zip(iter::repeat(From::from(CrateWorkspaceData {
|
||||
proc_macro_cwd: None,
|
||||
data_layout: target_data_layout,
|
||||
toolchain,
|
||||
})))
|
||||
.collect(),
|
||||
);
|
||||
change.source_change.set_crate_graph(crate_graph);
|
||||
|
||||
ChangeFixture { file_position, files, change }
|
||||
|
Loading…
Reference in New Issue
Block a user