use std::path::Path;
use std::sync::Arc;
use ktrs_editorconfig::{
AnyPropertyType, Cache, EditorConfig as Ec4jEditorConfig, ParseException, PropertyTypeRegistry,
PropertyValue,
};
use crate::editorconfig::{EditorConfigProperty, PropertyRef, PropertyValueType};
use crate::engine::editor_config_cache::THREAD_SAFE_EDITOR_CONFIG_CACHE;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct EditorConfigDefaults {
pub value: Arc<Ec4jEditorConfig>,
}
impl EditorConfigDefaults {
pub fn empty() -> EditorConfigDefaults {
EditorConfigDefaults::default()
}
pub fn load(
path: Option<&Path>,
property_types: &[&'static dyn AnyPropertyType],
) -> Result<EditorConfigDefaults, ParseException> {
let Some(path) = path.filter(|p| !p.to_string_lossy().trim().is_empty()) else {
return Ok(EditorConfigDefaults::empty());
};
let editor_config_file_path = if path.is_dir() {
path.join(".editorconfig")
} else {
path.to_path_buf()
};
if !editor_config_file_path.exists() {
return Ok(EditorConfigDefaults::empty());
}
let registry = PropertyTypeRegistry::with_defaults(property_types.iter().copied());
Ok(EditorConfigDefaults {
value: THREAD_SAFE_EDITOR_CONFIG_CACHE.get(&editor_config_file_path, ®istry)?,
})
}
}
#[derive(Clone, Debug, Default)]
pub struct EditorConfigOverride {
properties: Vec<(PropertyRef, PropertyValue<()>)>,
}
impl EditorConfigOverride {
pub fn empty() -> EditorConfigOverride {
EditorConfigOverride::default()
}
pub fn properties(&self) -> &[(PropertyRef, PropertyValue<()>)] {
&self.properties
}
pub fn is_empty(&self) -> bool {
self.properties.is_empty()
}
pub fn get(&self, property: &PropertyRef) -> Option<&PropertyValue<()>> {
self.properties
.iter()
.find(|(p, _)| p.identity() == property.identity())
.map(|(_, v)| v)
}
fn add(&mut self, property: PropertyRef, value: Option<&str>) {
let parsed = property.parse(value);
match self
.properties
.iter_mut()
.find(|(p, _)| p.identity() == property.identity())
{
Some(entry) => entry.1 = parsed,
None => self.properties.push((property, parsed)),
}
}
pub fn from(properties: Vec<(PropertyRef, Option<String>)>) -> EditorConfigOverride {
assert!(
!properties.is_empty(),
"IllegalArgumentException: Can not create an EditorConfigOverride without properties. Use 'emptyEditorConfigOverride' instead."
);
let mut editor_config_override = EditorConfigOverride::default();
properties
.into_iter()
.for_each(|(p, v)| editor_config_override.add(p, v.as_deref()));
editor_config_override
}
pub fn plus(&self, properties: Vec<(PropertyRef, Option<String>)>) -> EditorConfigOverride {
assert!(
!properties.is_empty(),
"IllegalArgumentException: Can not add EditorConfigOverride without properties."
);
let mut editor_config_override = self.clone();
properties
.into_iter()
.for_each(|(p, v)| editor_config_override.add(p, v.as_deref()));
editor_config_override
}
pub fn with<T: PropertyValueType>(
&self,
property: &'static EditorConfigProperty<T>,
value: T,
) -> EditorConfigOverride {
let mut editor_config_override = self.clone();
editor_config_override.add(property.into(), Some(&value.to_value_string()));
editor_config_override
}
}