use crate::scan_cache::build_and_record;
use evenframe_core::{
config::{
EvenframeConfig,
workspace::{Focus, Project, Workspace},
},
error::Result,
scan::ScanConfig,
types::{AllConfigs, merge_foreign_types, merge_project_types},
};
pub enum Target {
Project(EvenframeConfig),
Workspace(Workspace),
}
pub struct Scanned<'a> {
pub name: &'a str,
pub config: &'a EvenframeConfig,
pub types: AllConfigs,
}
impl Target {
pub fn discover() -> Result<Self> {
Ok(match Workspace::discover(false)? {
Some(workspace) => Self::Workspace(workspace),
None => Self::Project(EvenframeConfig::new_offline()?),
})
}
pub fn focused(&self) -> Vec<(&str, &EvenframeConfig)> {
match self {
Self::Project(config) => vec![("", config)],
Self::Workspace(workspace) => workspace.focused().map(named).collect(),
}
}
pub fn covers_workspace(&self) -> bool {
matches!(self, Self::Workspace(workspace) if workspace.focus == Focus::All)
}
fn all(&self) -> Vec<(&str, &EvenframeConfig)> {
match self {
Self::Project(config) => vec![("", config)],
Self::Workspace(workspace) => workspace.projects.iter().map(named).collect(),
}
}
pub fn scan_all(&self) -> Result<Vec<Scanned<'_>>> {
Self::scan(self.all())
}
pub fn scan_focused(&self) -> Result<Vec<Scanned<'_>>> {
Self::scan(self.focused())
}
fn scan<'a>(projects: Vec<(&'a str, &'a EvenframeConfig)>) -> Result<Vec<Scanned<'a>>> {
projects
.into_iter()
.map(|(name, config)| {
Ok(Scanned {
name,
config,
types: build_and_record(&ScanConfig::from_config(config))?,
})
})
.collect()
}
pub fn typesync_input(&self, scanned: &[Scanned<'_>]) -> Result<(EvenframeConfig, AllConfigs)> {
let mut config = match self {
Self::Project(config) => config.clone(),
Self::Workspace(workspace) => workspace.config.clone(),
};
config.general.foreign_types = merge_foreign_types(
scanned
.iter()
.map(|project| (project.name, &project.config.general.foreign_types)),
)?;
let types = merge_project_types(
scanned
.iter()
.map(|project| (project.name, project.types.clone())),
)?;
Ok((config, types))
}
}
fn named(project: &Project) -> (&str, &EvenframeConfig) {
(project.name.as_str(), &project.config)
}