sqruff_lib_core/segments.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
use crate::edit_type::EditType;
use crate::lint_fix::LintFix;
use crate::parser::segments::fix::SourceFix;
/// For a given fix anchor, count of the fix edit types and fixes for it."""
#[derive(Debug, Clone, Default)]
pub struct AnchorEditInfo {
pub delete: usize,
pub replace: usize,
pub create_before: usize,
pub create_after: usize,
pub fixes: Vec<LintFix>,
pub source_fixes: Vec<SourceFix>,
// First fix of edit_type "replace" in "fixes"
pub first_replace: Option<LintFix>,
}
impl AnchorEditInfo {
/// Returns total count of fixes.
#[allow(dead_code)]
fn total(&self) -> usize {
self.delete + self.replace + self.create_before + self.create_after
}
/// Returns True if valid combination of fixes for anchor.
///
/// Cases:
/// * 0-1 fixes of any type: Valid
/// * 2 fixes: Valid if and only if types are create_before and create_after
#[allow(dead_code)]
fn is_valid(&self) -> bool {
let total = self.total();
if total <= 1 {
// Definitely valid (i.e. no conflict) if 0 or 1. In practice, this
// function probably won't be called if there are 0 fixes, but 0 is
// valid; it simply means "no fixes to apply".
true
} else if total == 2 {
// This is only OK for this special case. We allow this because
// the intent is clear (i.e. no conflict): Insert something *before*
// the segment and something else *after* the segment.
self.create_before == 1 && self.create_after == 1
} else {
// Definitely bad if > 2.
false
}
}
/// Adds the fix and updates stats.
///
/// We also allow potentially multiple source fixes on the same anchor by
/// condensing them together here.
pub fn add(&mut self, fix: LintFix) {
if self.fixes.contains(&fix) {
// Deduplicate fixes in case it's already in there.
return;
};
if fix.is_just_source_edit() {
let edit = fix.edit.as_ref().unwrap();
self.source_fixes.extend(edit[0].get_source_fixes());
if let Some(_first_replace) = &self.first_replace {
unimplemented!();
}
}
self.fixes.push(fix.clone());
if fix.edit_type == EditType::Replace && self.first_replace.is_none() {
self.first_replace = Some(fix.clone());
}
match fix.edit_type {
EditType::CreateBefore => self.create_before += 1,
EditType::CreateAfter => self.create_after += 1,
EditType::Replace => self.replace += 1,
EditType::Delete => self.delete += 1,
};
}
}