codegraph_python/entities/
function.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct Parameter {
6 pub name: String,
8
9 pub type_annotation: Option<String>,
11
12 pub default_value: Option<String>,
14}
15
16impl Parameter {
17 pub fn new(name: impl Into<String>) -> Self {
19 Self {
20 name: name.into(),
21 type_annotation: None,
22 default_value: None,
23 }
24 }
25
26 pub fn with_type(name: impl Into<String>, type_annotation: impl Into<String>) -> Self {
28 Self {
29 name: name.into(),
30 type_annotation: Some(type_annotation.into()),
31 default_value: None,
32 }
33 }
34
35 pub fn with_default(mut self, default: impl Into<String>) -> Self {
37 self.default_value = Some(default.into());
38 self
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub struct FunctionEntity {
45 pub name: String,
47
48 pub signature: String,
50
51 pub visibility: String,
53
54 pub line_start: usize,
56
57 pub line_end: usize,
59
60 pub is_async: bool,
62
63 pub is_test: bool,
65
66 pub parameters: Vec<Parameter>,
68
69 pub return_type: Option<String>,
71
72 pub doc_comment: Option<String>,
74
75 pub parent: Option<String>,
77
78 pub attributes: Vec<String>,
80}
81
82impl FunctionEntity {
83 pub fn new(name: impl Into<String>, line_start: usize, line_end: usize) -> Self {
85 let name = name.into();
86 let visibility = if name.starts_with('_') {
87 "private".to_string()
88 } else {
89 "public".to_string()
90 };
91
92 let is_test = name.starts_with("test_") || name.starts_with("Test");
93
94 Self {
95 name: name.clone(),
96 signature: format!("def {name}"),
97 visibility,
98 line_start,
99 line_end,
100 is_async: false,
101 is_test,
102 parameters: Vec::new(),
103 return_type: None,
104 doc_comment: None,
105 parent: None,
106 attributes: Vec::new(),
107 }
108 }
109
110 pub fn is_method(&self) -> bool {
112 self.parent.is_some()
113 }
114
115 pub fn is_static(&self) -> bool {
117 self.attributes.iter().any(|a| a == "@staticmethod")
118 }
119
120 pub fn is_classmethod(&self) -> bool {
122 self.attributes.iter().any(|a| a == "@classmethod")
123 }
124
125 pub fn is_property(&self) -> bool {
127 self.attributes.iter().any(|a| a == "@property")
128 }
129
130 pub fn set_async(mut self, is_async: bool) -> Self {
132 self.is_async = is_async;
133 self
134 }
135
136 pub fn set_return_type(mut self, return_type: Option<String>) -> Self {
138 self.return_type = return_type;
139 self
140 }
141
142 pub fn set_doc_comment(mut self, doc: Option<String>) -> Self {
144 self.doc_comment = doc;
145 self
146 }
147
148 pub fn set_parent(mut self, parent: Option<String>) -> Self {
150 self.parent = parent;
151 self
152 }
153
154 pub fn add_attribute(mut self, attr: impl Into<String>) -> Self {
156 self.attributes.push(attr.into());
157 self
158 }
159
160 pub fn add_parameter(mut self, param: Parameter) -> Self {
162 self.parameters.push(param);
163 self
164 }
165
166 pub fn set_signature(mut self, sig: impl Into<String>) -> Self {
168 self.signature = sig.into();
169 self
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_parameter_new() {
179 let param = Parameter::new("arg");
180 assert_eq!(param.name, "arg");
181 assert!(param.type_annotation.is_none());
182 assert!(param.default_value.is_none());
183 }
184
185 #[test]
186 fn test_parameter_with_type() {
187 let param = Parameter::with_type("arg", "str");
188 assert_eq!(param.name, "arg");
189 assert_eq!(param.type_annotation, Some("str".to_string()));
190 }
191
192 #[test]
193 fn test_parameter_with_default() {
194 let param = Parameter::with_type("arg", "int").with_default("42");
195 assert_eq!(param.default_value, Some("42".to_string()));
196 }
197
198 #[test]
199 fn test_function_entity_visibility() {
200 let public_func = FunctionEntity::new("my_func", 1, 10);
201 assert_eq!(public_func.visibility, "public");
202
203 let private_func = FunctionEntity::new("_my_func", 1, 10);
204 assert_eq!(private_func.visibility, "private");
205 }
206
207 #[test]
208 fn test_function_entity_test_detection() {
209 let test_func = FunctionEntity::new("test_something", 1, 10);
210 assert!(test_func.is_test);
211
212 let regular_func = FunctionEntity::new("do_something", 1, 10);
213 assert!(!regular_func.is_test);
214 }
215
216 #[test]
217 fn test_function_entity_method_detection() {
218 let mut func = FunctionEntity::new("method", 1, 10);
219 assert!(!func.is_method());
220
221 func = func.set_parent(Some("MyClass".to_string()));
222 assert!(func.is_method());
223 }
224
225 #[test]
226 fn test_function_entity_decorators() {
227 let func = FunctionEntity::new("method", 1, 10).add_attribute("@staticmethod");
228
229 assert!(func.is_static());
230 assert!(!func.is_classmethod());
231 assert!(!func.is_property());
232 }
233}