1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum Language {
8 Python,
10 TypeScript,
11 JavaScript,
12 Go,
13 Rust,
14 Java,
15 C,
16 Cpp,
17 Ruby,
18 CSharp,
19 Kotlin,
21 Swift,
22 Scala,
23 Php,
24 Lua,
25 Elixir,
26 Haskell,
27 Ocaml,
28 Markdown,
30 Text,
31 Yaml,
32 Toml,
33 Json,
34 Dockerfile,
35 Makefile,
36 Shell,
37 Powershell,
38 AsciiDoc,
39 Org,
40}
41
42impl FromStr for Language {
43 type Err = String;
44
45 fn from_str(s: &str) -> Result<Self, Self::Err> {
46 match s.to_lowercase().as_str() {
47 "python" | "py" => Ok(Language::Python),
49 "typescript" | "ts" => Ok(Language::TypeScript),
50 "javascript" | "js" => Ok(Language::JavaScript),
51 "go" => Ok(Language::Go),
52 "rust" | "rs" => Ok(Language::Rust),
53 "java" => Ok(Language::Java),
54 "c" => Ok(Language::C),
55 "cpp" | "c++" => Ok(Language::Cpp),
56 "ruby" | "rb" => Ok(Language::Ruby),
57 "csharp" | "c#" | "cs" => Ok(Language::CSharp),
58 "kotlin" | "kt" => Ok(Language::Kotlin),
60 "swift" => Ok(Language::Swift),
61 "scala" => Ok(Language::Scala),
62 "php" => Ok(Language::Php),
63 "lua" => Ok(Language::Lua),
64 "elixir" | "ex" => Ok(Language::Elixir),
65 "haskell" | "hs" => Ok(Language::Haskell),
66 "ocaml" | "ml" => Ok(Language::Ocaml),
67 "markdown" | "md" => Ok(Language::Markdown),
69 "text" | "txt" => Ok(Language::Text),
70 "yaml" | "yml" => Ok(Language::Yaml),
71 "toml" => Ok(Language::Toml),
72 "json" => Ok(Language::Json),
73 "dockerfile" => Ok(Language::Dockerfile),
74 "makefile" => Ok(Language::Makefile),
75 "shell" | "sh" | "bash" => Ok(Language::Shell),
76 "powershell" | "ps1" => Ok(Language::Powershell),
77 "asciidoc" | "adoc" => Ok(Language::AsciiDoc),
78 "org" => Ok(Language::Org),
79 _ => Err(format!("Unknown language: {}", s)),
80 }
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
85#[serde(rename_all = "lowercase")]
86pub enum UnitType {
87 Function,
88 Method,
89 Class,
90 Document,
91 Section,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct CodeUnit {
97 pub name: String,
99 pub qualified_name: String,
100 pub file: PathBuf,
101 pub line: usize,
102 pub language: Language,
103 pub unit_type: UnitType,
104
105 pub signature: String,
107 pub docstring: Option<String>,
108 pub parameters: Vec<String>,
109 pub return_type: Option<String>,
110
111 pub calls: Vec<String>,
113 pub called_by: Vec<String>,
114
115 pub complexity: usize,
117 pub has_loops: bool,
118 pub has_branches: bool,
119 pub has_error_handling: bool,
120
121 pub variables: Vec<String>,
123
124 pub imports: Vec<String>,
126
127 pub code_preview: String,
129}
130
131impl CodeUnit {
132 pub fn new(
133 name: String,
134 file: PathBuf,
135 line: usize,
136 language: Language,
137 unit_type: UnitType,
138 parent_class: Option<&str>,
139 ) -> Self {
140 let qualified_name = match parent_class {
141 Some(c) => format!("{}::{}::{}", file.display(), c, name),
142 None => format!("{}::{}", file.display(), name),
143 };
144
145 Self {
146 name,
147 qualified_name,
148 file,
149 line,
150 language,
151 unit_type,
152 signature: String::new(),
153 docstring: None,
154 parameters: Vec::new(),
155 return_type: None,
156 calls: Vec::new(),
157 called_by: Vec::new(),
158 complexity: 1,
159 has_loops: false,
160 has_branches: false,
161 has_error_handling: false,
162 variables: Vec::new(),
163 imports: Vec::new(),
164 code_preview: String::new(),
165 }
166 }
167}