Skip to main content

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}