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