#!/usr/bin/env python3 """Analyze clippy warnings from output file.""" import re from collections import defaultdict from pathlib import Path def analyze_clippy_output(filepath): """Analyze clippy output and categorize warnings.""" warning_types = defaultdict(list) warning_counts = defaultdict(int) file_warnings = defaultdict(list) with open(filepath, 'r', encoding='utf-8') as f: lines = f.readlines() current_warning = None current_file = None for i, line in enumerate(lines): # Extract warning type and location if line.strip().startswith('warning:') and '-->' in (lines[i+1] if i+1 < len(lines) else ''): warning_text = line.strip() location = lines[i+1].strip() # Extract file path match = re.search(r'--> (.+):(\d+):(\d+)', location) if match: file_path = match.group(1) line_num = match.group(2) # Extract warning type from help text or note warning_type = "unknown" for j in range(i+1, min(i+10, len(lines))): if 'clippy::' in lines[j]: clippy_match = re.search(r'clippy::(\w+)', lines[j]) if clippy_match: warning_type = clippy_match.group(1) break warning_counts[warning_type] += 1 file_warnings[file_path].append({ 'type': warning_type, 'line': line_num, 'text': warning_text.replace('warning: ', '') }) return warning_counts, file_warnings def categorize_severity(warning_type): """Categorize warning by severity.""" critical = { 'correctness', 'suspicious', 'panic', 'unwrap_used', 'expect_used', 'indexing_slicing', 'panic_in_result_fn' } high = { 'perf', 'performance', 'nursery', 'cargo', 'missing_errors_doc', 'missing_panics_doc', 'must_use_candidate' } medium = { 'complexity', 'style', 'pedantic', 'redundant_clone', 'needless_pass_by_value', 'unnecessary_wraps' } low = { 'restriction', 'needless_raw_string_hashes', 'doc_markdown', 'missing_const_for_fn', 'default_numeric_fallback' } if warning_type in critical: return 'CRITICAL' elif warning_type in high: return 'HIGH' elif warning_type in medium: return 'MEDIUM' elif warning_type in low: return 'LOW' else: return 'UNKNOWN' def main(): filepath = Path('/home/jgrusewski/Work/foxhunt/clippy_full_output.txt') warning_counts, file_warnings = analyze_clippy_output(filepath) # Categorize by severity severity_counts = defaultdict(int) severity_types = defaultdict(list) for warning_type, count in warning_counts.items(): severity = categorize_severity(warning_type) severity_counts[severity] += count severity_types[severity].append((warning_type, count)) print("=" * 80) print("CLIPPY WARNING ANALYSIS") print("=" * 80) print() # Summary by severity print("SEVERITY SUMMARY:") print("-" * 80) for severity in ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'UNKNOWN']: if severity in severity_counts: print(f"{severity:10s}: {severity_counts[severity]:5d} warnings") print() # Top warnings by type print("TOP WARNING TYPES:") print("-" * 80) sorted_warnings = sorted(warning_counts.items(), key=lambda x: x[1], reverse=True) for warning_type, count in sorted_warnings[:20]: severity = categorize_severity(warning_type) print(f" [{severity:8s}] {warning_type:40s}: {count:5d}") print() # Files with most warnings print("FILES WITH MOST WARNINGS:") print("-" * 80) sorted_files = sorted(file_warnings.items(), key=lambda x: len(x[1]), reverse=True) for filepath, warnings in sorted_files[:15]: print(f" {filepath:60s}: {len(warnings):5d} warnings") print() # Critical warnings detail print("CRITICAL WARNINGS DETAIL:") print("-" * 80) for warning_type, count in sorted_warnings: if categorize_severity(warning_type) == 'CRITICAL': print(f"\n{warning_type.upper()} ({count} occurrences):") # Find examples examples = [] for filepath, warnings in file_warnings.items(): for w in warnings: if w['type'] == warning_type and len(examples) < 3: examples.append(f" - {filepath}:{w['line']} - {w['text']}") for ex in examples: print(ex) if __name__ == '__main__': main()