mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Combine krate_ratoml and workspace_ratomls into one
This commit is contained in:
parent
d7bedc85b3
commit
e0b6d2f681
2 changed files with 163 additions and 162 deletions
|
@ -751,6 +751,18 @@ config_data! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RatomlFileKind {
|
||||||
|
Workspace,
|
||||||
|
Crate,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum RatomlFile {
|
||||||
|
Workspace(GlobalLocalConfigInput),
|
||||||
|
Crate(LocalConfigInput),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
discovered_projects: Vec<ProjectManifest>,
|
discovered_projects: Vec<ProjectManifest>,
|
||||||
|
@ -779,11 +791,7 @@ pub struct Config {
|
||||||
/// Config node whose values apply to **every** Rust project.
|
/// Config node whose values apply to **every** Rust project.
|
||||||
user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>,
|
user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>,
|
||||||
|
|
||||||
/// TODO : This file can be used to make global changes while having only a workspace-wide scope.
|
ratoml_file: FxHashMap<SourceRootId, (RatomlFile, ConfigErrors)>,
|
||||||
workspace_ratoml: FxHashMap<SourceRootId, (GlobalLocalConfigInput, ConfigErrors)>,
|
|
||||||
|
|
||||||
/// For every `SourceRoot` there can be at most one RATOML file.
|
|
||||||
krate_ratoml: FxHashMap<SourceRootId, (LocalConfigInput, ConfigErrors)>,
|
|
||||||
|
|
||||||
/// Clone of the value that is stored inside a `GlobalState`.
|
/// Clone of the value that is stored inside a `GlobalState`.
|
||||||
source_root_parent_map: Arc<FxHashMap<SourceRootId, SourceRootId>>,
|
source_root_parent_map: Arc<FxHashMap<SourceRootId, SourceRootId>>,
|
||||||
|
@ -914,83 +922,95 @@ impl Config {
|
||||||
should_update = true;
|
should_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(change) = change.workspace_ratoml_change {
|
if let Some(change) = change.ratoml_file_change {
|
||||||
tracing::info!("updating root ra-toml config");
|
for (source_root_id, (kind, _, text)) in change {
|
||||||
for (source_root_id, (_, text)) in change {
|
match kind {
|
||||||
if let Some(text) = text {
|
RatomlFileKind::Crate => {
|
||||||
let mut toml_errors = vec![];
|
if let Some(text) = text {
|
||||||
match toml::from_str(&text) {
|
let mut toml_errors = vec![];
|
||||||
Ok(table) => {
|
tracing::info!("updating ra-toml config: {:#}", text);
|
||||||
validate_toml_table(
|
match toml::from_str(&text) {
|
||||||
GlobalLocalConfigInput::FIELDS,
|
Ok(table) => {
|
||||||
&table,
|
validate_toml_table(
|
||||||
&mut String::new(),
|
&[LocalConfigInput::FIELDS],
|
||||||
&mut toml_errors,
|
&table,
|
||||||
);
|
&mut String::new(),
|
||||||
config.workspace_ratoml.insert(
|
&mut toml_errors,
|
||||||
source_root_id,
|
);
|
||||||
(
|
config.ratoml_file.insert(
|
||||||
GlobalLocalConfigInput::from_toml(table, &mut toml_errors),
|
source_root_id,
|
||||||
ConfigErrors(
|
(
|
||||||
toml_errors
|
RatomlFile::Crate(LocalConfigInput::from_toml(
|
||||||
.into_iter()
|
&table,
|
||||||
.map(|(a, b)| ConfigErrorInner::Toml {
|
&mut toml_errors,
|
||||||
config_key: a,
|
)),
|
||||||
error: b,
|
ConfigErrors(
|
||||||
})
|
toml_errors
|
||||||
.map(Arc::new)
|
.into_iter()
|
||||||
.collect(),
|
.map(|(a, b)| ConfigErrorInner::Toml {
|
||||||
),
|
config_key: a,
|
||||||
),
|
error: b,
|
||||||
);
|
})
|
||||||
should_update = true;
|
.map(Arc::new)
|
||||||
}
|
.collect(),
|
||||||
Err(e) => {
|
),
|
||||||
config.validation_errors.0.push(
|
),
|
||||||
ConfigErrorInner::ParseError { reason: e.message().to_owned() }
|
);
|
||||||
.into(),
|
}
|
||||||
);
|
Err(e) => {
|
||||||
|
config.validation_errors.0.push(
|
||||||
|
ConfigErrorInner::ParseError {
|
||||||
|
reason: e.message().to_owned(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
RatomlFileKind::Workspace => {
|
||||||
}
|
if let Some(text) = text {
|
||||||
}
|
let mut toml_errors = vec![];
|
||||||
|
match toml::from_str(&text) {
|
||||||
if let Some(change) = change.ratoml_file_change {
|
Ok(table) => {
|
||||||
for (source_root_id, (_, text)) in change {
|
validate_toml_table(
|
||||||
if let Some(text) = text {
|
GlobalLocalConfigInput::FIELDS,
|
||||||
let mut toml_errors = vec![];
|
&table,
|
||||||
tracing::info!("updating ra-toml config: {:#}", text);
|
&mut String::new(),
|
||||||
match toml::from_str(&text) {
|
&mut toml_errors,
|
||||||
Ok(table) => {
|
);
|
||||||
validate_toml_table(
|
config.ratoml_file.insert(
|
||||||
&[LocalConfigInput::FIELDS],
|
source_root_id,
|
||||||
&table,
|
(
|
||||||
&mut String::new(),
|
RatomlFile::Workspace(
|
||||||
&mut toml_errors,
|
GlobalLocalConfigInput::from_toml(
|
||||||
);
|
table,
|
||||||
config.krate_ratoml.insert(
|
&mut toml_errors,
|
||||||
source_root_id,
|
),
|
||||||
(
|
),
|
||||||
LocalConfigInput::from_toml(&table, &mut toml_errors),
|
ConfigErrors(
|
||||||
ConfigErrors(
|
toml_errors
|
||||||
toml_errors
|
.into_iter()
|
||||||
.into_iter()
|
.map(|(a, b)| ConfigErrorInner::Toml {
|
||||||
.map(|(a, b)| ConfigErrorInner::Toml {
|
config_key: a,
|
||||||
config_key: a,
|
error: b,
|
||||||
error: b,
|
})
|
||||||
})
|
.map(Arc::new)
|
||||||
.map(Arc::new)
|
.collect(),
|
||||||
.collect(),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
should_update = true;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
config.validation_errors.0.push(
|
config.validation_errors.0.push(
|
||||||
ConfigErrorInner::ParseError { reason: e.message().to_owned() }
|
ConfigErrorInner::ParseError {
|
||||||
.into(),
|
reason: e.message().to_owned(),
|
||||||
);
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1022,9 +1042,8 @@ impl Config {
|
||||||
.1
|
.1
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.chain(config.workspace_ratoml.values().into_iter().flat_map(|it| it.1 .0.iter()))
|
|
||||||
.chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
|
.chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
|
||||||
.chain(config.krate_ratoml.values().flat_map(|it| it.1 .0.iter()))
|
.chain(config.ratoml_file.values().flat_map(|it| it.1 .0.iter()))
|
||||||
.chain(config.validation_errors.0.iter())
|
.chain(config.validation_errors.0.iter())
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -1052,8 +1071,8 @@ impl Config {
|
||||||
pub struct ConfigChange {
|
pub struct ConfigChange {
|
||||||
user_config_change: Option<Arc<str>>,
|
user_config_change: Option<Arc<str>>,
|
||||||
client_config_change: Option<serde_json::Value>,
|
client_config_change: Option<serde_json::Value>,
|
||||||
workspace_ratoml_change: Option<FxHashMap<SourceRootId, (VfsPath, Option<Arc<str>>)>>,
|
ratoml_file_change:
|
||||||
ratoml_file_change: Option<FxHashMap<SourceRootId, (VfsPath, Option<Arc<str>>)>>,
|
Option<FxHashMap<SourceRootId, (RatomlFileKind, VfsPath, Option<Arc<str>>)>>,
|
||||||
source_map_change: Option<Arc<FxHashMap<SourceRootId, SourceRootId>>>,
|
source_map_change: Option<Arc<FxHashMap<SourceRootId, SourceRootId>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,11 +1082,10 @@ impl ConfigChange {
|
||||||
source_root: SourceRootId,
|
source_root: SourceRootId,
|
||||||
vfs_path: VfsPath,
|
vfs_path: VfsPath,
|
||||||
content: Option<Arc<str>>,
|
content: Option<Arc<str>>,
|
||||||
) -> Option<(VfsPath, Option<Arc<str>>)> {
|
) -> Option<(RatomlFileKind, VfsPath, Option<Arc<str>>)> {
|
||||||
dbg!("change_ratoml", &vfs_path);
|
|
||||||
self.ratoml_file_change
|
self.ratoml_file_change
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.insert(source_root, (vfs_path, content))
|
.insert(source_root, (RatomlFileKind::Crate, vfs_path, content))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_user_config(&mut self, content: Option<Arc<str>>) {
|
pub fn change_user_config(&mut self, content: Option<Arc<str>>) {
|
||||||
|
@ -1080,11 +1098,10 @@ impl ConfigChange {
|
||||||
source_root: SourceRootId,
|
source_root: SourceRootId,
|
||||||
vfs_path: VfsPath,
|
vfs_path: VfsPath,
|
||||||
content: Option<Arc<str>>,
|
content: Option<Arc<str>>,
|
||||||
) -> Option<(VfsPath, Option<Arc<str>>)> {
|
) -> Option<(RatomlFileKind, VfsPath, Option<Arc<str>>)> {
|
||||||
dbg!("change_workspace", &vfs_path);
|
self.ratoml_file_change
|
||||||
self.workspace_ratoml_change
|
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.insert(source_root, (vfs_path, content))
|
.insert(source_root, (RatomlFileKind::Workspace, vfs_path, content))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_client_config(&mut self, change: serde_json::Value) {
|
pub fn change_client_config(&mut self, change: serde_json::Value) {
|
||||||
|
@ -1346,14 +1363,13 @@ impl Config {
|
||||||
workspace_roots,
|
workspace_roots,
|
||||||
visual_studio_code_version,
|
visual_studio_code_version,
|
||||||
client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
|
client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
|
||||||
krate_ratoml: FxHashMap::default(),
|
|
||||||
default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
|
default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
|
||||||
source_root_parent_map: Arc::new(FxHashMap::default()),
|
source_root_parent_map: Arc::new(FxHashMap::default()),
|
||||||
user_config: None,
|
user_config: None,
|
||||||
user_config_path,
|
user_config_path,
|
||||||
detached_files: Default::default(),
|
detached_files: Default::default(),
|
||||||
validation_errors: Default::default(),
|
validation_errors: Default::default(),
|
||||||
workspace_ratoml: Default::default(),
|
ratoml_file: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1874,7 +1890,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rustfmt(&self, source_root_id: Option<SourceRootId>) -> RustfmtConfig {
|
pub fn rustfmt(&self, source_root_id: Option<SourceRootId>) -> RustfmtConfig {
|
||||||
match &self.rustfmt_overrideCommand(None) {
|
match &self.rustfmt_overrideCommand(source_root_id) {
|
||||||
Some(args) if !args.is_empty() => {
|
Some(args) if !args.is_empty() => {
|
||||||
let mut args = args.clone();
|
let mut args = args.clone();
|
||||||
let command = args.remove(0);
|
let command = args.remove(0);
|
||||||
|
@ -2536,27 +2552,23 @@ macro_rules! _impl_for_config_data {
|
||||||
$($doc)*
|
$($doc)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
$vis fn $field(&self, source_root: Option<SourceRootId>) -> &$ty {
|
$vis fn $field(&self, source_root: Option<SourceRootId>) -> &$ty {
|
||||||
let follow = if stringify!($field) == "assist_emitMustUse" { dbg!("YEY"); true } else {false};
|
let mut source_root = source_root;
|
||||||
let mut current: Option<SourceRootId> = None;
|
while let Some(sr) = source_root {
|
||||||
let mut next: Option<SourceRootId> = source_root;
|
if let Some((file, _)) = self.ratoml_file.get(&sr) {
|
||||||
if follow { dbg!(&self.krate_ratoml);}
|
match file {
|
||||||
while let Some(source_root_id) = next {
|
RatomlFile::Workspace(config) => {
|
||||||
current = next;
|
if let Some(v) = config.local.$field.as_ref() {
|
||||||
next = self.source_root_parent_map.get(&source_root_id).copied();
|
return &v;
|
||||||
if let Some((config, _)) = self.krate_ratoml.get(&source_root_id) {
|
}
|
||||||
if let Some(value) = config.$field.as_ref() {
|
},
|
||||||
return value;
|
RatomlFile::Crate(config) => {
|
||||||
}
|
if let Some(value) = config.$field.as_ref() {
|
||||||
}
|
return value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if let Some(current) = current {
|
|
||||||
if follow { dbg!(&self.workspace_ratoml);}
|
|
||||||
if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
|
|
||||||
if let Some(v) = root_path_ratoml.local.$field.as_ref() {
|
|
||||||
return &v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
source_root = self.source_root_parent_map.get(&sr).copied();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.client_config.0.local.$field.as_ref() {
|
if let Some(v) = self.client_config.0.local.$field.as_ref() {
|
||||||
|
@ -2584,21 +2596,20 @@ macro_rules! _impl_for_config_data {
|
||||||
$($doc)*
|
$($doc)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
$vis fn $field(&self, source_root : Option<SourceRootId>) -> &$ty {
|
$vis fn $field(&self, source_root : Option<SourceRootId>) -> &$ty {
|
||||||
let follow = if stringify!($field) == "rustfmt_extraArgs" { dbg!("YEY"); true } else {false};
|
let mut source_root = source_root;
|
||||||
let mut current: Option<SourceRootId> = None;
|
while let Some(sr) = source_root {
|
||||||
let mut next: Option<SourceRootId> = source_root;
|
if let Some((file, _)) = self.ratoml_file.get(&sr) {
|
||||||
while let Some(source_root_id) = next {
|
match file {
|
||||||
current = next;
|
RatomlFile::Workspace(config) => {
|
||||||
next = self.source_root_parent_map.get(&source_root_id).copied();
|
if let Some(v) = config.global.$field.as_ref() {
|
||||||
}
|
return &v;
|
||||||
|
}
|
||||||
if let Some(current) = current {
|
},
|
||||||
if follow { dbg!(&self.workspace_ratoml);}
|
_ => ()
|
||||||
if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
|
|
||||||
if let Some(v) = root_path_ratoml.global.$field.as_ref() {
|
|
||||||
return &v;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_root = self.source_root_parent_map.get(&sr).copied();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = self.client_config.0.global.$field.as_ref() {
|
if let Some(v) = self.client_config.0.global.$field.as_ref() {
|
||||||
|
@ -3667,21 +3678,7 @@ mod tests {
|
||||||
let (_, e, _) = config.apply_change(change);
|
let (_, e, _) = config.apply_change(change);
|
||||||
expect_test::expect![[r#"
|
expect_test::expect![[r#"
|
||||||
ConfigErrors(
|
ConfigErrors(
|
||||||
[
|
[],
|
||||||
Toml {
|
|
||||||
config_key: "invalid/config/err",
|
|
||||||
error: Error {
|
|
||||||
inner: Error {
|
|
||||||
inner: TomlError {
|
|
||||||
message: "unexpected field",
|
|
||||||
raw: None,
|
|
||||||
keys: [],
|
|
||||||
span: None,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
"#]]
|
"#]]
|
||||||
.assert_debug_eq(&e);
|
.assert_debug_eq(&e);
|
||||||
|
|
|
@ -26,13 +26,10 @@ use triomphe::Arc;
|
||||||
use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs, VfsPath};
|
use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs, VfsPath};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, ConfigChange, ConfigErrors},
|
config::{Config, ConfigChange, ConfigErrors, RatomlFileKind},
|
||||||
diagnostics::{CheckFixes, DiagnosticCollection},
|
diagnostics::{CheckFixes, DiagnosticCollection},
|
||||||
line_index::{LineEndings, LineIndex},
|
line_index::{LineEndings, LineIndex},
|
||||||
lsp::{
|
lsp::{from_proto, to_proto::url_from_abs_path},
|
||||||
from_proto::{self},
|
|
||||||
to_proto::url_from_abs_path,
|
|
||||||
},
|
|
||||||
lsp_ext,
|
lsp_ext,
|
||||||
main_loop::Task,
|
main_loop::Task,
|
||||||
mem_docs::MemDocs,
|
mem_docs::MemDocs,
|
||||||
|
@ -411,27 +408,34 @@ impl GlobalState {
|
||||||
let sr_id = db.file_source_root(file_id);
|
let sr_id = db.file_source_root(file_id);
|
||||||
let sr = db.source_root(sr_id);
|
let sr = db.source_root(sr_id);
|
||||||
|
|
||||||
if workspace_ratoml_paths.contains(&vfs_path) {
|
|
||||||
change.change_workspace_ratoml(
|
|
||||||
sr_id,
|
|
||||||
vfs_path,
|
|
||||||
Some(db.file_text(file_id)),
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !sr.is_library {
|
if !sr.is_library {
|
||||||
if let Some((old_path, old_text)) = change.change_ratoml(
|
let entry = if workspace_ratoml_paths.contains(&vfs_path) {
|
||||||
sr_id,
|
change.change_workspace_ratoml(
|
||||||
vfs_path.clone(),
|
sr_id,
|
||||||
Some(db.file_text(file_id)),
|
vfs_path.clone(),
|
||||||
) {
|
Some(db.file_text(file_id)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
change.change_ratoml(
|
||||||
|
sr_id,
|
||||||
|
vfs_path.clone(),
|
||||||
|
Some(db.file_text(file_id)),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((kind, old_path, old_text)) = entry {
|
||||||
// SourceRoot has more than 1 RATOML files. In this case lexicographically smaller wins.
|
// SourceRoot has more than 1 RATOML files. In this case lexicographically smaller wins.
|
||||||
if old_path < vfs_path {
|
if old_path < vfs_path {
|
||||||
dbg!("HARBIDEN");
|
|
||||||
span!(Level::ERROR, "Two `rust-analyzer.toml` files were found inside the same crate. {vfs_path} has no effect.");
|
span!(Level::ERROR, "Two `rust-analyzer.toml` files were found inside the same crate. {vfs_path} has no effect.");
|
||||||
// Put the old one back in.
|
// Put the old one back in.
|
||||||
change.change_ratoml(sr_id, old_path, old_text);
|
match kind {
|
||||||
|
RatomlFileKind::Crate => {
|
||||||
|
change.change_ratoml(sr_id, old_path, old_text);
|
||||||
|
}
|
||||||
|
RatomlFileKind::Workspace => {
|
||||||
|
change.change_workspace_ratoml(sr_id, old_path, old_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue