Skip to main content

rapx/check/opt/checking/encoding_checking/
string_lowercase.rs

1use annotate_snippets::Level;
2
3use rustc_hir::intravisit;
4use rustc_middle::ty::TyCtxt;
5use rustc_span::Span;
6
7use crate::analysis::dataflow::Graph;
8use crate::check::opt::OptCheck;
9use crate::check::opt::loop_visitors::MethodCallFinder;
10
11use crate::check::opt::report::OptReport;
12
13crate::def_paths! {
14    string_to_lowercase: "str::to_lowercase",
15}
16
17pub struct StringLowercaseCheck {
18    record: Vec<Span>,
19}
20
21impl OptCheck for StringLowercaseCheck {
22    fn new() -> Self {
23        Self { record: Vec::new() }
24    }
25
26    fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
27        DEFPATHS.get_or_init(|| DefPaths::new(tcx));
28        let def_id = graph.def_id;
29        let body = tcx.hir_body_owned_by(def_id.as_local().unwrap());
30        let typeck_results = tcx.typeck(def_id.as_local().unwrap());
31        let target_def_id = DEFPATHS.get().unwrap().string_to_lowercase.last_def_id();
32        let mut finder = MethodCallFinder::new(typeck_results, target_def_id);
33        intravisit::walk_body(&mut finder, body);
34        self.record = finder.into_record();
35    }
36
37    fn report(&self, graph: &Graph) {
38        for contains_span in self.record.iter() {
39            report_string_ascii_bug(graph, *contains_span);
40        }
41    }
42
43    fn cnt(&self) -> usize {
44        self.record.len()
45    }
46}
47
48fn report_string_ascii_bug(graph: &Graph, contains_span: Span) {
49    OptReport::from_graph(graph)
50        .title("Unnecessary encoding checkings detected.")
51        .annotate(Level::Error, contains_span, "Checked here.")
52        .footer("Use to_ascii_lowercase instead.")
53        .emit();
54}