go_analyzer/types.rs
1use serde::{Deserialize, Serialize};
2use tower_lsp::lsp_types::Range;
3
4/// Структура для отправки уведомлений о прогрессе от сервера к клиенту LSP.
5/// Используется для передачи текстовых сообщений о ходе анализа или других длительных операций.
6pub struct ProgressNotification;
7/// Реализация LSP-уведомления для ProgressNotification.
8/// Метод "goanalyzer/progress" будет использоваться для отправки уведомлений.
9/// В качестве параметра передаётся строка (например, сообщение о прогрессе).
10impl tower_lsp::lsp_types::notification::Notification for ProgressNotification {
11 /// Имя метода уведомления, используемое клиентом и сервером LSP.
12 const METHOD: &'static str = "goanalyzer/progress";
13 /// Тип параметров, передаваемых с уведомлением (в данном случае — строка).
14 type Params = String;
15}
16
17/// Информация о переменной, используемой в анализе кода.
18/// Содержит имя, диапазон объявления, все использования, флаг указателя, информацию о гонках и уникальный идентификатор.
19#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct VariableInfo {
21 /// Имя переменной (например, "x")
22 pub name: String,
23 /// Диапазон (позиции) объявления переменной в исходном коде
24 pub declaration: Range,
25 /// Все диапазоны (позиции) использований переменной в коде
26 pub uses: Vec<Range>,
27 /// Является ли переменная указателем (true для *x или &x)
28 pub is_pointer: bool,
29 /// Потенциальная гонка данных обнаружена для этой переменной
30 pub potential_race: bool,
31 /// Серьёзность обнаруженной гонки данных (если есть)
32 pub race_severity: RaceSeverity,
33 /// Уникальный идентификатор переменной (используется для быстрого поиска в MutabilityMap)
34 // TODO: Id декларации, чтобы быстро искать в `MutabilityMap`
35 pub var_id: VarId,
36}
37
38/// Тип декорации для подсветки переменных и других сущностей в редакторе.
39/// Используется для визуального выделения объявлений, использований, указателей, гонок данных и других случаев.
40#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
41pub enum DecorationType {
42 /// Объявление переменной (например, `let x = ...` или `var x = ...`)
43 Declaration,
44 /// Использование переменной (например, просто `x` в выражении)
45 Use,
46 /// Переменная является указателем (например, `*x` или `&x`)
47 Pointer,
48 /// Обнаружена гонка данных (race condition) высокой или средней серьёзности
49 Race,
50 /// Гонка данных низкой серьёзности (например, потенциальная или ложноположительная)
51 RaceLow,
52 /// Переменная была переопределена (например, `x = ...` или повторное `:=`)
53 AliasReassigned, // «x = …» или повторное :=
54 /// Переменная захвачена в замыкании (closure) или горутине (goroutine)
55 AliasCaptured, // переменная захвачена в closure / goroutine
56}
57
58/// Уровень серьёзности гонки данных.
59/// Используется для классификации найденных гонок по степени опасности.
60#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
61pub enum RaceSeverity {
62 /// Высокий приоритет — явная гонка данных, требует немедленного внимания.
63 High,
64 /// Средний приоритет — потенциальная гонка, возможно, не всегда проявляется.
65 Medium,
66 /// Низкий приоритет — возможная ложная гонка (например, если есть синхронизация).
67 Low,
68}
69
70/// Структура для хранения информации о декорации (подсветке) в редакторе.
71/// Используется для выделения переменных, указателей, гонок данных и других сущностей.
72#[derive(Serialize, Deserialize, Debug, Clone)]
73pub struct Decoration {
74 /// Диапазон, к которому применяется декорация (позиции в документе)
75 pub range: Range,
76 /// Тип декорации (например, объявление, использование, гонка и т.д.)
77 pub kind: DecorationType,
78 /// Текст, который отображается при наведении курсора (hover)
79 pub hover_text: String,
80}
81
82/// Структура для хранения количества различных сущностей в исходном коде.
83/// Используется для подсчёта переменных, функций, каналов и горутин.
84pub struct EntityCount {
85 /// Количество переменных (например, объявлений переменных)
86 pub variables: usize,
87 /// Количество функций (объявлений функций)
88 pub functions: usize,
89 /// Количество каналов (например, make(chan ...) в Go)
90 pub channels: usize,
91 /// Количество горутин (go func(){}() в Go)
92 pub goroutines: usize,
93}
94
95/// Уникальный идентификатор декларации переменной.
96/// Используется для различения переменных по их положению в исходном коде.
97/// start_byte и end_byte — это байтовые диапазоны узла идентификатора в дереве разбора.
98#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
99pub struct VarId {
100 /// Начальная позиция идентификатора переменной в байтах
101 pub start_byte: usize,
102 /// Конечная позиция идентификатора переменной в байтах
103 pub end_byte: usize,
104}
105
106/// Статус изменяемости переменной.
107/// Показывает, может ли переменная быть изменена, была ли она переопределена,
108/// взят ли у неё адрес или захвачена ли она в замыкании/горутине.
109#[allow(dead_code)]
110#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
111pub enum Mutability {
112 /// Переменная неизменяема (например, объявлена как let x = ...)
113 Immutable,
114 /// Переменная была переопределена (например, x = ...)
115 Reassigned,
116 /// У переменной был взят адрес (например, &x)
117 AddressTaken,
118 /// Переменная была захвачена в замыкании или горутине
119 Captured,
120}
121
122/// Information about goroutine usage of a variable
123#[allow(dead_code)]
124#[derive(Serialize, Deserialize, Debug, Clone)]
125pub struct GoroutineUsage {
126 /// Range of the goroutine statement
127 pub goroutine_range: Range,
128 /// All variable accesses within this goroutine
129 pub variable_accesses: Vec<VariableAccess>,
130 /// Type of goroutine (function call, anonymous function, etc.)
131 pub goroutine_type: GoroutineType,
132 /// Calculated race severity level
133 pub potential_race_level: RaceSeverity,
134}
135
136/// Type of goroutine construct
137#[allow(dead_code)]
138#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
139pub enum GoroutineType {
140 /// go func() { ... }()
141 AnonymousFunction,
142 /// go myFunction()
143 FunctionCall,
144 /// go obj.method()
145 MethodCall,
146 /// Unknown or complex pattern
147 Unknown,
148}
149
150/// Information about a variable access within a goroutine
151#[allow(dead_code)]
152#[derive(Serialize, Deserialize, Debug, Clone)]
153pub struct VariableAccess {
154 /// Location of the access
155 pub range: Range,
156 /// Type of access (read, write, etc.)
157 pub access_type: VariableAccessType,
158 /// Context description
159 pub context: String,
160}
161
162/// Type of variable access
163#[allow(dead_code)]
164#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
165pub enum VariableAccessType {
166 /// Reading the variable value
167 Read,
168 /// Writing to the variable
169 Write,
170 /// Modifying the variable (++, --, +=, etc.)
171 Modify,
172 /// Taking address of variable (&var)
173 AddressOf,
174 /// Dereferencing variable (*var)
175 Dereference,
176}
177
178/// Context information about cursor position
179#[derive(Serialize, Deserialize, Debug, Clone)]
180pub struct CursorContext {
181 /// The node at the cursor position
182 pub target_node_kind: String,
183 /// The cursor position
184 pub position: Range,
185 /// Type of context
186 pub context_type: CursorContextType,
187 /// Parent context type (if available)
188 pub parent_context: Option<CursorContextType>,
189 /// Additional context information
190 pub details: Option<String>,
191}
192
193/// Types of contexts where cursor can be positioned
194#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
195pub enum CursorContextType {
196 /// Cursor is on a variable declaration
197 VariableDeclaration,
198 /// Cursor is on a parameter declaration
199 ParameterDeclaration,
200 /// Cursor is on a variable usage
201 VariableUse,
202 /// Cursor is on a struct field access (obj.field)
203 FieldAccess,
204 /// Cursor is on the object part of field access
205 ObjectAccess,
206 /// Cursor is on a struct field definition
207 StructField,
208 /// Cursor is on a function name (declaration)
209 FunctionName,
210 /// Cursor is on a function declaration
211 FunctionDeclaration,
212 /// Cursor is on a function call
213 FunctionCall,
214 /// Cursor is on an assignment statement
215 Assignment,
216 /// Cursor is in a goroutine context
217 GoroutineContext,
218 /// Cursor is on a go statement
219 GoroutineStatement,
220 /// Cursor is on a type reference
221 TypeReference,
222 /// Cursor is on a package reference
223 PackageReference,
224 /// Cursor is on a channel type
225 ChannelType,
226 /// Cursor is on an interface type
227 InterfaceType,
228 /// Cursor is on a struct type
229 StructType,
230 /// Unknown or unsupported context
231 Unknown,
232}
233
234pub const ATOMIC_FUNCS: &[&str] = &[
235 "AddInt32",
236 "AddInt64",
237 "AddUint32",
238 "AddUint64",
239 "AddUintptr",
240 "CompareAndSwapInt32",
241 "CompareAndSwapInt64",
242 "CompareAndSwapPointer",
243 "CompareAndSwapUint32",
244 "CompareAndSwapUint64",
245 "LoadInt32",
246 "LoadInt64",
247 "LoadPointer",
248 "LoadUint32",
249 "LoadUint64",
250 "StoreInt32",
251 "StoreInt64",
252 "StorePointer",
253 "StoreUint32",
254 "StoreUint64",
255];
256
257#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
258pub enum GraphEntityType {
259 Variable,
260 Function,
261 Channel,
262 Goroutine,
263 SyncBlock,
264}
265
266#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
267pub enum GraphEdgeType {
268 // переменная используется
269 Use,
270 // вызов функции
271 Call,
272 // отправка в канал
273 Send,
274 // получение из канала
275 Receive,
276 // запуск горутины
277 Spawn,
278 // синхронизация
279 Sync,
280}
281
282#[derive(Serialize, Deserialize, Debug, Clone)]
283pub struct GraphNode {
284 // уникальный идентификатор (например, имя+позиция)
285 pub id: String,
286 // отображаемое имя
287 pub label: String,
288 pub entity_type: GraphEntityType,
289 pub range: Range,
290 // для доп. информации (тип, гонка, и т.д.)
291 pub extra: Option<serde_json::Value>,
292}
293
294#[derive(Serialize, Deserialize, Debug, Clone)]
295pub struct GraphEdge {
296 // id источника
297 pub from: String,
298 // id назначения
299 pub to: String,
300 pub edge_type: GraphEdgeType,
301}
302
303#[derive(Serialize, Deserialize, Debug, Clone)]
304pub struct GraphData {
305 pub nodes: Vec<GraphNode>,
306 pub edges: Vec<GraphEdge>,
307}