rapx/check/opt/checking/encoding_checking/
string_lowercase.rs1use 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}