use std::collections::HashMap;
use serde_yml::Value;
use crate::cop::{CopConfig, EnabledState};
use super::ResolvedConfig;
pub(crate) fn inject_f64(opts: &mut HashMap<String, Value>, key: &str, val: Option<f64>) {
if let Some(v) = val {
opts.entry(key.to_string())
.or_insert_with(|| Value::Number(serde_yml::Number::from(v)));
}
}
pub(crate) fn inject_bool(opts: &mut HashMap<String, Value>, key: &str, val: bool) {
opts.entry(key.to_string())
.or_insert_with(|| Value::Bool(val));
}
pub(crate) fn inject_sibling_str(
opts: &mut HashMap<String, Value>,
configs: &HashMap<String, CopConfig>,
sibling: &str,
sibling_key: &str,
dest_key: &str,
default: &str,
) {
let style = configs
.get(sibling)
.and_then(|cc| cc.options.get(sibling_key))
.and_then(|v| v.as_str())
.unwrap_or(default);
opts.entry(dest_key.to_string())
.or_insert_with(|| Value::String(style.to_string()));
}
pub(crate) fn sibling_enabled(
configs: &HashMap<String, CopConfig>,
sibling: &str,
) -> bool {
configs
.get(sibling)
.map(|cc| !matches!(cc.enabled, EnabledState::False))
.unwrap_or(true)
}
pub(crate) fn inject_globals(cfg: &ResolvedConfig, config: &mut CopConfig) {
inject_f64(
&mut config.options,
"TargetRubyVersion",
cfg.target_ruby_version,
);
inject_f64(
&mut config.options,
"TargetRailsVersion",
cfg.target_rails_version,
);
inject_bool(
&mut config.options,
"__RailtiesInLockfile",
cfg.railties_in_lockfile,
);
inject_f64(
&mut config.options,
"__RailtiesVersion",
cfg.railties_version,
);
}
pub(crate) fn inject_rack_version(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if !matches!(
name,
"Rails/HttpStatusNameConsistency" | "RSpecRails/HttpStatusNameConsistency"
) {
return;
}
inject_f64(&mut config.options, "__RackVersion", cfg.rack_version);
}
const LINE_LENGTH_COPS: &[&str] = &[
"Style/IfUnlessModifier",
"Style/WhileUntilModifier",
"Style/ConditionalAssignment",
"Style/GuardClause",
"Style/SoleNestedConditional",
"Style/MultilineMethodSignature",
"Layout/RedundantLineBreak",
];
pub(crate) fn inject_line_length(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if !LINE_LENGTH_COPS.contains(&name) {
return;
}
let ll = cfg.cop_configs.get("Layout/LineLength");
inject_line_length_max(ll, config);
inject_line_length_enabled(ll, config);
}
fn inject_line_length_max(ll: Option<&CopConfig>, config: &mut CopConfig) {
if config.options.contains_key("MaxLineLength") {
return;
}
config.options.insert(
"MaxLineLength".to_string(),
Value::Number(serde_yml::Number::from(
ll.and_then(|cc| cc.options.get("Max"))
.and_then(|v| v.as_u64())
.unwrap_or(120),
)),
);
}
fn inject_line_length_enabled(ll: Option<&CopConfig>, config: &mut CopConfig) {
if config.options.contains_key("LineLengthEnabled") {
return;
}
config.options.insert(
"LineLengthEnabled".to_string(),
Value::Bool(
ll.map(|cc| !matches!(cc.enabled, EnabledState::False))
.unwrap_or(true),
),
);
}
pub(crate) fn inject_redundant_line_break(
cfg: &ResolvedConfig,
name: &str,
config: &mut CopConfig,
) {
if name != "Layout/RedundantLineBreak" {
return;
}
if config.options.contains_key("SingleLineBlockChainEnabled") {
return;
}
config.options.insert(
"SingleLineBlockChainEnabled".to_string(),
Value::Bool(sibling_enabled(
&cfg.cop_configs,
"Layout/SingleLineBlockChain",
)),
);
}
const AS_EXTENSION_COPS: &[&str] = &[
"Lint/DuplicateMethods",
"Lint/UselessAccessModifier",
"Style/ArrayIntersect",
"Style/CollectionQuerying",
"Style/RedundantFilterChain",
];
pub(crate) fn inject_active_support(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if !AS_EXTENSION_COPS.contains(&name) {
return;
}
inject_bool(
&mut config.options,
"ActiveSupportExtensionsEnabled",
cfg.active_support_extensions_enabled,
);
}
pub(crate) fn inject_hash_alignment(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/HashAlignment" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/ArgumentAlignment",
"EnforcedStyle",
"ArgumentAlignmentStyle",
"with_first_argument",
);
}
pub(crate) fn inject_first_argument(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/FirstArgumentIndentation" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/ArgumentAlignment",
"EnforcedStyle",
"ArgumentAlignmentStyle",
"with_first_argument",
);
inject_bool(
&mut config.options,
"FirstMethodArgumentLineBreakEnabled",
sibling_enabled(&cfg.cop_configs, "Layout/FirstMethodArgumentLineBreak"),
);
}
fn argument_alignment_fixed(configs: &HashMap<String, CopConfig>) -> bool {
sibling_enabled(configs, "Layout/ArgumentAlignment")
&& configs
.get("Layout/ArgumentAlignment")
.and_then(|cc| cc.options.get("EnforcedStyle"))
.and_then(|v| v.as_str())
== Some("with_fixed_indentation")
}
pub(crate) fn inject_first_hash_indent(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/FirstHashElementIndentation" {
return;
}
for (key, default) in [
("EnforcedColonStyle", "key"),
("EnforcedHashRocketStyle", "key"),
] {
config
.options
.entry(key.to_string())
.or_insert(
cfg.cop_configs
.get("Layout/HashAlignment")
.and_then(|cc| cc.options.get(key))
.cloned()
.unwrap_or_else(|| Value::String(default.to_string())),
);
}
inject_bool(
&mut config.options,
"FixedArgumentIndentation",
argument_alignment_fixed(&cfg.cop_configs),
);
}
pub(crate) fn inject_end_alignment(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/ElseAlignment" && name != "Layout/IndentationWidth" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/EndAlignment",
"EnforcedStyleAlignWith",
"EndAlignmentStyle",
"keyword",
);
}
pub(crate) fn inject_rescue_ensure_alignment(
cfg: &ResolvedConfig,
name: &str,
config: &mut CopConfig,
) {
if name != "Layout/RescueEnsureAlignment" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/BeginEndAlignment",
"EnforcedStyleAlignWith",
"BeginEndAlignmentStyle",
"begin",
);
inject_bool(
&mut config.options,
"BeginEndAlignmentEnabled",
sibling_enabled(&cfg.cop_configs, "Layout/BeginEndAlignment"),
);
}
pub(crate) fn inject_indentation_width(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/IndentationWidth" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/IndentationConsistency",
"EnforcedStyle",
"IndentationConsistencyStyle",
"normal",
);
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/AccessModifierIndentation",
"EnforcedStyle",
"AccessModifierIndentationStyle",
"indent",
);
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/IndentationStyle",
"EnforcedStyle",
"IndentationStyleEnforced",
"spaces",
);
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/DefEndAlignment",
"EnforcedStyleAlignWith",
"DefEndAlignmentStyle",
"start_of_line",
);
}
pub(crate) fn inject_space_after_comma(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Layout/SpaceAfterComma" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Layout/SpaceInsideHashLiteralBraces",
"EnforcedStyle",
"__SpaceInsideHashBracesStyle",
"space",
);
}
pub(crate) fn inject_missing_else(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Style/MissingElse" {
return;
}
inject_bool(
&mut config.options,
"UnlessElseEnabled",
sibling_enabled(&cfg.cop_configs, "Style/UnlessElse"),
);
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Style/EmptyElse",
"EnforcedStyle",
"EmptyElseStyle",
"both",
);
}
pub(crate) fn inject_quoted_symbols(cfg: &ResolvedConfig, name: &str, config: &mut CopConfig) {
if name != "Style/QuotedSymbols" {
return;
}
inject_sibling_str(
&mut config.options,
&cfg.cop_configs,
"Style/StringLiterals",
"EnforcedStyle",
"StringLiteralsEnforcedStyle",
"single_quotes",
);
}
pub(crate) fn inject_config_disabled_cops(
cfg: &ResolvedConfig,
name: &str,
config: &mut CopConfig,
) {
if name != "Lint/RedundantCopEnableDirective" {
return;
}
config
.options
.entry("ConfigDisabledCops".into())
.or_insert(Value::Sequence(
cfg.cop_configs
.iter()
.filter(|(_, c)| matches!(c.enabled, EnabledState::False))
.map(|(n, _)| Value::String(n.clone()))
.collect(),
));
}