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