1use std::collections::BTreeSet;
12
13use backhopper_core::{ApplicationName, BehaviourName, Mfa, ModuleName};
14use backhopper_xref_graph::{
15 CallKind, DeprecationTier, FunctionRef, FunctionSig, Loc, UnresolvedCallSite,
16};
17use serde::{Deserialize, Serialize};
18
19pub trait AnalysisResult: serde::Serialize {
20 fn is_clean(&self) -> bool;
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct UndefinedFunctionCall {
25 pub caller: Mfa,
26 pub callee: FunctionRef,
27 pub kind: CallKind,
28 pub locations: Vec<Loc>,
29}
30
31#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
32pub struct UndefinedFunctionCalls {
33 pub entries: Vec<UndefinedFunctionCall>,
34}
35
36impl AnalysisResult for UndefinedFunctionCalls {
37 fn is_clean(&self) -> bool {
38 self.entries.is_empty()
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
43pub struct UnusedLocal {
44 pub mfa: Mfa,
45 pub def_loc: Option<Loc>,
46}
47
48#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
49pub struct LocalsNotUsed {
50 pub entries: Vec<UnusedLocal>,
51}
52
53impl AnalysisResult for LocalsNotUsed {
54 fn is_clean(&self) -> bool {
55 self.entries.is_empty()
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60pub struct UnusedExport {
61 pub mfa: Mfa,
62 pub def_loc: Option<Loc>,
63 pub satisfies_callback: bool,
64 pub is_on_load: bool,
65}
66
67#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
68pub struct ExportsNotUsed {
69 pub entries: Vec<UnusedExport>,
70}
71
72impl AnalysisResult for ExportsNotUsed {
73 fn is_clean(&self) -> bool {
74 self.entries.is_empty()
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
79pub struct DeprecatedCall {
80 pub caller: Mfa,
81 pub callee: Mfa,
82 pub tier: DeprecationTier,
83 pub message: Option<String>,
84 pub locations: Vec<Loc>,
85}
86
87#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
88pub struct DeprecatedFunctionCalls {
89 pub entries: Vec<DeprecatedCall>,
90}
91
92impl AnalysisResult for DeprecatedFunctionCalls {
93 fn is_clean(&self) -> bool {
94 self.entries.is_empty()
95 }
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
99pub struct CallerEntry {
100 pub caller: Mfa,
101 pub kind: CallKind,
102 pub locations: Vec<Loc>,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
106pub struct CallersOf {
107 pub target: Mfa,
108 pub entries: Vec<CallerEntry>,
109}
110
111impl AnalysisResult for CallersOf {
112 fn is_clean(&self) -> bool {
113 self.entries.is_empty()
114 }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
118pub struct CalleeEntry {
119 pub callee: FunctionRef,
120 pub kind: CallKind,
121 pub locations: Vec<Loc>,
122}
123
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
125pub struct CalleesOf {
126 pub source: Mfa,
127 pub entries: Vec<CalleeEntry>,
128}
129
130impl AnalysisResult for CalleesOf {
131 fn is_clean(&self) -> bool {
132 self.entries.is_empty()
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
137pub struct ModuleCallers {
138 pub target: ModuleName,
139 pub entries: BTreeSet<ModuleName>,
140}
141
142impl AnalysisResult for ModuleCallers {
143 fn is_clean(&self) -> bool {
144 self.entries.is_empty()
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
149pub struct ModuleDependencies {
150 pub source: ModuleName,
151 pub entries: BTreeSet<ModuleName>,
152}
153
154impl AnalysisResult for ModuleDependencies {
155 fn is_clean(&self) -> bool {
156 self.entries.is_empty()
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161pub struct AppDependencies {
162 pub source: ApplicationName,
163 pub entries: BTreeSet<ApplicationName>,
164}
165
166impl AnalysisResult for AppDependencies {
167 fn is_clean(&self) -> bool {
168 self.entries.is_empty()
169 }
170}
171
172#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
173pub struct NonConformance {
174 pub implementer: ModuleName,
175 pub behaviour: BehaviourName,
176 pub missing: BTreeSet<FunctionSig>,
177}
178
179impl AnalysisResult for NonConformance {
180 fn is_clean(&self) -> bool {
181 self.missing.is_empty()
182 }
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
186pub struct UnresolvedCalls {
187 pub entries: Vec<UnresolvedCallSite>,
188}
189
190impl AnalysisResult for UnresolvedCalls {
191 fn is_clean(&self) -> bool {
192 self.entries.is_empty()
193 }
194}