1
+ """Zig language analyzer."""
2
+
3
+ import os
4
+ from typing import Dict , Any
5
+ from .base_analyzer import LanguageAnalyzer
6
+ from .analysis_result import AnalysisResult
7
+
8
+
9
+ class ZigAnalyzer (LanguageAnalyzer ):
10
+ """Analyzer for Zig files."""
11
+
12
+ def analyze (self , content : str , file_path : str , full_path : str = None ) -> AnalysisResult :
13
+ """Analyze Zig file content."""
14
+ lines = content .splitlines ()
15
+
16
+ # Create result object
17
+ _ , ext = os .path .splitext (file_path )
18
+ result = AnalysisResult (
19
+ file_path = file_path ,
20
+ line_count = self ._count_lines (content ),
21
+ size_bytes = self ._get_file_size (content , full_path ),
22
+ extension = ext ,
23
+ analysis_type = "zig"
24
+ )
25
+
26
+ # Zig-specific analysis
27
+ for i , line in enumerate (lines ):
28
+ line_stripped = line .strip ()
29
+
30
+ # Skip empty lines and comments
31
+ if not line_stripped or line_stripped .startswith ('//' ):
32
+ continue
33
+
34
+ # Check for imports
35
+ if '@import(' in line_stripped :
36
+ # Extract module name from @import("module") or @import("module.zig")
37
+ import_match = line_stripped .split ('@import(' )
38
+ if len (import_match ) > 1 :
39
+ import_name = import_match [1 ].split (')' )[0 ].strip ('"\' ' )
40
+ result .add_symbol ("import" , f"@import({ import_name } )" , i + 1 )
41
+
42
+ if '@cImport(' in line_stripped :
43
+ result .add_symbol ("import" , "@cImport" , i + 1 )
44
+
45
+ # Check for function definitions
46
+ if ' fn ' in line_stripped or line_stripped .startswith ('fn ' ):
47
+ # Handle both 'pub fn' and 'fn' declarations
48
+ if 'fn ' in line_stripped :
49
+ fn_part = line_stripped .split ('fn ' , 1 )[1 ]
50
+ func_name = fn_part .split ('(' )[0 ].strip ()
51
+ if func_name :
52
+ symbol_type = "function"
53
+ if 'pub fn' in line_stripped :
54
+ symbol_type = "function_public"
55
+ result .add_symbol (symbol_type , func_name , i + 1 )
56
+
57
+ # Check for struct definitions
58
+ if ' struct ' in line_stripped or ' struct{' in line_stripped :
59
+ # Look for const Name = struct pattern
60
+ if 'const ' in line_stripped and '=' in line_stripped :
61
+ const_part = line_stripped .split ('const ' , 1 )[1 ]
62
+ struct_name = const_part .split ('=' )[0 ].strip ()
63
+ if struct_name :
64
+ result .add_symbol ("struct" , struct_name , i + 1 )
65
+
66
+ # Check for enum definitions
67
+ if ' enum ' in line_stripped or ' enum{' in line_stripped or ' enum(' in line_stripped :
68
+ # Look for const Name = enum pattern
69
+ if 'const ' in line_stripped and '=' in line_stripped :
70
+ const_part = line_stripped .split ('const ' , 1 )[1 ]
71
+ enum_name = const_part .split ('=' )[0 ].strip ()
72
+ if enum_name :
73
+ result .add_symbol ("enum" , enum_name , i + 1 )
74
+
75
+ # Check for error set definitions
76
+ if ' error{' in line_stripped or '= error{' in line_stripped :
77
+ # Look for const Name = error pattern
78
+ if 'const ' in line_stripped and '=' in line_stripped :
79
+ const_part = line_stripped .split ('const ' , 1 )[1 ]
80
+ error_name = const_part .split ('=' )[0 ].strip ()
81
+ if error_name :
82
+ result .add_symbol ("error_set" , error_name , i + 1 )
83
+
84
+ # Check for test blocks
85
+ if line_stripped .startswith ('test ' ):
86
+ test_name = line_stripped [5 :].split ('{' )[0 ].strip ().strip ('"' )
87
+ if test_name :
88
+ result .add_symbol ("test" , test_name , i + 1 )
89
+
90
+ # Check for const/var declarations at module level
91
+ if line_stripped .startswith ('pub const ' ) or line_stripped .startswith ('const ' ):
92
+ # Skip struct/enum/error definitions already handled
93
+ if not any (keyword in line_stripped for keyword in [' struct' , ' enum' , ' error{' ]):
94
+ const_part = line_stripped .replace ('pub const ' , '' ).replace ('const ' , '' )
95
+ if ':' in const_part or '=' in const_part :
96
+ const_name = const_part .split (':' )[0 ].split ('=' )[0 ].strip ()
97
+ if const_name :
98
+ symbol_type = "const_public" if line_stripped .startswith ('pub const' ) else "const"
99
+ result .add_symbol (symbol_type , const_name , i + 1 )
100
+
101
+ if line_stripped .startswith ('pub var ' ) or line_stripped .startswith ('var ' ):
102
+ var_part = line_stripped .replace ('pub var ' , '' ).replace ('var ' , '' )
103
+ if ':' in var_part or '=' in var_part :
104
+ var_name = var_part .split (':' )[0 ].split ('=' )[0 ].strip ()
105
+ if var_name :
106
+ symbol_type = "var_public" if line_stripped .startswith ('pub var' ) else "var"
107
+ result .add_symbol (symbol_type , var_name , i + 1 )
108
+
109
+ return result
0 commit comments