#!/usr/bin/env python3 """ Analyze Rust workspace for unused dependencies. Checks if dependencies in Cargo.toml are actually used in source code. """ import os import re import subprocess from pathlib import Path from collections import defaultdict def parse_cargo_toml(path): """Parse dependencies from Cargo.toml""" deps = [] try: with open(path, 'r') as f: content = f.read() # Extract dependencies section in_deps = False in_dev_deps = False for line in content.split('\n'): if line.strip().startswith('[dependencies]'): in_deps = True in_dev_deps = False continue elif line.strip().startswith('[dev-dependencies]'): in_deps = False in_dev_deps = True continue elif line.strip().startswith('['): in_deps = False in_dev_deps = False continue if in_deps and line.strip() and not line.strip().startswith('#'): # Extract dependency name match = re.match(r'^([a-zA-Z0-9_-]+)\s*=', line) if match: dep_name = match.group(1).replace('-', '_') deps.append((dep_name, 'normal')) elif in_dev_deps and line.strip() and not line.strip().startswith('#'): match = re.match(r'^([a-zA-Z0-9_-]+)\s*=', line) if match: dep_name = match.group(1).replace('-', '_') deps.append((dep_name, 'dev')) except Exception as e: print(f"Error parsing {path}: {e}") return deps def check_dep_usage(crate_path, dep_name): """Check if dependency is used in Rust source files""" src_path = os.path.join(crate_path, 'src') tests_path = os.path.join(crate_path, 'tests') benches_path = os.path.join(crate_path, 'benches') examples_path = os.path.join(crate_path, 'examples') patterns = [ f'use {dep_name}', f'use {dep_name}::', f'extern crate {dep_name}', f'{dep_name}::', ] for base_path in [src_path, tests_path, benches_path, examples_path]: if not os.path.exists(base_path): continue for root, dirs, files in os.walk(base_path): # Skip target directory if 'target' in dirs: dirs.remove('target') for file in files: if not file.endswith('.rs'): continue file_path = os.path.join(root, file) try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() for pattern in patterns: if pattern in content: return True except Exception: continue return False def analyze_workspace(): """Analyze all crates in workspace""" workspace_root = '/home/jgrusewski/Work/foxhunt' # Find all Cargo.toml files (excluding target directories) cargo_tomls = [] for root, dirs, files in os.walk(workspace_root): # Skip target and vendor directories if 'target' in dirs: dirs.remove('target') if '.git' in dirs: dirs.remove('.git') if 'Cargo.toml' in files: cargo_path = os.path.join(root, 'Cargo.toml') # Skip if it's a workspace-only Cargo.toml with open(cargo_path, 'r') as f: content = f.read() if '[package]' in content: cargo_tomls.append(cargo_path) results = {} for cargo_toml in cargo_tomls[:15]: # Limit to first 15 for performance crate_path = os.path.dirname(cargo_toml) crate_name = os.path.basename(crate_path) print(f"\nAnalyzing {crate_name}...") deps = parse_cargo_toml(cargo_toml) unused = [] for dep_name, dep_type in deps: # Skip workspace crates if dep_name in ['trading_engine', 'risk', 'data', 'backtesting', 'common', 'storage', 'ml', 'config', 'database', 'market_data', 'tli', 'risk_data', 'trading_data', 'adaptive_strategy', 'model_loader']: continue # Check if dependency is used if not check_dep_usage(crate_path, dep_name): unused.append((dep_name, dep_type)) if unused: results[crate_name] = unused return results if __name__ == '__main__': print("=== UNUSED DEPENDENCY ANALYSIS ===\n") results = analyze_workspace() if not results: print("\n✅ No obvious unused dependencies found!") else: print("\n⚠️ POTENTIALLY UNUSED DEPENDENCIES:\n") for crate, unused in results.items(): print(f"\n{crate}:") for dep, dep_type in unused: print(f" - {dep} ({dep_type})") print("\n=== ANALYSIS COMPLETE ===")