mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
Add new module for project loading stuff
This commit is contained in:
parent
3d0f782138
commit
72fb712dff
5 changed files with 260 additions and 238 deletions
|
@ -9,7 +9,7 @@ use ra_ide::{AnalysisChange, AnalysisHost};
|
|||
use ra_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
|
||||
use vfs::{loader::Handle, AbsPath};
|
||||
|
||||
use crate::global_state::{ProjectFolders, SourceRootConfig};
|
||||
use crate::reload::{ProjectFolders, SourceRootConfig};
|
||||
|
||||
pub fn load_cargo(
|
||||
root: &Path,
|
||||
|
|
|
@ -30,7 +30,7 @@ pub struct Config {
|
|||
|
||||
pub cargo: CargoConfig,
|
||||
pub rustfmt: RustfmtConfig,
|
||||
pub check: Option<FlycheckConfig>,
|
||||
pub flycheck: Option<FlycheckConfig>,
|
||||
|
||||
pub inlay_hints: InlayHintsConfig,
|
||||
pub completion: CompletionConfig,
|
||||
|
@ -147,7 +147,7 @@ impl Config {
|
|||
|
||||
cargo: CargoConfig::default(),
|
||||
rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
|
||||
check: Some(FlycheckConfig::CargoCommand {
|
||||
flycheck: Some(FlycheckConfig::CargoCommand {
|
||||
command: "check".to_string(),
|
||||
all_targets: true,
|
||||
all_features: false,
|
||||
|
@ -227,14 +227,14 @@ impl Config {
|
|||
|
||||
if let Some(false) = get(value, "/checkOnSave/enable") {
|
||||
// check is disabled
|
||||
self.check = None;
|
||||
self.flycheck = None;
|
||||
} else {
|
||||
// check is enabled
|
||||
match get::<Vec<String>>(value, "/checkOnSave/overrideCommand") {
|
||||
// first see if the user has completely overridden the command
|
||||
Some(mut args) if !args.is_empty() => {
|
||||
let command = args.remove(0);
|
||||
self.check = Some(FlycheckConfig::CustomCommand {
|
||||
self.flycheck = Some(FlycheckConfig::CustomCommand {
|
||||
command,
|
||||
args,
|
||||
});
|
||||
|
@ -242,7 +242,7 @@ impl Config {
|
|||
// otherwise configure command customizations
|
||||
_ => {
|
||||
if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets, all_features, features })
|
||||
= &mut self.check
|
||||
= &mut self.flycheck
|
||||
{
|
||||
set(value, "/checkOnSave/extraArgs", extra_args);
|
||||
set(value, "/checkOnSave/command", command);
|
||||
|
|
|
@ -3,24 +3,25 @@
|
|||
//!
|
||||
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
|
||||
|
||||
use std::{convert::TryFrom, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use flycheck::{FlycheckConfig, FlycheckHandle};
|
||||
use lsp_types::{request::Request, Url};
|
||||
use flycheck::FlycheckHandle;
|
||||
use lsp_types::Url;
|
||||
use parking_lot::RwLock;
|
||||
use ra_db::{CrateId, SourceRoot, VfsPath};
|
||||
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId};
|
||||
use ra_project_model::{CargoWorkspace, PackageRoot, ProcMacroClient, ProjectWorkspace, Target};
|
||||
use ra_db::{CrateId, VfsPath};
|
||||
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId};
|
||||
use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
|
||||
use stdx::format_to;
|
||||
use vfs::{file_set::FileSetConfig, loader::Handle, AbsPath, AbsPathBuf};
|
||||
use vfs::loader::Handle;
|
||||
|
||||
use crate::{
|
||||
config::{Config, FilesWatcher, LinkedProject},
|
||||
config::Config,
|
||||
diagnostics::{CheckFixes, DiagnosticCollection},
|
||||
from_proto,
|
||||
line_endings::LineEndings,
|
||||
main_loop::{ReqQueue, Task},
|
||||
reload::SourceRootConfig,
|
||||
request_metrics::{LatestRequests, RequestMetrics},
|
||||
show_message,
|
||||
thread_pool::TaskPool,
|
||||
|
@ -29,26 +30,6 @@ use crate::{
|
|||
};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
fn create_flycheck(
|
||||
workspaces: &[ProjectWorkspace],
|
||||
config: &FlycheckConfig,
|
||||
) -> Option<(FlycheckHandle, Receiver<flycheck::Message>)> {
|
||||
// FIXME: Figure out the multi-workspace situation
|
||||
workspaces.iter().find_map(move |w| match w {
|
||||
ProjectWorkspace::Cargo { cargo, .. } => {
|
||||
let (sender, receiver) = unbounded();
|
||||
let sender = Box::new(move |msg| sender.send(msg).unwrap());
|
||||
let cargo_project_root = cargo.workspace_root().to_path_buf();
|
||||
let flycheck = FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into());
|
||||
Some((flycheck, receiver))
|
||||
}
|
||||
ProjectWorkspace::Json { .. } => {
|
||||
log::warn!("Cargo check watching only supported for cargo workspaces, disabling");
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub(crate) enum Status {
|
||||
Loading,
|
||||
|
@ -79,10 +60,10 @@ pub(crate) struct GlobalState {
|
|||
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
|
||||
pub(crate) status: Status,
|
||||
pub(crate) req_queue: ReqQueue,
|
||||
pub(crate) source_root_config: SourceRootConfig,
|
||||
pub(crate) proc_macro_client: ProcMacroClient,
|
||||
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
latest_requests: Arc<RwLock<LatestRequests>>,
|
||||
source_root_config: SourceRootConfig,
|
||||
proc_macro_client: ProcMacroClient,
|
||||
workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
}
|
||||
|
||||
/// An immutable snapshot of the world's state at a point in time.
|
||||
|
@ -135,132 +116,6 @@ impl GlobalState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn reload(&mut self) {
|
||||
let workspaces = {
|
||||
if self.config.linked_projects.is_empty()
|
||||
&& self.config.notifications.cargo_toml_not_found
|
||||
{
|
||||
self.show_message(
|
||||
lsp_types::MessageType::Error,
|
||||
"rust-analyzer failed to discover workspace".to_string(),
|
||||
);
|
||||
};
|
||||
|
||||
self.config
|
||||
.linked_projects
|
||||
.iter()
|
||||
.filter_map(|project| match project {
|
||||
LinkedProject::ProjectManifest(manifest) => {
|
||||
ra_project_model::ProjectWorkspace::load(
|
||||
manifest.clone(),
|
||||
&self.config.cargo,
|
||||
self.config.with_sysroot,
|
||||
)
|
||||
.map_err(|err| {
|
||||
log::error!("failed to load workspace: {:#}", err);
|
||||
self.show_message(
|
||||
lsp_types::MessageType::Error,
|
||||
format!("rust-analyzer failed to load workspace: {:#}", err),
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
LinkedProject::InlineJsonProject(it) => {
|
||||
Some(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
if let FilesWatcher::Client = self.config.files.watcher {
|
||||
let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
|
||||
watchers: workspaces
|
||||
.iter()
|
||||
.flat_map(ProjectWorkspace::to_roots)
|
||||
.filter(PackageRoot::is_member)
|
||||
.map(|root| format!("{}/**/*.rs", root.path().display()))
|
||||
.map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
|
||||
.collect(),
|
||||
};
|
||||
let registration = lsp_types::Registration {
|
||||
id: "file-watcher".to_string(),
|
||||
method: "workspace/didChangeWatchedFiles".to_string(),
|
||||
register_options: Some(serde_json::to_value(registration_options).unwrap()),
|
||||
};
|
||||
let params = lsp_types::RegistrationParams { registrations: vec![registration] };
|
||||
let request = self.req_queue.outgoing.register(
|
||||
lsp_types::request::RegisterCapability::METHOD.to_string(),
|
||||
params,
|
||||
|_, _| (),
|
||||
);
|
||||
self.send(request.into());
|
||||
}
|
||||
|
||||
let mut change = AnalysisChange::new();
|
||||
|
||||
let project_folders = ProjectFolders::new(&workspaces);
|
||||
|
||||
self.proc_macro_client = match &self.config.proc_macro_srv {
|
||||
None => ProcMacroClient::dummy(),
|
||||
Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
|
||||
Ok(it) => it,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
"Failed to run ra_proc_macro_srv from path {}, error: {:?}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
ProcMacroClient::dummy()
|
||||
}
|
||||
},
|
||||
};
|
||||
let watch = match self.config.files.watcher {
|
||||
FilesWatcher::Client => vec![],
|
||||
FilesWatcher::Notify => project_folders.watch,
|
||||
};
|
||||
self.loader.set_config(vfs::loader::Config { load: project_folders.load, watch });
|
||||
|
||||
// Create crate graph from all the workspaces
|
||||
let crate_graph = {
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let vfs = &mut self.vfs.write().0;
|
||||
let loader = &mut self.loader;
|
||||
let mut load = |path: &AbsPath| {
|
||||
let contents = loader.load_sync(path);
|
||||
let path = vfs::VfsPath::from(path.to_path_buf());
|
||||
vfs.set_file_contents(path.clone(), contents);
|
||||
vfs.file_id(&path)
|
||||
};
|
||||
for ws in workspaces.iter() {
|
||||
crate_graph.extend(ws.to_crate_graph(
|
||||
self.config.cargo.target.as_deref(),
|
||||
&self.proc_macro_client,
|
||||
&mut load,
|
||||
));
|
||||
}
|
||||
|
||||
crate_graph
|
||||
};
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
||||
self.flycheck = self.config.check.as_ref().and_then(|c| create_flycheck(&workspaces, c));
|
||||
self.source_root_config = project_folders.source_root_config;
|
||||
self.workspaces = Arc::new(workspaces);
|
||||
|
||||
self.analysis_host.apply_change(change);
|
||||
self.process_changes();
|
||||
}
|
||||
|
||||
pub(crate) fn update_configuration(&mut self, config: Config) {
|
||||
self.analysis_host.update_lru_capacity(config.lru_capacity);
|
||||
if config.check != self.config.check {
|
||||
self.flycheck =
|
||||
config.check.as_ref().and_then(|it| create_flycheck(&self.workspaces, it));
|
||||
}
|
||||
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
pub(crate) fn process_changes(&mut self) -> bool {
|
||||
let change = {
|
||||
let mut change = AnalysisChange::new();
|
||||
|
@ -408,78 +263,3 @@ pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
|
|||
let path = path.as_path().unwrap();
|
||||
url_from_abs_path(&path)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ProjectFolders {
|
||||
pub(crate) load: Vec<vfs::loader::Entry>,
|
||||
pub(crate) watch: Vec<usize>,
|
||||
pub(crate) source_root_config: SourceRootConfig,
|
||||
}
|
||||
|
||||
impl ProjectFolders {
|
||||
pub(crate) fn new(workspaces: &[ProjectWorkspace]) -> ProjectFolders {
|
||||
let mut res = ProjectFolders::default();
|
||||
let mut fsc = FileSetConfig::builder();
|
||||
let mut local_filesets = vec![];
|
||||
|
||||
for root in workspaces.iter().flat_map(|it| it.to_roots()) {
|
||||
let path = root.path().to_owned();
|
||||
|
||||
let mut file_set_roots: Vec<VfsPath> = vec![];
|
||||
|
||||
let entry = if root.is_member() {
|
||||
vfs::loader::Entry::local_cargo_package(path.to_path_buf())
|
||||
} else {
|
||||
vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
|
||||
};
|
||||
res.load.push(entry);
|
||||
if root.is_member() {
|
||||
res.watch.push(res.load.len() - 1);
|
||||
}
|
||||
|
||||
if let Some(out_dir) = root.out_dir() {
|
||||
let out_dir = AbsPathBuf::try_from(out_dir.to_path_buf()).unwrap();
|
||||
res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone()));
|
||||
if root.is_member() {
|
||||
res.watch.push(res.load.len() - 1);
|
||||
}
|
||||
file_set_roots.push(out_dir.into());
|
||||
}
|
||||
file_set_roots.push(path.to_path_buf().into());
|
||||
|
||||
if root.is_member() {
|
||||
local_filesets.push(fsc.len());
|
||||
}
|
||||
fsc.add_file_set(file_set_roots)
|
||||
}
|
||||
|
||||
let fsc = fsc.build();
|
||||
res.source_root_config = SourceRootConfig { fsc, local_filesets };
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub(crate) struct SourceRootConfig {
|
||||
pub(crate) fsc: FileSetConfig,
|
||||
pub(crate) local_filesets: Vec<usize>,
|
||||
}
|
||||
|
||||
impl SourceRootConfig {
|
||||
pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
|
||||
self.fsc
|
||||
.partition(vfs)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, file_set)| {
|
||||
let is_local = self.local_filesets.contains(&idx);
|
||||
if is_local {
|
||||
SourceRoot::new_local(file_set)
|
||||
} else {
|
||||
SourceRoot::new_library(file_set)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ macro_rules! eprintln {
|
|||
}
|
||||
|
||||
mod global_state;
|
||||
mod reload;
|
||||
mod main_loop;
|
||||
mod dispatch;
|
||||
mod handlers;
|
||||
|
|
241
crates/rust-analyzer/src/reload.rs
Normal file
241
crates/rust-analyzer/src/reload.rs
Normal file
|
@ -0,0 +1,241 @@
|
|||
//! Project loading & configuration updates
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam_channel::unbounded;
|
||||
use flycheck::FlycheckHandle;
|
||||
use lsp_types::request::Request;
|
||||
use ra_db::{CrateGraph, SourceRoot, VfsPath};
|
||||
use ra_ide::AnalysisChange;
|
||||
use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
|
||||
use vfs::{file_set::FileSetConfig, AbsPath};
|
||||
|
||||
use crate::{
|
||||
config::{Config, FilesWatcher, LinkedProject},
|
||||
global_state::GlobalState,
|
||||
};
|
||||
|
||||
impl GlobalState {
|
||||
pub(crate) fn update_configuration(&mut self, new_config: Config) {
|
||||
self.analysis_host.update_lru_capacity(new_config.lru_capacity);
|
||||
if new_config.flycheck != self.config.flycheck {
|
||||
self.reload_flycheck();
|
||||
}
|
||||
self.config = new_config;
|
||||
}
|
||||
pub(crate) fn reload(&mut self) {
|
||||
let workspaces = {
|
||||
if self.config.linked_projects.is_empty()
|
||||
&& self.config.notifications.cargo_toml_not_found
|
||||
{
|
||||
self.show_message(
|
||||
lsp_types::MessageType::Error,
|
||||
"rust-analyzer failed to discover workspace".to_string(),
|
||||
);
|
||||
};
|
||||
|
||||
self.config
|
||||
.linked_projects
|
||||
.iter()
|
||||
.filter_map(|project| match project {
|
||||
LinkedProject::ProjectManifest(manifest) => {
|
||||
ra_project_model::ProjectWorkspace::load(
|
||||
manifest.clone(),
|
||||
&self.config.cargo,
|
||||
self.config.with_sysroot,
|
||||
)
|
||||
.map_err(|err| {
|
||||
log::error!("failed to load workspace: {:#}", err);
|
||||
self.show_message(
|
||||
lsp_types::MessageType::Error,
|
||||
format!("rust-analyzer failed to load workspace: {:#}", err),
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
LinkedProject::InlineJsonProject(it) => {
|
||||
Some(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
if let FilesWatcher::Client = self.config.files.watcher {
|
||||
let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
|
||||
watchers: workspaces
|
||||
.iter()
|
||||
.flat_map(ProjectWorkspace::to_roots)
|
||||
.filter(PackageRoot::is_member)
|
||||
.map(|root| format!("{}/**/*.rs", root.path().display()))
|
||||
.map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
|
||||
.collect(),
|
||||
};
|
||||
let registration = lsp_types::Registration {
|
||||
id: "file-watcher".to_string(),
|
||||
method: "workspace/didChangeWatchedFiles".to_string(),
|
||||
register_options: Some(serde_json::to_value(registration_options).unwrap()),
|
||||
};
|
||||
let params = lsp_types::RegistrationParams { registrations: vec![registration] };
|
||||
let request = self.req_queue.outgoing.register(
|
||||
lsp_types::request::RegisterCapability::METHOD.to_string(),
|
||||
params,
|
||||
|_, _| (),
|
||||
);
|
||||
self.send(request.into());
|
||||
}
|
||||
|
||||
let mut change = AnalysisChange::new();
|
||||
|
||||
let project_folders = ProjectFolders::new(&workspaces);
|
||||
|
||||
self.proc_macro_client = match &self.config.proc_macro_srv {
|
||||
None => ProcMacroClient::dummy(),
|
||||
Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
|
||||
Ok(it) => it,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
"Failed to run ra_proc_macro_srv from path {}, error: {:?}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
ProcMacroClient::dummy()
|
||||
}
|
||||
},
|
||||
};
|
||||
let watch = match self.config.files.watcher {
|
||||
FilesWatcher::Client => vec![],
|
||||
FilesWatcher::Notify => project_folders.watch,
|
||||
};
|
||||
self.loader.set_config(vfs::loader::Config { load: project_folders.load, watch });
|
||||
|
||||
// Create crate graph from all the workspaces
|
||||
let crate_graph = {
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
let vfs = &mut self.vfs.write().0;
|
||||
let loader = &mut self.loader;
|
||||
let mut load = |path: &AbsPath| {
|
||||
let contents = loader.load_sync(path);
|
||||
let path = vfs::VfsPath::from(path.to_path_buf());
|
||||
vfs.set_file_contents(path.clone(), contents);
|
||||
vfs.file_id(&path)
|
||||
};
|
||||
for ws in workspaces.iter() {
|
||||
crate_graph.extend(ws.to_crate_graph(
|
||||
self.config.cargo.target.as_deref(),
|
||||
&self.proc_macro_client,
|
||||
&mut load,
|
||||
));
|
||||
}
|
||||
|
||||
crate_graph
|
||||
};
|
||||
change.set_crate_graph(crate_graph);
|
||||
|
||||
self.source_root_config = project_folders.source_root_config;
|
||||
self.workspaces = Arc::new(workspaces);
|
||||
|
||||
self.analysis_host.apply_change(change);
|
||||
self.process_changes();
|
||||
self.reload_flycheck();
|
||||
}
|
||||
|
||||
fn reload_flycheck(&mut self) {
|
||||
let config = match self.config.flycheck.clone() {
|
||||
Some(it) => it,
|
||||
None => {
|
||||
self.flycheck = None;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: Figure out the multi-workspace situation
|
||||
self.flycheck = self.workspaces.iter().find_map(move |w| match w {
|
||||
ProjectWorkspace::Cargo { cargo, .. } => {
|
||||
let (sender, receiver) = unbounded();
|
||||
let sender = Box::new(move |msg| sender.send(msg).unwrap());
|
||||
let cargo_project_root = cargo.workspace_root().to_path_buf();
|
||||
let flycheck =
|
||||
FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into());
|
||||
Some((flycheck, receiver))
|
||||
}
|
||||
ProjectWorkspace::Json { .. } => {
|
||||
log::warn!("Cargo check watching only supported for cargo workspaces, disabling");
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ProjectFolders {
|
||||
pub(crate) load: Vec<vfs::loader::Entry>,
|
||||
pub(crate) watch: Vec<usize>,
|
||||
pub(crate) source_root_config: SourceRootConfig,
|
||||
}
|
||||
|
||||
impl ProjectFolders {
|
||||
pub(crate) fn new(workspaces: &[ProjectWorkspace]) -> ProjectFolders {
|
||||
let mut res = ProjectFolders::default();
|
||||
let mut fsc = FileSetConfig::builder();
|
||||
let mut local_filesets = vec![];
|
||||
|
||||
for root in workspaces.iter().flat_map(|it| it.to_roots()) {
|
||||
let path = root.path().to_owned();
|
||||
|
||||
let mut file_set_roots: Vec<VfsPath> = vec![];
|
||||
|
||||
let entry = if root.is_member() {
|
||||
vfs::loader::Entry::local_cargo_package(path.to_path_buf())
|
||||
} else {
|
||||
vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
|
||||
};
|
||||
res.load.push(entry);
|
||||
if root.is_member() {
|
||||
res.watch.push(res.load.len() - 1);
|
||||
}
|
||||
|
||||
if let Some(out_dir) = root.out_dir() {
|
||||
let out_dir = out_dir.to_path_buf();
|
||||
res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone()));
|
||||
if root.is_member() {
|
||||
res.watch.push(res.load.len() - 1);
|
||||
}
|
||||
file_set_roots.push(out_dir.into());
|
||||
}
|
||||
file_set_roots.push(path.to_path_buf().into());
|
||||
|
||||
if root.is_member() {
|
||||
local_filesets.push(fsc.len());
|
||||
}
|
||||
fsc.add_file_set(file_set_roots)
|
||||
}
|
||||
|
||||
let fsc = fsc.build();
|
||||
res.source_root_config = SourceRootConfig { fsc, local_filesets };
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub(crate) struct SourceRootConfig {
|
||||
pub(crate) fsc: FileSetConfig,
|
||||
pub(crate) local_filesets: Vec<usize>,
|
||||
}
|
||||
|
||||
impl SourceRootConfig {
|
||||
pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
|
||||
self.fsc
|
||||
.partition(vfs)
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, file_set)| {
|
||||
let is_local = self.local_filesets.contains(&idx);
|
||||
if is_local {
|
||||
SourceRoot::new_local(file_set)
|
||||
} else {
|
||||
SourceRoot::new_library(file_set)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue