1use serde::{Deserialize, Serialize};
2
3use crate::schema;
4
5#[derive(Debug, Default, Serialize, Deserialize)]
12pub struct ProjectIr {
13 pub files: Vec<FileIr>,
14 pub modules: Vec<ModuleIr>,
15 pub functions: Vec<FunctionIr>,
16 pub api_endpoints: Vec<ApiEndpointIr>,
17 pub external_apis: Vec<ExternalApiIr>,
18 pub edges: Vec<EdgeIr>,
19 #[serde(default)]
21 pub classes: Vec<ClassIr>,
22 #[serde(default)]
24 pub properties: Vec<PropertyIr>,
25 #[serde(default)]
27 pub behaviours: Vec<BehaviourIr>,
28 #[serde(default)]
30 pub callbacks: Vec<CallbackIr>,
31}
32
33impl ProjectIr {
34 pub fn empty() -> Self {
35 Self::default()
36 }
37}
38
39#[derive(Debug, Serialize, Deserialize)]
41pub struct FileIr {
42 pub path: String,
43 pub language: String,
44 pub framework: Option<String>,
45 pub project_name: Option<String>,
46}
47
48#[derive(Debug, Serialize, Deserialize)]
50pub struct ModuleIr {
51 pub name: String,
52 pub path: String,
53 pub language: String,
54 pub framework: Option<String>,
55 pub project_name: Option<String>,
56}
57
58#[derive(Debug, Serialize, Deserialize)]
60pub struct ClassIr {
61 pub fqn: String,
62 pub name: String,
63 pub path: String,
64 pub language: String,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub project_name: Option<String>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub kind: Option<String>,
69}
70
71#[derive(Debug, Serialize, Deserialize)]
73pub struct PropertyIr {
74 pub fqn: String,
75 pub name: String,
76 pub class_fqn: String,
77 pub path: String,
78 pub language: String,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub project_name: Option<String>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub declared_type: Option<String>,
83}
84
85#[derive(Debug, Serialize, Deserialize)]
87pub struct FunctionIr {
88 pub name: String,
89 pub fqn: String,
90 pub path: String,
91 pub language: String,
92 pub framework: Option<String>,
93 pub project_name: Option<String>,
94 pub arity: Option<u32>,
95 pub return_type: Option<String>,
96 pub param_count: Option<u32>,
97 pub param_types: Vec<String>,
98}
99
100#[derive(Debug, Serialize, Deserialize)]
102pub struct ApiEndpointIr {
103 pub methods: Vec<String>,
104 pub path: String,
105 pub protocol: Option<String>,
106 pub framework: Option<String>,
107 pub project_name: Option<String>,
108}
109
110#[derive(Debug, Serialize, Deserialize)]
112pub struct ExternalApiIr {
113 pub name: String,
114 pub base_url: Option<String>,
115 pub protocol: Option<String>,
116 pub provider: Option<String>,
117 pub service: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
119 pub norm_path: Option<String>,
120}
121
122#[derive(Debug, Serialize, Deserialize)]
124pub struct BehaviourIr {
125 pub name: String,
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub path: Option<String>,
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub language: Option<String>,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub project_name: Option<String>,
132}
133
134#[derive(Debug, Serialize, Deserialize)]
136pub struct CallbackIr {
137 pub name: String,
138 pub fqn: String,
139 pub arity: u32,
140 pub optional: bool,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub language: Option<String>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub project_name: Option<String>,
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149pub enum EdgeKind {
150 DeclaresModule,
151 DeclaresFunction,
152 DeclaresClass,
153 DeclaresProperty,
154 DependsOnFile,
155 CallsFunction,
156 HandlesApi,
157 CallsExternalApi,
158 UsesClass,
160 ClassUsesClass,
162 SameApi,
163 ImplementsBehaviour,
164 DeclaresCallback,
165 ImplementsCallback,
166 DeclaresBehaviour,
167 ExtendsBehaviour,
168 OverridesCallback,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct EdgeIr {
185 pub kind: EdgeKind,
186 pub from_label: String,
188 pub from_key: String,
190 pub to_label: String,
192 pub to_key: String,
194}
195
196impl EdgeKind {
197 pub fn to_rel_type(&self) -> crate::edge::RelType {
201 use crate::edge::RelType;
202 match self {
203 EdgeKind::DeclaresModule => RelType::DeclaresModule,
204 EdgeKind::DeclaresFunction => RelType::DeclaresFunction,
205 EdgeKind::DeclaresClass => RelType::DeclaresClass,
206 EdgeKind::DeclaresProperty => RelType::DeclaresProperty,
207 EdgeKind::DependsOnFile => RelType::DependsOnFile,
208 EdgeKind::CallsFunction => RelType::CallsFunction,
209 EdgeKind::HandlesApi => RelType::HandlesApi,
210 EdgeKind::CallsExternalApi => RelType::CallsExternalApi,
211 EdgeKind::UsesClass => RelType::UsesClass,
212 EdgeKind::ClassUsesClass => RelType::ClassUsesClass,
213 EdgeKind::SameApi => RelType::SameApi,
214 EdgeKind::ImplementsBehaviour => RelType::ImplementsBehaviour,
215 EdgeKind::DeclaresCallback => RelType::DeclaresCallback,
216 EdgeKind::ImplementsCallback => RelType::ImplementsCallback,
217 EdgeKind::DeclaresBehaviour => RelType::DeclaresBehaviour,
218 EdgeKind::ExtendsBehaviour => RelType::ExtendsBehaviour,
219 EdgeKind::OverridesCallback => RelType::OverridesCallback,
220 }
221 }
222}
223
224pub fn external_api_key(base_url: &str, norm_path: &str) -> String {
226 format!("{base_url}|{norm_path}")
227}
228
229pub fn api_endpoint_key(methods: &[String], path: &str) -> String {
231 format!("{} {}", methods.join(","), path)
232}
233
234pub fn module_key(name: &str, path: &str) -> String {
236 format!("{name}@{path}")
237}
238
239impl From<schema::NodeLabel> for String {
240 fn from(label: schema::NodeLabel) -> Self {
241 label.to_string()
242 }
243}
244
245