Skip to content

Commit 375eefb

Browse files
committed
Don't add default fields when automatically editing .emmyrc.json
Right now, `disable_code` and `add_doc_tag` commands load `.emmyrc.json` into an `EmmyRc` object, change it, and then write it back. This results in serialization of all possible fields, even those that were missing in the original JSON file. This behaviour might cause an issue if these newly serialized fields shadow those configured in a global `.emmyrc.json`. This PR changes edit logic to avoid creating full `EmmyRc` object. Instead, it parses `.emmyrc.json` into a `Value`, modifies it directly, and dumps it back. This way, only fields requested by the user are injected, and nothing else.
1 parent 5e7c78e commit 375eefb

File tree

4 files changed

+46
-40
lines changed

4 files changed

+46
-40
lines changed

crates/emmylua_code_analysis/src/config/config_loader.rs

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::read_file_with_encoding;
66

77
use super::{Emmyrc, flatten_config::FlattenConfigObject};
88

9-
pub fn load_configs(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<Value>>) -> Emmyrc {
9+
pub fn load_configs_raw(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<Value>>) -> Value {
1010
let mut config_jsons = Vec::new();
1111

1212
for config_file in config_files {
@@ -45,26 +45,15 @@ pub fn load_configs(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<Valu
4545

4646
if config_jsons.is_empty() {
4747
log::info!("No valid config file found.");
48-
Emmyrc::default()
48+
Value::Object(Default::default())
4949
} else if config_jsons.len() == 1 {
50-
let first_config = match config_jsons.into_iter().next() {
51-
Some(config) => config,
52-
None => {
53-
log::error!("No valid config file found.");
54-
return Emmyrc::default();
55-
}
56-
};
50+
let first_config = config_jsons.into_iter().next().unwrap_or_else(|| {
51+
log::error!("No valid config file found.");
52+
Value::Object(Default::default())
53+
});
5754

5855
let flatten_config = FlattenConfigObject::parse(first_config);
59-
let emmyrc_json_value = flatten_config.to_emmyrc();
60-
let emmyrc: Emmyrc = match serde_json::from_value(emmyrc_json_value) {
61-
Ok(config) => config,
62-
Err(err) => {
63-
log::error!("Failed to parse config, error: {:?}", err);
64-
Emmyrc::default()
65-
}
66-
};
67-
emmyrc
56+
flatten_config.to_emmyrc()
6857
} else {
6958
let merge_config =
7059
config_jsons
@@ -74,18 +63,18 @@ pub fn load_configs(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<Valu
7463
acc
7564
});
7665
let flatten_config = FlattenConfigObject::parse(merge_config.clone());
77-
let emmyrc_json_value = flatten_config.to_emmyrc();
78-
let emmyrc: Emmyrc = match serde_json::from_value(emmyrc_json_value) {
79-
Ok(config) => config,
80-
Err(err) => {
81-
log::error!("Failed to parse config: error: {:?}", err);
82-
Emmyrc::default()
83-
}
84-
};
85-
emmyrc
66+
flatten_config.to_emmyrc()
8667
}
8768
}
8869

70+
pub fn load_configs(config_files: Vec<PathBuf>, partial_emmyrcs: Option<Vec<Value>>) -> Emmyrc {
71+
let emmyrc_json_value = load_configs_raw(config_files, partial_emmyrcs);
72+
serde_json::from_value(emmyrc_json_value).unwrap_or_else(|err| {
73+
log::error!("Failed to parse config: error: {:?}", err);
74+
Emmyrc::default()
75+
})
76+
}
77+
8978
fn merge_values(base: &mut Value, overlay: Value) {
9079
match (base, overlay) {
9180
(Value::Object(base_map), Value::Object(overlay_map)) => {

crates/emmylua_code_analysis/src/config/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ use std::{
77
path::{Path, PathBuf},
88
};
99

10-
pub use config_loader::load_configs;
11-
pub use configs::EmmyrcFilenameConvention;
12-
pub use configs::EmmyrcLuaVersion;
13-
use configs::{EmmyrcCodeAction, EmmyrcDocumentColor};
10+
pub use config_loader::{load_configs, load_configs_raw};
1411
use configs::{
15-
EmmyrcCodeLen, EmmyrcCompletion, EmmyrcDiagnostic, EmmyrcDoc, EmmyrcHover, EmmyrcInlayHint,
16-
EmmyrcInlineValues, EmmyrcReference, EmmyrcResource, EmmyrcRuntime, EmmyrcSemanticToken,
17-
EmmyrcSignature, EmmyrcStrict, EmmyrcWorkspace,
12+
EmmyrcCodeAction, EmmyrcCodeLen, EmmyrcCompletion, EmmyrcDiagnostic, EmmyrcDoc,
13+
EmmyrcDocumentColor, EmmyrcHover, EmmyrcInlayHint, EmmyrcInlineValues, EmmyrcReference,
14+
EmmyrcResource, EmmyrcRuntime, EmmyrcSemanticToken, EmmyrcSignature, EmmyrcStrict,
15+
EmmyrcWorkspace,
1816
};
17+
pub use configs::{EmmyrcFilenameConvention, EmmyrcLuaVersion};
1918
use emmylua_parser::{LuaLanguageLevel, ParserConfig, SpecialFunction};
2019
use regex::Regex;
2120
use rowan::NodeCache;

crates/emmylua_ls/src/handlers/command/commands/emmy_add_doc_tag.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{fs::OpenOptions, io::Write, sync::Arc};
22

3-
use emmylua_code_analysis::load_configs;
3+
use emmylua_code_analysis::load_configs_raw;
44
use lsp_types::Command;
55
use serde_json::Value;
66
use tokio::sync::RwLock;
@@ -38,10 +38,19 @@ async fn add_doc_tag(
3838
let config_manager = config_manager.read().await;
3939
let main_workspace = config_manager.workspace_folders.get(0)?;
4040
let emmyrc_path = main_workspace.join(".emmyrc.json");
41-
let mut emmyrc = load_configs(vec![emmyrc_path.clone()], None);
42-
emmyrc.doc.known_tags.push(tag_name);
41+
let mut emmyrc = load_configs_raw(vec![emmyrc_path.clone()], None);
4342
drop(config_manager);
4443

44+
emmyrc
45+
.as_object_mut()?
46+
.entry("doc")
47+
.or_insert_with(|| Value::Object(Default::default()))
48+
.as_object_mut()?
49+
.entry("knownTags")
50+
.or_insert_with(|| Value::Array(Default::default()))
51+
.as_array_mut()?
52+
.push(Value::String(tag_name));
53+
4554
let emmyrc_json = serde_json::to_string_pretty(&emmyrc).ok()?;
4655
if let Ok(mut file) = OpenOptions::new()
4756
.write(true)

crates/emmylua_ls/src/handlers/command/commands/emmy_disable_code.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{fs::OpenOptions, io::Write, sync::Arc};
22

3-
use emmylua_code_analysis::{DiagnosticCode, FileId, load_configs};
3+
use emmylua_code_analysis::{DiagnosticCode, FileId, load_configs_raw};
44
use lsp_types::{Command, Range};
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
@@ -66,10 +66,19 @@ async fn add_disable_project(
6666
let config_manager = config_manager.read().await;
6767
let main_workspace = config_manager.workspace_folders.get(0)?;
6868
let emmyrc_path = main_workspace.join(".emmyrc.json");
69-
let mut emmyrc = load_configs(vec![emmyrc_path.clone()], None);
70-
emmyrc.diagnostics.disable.push(code);
69+
let mut emmyrc = load_configs_raw(vec![emmyrc_path.clone()], None);
7170
drop(config_manager);
7271

72+
emmyrc
73+
.as_object_mut()?
74+
.entry("diagnostics")
75+
.or_insert_with(|| Value::Object(Default::default()))
76+
.as_object_mut()?
77+
.entry("disable")
78+
.or_insert_with(|| Value::Array(Default::default()))
79+
.as_array_mut()?
80+
.push(Value::String(code.to_string()));
81+
7382
let emmyrc_json = serde_json::to_string_pretty(&emmyrc).ok()?;
7483
if let Ok(mut file) = OpenOptions::new()
7584
.write(true)

0 commit comments

Comments
 (0)