Fix file loading of r-a toml files
This commit is contained in:
parent
003106cf6b
commit
d726854555
3 changed files with 37 additions and 90 deletions
|
|
@ -902,10 +902,10 @@ impl Config {
|
|||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ConfigChange {
|
||||
user_config_change: Option<String>,
|
||||
root_ratoml_change: Option<String>,
|
||||
user_config_change: Option<Arc<str>>,
|
||||
root_ratoml_change: Option<Arc<str>>,
|
||||
client_config_change: Option<serde_json::Value>,
|
||||
ratoml_file_change: Option<FxHashMap<SourceRootId, (VfsPath, Option<String>)>>,
|
||||
ratoml_file_change: Option<FxHashMap<SourceRootId, (VfsPath, Option<Arc<str>>)>>,
|
||||
source_map_change: Option<Arc<FxHashMap<SourceRootId, SourceRootId>>>,
|
||||
}
|
||||
|
||||
|
|
@ -914,19 +914,19 @@ impl ConfigChange {
|
|||
&mut self,
|
||||
source_root: SourceRootId,
|
||||
vfs_path: VfsPath,
|
||||
content: Option<String>,
|
||||
) -> Option<(VfsPath, Option<String>)> {
|
||||
content: Option<Arc<str>>,
|
||||
) -> Option<(VfsPath, Option<Arc<str>>)> {
|
||||
self.ratoml_file_change
|
||||
.get_or_insert_with(Default::default)
|
||||
.insert(source_root, (vfs_path, content))
|
||||
}
|
||||
|
||||
pub fn change_user_config(&mut self, content: Option<String>) {
|
||||
pub fn change_user_config(&mut self, content: Option<Arc<str>>) {
|
||||
assert!(self.user_config_change.is_none()); // Otherwise it is a double write.
|
||||
self.user_config_change = content;
|
||||
}
|
||||
|
||||
pub fn change_root_ratoml(&mut self, content: Option<String>) {
|
||||
pub fn change_root_ratoml(&mut self, content: Option<Arc<str>>) {
|
||||
assert!(self.user_config_change.is_none()); // Otherwise it is a double write.
|
||||
self.root_ratoml_change = content;
|
||||
}
|
||||
|
|
@ -1206,8 +1206,7 @@ impl Config {
|
|||
client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
|
||||
user_config: None,
|
||||
ratoml_files: FxHashMap::default(),
|
||||
default_config: DEFAULT_CONFIG_DATA
|
||||
.get_or_init(|| Box::leak(Box::new(DefaultConfigData::default()))),
|
||||
default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
|
||||
source_root_parent_map: Arc::new(FxHashMap::default()),
|
||||
user_config_path,
|
||||
root_ratoml: None,
|
||||
|
|
@ -3548,7 +3547,8 @@ mod tests {
|
|||
[cargo.sysroot]
|
||||
non-table = "expected"
|
||||
}
|
||||
.to_string(),
|
||||
.to_string()
|
||||
.into(),
|
||||
));
|
||||
|
||||
let (config, e, _) = config.apply_change(change);
|
||||
|
|
@ -3582,9 +3582,9 @@ mod tests {
|
|||
be = "be"
|
||||
valid = "valid"
|
||||
}
|
||||
.to_string(),
|
||||
.to_string()
|
||||
.into(),
|
||||
));
|
||||
|
||||
let (_, e, _) = config.apply_change(change);
|
||||
expect_test::expect![[r#"
|
||||
ConfigErrors(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use project_model::{
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use tracing::{span, Level};
|
||||
use triomphe::Arc;
|
||||
use vfs::{AnchoredPathBuf, Vfs, VfsPath};
|
||||
use vfs::{AnchoredPathBuf, ChangeKind, Vfs};
|
||||
|
||||
use crate::{
|
||||
config::{Config, ConfigChange, ConfigErrors},
|
||||
|
|
@ -262,19 +262,9 @@ impl GlobalState {
|
|||
// that can be used by the config module because config talks
|
||||
// in `SourceRootId`s instead of `FileId`s and `FileId` -> `SourceRootId`
|
||||
// mapping is not ready until `AnalysisHost::apply_changes` has been called.
|
||||
let mut modified_ratoml_files: FxHashMap<FileId, vfs::VfsPath> = FxHashMap::default();
|
||||
let mut ratoml_text_map: FxHashMap<FileId, (vfs::VfsPath, Option<String>)> =
|
||||
let mut modified_ratoml_files: FxHashMap<FileId, (ChangeKind, vfs::VfsPath)> =
|
||||
FxHashMap::default();
|
||||
|
||||
let mut user_config_file: Option<Option<String>> = None;
|
||||
let mut root_path_ratoml: Option<Option<String>> = None;
|
||||
|
||||
let root_vfs_path = {
|
||||
let mut root_vfs_path = self.config.root_path().to_path_buf();
|
||||
root_vfs_path.push("rust-analyzer.toml");
|
||||
VfsPath::new_real_path(root_vfs_path.to_string())
|
||||
};
|
||||
|
||||
let (change, modified_rust_files, workspace_structure_change) = {
|
||||
let mut change = ChangeWithProcMacros::new();
|
||||
let mut guard = self.vfs.write();
|
||||
|
|
@ -296,7 +286,7 @@ impl GlobalState {
|
|||
let vfs_path = vfs.file_path(file.file_id);
|
||||
if let Some(("rust-analyzer", Some("toml"))) = vfs_path.name_and_extension() {
|
||||
// Remember ids to use them after `apply_changes`
|
||||
modified_ratoml_files.insert(file.file_id, vfs_path.clone());
|
||||
modified_ratoml_files.insert(file.file_id, (file.kind(), vfs_path.clone()));
|
||||
}
|
||||
|
||||
if let Some(path) = vfs_path.as_path() {
|
||||
|
|
@ -344,17 +334,7 @@ impl GlobalState {
|
|||
Some(text)
|
||||
}
|
||||
};
|
||||
|
||||
change.change_file(file_id, text.clone());
|
||||
if let Some(vfs_path) = modified_ratoml_files.get(&file_id) {
|
||||
if vfs_path == self.config.user_config_path() {
|
||||
user_config_file = Some(text);
|
||||
} else if vfs_path == &root_vfs_path {
|
||||
root_path_ratoml = Some(text);
|
||||
} else {
|
||||
ratoml_text_map.insert(file_id, (vfs_path.clone(), text));
|
||||
}
|
||||
}
|
||||
change.change_file(file_id, text);
|
||||
});
|
||||
if has_structure_changes {
|
||||
let roots = self.source_root_config.partition(vfs);
|
||||
|
|
@ -365,22 +345,35 @@ impl GlobalState {
|
|||
|
||||
let _p = span!(Level::INFO, "GlobalState::process_changes/apply_change").entered();
|
||||
self.analysis_host.apply_change(change);
|
||||
if !(ratoml_text_map.is_empty() && user_config_file.is_none() && root_path_ratoml.is_none())
|
||||
{
|
||||
if !modified_ratoml_files.is_empty() {
|
||||
let config_change = {
|
||||
let user_config_path = self.config.user_config_path();
|
||||
let root_ratoml_path = self.config.root_ratoml_path();
|
||||
let mut change = ConfigChange::default();
|
||||
let db = self.analysis_host.raw_database();
|
||||
|
||||
for (file_id, (vfs_path, text)) in ratoml_text_map {
|
||||
for (file_id, (_change_kind, vfs_path)) in modified_ratoml_files {
|
||||
if vfs_path == *user_config_path {
|
||||
change.change_user_config(Some(db.file_text(file_id)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if vfs_path == *root_ratoml_path {
|
||||
change.change_root_ratoml(Some(db.file_text(file_id)));
|
||||
continue;
|
||||
}
|
||||
|
||||
// If change has been made to a ratoml file that
|
||||
// belongs to a non-local source root, we will ignore it.
|
||||
// As it doesn't make sense a users to use external config files.
|
||||
let sr_id = db.file_source_root(file_id);
|
||||
let sr = db.source_root(sr_id);
|
||||
if !sr.is_library {
|
||||
if let Some((old_path, old_text)) =
|
||||
change.change_ratoml(sr_id, vfs_path.clone(), text)
|
||||
{
|
||||
if let Some((old_path, old_text)) = change.change_ratoml(
|
||||
sr_id,
|
||||
vfs_path.clone(),
|
||||
Some(db.file_text(file_id)),
|
||||
) {
|
||||
// SourceRoot has more than 1 RATOML files. In this case lexicographically smaller wins.
|
||||
if old_path < vfs_path {
|
||||
span!(Level::ERROR, "Two `rust-analyzer.toml` files were found inside the same crate. {vfs_path} has no effect.");
|
||||
|
|
@ -394,14 +387,6 @@ impl GlobalState {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(Some(txt)) = user_config_file {
|
||||
change.change_user_config(Some(txt));
|
||||
}
|
||||
|
||||
if let Some(Some(txt)) = root_path_ratoml {
|
||||
change.change_root_ratoml(Some(txt));
|
||||
}
|
||||
|
||||
change
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
//! project is currently loading and we don't have a full project model, we
|
||||
//! still want to respond to various requests.
|
||||
// FIXME: This is a mess that needs some untangling work
|
||||
use std::{iter, mem, ops::Not as _};
|
||||
use std::{iter, mem};
|
||||
|
||||
use flycheck::{FlycheckConfig, FlycheckHandle};
|
||||
use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros};
|
||||
|
|
@ -28,12 +28,11 @@ use lsp_types::FileSystemWatcher;
|
|||
use proc_macro_api::ProcMacroServer;
|
||||
use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
|
||||
use stdx::{format_to, thread::ThreadIntent};
|
||||
use tracing::error;
|
||||
use triomphe::Arc;
|
||||
use vfs::{AbsPath, AbsPathBuf, ChangeKind};
|
||||
|
||||
use crate::{
|
||||
config::{Config, ConfigChange, FilesWatcher, LinkedProject},
|
||||
config::{Config, FilesWatcher, LinkedProject},
|
||||
global_state::GlobalState,
|
||||
lsp_ext,
|
||||
main_loop::Task,
|
||||
|
|
@ -573,43 +572,6 @@ impl GlobalState {
|
|||
self.source_root_config = project_folders.source_root_config;
|
||||
self.local_roots_parent_map = Arc::new(self.source_root_config.source_root_parent_map());
|
||||
|
||||
let user_config_path = self.config.user_config_path();
|
||||
let root_ratoml_path = self.config.root_ratoml_path();
|
||||
|
||||
{
|
||||
let vfs = &mut self.vfs.write().0;
|
||||
let loader = &mut self.loader;
|
||||
|
||||
if vfs.file_id(user_config_path).is_none() {
|
||||
if let Some(user_cfg_abs) = user_config_path.as_path() {
|
||||
let contents = loader.handle.load_sync(user_cfg_abs);
|
||||
vfs.set_file_contents(user_config_path.clone(), contents);
|
||||
} else {
|
||||
error!("Non-abs virtual path for user config.");
|
||||
}
|
||||
}
|
||||
|
||||
if vfs.file_id(root_ratoml_path).is_none() {
|
||||
// FIXME @alibektas : Sometimes root_path_ratoml collide with a regular ratoml.
|
||||
// Although this shouldn't be a problem because everything is mapped to a `FileId`.
|
||||
// We may want to further think about this.
|
||||
if let Some(root_ratoml_abs) = root_ratoml_path.as_path() {
|
||||
let contents = loader.handle.load_sync(root_ratoml_abs);
|
||||
vfs.set_file_contents(root_ratoml_path.clone(), contents);
|
||||
} else {
|
||||
error!("Non-abs virtual path for user config.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut config_change = ConfigChange::default();
|
||||
config_change.change_source_root_parent_map(self.local_roots_parent_map.clone());
|
||||
|
||||
let (config, e, _) = self.config.apply_change(config_change);
|
||||
self.config_errors = e.is_empty().not().then_some(e);
|
||||
|
||||
self.config = Arc::new(config);
|
||||
|
||||
self.recreate_crate_graph(cause);
|
||||
|
||||
tracing::info!("did switch workspaces");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue