Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify #3798

Merged
merged 7 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 54 additions & 75 deletions crates/ra_project_model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ pub struct PackageRoot {
/// Is a member of the current workspace
is_member: bool,
}

impl PackageRoot {
pub fn new(path: PathBuf, is_member: bool) -> PackageRoot {
PackageRoot { path, is_member }
pub fn new_member(path: PathBuf) -> PackageRoot {
Self { path, is_member: true }
}

pub fn path(&self) -> &PathBuf {
pub fn new_non_member(path: PathBuf) -> PackageRoot {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better name is new_foreign?

Self { path, is_member: false }
}
pub fn path(&self) -> &Path {
&self.path
}

pub fn is_member(&self) -> bool {
self.is_member
}
Expand Down Expand Up @@ -130,70 +130,45 @@ impl ProjectWorkspace {
pub fn to_roots(&self) -> Vec<PackageRoot> {
match self {
ProjectWorkspace::Json { project } => {
let mut roots = Vec::with_capacity(project.roots.len());
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
project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect()
}
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(),
}
}

pub fn out_dirs(&self) -> Vec<PathBuf> {
match self {
ProjectWorkspace::Json { project } => {
let mut out_dirs = Vec::with_capacity(project.crates.len());
for krate in &project.crates {
if let Some(out_dir) = &krate.out_dir {
out_dirs.push(out_dir.to_path_buf());
}
}
out_dirs
project.crates.iter().filter_map(|krate| krate.out_dir.as_ref()).cloned().collect()
}
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
let mut out_dirs = Vec::with_capacity(cargo.packages().len());
for pkg in cargo.packages() {
if let Some(out_dir) = &cargo[pkg].out_dir {
out_dirs.push(out_dir.to_path_buf());
}
}
out_dirs
ProjectWorkspace::Cargo { cargo, sysroot: _ } => {
cargo.packages().filter_map(|pkg| cargo[pkg].out_dir.as_ref()).cloned().collect()
}
}
}

pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
match self {
ProjectWorkspace::Json { project } => {
let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len());
for krate in &project.crates {
if let Some(out_dir) = &krate.proc_macro_dylib_path {
proc_macro_dylib_paths.push(out_dir.to_path_buf());
}
}
proc_macro_dylib_paths
}
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len());
for pkg in cargo.packages() {
if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path {
proc_macro_dylib_paths.push(dylib_path.to_path_buf());
}
}
proc_macro_dylib_paths
}
ProjectWorkspace::Json { project } => project
.crates
.iter()
.filter_map(|krate| krate.proc_macro_dylib_path.as_ref())
.cloned()
.collect(),
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo
.packages()
.filter_map(|pkg| cargo[pkg].proc_macro_dylib_path.as_ref())
.cloned()
.collect(),
}
}

Expand All @@ -216,10 +191,12 @@ impl ProjectWorkspace {
let mut crate_graph = CrateGraph::default();
match self {
ProjectWorkspace::Json { project } => {
let mut crates = FxHashMap::default();
for (id, krate) in project.crates.iter().enumerate() {
let crate_id = json_project::CrateId(id);
if let Some(file_id) = load(&krate.root_module) {
let crates: FxHashMap<_, _> = project
.crates
.iter()
.enumerate()
.filter_map(|(seq_index, krate)| {
let file_id = load(&krate.root_module)?;
let edition = match krate.edition {
json_project::Edition::Edition2015 => Edition::Edition2015,
json_project::Edition::Edition2018 => Edition::Edition2018,
Expand Down Expand Up @@ -249,8 +226,8 @@ impl ProjectWorkspace {
.clone()
.map(|it| proc_macro_client.by_dylib_path(&it));
// FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
crates.insert(
crate_id,
Some((
json_project::CrateId(seq_index),
crate_graph.add_crate_root(
file_id,
edition,
Expand All @@ -261,9 +238,9 @@ impl ProjectWorkspace {
extern_source,
proc_macro.unwrap_or_default(),
),
);
}
}
))
})
.collect();

for (id, krate) in project.crates.iter().enumerate() {
for dep in &krate.deps {
Expand All @@ -287,9 +264,11 @@ impl ProjectWorkspace {
}
}
ProjectWorkspace::Cargo { cargo, sysroot } => {
let mut sysroot_crates = FxHashMap::default();
for krate in sysroot.crates() {
if let Some(file_id) = load(&sysroot[krate].root) {
let sysroot_crates: FxHashMap<_, _> = sysroot
.crates()
.filter_map(|krate| {
let file_id = load(&sysroot[krate].root)?;

// Crates from sysroot have `cfg(test)` disabled
let cfg_options = {
let mut opts = default_cfg_options.clone();
Expand All @@ -300,22 +279,22 @@ impl ProjectWorkspace {
let env = Env::default();
let extern_source = ExternSource::default();
let proc_macro = vec![];
let crate_name = CrateName::new(&sysroot[krate].name)
.expect("Sysroot crate names should not contain dashes");

let crate_id = crate_graph.add_crate_root(
file_id,
Edition::Edition2018,
Some(
CrateName::new(&sysroot[krate].name)
.expect("Sysroot crate names should not contain dashes"),
),
Some(crate_name),
cfg_options,
env,
extern_source,
proc_macro,
);
sysroot_crates.insert(krate, crate_id);
}
}
Some((krate, crate_id))
})
.collect();

for from in sysroot.crates() {
for &to in sysroot[from].deps.iter() {
let name = &sysroot[to].name;
Expand Down
11 changes: 5 additions & 6 deletions crates/rust-analyzer/src/cli/load_cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ pub(crate) fn load_cargo(
extern_dirs.extend(ws.out_dirs());

let mut project_roots = ws.to_roots();
project_roots
.extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false)));
project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member));

let (sender, receiver) = unbounded();
let sender = Box::new(move |t| sender.send(t).unwrap());
Expand All @@ -46,7 +45,7 @@ pub(crate) fn load_cargo(
.iter()
.map(|pkg_root| {
RootEntry::new(
pkg_root.path().clone(),
pkg_root.path().to_owned(),
RustPackageFilterBuilder::default()
.set_member(pkg_root.is_member())
.into_vfs_filter(),
Expand All @@ -58,12 +57,12 @@ pub(crate) fn load_cargo(
);

let source_roots = roots
.iter()
.map(|&vfs_root| {
.into_iter()
.map(|vfs_root| {
let source_root_id = vfs_root_to_id(vfs_root);
let project_root = project_roots
.iter()
.find(|it| it.path() == &vfs.root2path(vfs_root))
.find(|it| it.path() == vfs.root2path(vfs_root))
.unwrap()
.clone();
(source_root_id, project_root)
Expand Down
5 changes: 3 additions & 2 deletions crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use lsp_types::{
use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask};
use ra_ide::{Canceled, FileId, LibraryData, SourceRootId};
use ra_prof::profile;
use ra_project_model::{PackageRoot, ProjectWorkspace};
use ra_vfs::{VfsFile, VfsTask, Watch};
use relative_path::RelativePathBuf;
use rustc_hash::FxHashSet;
Expand Down Expand Up @@ -131,8 +132,8 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
let registration_options = req::DidChangeWatchedFilesRegistrationOptions {
watchers: workspaces
.iter()
.flat_map(|ws| ws.to_roots())
.filter(|root| root.is_member())
.flat_map(ProjectWorkspace::to_roots)
.filter(PackageRoot::is_member)
.map(|root| format!("{}/**/*.rs", root.path().display()))
.map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None })
.collect(),
Expand Down
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/main_loop/subscriptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ impl Subscriptions {
self.subs.remove(&file_id);
}
pub(crate) fn subscriptions(&self) -> Vec<FileId> {
self.subs.iter().cloned().collect()
self.subs.iter().copied().collect()
}
}
10 changes: 7 additions & 3 deletions crates/rust-analyzer/src/vfs_glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ impl RustPackageFilterBuilder {
self.is_member = is_member;
self
}
pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder {
self.exclude.add(glob);

pub fn exclude(mut self, globs: impl IntoIterator<Item = Glob>) -> RustPackageFilterBuilder {
for glob in globs.into_iter() {
self.exclude.add(glob);
}
self
}

pub fn into_vfs_filter(self) -> Box<dyn Filter> {
let RustPackageFilterBuilder { is_member, mut exclude } = self;
for &glob in ALWAYS_IGNORED {
Expand Down Expand Up @@ -87,7 +91,7 @@ fn test_globs() {

let filter = RustPackageFilterBuilder::default()
.set_member(true)
.exclude(Glob::new("src/llvm-project/**").unwrap())
.exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap()))
Copy link
Contributor Author

@Veetaha Veetaha Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, this also works since impl IntoIter for Option holds:

        .exclude(Some(Glob::new("src/llvm-project/**").unwrap()))

But it looks very hacky :D

Copy link
Member

@lnicola lnicola Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.exclude([Glob::new("src/llvm-project/**")])?

Copy link
Contributor Author

@Veetaha Veetaha Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, there is not into_iter for [T; N]

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&[T] yields only refs &T, but here we need T

.into_vfs_filter();

assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang")));
Expand Down
57 changes: 24 additions & 33 deletions crates/rust-analyzer/src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,44 +87,35 @@ impl WorldState {
) -> WorldState {
let mut change = AnalysisChange::new();

let mut roots = Vec::new();
roots.extend(folder_roots.iter().map(|path| {
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();
for ws in workspaces.iter() {
extern_dirs.extend(ws.out_dirs());
}

let mut extern_source_roots = FxHashMap::default();

roots.extend(extern_dirs.iter().map(|path| {
let mut filter = RustPackageFilterBuilder::default().set_member(false);
for glob in exclude_globs.iter() {
filter = filter.exclude(glob.clone());
}
RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter())
}));
let extern_dirs: FxHashSet<_> =
workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect();

let roots: Vec<_> = {
let create_filter = |is_member| {
RustPackageFilterBuilder::default()
.set_member(is_member)
.exclude(exclude_globs.iter().cloned())
.into_vfs_filter()
};
folder_roots
.iter()
.map(|path| RootEntry::new(path.clone(), create_filter(true)))
.chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| {
RootEntry::new(pkg_root.path().to_owned(), create_filter(pkg_root.is_member()))
}))
.chain(
extern_dirs
.iter()
.map(|path| RootEntry::new(path.to_owned(), create_filter(false))),
)
.collect()
};

let (task_sender, task_receiver) = unbounded();
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 extern_source_roots = FxHashMap::default();
for r in vfs_roots {
let vfs_root_path = vfs.root2path(r);
let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
Expand Down