dprint_plugin_json/configuration/
resolve_config.rs1use super::builder::ConfigurationBuilder;
2use super::types::TrailingCommaKind;
3use super::Configuration;
4use dprint_core::configuration::*;
5
6pub fn resolve_config(
29 config: ConfigKeyMap,
30 global_config: &GlobalConfiguration,
31) -> ResolveConfigurationResult<Configuration> {
32 let mut diagnostics = Vec::new();
33 let mut config = config;
34
35 if get_value(&mut config, "deno", false, &mut diagnostics) {
36 fill_deno_config(&mut config);
37 }
38
39 let prefer_single_line = get_value(&mut config, "preferSingleLine", false, &mut diagnostics);
40
41 let resolved_config = Configuration {
42 line_width: get_value(
43 &mut config,
44 "lineWidth",
45 global_config
46 .line_width
47 .unwrap_or(RECOMMENDED_GLOBAL_CONFIGURATION.line_width),
48 &mut diagnostics,
49 ),
50 use_tabs: get_value(
51 &mut config,
52 "useTabs",
53 global_config
54 .use_tabs
55 .unwrap_or(RECOMMENDED_GLOBAL_CONFIGURATION.use_tabs),
56 &mut diagnostics,
57 ),
58 indent_width: get_value(
59 &mut config,
60 "indentWidth",
61 global_config.indent_width.unwrap_or(2),
62 &mut diagnostics,
63 ),
64 new_line_kind: get_value(
65 &mut config,
66 "newLineKind",
67 global_config
68 .new_line_kind
69 .unwrap_or(RECOMMENDED_GLOBAL_CONFIGURATION.new_line_kind),
70 &mut diagnostics,
71 ),
72 comment_line_force_space_after_slashes: get_value(
73 &mut config,
74 "commentLine.forceSpaceAfterSlashes",
75 true,
76 &mut diagnostics,
77 ),
78 ignore_node_comment_text: get_value(
79 &mut config,
80 "ignoreNodeCommentText",
81 String::from("dprint-ignore"),
82 &mut diagnostics,
83 ),
84 array_prefer_single_line: get_value(
85 &mut config,
86 "array.preferSingleLine",
87 prefer_single_line,
88 &mut diagnostics,
89 ),
90 object_prefer_single_line: get_value(
91 &mut config,
92 "object.preferSingleLine",
93 prefer_single_line,
94 &mut diagnostics,
95 ),
96 trailing_commas: get_value(
97 &mut config,
98 "trailingCommas",
99 TrailingCommaKind::Jsonc,
100 &mut diagnostics,
101 ),
102 json_trailing_comma_files: get_trailing_comma_files(&mut config, "jsonTrailingCommaFiles", &mut diagnostics),
103 };
104
105 diagnostics.extend(get_unknown_property_diagnostics(config));
106
107 ResolveConfigurationResult {
108 config: resolved_config,
109 diagnostics,
110 }
111}
112
113fn fill_deno_config(config: &mut ConfigKeyMap) {
114 for (key, value) in ConfigurationBuilder::new().deno().config.iter() {
115 if !config.contains_key(key) {
116 config.insert(key.clone(), value.clone());
117 }
118 }
119}
120
121fn get_trailing_comma_files(
122 config: &mut ConfigKeyMap,
123 key: &str,
124 diagnostics: &mut Vec<ConfigurationDiagnostic>,
125) -> Vec<String> {
126 let mut entries = Vec::with_capacity(0);
127 if let Some(values) = config.shift_remove(key) {
128 if let ConfigKeyValue::Array(values) = values {
129 entries = Vec::with_capacity(values.len() * 2);
130 for (i, value) in values.into_iter().enumerate() {
131 if let ConfigKeyValue::String(value) = value {
132 if value.starts_with("./") {
133 diagnostics.push(ConfigurationDiagnostic {
134 property_name: key.to_string(),
135 message: format!(
136 "Element at index {} starting with dot slash (./) is not supported. Remove the leading dot slash.",
137 i
138 ),
139 });
140 } else if value.chars().any(|c| matches!(c, '\\' | '/')) {
141 let value = if value.starts_with('/') || value.starts_with('\\') {
142 value
143 } else {
144 format!("/{}", value)
145 };
146 entries.push(value.replace('/', "\\"));
147 entries.push(value.replace('\\', "/"));
148 } else {
149 entries.push(format!("/{}", value));
150 entries.push(format!("\\{}", value));
151 }
152 } else {
153 diagnostics.push(ConfigurationDiagnostic {
154 property_name: key.to_string(),
155 message: format!("Expected element at index {} to be a string.", i),
156 });
157 }
158 }
159 } else {
160 diagnostics.push(ConfigurationDiagnostic {
161 property_name: key.to_string(),
162 message: "Expected an array.".to_string(),
163 });
164 }
165 }
166 entries
167}
168
169#[cfg(test)]
170mod test {
171 use dprint_core::configuration::ConfigKeyMap;
172 use dprint_core::configuration::ConfigKeyValue;
173 use dprint_core::configuration::GlobalConfiguration;
174
175 use super::resolve_config;
176
177 #[test]
178 fn json_trailing_comma_files() {
179 let global_config = GlobalConfiguration::default();
180 {
181 let result = resolve_config(
182 ConfigKeyMap::from([(
183 "jsonTrailingCommaFiles".to_string(),
184 ConfigKeyValue::Array(vec![ConfigKeyValue::String("test.json".to_string())]),
185 )]),
186 &global_config,
187 );
188 assert!(result.diagnostics.is_empty());
189 assert_eq!(
190 result.config.json_trailing_comma_files,
191 vec!["/test.json".to_string(), "\\test.json".to_string(),]
192 );
193 }
194 {
195 let result = resolve_config(
196 ConfigKeyMap::from([(
197 "jsonTrailingCommaFiles".to_string(),
198 ConfigKeyValue::Array(vec![ConfigKeyValue::String("./test.json".to_string())]),
199 )]),
200 &global_config,
201 );
202 assert_eq!(
203 result.diagnostics[0].message,
204 "Element at index 0 starting with dot slash (./) is not supported. Remove the leading dot slash."
205 );
206 }
207 {
208 let result = resolve_config(
209 ConfigKeyMap::from([(
210 "jsonTrailingCommaFiles".to_string(),
211 ConfigKeyValue::Array(vec![ConfigKeyValue::Number(5)]),
212 )]),
213 &global_config,
214 );
215 assert_eq!(
216 result.diagnostics[0].message,
217 "Expected element at index 0 to be a string."
218 );
219 }
220 }
221}