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
80
81
82
83
84
85
use crate::lint_fix::LintFix;
use crate::parser::segments::fix::SourceFix;
type LintFixIdx = usize;
/// For a given fix anchor, count of the fix edit types and fixes for it."""
#[derive(Debug, 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<LintFixIdx>,
}
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() {
if let LintFix::Replace { edit, .. } = &fix
&& !edit.is_empty()
{
self.source_fixes.extend(edit[0].get_source_fixes());
}
if let Some(_first_replace) = &self.first_replace {
unimplemented!();
}
}
if matches!(fix, LintFix::Replace { .. }) && self.first_replace.is_none() {
self.first_replace = Some(self.fixes.len());
}
match fix {
LintFix::CreateBefore { .. } => self.create_before += 1,
LintFix::CreateAfter { .. } => self.create_after += 1,
LintFix::Replace { .. } => self.replace += 1,
LintFix::Delete { .. } => self.delete += 1,
};
self.fixes.push(fix);
}
}