qlty_analysis/code/
line_index.rs1use std::{
2 collections::{HashMap, HashSet},
3 ops::RangeInclusive,
4 path::{Path, PathBuf},
5};
6
7type LineNumber = u32;
8
9#[derive(Debug, Default, Clone)]
10pub struct FileInfo {
11 pub new_file: bool,
12 pub line_numbers: HashSet<LineNumber>,
13}
14
15impl FileInfo {
16 pub fn insert(&mut self, line_number: LineNumber) {
17 self.line_numbers.insert(line_number);
18 }
19}
20
21#[derive(Debug, Default, Clone)]
22pub struct FileIndex {
23 inner: HashMap<PathBuf, FileInfo>,
24}
25
26impl FileIndex {
27 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub fn insert_line(&mut self, path: &Path, line_number: LineNumber) {
32 if !self.inner.contains_key(path) {
33 self.inner.insert(
34 path.to_path_buf(),
35 FileInfo {
36 new_file: false,
37 line_numbers: HashSet::new(),
38 },
39 );
40 }
41
42 self.inner.get_mut(path).unwrap().insert(line_number);
43 }
44
45 pub fn insert_file(&mut self, path: &Path) {
46 if !self.inner.contains_key(path) {
47 self.inner.insert(
48 path.to_path_buf(),
49 FileInfo {
50 new_file: true,
51 line_numbers: HashSet::new(),
52 },
53 );
54 }
55 }
56
57 pub fn matches_path(&self, path: &Path) -> bool {
58 self.inner.contains_key(path)
59 }
60
61 pub fn matches_line_range(
63 &self,
64 path: &Path,
65 line_numbers: RangeInclusive<LineNumber>,
66 ) -> bool {
67 if let Some(file_info) = self.inner.get(path) {
68 if file_info.new_file {
69 return true;
70 }
71
72 for line_number in line_numbers {
73 if file_info.line_numbers.get(&line_number).is_some() {
74 return true;
75 }
76 }
77
78 false
79 } else {
80 false
81 }
82 }
83}