rapx/analysis/core/api_dependency/
mod.rs1#[allow(unused)]
6pub mod graph;
7mod mono;
8mod utils;
9#[allow(unused)]
10mod visitor;
11
12use crate::analysis::Analysis;
13pub use graph::ApiDependencyGraph;
14pub use graph::{DepEdge, DepNode};
15use rustc_hir::def_id::{DefId, LOCAL_CRATE};
16use rustc_middle::ty::TyCtxt;
17pub use utils::is_fuzzable_ty;
18
19#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Default)]
20pub struct Config {
21 pub pub_only: bool,
22 pub resolve_generic: bool,
23 pub ignore_const_generic: bool,
24}
25
26pub fn is_def_id_public(fn_def_id: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
27 let fn_def_id: DefId = fn_def_id.into();
28 let local_id = fn_def_id.expect_local();
29 rap_trace!(
30 "vis: {:?} (path: {}) => {:?}",
31 fn_def_id,
32 tcx.def_path_str(fn_def_id),
33 tcx.effective_visibilities(()).effective_vis(local_id)
34 );
35 tcx.effective_visibilities(()).is_directly_public(local_id)
36 }
38
39pub trait ApiDependencyAnalysis<'tcx> {
40 fn get_api_dependency_graph(&self) -> ApiDependencyGraph<'tcx>;
41}
42
43pub struct ApiDependencyAnalyzer<'tcx> {
44 tcx: TyCtxt<'tcx>,
45 config: Config,
46 api_graph: ApiDependencyGraph<'tcx>,
47}
48
49impl<'tcx> ApiDependencyAnalyzer<'tcx> {
50 pub fn new(tcx: TyCtxt<'tcx>, config: Config) -> ApiDependencyAnalyzer<'tcx> {
51 ApiDependencyAnalyzer {
52 tcx,
53 config,
54 api_graph: ApiDependencyGraph::new(tcx),
55 }
56 }
57}
58
59impl<'tcx> Analysis for ApiDependencyAnalyzer<'tcx> {
60 fn name(&self) -> &'static str {
61 "Default API dependency graph analysis algorithm."
62 }
63
64 fn run(&mut self) {
65 let local_crate_name = self.tcx.crate_name(LOCAL_CRATE);
66 let local_crate_type = self.tcx.crate_types()[0];
67 let config = self.config;
68 rap_debug!(
69 "Build API dependency graph on {} ({}), config = {:?}",
70 local_crate_name.as_str(),
71 local_crate_type,
72 config,
73 );
74
75 let mut api_graph = ApiDependencyGraph::new(self.tcx);
76 api_graph.build(config);
77
78 let (estimate, total) = api_graph.estimate_coverage();
79
80 let statistics = api_graph.statistics();
81 rap_info!(
83 "API Graph contains {} API nodes, {} type nodes, {} edges",
84 statistics.api_count,
85 statistics.type_count,
86 statistics.edge_cnt
87 );
88 rap_info!(
89 "estimate coverage: {:.2} ({}/{})",
90 estimate as f64 / total as f64,
91 estimate,
92 total
93 );
94 let dot_path = format!("api_graph_{}_{}.dot", local_crate_name, local_crate_type);
95 let json_path = format!("api_graph_{}_{}.json", local_crate_name, local_crate_type);
96 rap_info!("Dump API dependency graph to {}", dot_path);
97 api_graph.dump_to_dot(dot_path, self.tcx);
98 api_graph
99 .dump_to_json(&json_path)
100 .expect("failed to dump API graph to JSON");
101 rap_info!("Dump API dependency graph to {}", json_path);
102 }
103
104 fn reset(&mut self) {
105 todo!();
106 }
107}
108
109impl<'tcx> ApiDependencyAnalysis<'tcx> for ApiDependencyAnalyzer<'tcx> {
110 fn get_api_dependency_graph(&self) -> ApiDependencyGraph<'tcx> {
111 self.api_graph.clone()
112 }
113}