mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Simpify workspace handling
This commit is contained in:
parent
4b2bf9cf66
commit
b7d5172f69
7 changed files with 62 additions and 82 deletions
|
@ -58,22 +58,16 @@ pub enum ProjectWorkspace {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PackageRoot {
|
pub struct PackageRoot {
|
||||||
/// Path to the root folder
|
/// Path to the root folder
|
||||||
path: PathBuf,
|
pub path: PathBuf,
|
||||||
/// Is a member of the current workspace
|
/// Is a member of the current workspace
|
||||||
is_member: bool,
|
pub is_member: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PackageRoot {
|
impl PackageRoot {
|
||||||
pub fn new(path: PathBuf, is_member: bool) -> PackageRoot {
|
pub fn new_member(path: PathBuf) -> PackageRoot {
|
||||||
PackageRoot { path, is_member }
|
Self { path, is_member: true }
|
||||||
}
|
}
|
||||||
|
pub fn new_non_member(path: PathBuf) -> PackageRoot {
|
||||||
pub fn path(&self) -> &PathBuf {
|
Self { path, is_member: false }
|
||||||
&self.path
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_member(&self) -> bool {
|
|
||||||
self.is_member
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,24 +124,18 @@ impl ProjectWorkspace {
|
||||||
pub fn to_roots(&self) -> Vec<PackageRoot> {
|
pub fn to_roots(&self) -> Vec<PackageRoot> {
|
||||||
match self {
|
match self {
|
||||||
ProjectWorkspace::Json { project } => {
|
ProjectWorkspace::Json { project } => {
|
||||||
let mut roots = Vec::with_capacity(project.roots.len());
|
project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect()
|
||||||
for root in &project.roots {
|
|
||||||
roots.push(PackageRoot::new(root.path.clone(), true));
|
|
||||||
}
|
|
||||||
roots
|
|
||||||
}
|
|
||||||
ProjectWorkspace::Cargo { cargo, sysroot } => {
|
|
||||||
let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len());
|
|
||||||
for pkg in cargo.packages() {
|
|
||||||
let root = cargo[pkg].root().to_path_buf();
|
|
||||||
let member = cargo[pkg].is_member;
|
|
||||||
roots.push(PackageRoot::new(root, member));
|
|
||||||
}
|
|
||||||
for krate in sysroot.crates() {
|
|
||||||
roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false))
|
|
||||||
}
|
|
||||||
roots
|
|
||||||
}
|
}
|
||||||
|
ProjectWorkspace::Cargo { cargo, sysroot } => cargo
|
||||||
|
.packages()
|
||||||
|
.map(|pkg| PackageRoot {
|
||||||
|
path: cargo[pkg].root().to_path_buf(),
|
||||||
|
is_member: cargo[pkg].is_member,
|
||||||
|
})
|
||||||
|
.chain(sysroot.crates().map(|krate| {
|
||||||
|
PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf())
|
||||||
|
}))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,10 @@ pub fn analysis_bench(
|
||||||
roots
|
roots
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(source_root_id, project_root)| {
|
.find_map(|(source_root_id, project_root)| {
|
||||||
if project_root.is_member() {
|
if project_root.is_member {
|
||||||
for file_id in db.source_root(*source_root_id).walk() {
|
for file_id in db.source_root(*source_root_id).walk() {
|
||||||
let rel_path = db.file_relative_path(file_id);
|
let rel_path = db.file_relative_path(file_id);
|
||||||
let abs_path = rel_path.to_path(project_root.path());
|
let abs_path = rel_path.to_path(&project_root.path);
|
||||||
if abs_path == path {
|
if abs_path == path {
|
||||||
return Some(file_id);
|
return Some(file_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub fn analysis_stats(
|
||||||
roots
|
roots
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(source_root_id, project_root)| {
|
.filter_map(|(source_root_id, project_root)| {
|
||||||
if with_deps || project_root.is_member() {
|
if with_deps || project_root.is_member {
|
||||||
Some(source_root_id)
|
Some(source_root_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -36,8 +36,7 @@ pub(crate) fn load_cargo(
|
||||||
extern_dirs.extend(ws.out_dirs());
|
extern_dirs.extend(ws.out_dirs());
|
||||||
|
|
||||||
let mut project_roots = ws.to_roots();
|
let mut project_roots = ws.to_roots();
|
||||||
project_roots
|
project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member));
|
||||||
.extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false)));
|
|
||||||
|
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
let sender = Box::new(move |t| sender.send(t).unwrap());
|
let sender = Box::new(move |t| sender.send(t).unwrap());
|
||||||
|
@ -46,9 +45,9 @@ pub(crate) fn load_cargo(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pkg_root| {
|
.map(|pkg_root| {
|
||||||
RootEntry::new(
|
RootEntry::new(
|
||||||
pkg_root.path().clone(),
|
pkg_root.path.clone(),
|
||||||
RustPackageFilterBuilder::default()
|
RustPackageFilterBuilder::default()
|
||||||
.set_member(pkg_root.is_member())
|
.set_member(pkg_root.is_member)
|
||||||
.into_vfs_filter(),
|
.into_vfs_filter(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -58,14 +57,11 @@ pub(crate) fn load_cargo(
|
||||||
);
|
);
|
||||||
|
|
||||||
let source_roots = roots
|
let source_roots = roots
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|&vfs_root| {
|
.map(|vfs_root| {
|
||||||
let source_root_id = vfs_root_to_id(vfs_root);
|
let source_root_id = vfs_root_to_id(vfs_root);
|
||||||
let project_root = project_roots
|
let project_root =
|
||||||
.iter()
|
project_roots.iter().find(|it| it.path == vfs.root2path(vfs_root)).unwrap().clone();
|
||||||
.find(|it| it.path() == &vfs.root2path(vfs_root))
|
|
||||||
.unwrap()
|
|
||||||
.clone();
|
|
||||||
(source_root_id, project_root)
|
(source_root_id, project_root)
|
||||||
})
|
})
|
||||||
.collect::<FxHashMap<_, _>>();
|
.collect::<FxHashMap<_, _>>();
|
||||||
|
@ -97,7 +93,7 @@ pub(crate) fn load(
|
||||||
match change {
|
match change {
|
||||||
VfsChange::AddRoot { root, files } => {
|
VfsChange::AddRoot { root, files } => {
|
||||||
let source_root_id = vfs_root_to_id(root);
|
let source_root_id = vfs_root_to_id(root);
|
||||||
let is_local = source_roots[&source_root_id].is_member();
|
let is_local = source_roots[&source_root_id].is_member;
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"loaded source root {:?} with path {:?}",
|
"loaded source root {:?} with path {:?}",
|
||||||
source_root_id,
|
source_root_id,
|
||||||
|
@ -106,7 +102,7 @@ pub(crate) fn load(
|
||||||
analysis_change.add_root(source_root_id, is_local);
|
analysis_change.add_root(source_root_id, is_local);
|
||||||
analysis_change.set_debug_root_path(
|
analysis_change.set_debug_root_path(
|
||||||
source_root_id,
|
source_root_id,
|
||||||
source_roots[&source_root_id].path().display().to_string(),
|
source_roots[&source_root_id].path.display().to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let vfs_root_path = vfs.root2path(root);
|
let vfs_root_path = vfs.root2path(root);
|
||||||
|
|
|
@ -132,8 +132,8 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||||
watchers: workspaces
|
watchers: workspaces
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|ws| ws.to_roots())
|
.flat_map(|ws| ws.to_roots())
|
||||||
.filter(|root| root.is_member())
|
.filter(|root| root.is_member)
|
||||||
.map(|root| format!("{}/**/*.rs", root.path().display()))
|
.map(|root| format!("{}/**/*.rs", root.path.display()))
|
||||||
.map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None })
|
.map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None })
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,10 +29,14 @@ impl RustPackageFilterBuilder {
|
||||||
self.is_member = is_member;
|
self.is_member = is_member;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder {
|
|
||||||
|
pub fn exclude(mut self, globs: impl IntoIterator<Item = Glob>) -> RustPackageFilterBuilder {
|
||||||
|
for glob in globs.into_iter() {
|
||||||
self.exclude.add(glob);
|
self.exclude.add(glob);
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_vfs_filter(self) -> Box<dyn Filter> {
|
pub fn into_vfs_filter(self) -> Box<dyn Filter> {
|
||||||
let RustPackageFilterBuilder { is_member, mut exclude } = self;
|
let RustPackageFilterBuilder { is_member, mut exclude } = self;
|
||||||
for &glob in ALWAYS_IGNORED {
|
for &glob in ALWAYS_IGNORED {
|
||||||
|
@ -87,7 +91,7 @@ fn test_globs() {
|
||||||
|
|
||||||
let filter = RustPackageFilterBuilder::default()
|
let filter = RustPackageFilterBuilder::default()
|
||||||
.set_member(true)
|
.set_member(true)
|
||||||
.exclude(Glob::new("src/llvm-project/**").unwrap())
|
.exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap()))
|
||||||
.into_vfs_filter();
|
.into_vfs_filter();
|
||||||
|
|
||||||
assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang")));
|
assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang")));
|
||||||
|
|
|
@ -87,44 +87,35 @@ impl WorldState {
|
||||||
) -> WorldState {
|
) -> WorldState {
|
||||||
let mut change = AnalysisChange::new();
|
let mut change = AnalysisChange::new();
|
||||||
|
|
||||||
let mut roots = Vec::new();
|
let extern_dirs: FxHashSet<_> =
|
||||||
roots.extend(folder_roots.iter().map(|path| {
|
workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect();
|
||||||
let mut filter = RustPackageFilterBuilder::default().set_member(true);
|
|
||||||
for glob in exclude_globs.iter() {
|
|
||||||
filter = filter.exclude(glob.clone());
|
|
||||||
}
|
|
||||||
RootEntry::new(path.clone(), filter.into_vfs_filter())
|
|
||||||
}));
|
|
||||||
for ws in workspaces.iter() {
|
|
||||||
roots.extend(ws.to_roots().into_iter().map(|pkg_root| {
|
|
||||||
let mut filter =
|
|
||||||
RustPackageFilterBuilder::default().set_member(pkg_root.is_member());
|
|
||||||
for glob in exclude_globs.iter() {
|
|
||||||
filter = filter.exclude(glob.clone());
|
|
||||||
}
|
|
||||||
RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter())
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut extern_dirs = FxHashSet::default();
|
let roots: Vec<_> = {
|
||||||
for ws in workspaces.iter() {
|
let create_filter = |is_member| {
|
||||||
extern_dirs.extend(ws.out_dirs());
|
RustPackageFilterBuilder::default()
|
||||||
}
|
.set_member(is_member)
|
||||||
|
.exclude(exclude_globs.iter().cloned())
|
||||||
let mut extern_source_roots = FxHashMap::default();
|
.into_vfs_filter()
|
||||||
|
};
|
||||||
roots.extend(extern_dirs.iter().map(|path| {
|
folder_roots
|
||||||
let mut filter = RustPackageFilterBuilder::default().set_member(false);
|
.iter()
|
||||||
for glob in exclude_globs.iter() {
|
.map(|path| RootEntry::new(path.clone(), create_filter(true)))
|
||||||
filter = filter.exclude(glob.clone());
|
.chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| {
|
||||||
}
|
RootEntry::new(pkg_root.path, create_filter(pkg_root.is_member))
|
||||||
RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter())
|
}))
|
||||||
}));
|
.chain(
|
||||||
|
extern_dirs
|
||||||
|
.iter()
|
||||||
|
.map(|path| RootEntry::new(path.to_owned(), create_filter(false))),
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
let (task_sender, task_receiver) = unbounded();
|
let (task_sender, task_receiver) = unbounded();
|
||||||
let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
|
let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
|
||||||
let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
|
let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
|
||||||
|
|
||||||
|
let mut extern_source_roots = FxHashMap::default();
|
||||||
for r in vfs_roots {
|
for r in vfs_roots {
|
||||||
let vfs_root_path = vfs.root2path(r);
|
let vfs_root_path = vfs.root2path(r);
|
||||||
let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
|
let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
|
||||||
|
@ -132,6 +123,7 @@ impl WorldState {
|
||||||
change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string());
|
change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string());
|
||||||
|
|
||||||
// FIXME: add path2root in vfs to simpily this logic
|
// FIXME: add path2root in vfs to simpily this logic
|
||||||
|
|
||||||
if extern_dirs.contains(&vfs_root_path) {
|
if extern_dirs.contains(&vfs_root_path) {
|
||||||
extern_source_roots.insert(vfs_root_path, ExternSourceId(r.0));
|
extern_source_roots.insert(vfs_root_path, ExternSourceId(r.0));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue