use serde::Deserialize;
use super::linter_rule_options::{ConfigLintRuleOptions, LintRuleOptions};
use super::{
compiler::{RawCompilerConfig, RawTemplateSyntaxConfig},
linter::{LintRuleSeverity, LinterConfig, RawLinterConfig},
};
use crate::String;
#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default, rename_all = "camelCase")]
pub(crate) struct RawConfigEntry {
pub base_path: Option<String>,
pub files: Option<Vec<String>>,
pub ignores: Option<Vec<String>>,
pub compiler: RawCompilerConfig,
pub linter: RawLinterConfig,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConfigEntryIgnore {
pub base_path: Option<String>,
pub pattern: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConfigEntryFiles {
pub base_path: Option<String>,
pub files: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompilerConfigEntry {
pub base_path: Option<String>,
pub files: Option<Vec<String>>,
pub ignores: Vec<String>,
pub template_syntax: Option<&'static str>,
pub whitespace: Option<String>,
pub vapor: Option<bool>,
pub custom_elements: Vec<String>,
}
impl CompilerConfigEntry {
pub(crate) fn from_raw(entry: &RawConfigEntry) -> Self {
Self {
base_path: entry.base_path.clone(),
files: entry.files.clone(),
ignores: entry.ignores.clone().unwrap_or_default(),
template_syntax: entry
.compiler
.template_syntax
.map(RawTemplateSyntaxConfig::as_str),
whitespace: entry.compiler.whitespace.as_deref().map(String::from),
vapor: entry.compiler.vapor,
custom_elements: entry.compiler.custom_elements.clone(),
}
}
pub(crate) fn has_overrides(&self) -> bool {
self.template_syntax.is_some()
|| self.whitespace.is_some()
|| self.vapor.is_some()
|| !self.custom_elements.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LinterConfigEntry {
pub base_path: Option<String>,
pub files: Option<Vec<String>>,
pub ignores: Vec<String>,
pub rules: crate::FxHashMap<String, LintRuleSeverity>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct LinterConfigPlan {
pub base: LinterConfig,
pub entries: Vec<LinterConfigEntry>,
pub global_ignores: Vec<ConfigEntryIgnore>,
pub rule_options: LintRuleOptions,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ResolvedLinterConfig {
pub config: LinterConfig,
pub rule_options: LintRuleOptions,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct LinterConfigPlanWithRuleOptions {
pub plan: LinterConfigPlan,
pub entry_rule_options: Vec<LintRuleOptions>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ResolvedLinterConfigWithConfigRuleOptions {
pub config: LinterConfig,
pub rule_options: ConfigLintRuleOptions,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct LinterConfigPlanWithConfigRuleOptions {
pub plan: LinterConfigPlan,
pub rule_options: ConfigLintRuleOptions,
pub entry_rule_options: Vec<ConfigLintRuleOptions>,
}
impl From<LinterConfigPlan> for LinterConfigPlanWithRuleOptions {
fn from(plan: LinterConfigPlan) -> Self {
let entry_rule_options = vec![LintRuleOptions::default(); plan.entries.len()];
Self {
plan,
entry_rule_options,
}
}
}
impl From<LinterConfigPlan> for LinterConfigPlanWithConfigRuleOptions {
fn from(plan: LinterConfigPlan) -> Self {
let rule_options = ConfigLintRuleOptions::from_stable_options(plan.rule_options.clone());
let entry_rule_options = vec![ConfigLintRuleOptions::default(); plan.entries.len()];
Self {
plan,
rule_options,
entry_rule_options,
}
}
}
impl LinterConfigPlan {
pub fn resolve_matching_entries(&self, matching_entries: &[usize]) -> LinterConfig {
let mut resolved = self.base.clone();
let mut matches = vec![false; self.entries.len()];
for index in matching_entries {
if let Some(value) = matches.get_mut(*index) {
*value = true;
}
}
for (matches, entry) in matches.into_iter().zip(&self.entries) {
if matches {
resolved.rules.extend(entry.rules.clone());
}
}
resolved
}
}
impl LinterConfigPlanWithRuleOptions {
pub fn resolve_matching_entries(&self, matching_entries: &[usize]) -> ResolvedLinterConfig {
let mut rule_options = self.plan.rule_options.clone();
let mut matches = vec![false; self.plan.entries.len()];
for index in matching_entries {
if let Some(value) = matches.get_mut(*index) {
*value = true;
}
}
for (index, matches) in matches.into_iter().enumerate() {
if matches && let Some(options) = self.entry_rule_options.get(index) {
rule_options.merge_from(options);
}
}
ResolvedLinterConfig {
config: self.plan.resolve_matching_entries(matching_entries),
rule_options,
}
}
}
impl LinterConfigPlanWithConfigRuleOptions {
pub fn resolve_matching_entries(
&self,
matching_entries: &[usize],
) -> ResolvedLinterConfigWithConfigRuleOptions {
let mut rule_options = self.rule_options.clone();
let mut matches = vec![false; self.plan.entries.len()];
for index in matching_entries {
if let Some(value) = matches.get_mut(*index) {
*value = true;
}
}
for (index, matches) in matches.into_iter().enumerate() {
if matches && let Some(options) = self.entry_rule_options.get(index) {
rule_options.merge_from(options);
}
}
ResolvedLinterConfigWithConfigRuleOptions {
config: self.plan.resolve_matching_entries(matching_entries),
rule_options,
}
}
}