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