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
use std::{fmt::Display, path::PathBuf};

use crate::filesystem::FileSystem;
use rustc_lint::{LateContext, LintContext};
use rustc_span::Span;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RawLoc {
    pub filename: rustc_span::FileName,
    pub lines: Vec<rustc_span::LineInfo>,
}

unsafe impl Send for RawLoc {}

impl RawLoc {
    pub fn new<'a>(ctx: &LateContext<'a>, span: Span) -> Self {
        let sess = ctx.sess();
        let source_map = sess.source_map();
        let lines = source_map.span_to_lines(span).expect("").lines;
        let filename = source_map.span_to_filename(span);
        Self { lines, filename }
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Loc(PathBuf, String);

impl Loc {
    pub fn path(&self) -> &PathBuf {
        &self.0
    }

    pub fn fn_name(&self) -> &str {
        self.1.split("::").last().unwrap()
    }
    pub fn full_fn_name(&self) -> &str {
        &self.1
    }
    pub fn file_name(&self) -> String {
        let split_str = self.1.split("::");
        let mut split_as_vec = split_str.collect::<Vec<&str>>();
        split_as_vec.pop();
        let new_str = split_as_vec.join("::");
        let new_str_cloned = new_str.clone();
        new_str_cloned
    }
    pub fn read_source<S: FileSystem>(&self, fs: &S) -> Result<String, S::FSError> {
        fs.read(&self.0)
    }

    pub fn write_source<S: FileSystem>(&self, fs: &S, str: &str) -> Result<(), S::FSError> {
        fs.write(&self.0, str.as_bytes())
    }
}

impl Display for Loc {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}:{}", self.0.to_str().unwrap(), self.1)
    }
}

impl From<(RawLoc, string_cache::DefaultAtom)> for Loc {
    fn from((loc, name): (RawLoc, string_cache::DefaultAtom)) -> Self {
        match loc.filename {
            rustc_span::FileName::Real(path) => {
                Loc(path.local_path().unwrap().into(), format!("{}", name))
            }
            _ => panic!("unsupported source location"),
        }
    }
}