1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/// Where a referenced type is defined, from the perspective of the file that
/// uses it. Used by abstraction-boundary analyses to distinguish "own domain"
/// types from "pulled in from a library" types.
#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case", tag = "kind", content = "module")]
pub enum TypeOrigin {
/// Declared inside the project (resolved via project-wide type registry
/// or an import pointing at a project-local path).
Local,
/// Imported from an external module / crate / package. Carries the module
/// name if known (Rust crate path root, Go module path, npm package name,
/// C header filename without extension). May be empty if only structure
/// says "external" (e.g. `#include <...>` without the header name).
External(String),
/// Built-in primitive / standard library scalar (int, bool, &str, char…).
Primitive,
/// Could not be resolved. Detection treats this as potentially external
/// but with lower confidence.
#[default]
Unknown,
}
/// A function parameter's (or return value's) type, with resolved origin.
/// Produced by parsers after combining AST type text with the file's imports.
#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
pub struct TypeRef {
/// Innermost identifier after stripping references, generics, containers.
/// e.g. `&mut Vec<tree_sitter::Node>` → `"Node"`.
pub name: String,
/// Original source text as written, for messages and debugging.
/// e.g. `"&mut Vec<tree_sitter::Node>"`.
pub raw: String,
/// Where the type is declared.
pub origin: TypeOrigin,
}
/// Extracted function info from AST.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct FunctionInfo {
pub name: String,
pub start_line: usize,
pub end_line: usize,
/// 0-based column of the function name identifier.
pub name_col: usize,
/// 0-based end column of the function name identifier.
pub name_end_col: usize,
pub line_count: usize,
/// Cyclomatic complexity (1 + number of branch points).
pub complexity: usize,
/// Hash of the function body AST structure for duplicate detection.
pub body_hash: Option<u64>,
/// Whether this function is exported (pub/export).
pub is_exported: bool,
/// Number of parameters.
pub parameter_count: usize,
/// Names of external identifiers referenced in the body (for Feature Envy).
pub external_refs: Vec<String>,
/// Max method chain depth in the body (for Message Chains).
pub chain_depth: usize,
/// Number of switch/match arms (for Switch Statements).
pub switch_arms: usize,
/// Whether this function only delegates to another object's method (for Middle Man).
pub is_delegating: bool,
/// Parameter types **in declaration order**, each resolved to a TypeRef.
/// Preserves position (first param = index 0) so positional analyses work.
pub parameter_types: Vec<TypeRef>,
/// Number of comment lines in the function body.
pub comment_lines: usize,
/// Field names referenced in this function body (for Temporary Field).
pub referenced_fields: Vec<String>,
/// Field names checked for null/None in this function (for Null Object pattern).
pub null_check_fields: Vec<String>,
/// The field/variable name being dispatched on in switch/match (for Strategy/State).
pub switch_dispatch_target: Option<String>,
/// Number of optional parameters (for Builder pattern).
pub optional_param_count: usize,
/// Names of functions/methods called in this function body (for call graph).
pub called_functions: Vec<String>,
/// Cognitive complexity score [SonarSource 2017] — nesting-aware understandability metric.
pub cognitive_complexity: usize,
/// Declared return type (None if not annotated or inferred), resolved the
/// same way as parameter types. Drives return_type_leak detection.
pub return_type: Option<TypeRef>,
}
/// Extracted class/struct info from AST.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct ClassInfo {
pub name: String,
pub start_line: usize,
pub end_line: usize,
/// 0-based column of the class/struct name identifier.
pub name_col: usize,
/// 0-based end column of the class/struct name identifier.
pub name_end_col: usize,
pub method_count: usize,
pub line_count: usize,
/// Whether this class is exported.
pub is_exported: bool,
/// Number of methods that only delegate to another object.
pub delegating_method_count: usize,
/// Number of fields/properties.
pub field_count: usize,
/// Field names declared in this class.
pub field_names: Vec<String>,
/// Field types (parallel to field_names).
pub field_types: Vec<String>,
/// Whether the class has non-accessor methods (business logic).
pub has_behavior: bool,
/// Whether this is an interface or abstract class.
pub is_interface: bool,
/// Parent class/trait name (for Refused Bequest).
pub parent_name: Option<String>,
/// Number of overridden methods (for Refused Bequest).
pub override_count: usize,
/// Number of self-method calls in the longest method (for Template Method).
pub self_call_count: usize,
/// Whether the class has a listener/callback collection field.
pub has_listener_field: bool,
/// Whether the class has a notify/emit method.
pub has_notify_method: bool,
}
/// Extracted import info.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct ImportInfo {
pub source: String,
pub line: usize,
/// 0-based column of the import statement.
pub col: usize,
/// True for module declarations (e.g. Rust `mod foo;`).
pub is_module_decl: bool,
}
/// A comment extracted from source code by the language parser.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CommentInfo {
pub text: String,
pub line: usize,
}
/// Unified source model produced by parsing.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SourceModel {
pub language: String,
pub total_lines: usize,
pub functions: Vec<FunctionInfo>,
pub classes: Vec<ClassInfo>,
pub imports: Vec<ImportInfo>,
pub comments: Vec<CommentInfo>,
/// Type aliases: (alias, original). e.g. typedef, using, type =
pub type_aliases: Vec<(String, String)>,
}