@@ -92,6 +92,7 @@ impl SorobanAnalyzer {
9292 description : "Contract should have a constructor function for initialization" . to_string ( ) ,
9393 suggestion : "Add a 'new' function that initializes the contract state" . to_string ( ) ,
9494 line_number : 1 ,
95+ column_number : 0 ,
9596 variable_name : contract. name . clone ( ) ,
9697 severity : ViolationSeverity :: Warning ,
9798 } ) ;
@@ -112,6 +113,7 @@ impl SorobanAnalyzer {
112113 description : "Consider adding an admin/owner field for access control" . to_string ( ) ,
113114 suggestion : "Add an 'admin: Address' field to your contract state" . to_string ( ) ,
114115 line_number : 1 ,
116+ column_number : 0 ,
115117 variable_name : contract. name . clone ( ) ,
116118 severity : ViolationSeverity :: Info ,
117119 } ) ;
@@ -128,14 +130,15 @@ impl SorobanAnalyzer {
128130 // Count occurrences of field name in the source (excluding struct definition)
129131 let field_usage_count = source. matches ( & field. name ) . count ( ) ;
130132
131- // If field is only mentioned in its own declaration, it's likely unused
132- // (this is a heuristic - a more sophisticated analysis would be needed for production)
133- if field_usage_count <= 1 {
133+ // Heuristic: Definition + Initialization = 2 occurrences.
134+ // If it's <= 2, it's likely defined and initialized but never accessed again.
135+ if field_usage_count <= 2 {
134136 violations. push ( RuleViolation {
135137 rule_name : "unused-state-variable" . to_string ( ) ,
136138 description : format ! ( "State variable '{}' appears to be unused" , field. name) ,
137139 suggestion : format ! ( "Remove unused state variable '{}' to save ledger storage" , field. name) ,
138140 line_number : field. line_number ,
141+ column_number : 0 ,
139142 variable_name : field. name . clone ( ) ,
140143 severity : ViolationSeverity :: Warning ,
141144 } ) ;
@@ -155,8 +158,9 @@ impl SorobanAnalyzer {
155158 violations. push ( RuleViolation {
156159 rule_name : "inefficient-integer-type" . to_string ( ) ,
157160 description : format ! ( "Field '{}' uses {} which may be unnecessarily large" , field. name, field. type_name) ,
158- suggestion : format ! ( "Consider using a smaller integer type like u64 or u32 if the range permits" , field . name ) ,
161+ suggestion : "Consider using a smaller integer type like u64 or u32 if the range permits" . to_string ( ) ,
159162 line_number : field. line_number ,
163+ column_number : 0 ,
160164 variable_name : field. name . clone ( ) ,
161165 severity : ViolationSeverity :: Info ,
162166 } ) ;
@@ -169,6 +173,7 @@ impl SorobanAnalyzer {
169173 description : format ! ( "Field '{}' uses String type" , field. name) ,
170174 suggestion : "Consider using Symbol for fixed string values to save storage costs" . to_string ( ) ,
171175 line_number : field. line_number ,
176+ column_number : 0 ,
172177 variable_name : field. name . clone ( ) ,
173178 severity : ViolationSeverity :: Info ,
174179 } ) ;
@@ -189,6 +194,7 @@ impl SorobanAnalyzer {
189194 description : format ! ( "Field '{}' is private but contract fields should typically be public" , field. name) ,
190195 suggestion : format ! ( "Change '{}' to 'pub {}' to make it accessible" , field. name, field. name) ,
191196 line_number : field. line_number ,
197+ column_number : 0 ,
192198 variable_name : field. name . clone ( ) ,
193199 severity : ViolationSeverity :: Warning ,
194200 } ) ;
@@ -199,17 +205,18 @@ impl SorobanAnalyzer {
199205 }
200206
201207 /// Check for expensive operations in functions
202- fn check_expensive_operations ( function : & SorobanFunction , source : & str ) -> Vec < RuleViolation > {
208+ fn check_expensive_operations ( function : & SorobanFunction , _source : & str ) -> Vec < RuleViolation > {
203209 let mut violations = Vec :: new ( ) ;
204210 let function_source = & function. raw_definition ;
205211
206212 // Check for string operations
207213 if function_source. contains ( ".to_string()" ) || function_source. contains ( "String::from(" ) {
208214 violations. push ( RuleViolation {
209215 rule_name : "expensive-string-operation" . to_string ( ) ,
210- description : "String operations can be expensive in terms of gas/storage" ,
211- suggestion : "Consider using Symbol or Bytes for fixed data, or minimize string operations" ,
216+ description : "String operations can be expensive in terms of gas/storage" . to_string ( ) ,
217+ suggestion : "Consider using Symbol or Bytes for fixed data, or minimize string operations" . to_string ( ) ,
212218 line_number : function. line_number ,
219+ column_number : 0 ,
213220 variable_name : function. name . clone ( ) ,
214221 severity : ViolationSeverity :: Medium ,
215222 } ) ;
@@ -219,9 +226,10 @@ impl SorobanAnalyzer {
219226 if function_source. contains ( "Vec::new()" ) && !function_source. contains ( "with_capacity" ) {
220227 violations. push ( RuleViolation {
221228 rule_name : "vec-without-capacity" . to_string ( ) ,
222- description : "Vec::new() without capacity can cause multiple reallocations" ,
223- suggestion : "Use Vec::with_capacity() to pre-allocate memory when size is known" ,
229+ description : "Vec::new() without capacity can cause multiple reallocations" . to_string ( ) ,
230+ suggestion : "Use Vec::with_capacity() to pre-allocate memory when size is known" . to_string ( ) ,
224231 line_number : function. line_number ,
232+ column_number : 0 ,
225233 variable_name : function. name . clone ( ) ,
226234 severity : ViolationSeverity :: Medium ,
227235 } ) ;
@@ -231,9 +239,10 @@ impl SorobanAnalyzer {
231239 if function_source. contains ( ".clone()" ) {
232240 violations. push ( RuleViolation {
233241 rule_name : "unnecessary-clone" . to_string ( ) ,
234- description : "Clone operations increase resource usage and gas costs" ,
235- suggestion : "Avoid unnecessary cloning, use references where possible" ,
242+ description : "Clone operations increase resource usage and gas costs" . to_string ( ) ,
243+ suggestion : "Avoid unnecessary cloning, use references where possible" . to_string ( ) ,
236244 line_number : function. line_number ,
245+ column_number : 0 ,
237246 variable_name : function. name . clone ( ) ,
238247 severity : ViolationSeverity :: Medium ,
239248 } ) ;
@@ -254,8 +263,9 @@ impl SorobanAnalyzer {
254263 violations. push ( RuleViolation {
255264 rule_name : "missing-address-validation" . to_string ( ) ,
256265 description : format ! ( "Function '{}' takes Address parameter but may lack validation" , function. name) ,
257- suggestion : "Validate Address parameters to prevent invalid addresses" ,
266+ suggestion : "Validate Address parameters to prevent invalid addresses" . to_string ( ) ,
258267 line_number : function. line_number ,
268+ column_number : 0 ,
259269 variable_name : function. name . clone ( ) ,
260270 severity : ViolationSeverity :: Medium ,
261271 } ) ;
@@ -279,8 +289,9 @@ impl SorobanAnalyzer {
279289 violations. push ( RuleViolation {
280290 rule_name : "missing-error-handling" . to_string ( ) ,
281291 description : format ! ( "Function '{}' should return Result for error handling" , function. name) ,
282- suggestion : "Return Result<(), Error> to properly handle operation failures" ,
292+ suggestion : "Return Result<(), Error> to properly handle operation failures" . to_string ( ) ,
283293 line_number : function. line_number ,
294+ column_number : 0 ,
284295 variable_name : function. name . clone ( ) ,
285296 severity : ViolationSeverity :: Medium ,
286297 } ) ;
@@ -291,7 +302,7 @@ impl SorobanAnalyzer {
291302 }
292303
293304 /// Check for unbounded loops
294- fn check_unbounded_loops ( implementation : & SorobanImpl , source : & str ) -> Vec < RuleViolation > {
305+ fn check_unbounded_loops ( implementation : & SorobanImpl , _source : & str ) -> Vec < RuleViolation > {
295306 let mut violations = Vec :: new ( ) ;
296307
297308 for function in & implementation. functions {
@@ -304,8 +315,9 @@ impl SorobanAnalyzer {
304315 violations. push ( RuleViolation {
305316 rule_name : "unbounded-loop" . to_string ( ) ,
306317 description : format ! ( "Function '{}' contains potentially unbounded loop" , function. name) ,
307- suggestion : "Ensure loops have clear termination conditions to prevent CPU limit exhaustion" ,
318+ suggestion : "Ensure loops have clear termination conditions to prevent CPU limit exhaustion" . to_string ( ) ,
308319 line_number : function. line_number ,
320+ column_number : 0 ,
309321 variable_name : function. name . clone ( ) ,
310322 severity : ViolationSeverity :: High ,
311323 } ) ;
@@ -316,7 +328,7 @@ impl SorobanAnalyzer {
316328 }
317329
318330 /// Check for inefficient storage patterns
319- fn check_storage_patterns ( implementation : & SorobanImpl , source : & str ) -> Vec < RuleViolation > {
331+ fn check_storage_patterns ( implementation : & SorobanImpl , _source : & str ) -> Vec < RuleViolation > {
320332 let mut violations = Vec :: new ( ) ;
321333
322334 // Check for multiple storage reads of the same key
@@ -339,8 +351,9 @@ impl SorobanAnalyzer {
339351 violations. push ( RuleViolation {
340352 rule_name : "inefficient-storage-access" . to_string ( ) ,
341353 description : format ! ( "Function '{}' performs {} storage reads - consider caching" , function. name, read_count) ,
342- suggestion : "Cache frequently accessed storage values in local variables" ,
354+ suggestion : "Cache frequently accessed storage values in local variables" . to_string ( ) ,
343355 line_number : function. line_number ,
356+ column_number : 0 ,
344357 variable_name : function. name . clone ( ) ,
345358 severity : ViolationSeverity :: Medium ,
346359 } ) ;
0 commit comments