import os
import sys
import statistics
from pathlib import Path
EXCLUDE_DIRS = {'target', '.git', 'node_modules'}
def count_real_loc(filepath):
loc = 0
try:
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
stripped = line.strip()
if stripped and not stripped.startswith('//'):
loc += 1
except Exception as e:
print(f"無法讀取 {filepath}: {e}")
return loc
def get_rust_files(root_dir):
rust_files = []
for dirpath, dirnames, filenames in os.walk(root_dir):
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
for f in filenames:
if f.endswith('.rs'):
rust_files.append(os.path.join(dirpath, f))
return rust_files
def main():
target_dir = sys.argv[1] if len(sys.argv) > 1 else "."
print(f"🔍 開始掃描目錄: {os.path.abspath(target_dir)}")
rust_files = get_rust_files(target_dir)
if not rust_files:
print("❌ 找不到任何 .rs 檔案!")
return
file_stats = []
for path in rust_files:
loc = count_real_loc(path)
file_stats.append({'path': path, 'loc': loc})
file_stats.sort(key=lambda x: x['loc'])
loc_values = [x['loc'] for x in file_stats]
median_loc = statistics.median(loc_values)
mean_loc = statistics.mean(loc_values)
print("\n📊 專案宏觀數據:")
print(f" - 總檔案數: {len(file_stats)} 個")
print(f" - 平均行數: {mean_loc:.1f} 行")
print(f" - 中位數行數: {median_loc:.1f} 行")
print("-" * 50)
threshold = min(median_loc, 100)
candidates = [f for f in file_stats if f['loc'] <= threshold]
if candidates:
print(f"🚨 發現 {len(candidates)} 個極小部件 (LOC <= {threshold:.0f}),強烈建議合併:\n")
for f in candidates:
filename = os.path.basename(f['path'])
if filename == 'mod.rs' or filename == 'lib.rs' or filename == 'main.rs':
print(f" [略過路由/入口] {f['path']} ({f['loc']} 行)")
else:
print(f" 👉 [建議合併] {f['path']} ({f['loc']} 行)")
else:
print("✅ 您的專案很健康,沒有發現過度解耦的碎片檔案!")
print("-" * 50)
if __name__ == "__main__":
main()