rapx/analysis/core/api_dependency/
visitor.rs1use super::graph::ApiDependencyGraph;
2use super::graph::{DepEdge, DepNode};
3use super::is_def_id_public;
4use super::Config;
5use crate::analysis::core::api_dependency::mono;
6use crate::{rap_debug, rap_trace};
7use rustc_hir::{
8 def_id::{DefId, LocalDefId},
9 intravisit::{FnKind, Visitor},
10 BodyId, BodyOwnerKind, FnDecl,
11};
12use rustc_middle::ty::{self, FnSig, ParamEnv, Ty, TyCtxt, TyKind};
13use rustc_span::Span;
14use std::io::Write;
15
16pub struct FnVisitor<'tcx, 'a> {
17 tcx: TyCtxt<'tcx>,
18 apis: Vec<DefId>,
19 config: Config,
20 graph: &'a mut ApiDependencyGraph<'tcx>,
21}
22
23impl<'tcx, 'a> FnVisitor<'tcx, 'a> {
24 pub fn new(
25 graph: &'a mut ApiDependencyGraph<'tcx>,
26 config: Config,
27 tcx: TyCtxt<'tcx>,
28 ) -> FnVisitor<'tcx, 'a> {
29 let fn_cnt = 0;
30 let funcs = Vec::new();
31 FnVisitor {
32 tcx,
33 graph,
34 apis: funcs,
35 config,
36 }
37 }
38
39 pub fn count_api(&self) -> usize {
40 self.apis.len()
41 }
42
43 pub fn apis(self) -> Vec<DefId> {
44 self.apis
45 }
46
47 pub fn write_funcs<T: Write>(&self, f: &mut T) {
48 for id in &self.apis {
49 write!(f, "{}\n", self.tcx.def_path_str(id)).expect("fail when write funcs");
50 }
51 }
52}
53
54pub fn has_const_generics(generics: &ty::Generics, tcx: TyCtxt<'_>) -> bool {
55 if generics
56 .own_params
57 .iter()
58 .any(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
59 {
60 return true;
61 }
62
63 if let Some(parent_def_id) = generics.parent {
64 let parent = tcx.generics_of(parent_def_id);
65 has_const_generics(parent, tcx)
66 } else {
67 false
68 }
69}
70
71impl<'tcx, 'a> Visitor<'tcx> for FnVisitor<'tcx, 'a> {
72 fn visit_fn<'v>(
73 &mut self,
74 _fk: FnKind<'v>,
75 _fd: &'v FnDecl<'v>,
76 _b: BodyId,
77 _span: Span,
78 id: LocalDefId,
79 ) -> Self::Result {
80 let fn_did = id.to_def_id();
81 let generics = self.tcx.generics_of(fn_did);
82
83 let is_generic = generics.requires_monomorphization(self.tcx);
84 if self.config.pub_only && !is_def_id_public(fn_did, self.tcx) {
85 return;
86 }
87
88 if !self.config.resolve_generic && is_generic {
91 return;
92 }
93
94 if self.config.ignore_const_generic && has_const_generics(generics, self.tcx) {
97 return;
98 }
99
100 if !is_generic {
101 let args = ty::GenericArgs::identity_for_item(self.tcx, fn_did);
102 self.graph.add_api(fn_did, &args);
103 }
104
105 self.apis.push(fn_did);
106 }
107}