Files
superport/final_unused_analysis.py

282 lines
14 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
import os
import re
from pathlib import Path
from typing import Set, Dict, List, Tuple
import subprocess
class FinalDartFileAnalyzer:
def __init__(self, project_root: str):
self.project_root = Path(project_root)
self.lib_path = self.project_root / "lib"
# 확실히 사용되지 않는 파일들 (분석 결과 기반)
self.definitely_unused = [
# Models - Equipment 관련 (백엔드 스키마 변경으로 미사용)
"lib/data/models/equipment/equipment_in_request.dart",
"lib/data/models/equipment/equipment_io_response.dart",
"lib/data/models/equipment/equipment_list_dto.dart",
"lib/data/models/equipment/equipment_out_request.dart",
"lib/data/models/equipment/equipment_request.dart",
"lib/data/models/equipment/equipment_response.dart",
"lib/data/models/equipment_history_companies_link_dto.dart",
"lib/models/user_phone_field.dart",
# Administrator (UI에서 연결되지 않음)
"lib/screens/administrator/administrator_list.dart",
# Deprecated UI Components
"lib/screens/common/custom_widgets/autocomplete_dropdown.dart",
"lib/screens/common/custom_widgets/category_data.dart",
"lib/screens/common/custom_widgets/category_selection_field.dart",
"lib/screens/common/custom_widgets/date_picker_field.dart",
"lib/screens/common/custom_widgets/highlight_text.dart",
"lib/screens/common/widgets/address_input.dart",
"lib/screens/common/widgets/autocomplete_dropdown_field.dart",
"lib/screens/common/widgets/category_autocomplete_field.dart",
"lib/screens/common/widgets/company_branch_dropdown.dart",
# Company widgets (복잡한 UI에서 단순화됨)
"lib/screens/company/widgets/company_branch_dialog.dart",
"lib/screens/company/widgets/company_form_header.dart",
"lib/screens/company/widgets/company_info_card.dart",
"lib/screens/company/widgets/company_name_autocomplete.dart",
"lib/screens/company/widgets/duplicate_company_dialog.dart",
"lib/screens/company/widgets/map_dialog.dart",
# Equipment widgets (Phase 4에서 단순화됨)
"lib/screens/equipment/widgets/autocomplete_text_field.dart",
"lib/screens/equipment/widgets/custom_dropdown_field.dart",
"lib/screens/equipment/widgets/equipment_basic_info_section.dart",
"lib/screens/equipment/widgets/equipment_history_panel.dart",
"lib/screens/equipment/widgets/equipment_out_info.dart",
"lib/screens/equipment/widgets/equipment_status_chip.dart",
# Inventory components
"lib/screens/inventory/components/stock_level_indicator.dart",
"lib/screens/inventory/controllers/equipment_history_controller.dart",
# Model components (단순화됨)
"lib/screens/model/components/model_grouped_table.dart",
"lib/screens/model/components/model_vendor_cascade.dart",
# Rent (단순화됨)
"lib/screens/rent/rent_list_screen_simple.dart",
# Deprecated services
"lib/services/health_check_service_web.dart",
# Unused repositories
"lib/data/repositories/lookups_repository_impl.dart",
"lib/data/repositories/rent_repository.dart",
"lib/domain/repositories/lookups_repository.dart",
# Shadcn widgets (별도 컴포넌트로 대체됨)
"lib/widgets/shadcn/shad_date_picker.dart",
"lib/widgets/shadcn/shad_dialog.dart",
"lib/widgets/shadcn/shad_select.dart",
"lib/widgets/shadcn/shad_table.dart",
# Utils (안전함)
"lib/utils/address_constants.dart",
"lib/utils/equipment_display_helper.dart",
"lib/utils/formatters/business_number_formatter.dart",
"lib/utils/user_utils.dart",
# UseCase 통합 파일들 (개별 파일로 분리됨)
"lib/domain/usecases/auth/auth_usecases.dart",
"lib/domain/usecases/company/company_usecases.dart",
"lib/domain/usecases/equipment/equipment_usecases.dart",
"lib/domain/usecases/lookups/get_lookups_by_type.dart",
"lib/domain/usecases/lookups/initialize_lookups.dart",
"lib/domain/usecases/user/delete_user_usecase.dart",
"lib/domain/usecases/user/get_user_detail_usecase.dart",
"lib/domain/usecases/user/reset_password_usecase.dart",
"lib/domain/usecases/user/toggle_user_status_usecase.dart",
"lib/domain/usecases/user/update_user_usecase.dart",
"lib/domain/usecases/user/user_usecases.dart",
"lib/domain/usecases/warehouse_location/warehouse_location_usecases.dart",
]
# 검토가 필요한 파일들
self.needs_review = [
# Core utils (사용될 수 있음)
"lib/core/utils/formatters.dart",
"lib/core/utils/login_diagnostics.dart",
"lib/core/utils/validators.dart",
# Migration 관련 (일회성이지만 중요)
"lib/core/migrations/execute_migration.dart",
"lib/core/migrations/license_to_maintenance_migration.dart",
"lib/core/migrations/maintenance_data_validator.dart",
# Theme (사용될 수 있음)
"lib/core/theme/shadcn_theme.dart",
]
def check_git_status(self) -> List[str]:
"""Git에서 삭제된 dart 파일들 확인"""
try:
result = subprocess.run(['git', 'status', '--porcelain'],
cwd=self.project_root,
capture_output=True,
text=True)
git_status = result.stdout
deleted_files = []
for line in git_status.split('\n'):
if line.startswith('D ') and line.endswith('.dart'):
deleted_files.append(line[3:]) # Remove 'D ' prefix
return deleted_files
except Exception as e:
print(f"Git status 확인 실패: {e}")
return []
def verify_file_usage(self, file_path: str) -> Tuple[bool, List[str]]:
"""파일이 실제로 사용되는지 grep으로 확인"""
path_obj = Path(file_path)
if not path_obj.exists():
return False, ["파일이 존재하지 않음"]
# 파일명에서 클래스/타입 이름 추출
filename = path_obj.stem
possible_names = [
filename,
''.join(word.capitalize() for word in filename.split('_')),
filename.replace('_', ''),
]
references = []
try:
for name in possible_names:
result = subprocess.run(
['grep', '-r', '-l', name, 'lib/'],
cwd=self.project_root,
capture_output=True,
text=True
)
if result.returncode == 0:
found_files = result.stdout.strip().split('\n')
# 자기 자신과 생성 파일 제외
filtered_files = [f for f in found_files
if f != file_path and
not f.endswith('.g.dart') and
not f.endswith('.freezed.dart')]
references.extend(filtered_files)
except Exception:
pass
return len(references) > 0, list(set(references))
def generate_final_report(self) -> None:
"""최종 삭제 권장 보고서 생성"""
print("\n" + "="*80)
print("FLUTTER 프로젝트 사용되지 않는 파일 최종 분석 보고서")
print("="*80)
print(f"📂 프로젝트: {self.project_root}")
print(f"📅 분석 일시: 2025-08-29 (Phase 10 완료 후)")
# Git 상태 확인
deleted_files = self.check_git_status()
print(f"\n📋 Git Status:")
if deleted_files:
print(f" 🗑️ 이미 삭제된 파일: {len(deleted_files)}")
for deleted in deleted_files[:5]:
print(f" - {deleted}")
if len(deleted_files) > 5:
print(f" ... 및 {len(deleted_files) - 5}개 더")
else:
print(" ✅ 삭제된 dart 파일 없음")
print(f"\n🎯 삭제 권장 파일 분석:")
print(f" ✅ 안전 삭제 가능: {len(self.definitely_unused)}")
print(f" ⚠️ 검토 후 삭제: {len(self.needs_review)}")
# 카테고리별 안전 삭제 가능 파일들
categories = {
'Equipment Models (백엔드 스키마 변경)': [f for f in self.definitely_unused if 'equipment/' in f or 'equipment_' in f],
'Administrator (UI 미연결)': [f for f in self.definitely_unused if 'administrator' in f],
'Deprecated UI Components': [f for f in self.definitely_unused if 'widgets/' in f or 'custom_widgets/' in f],
'Company Widgets (단순화됨)': [f for f in self.definitely_unused if 'company/widgets/' in f],
'Equipment Widgets (Phase 4 단순화)': [f for f in self.definitely_unused if 'equipment/widgets/' in f],
'Shadcn Components (대체됨)': [f for f in self.definitely_unused if 'widgets/shadcn/' in f],
'UseCase 통합 파일들': [f for f in self.definitely_unused if 'usecases/' in f and ('_usecases.dart' in f or 'lookups/' in f)],
'기타 Utils 및 Services': [f for f in self.definitely_unused if f not in sum([
[f for f in self.definitely_unused if 'equipment/' in f or 'equipment_' in f],
[f for f in self.definitely_unused if 'administrator' in f],
[f for f in self.definitely_unused if 'widgets/' in f or 'custom_widgets/' in f],
[f for f in self.definitely_unused if 'company/widgets/' in f],
[f for f in self.definitely_unused if 'equipment/widgets/' in f],
[f for f in self.definitely_unused if 'widgets/shadcn/' in f],
[f for f in self.definitely_unused if 'usecases/' in f and ('_usecases.dart' in f or 'lookups/' in f)],
], [])],
}
print(f"\n📂 카테고리별 안전 삭제 가능 파일:")
total_safe = 0
for category, files in categories.items():
if files:
print(f"\n📁 {category} ({len(files)}개):")
for file_path in sorted(files)[:5]: # 처음 5개만 표시
print(f"{file_path}")
if len(files) > 5:
print(f" ... 및 {len(files) - 5}개 더")
total_safe += len(files)
print(f"\n⚠️ 검토 필요 파일들 ({len(self.needs_review)}개):")
for file_path in self.needs_review:
print(f" ⚠️ {file_path}")
if 'formatters.dart' in file_path:
print(f" → 유틸리티 함수들이 다른 곳에서 사용될 수 있음")
elif 'migration' in file_path:
print(f" → 마이그레이션 완료 후 삭제 가능")
elif 'theme' in file_path:
print(f" → 테마 정의 파일, 실제 사용 여부 확인 필요")
print(f"\n🚀 즉시 실행 가능한 삭제 명령어:")
print(f"# 1단계: 안전 삭제 가능 파일들 (백업 권장)")
# 10개씩 나누어 삭제 명령 생성
chunks = [self.definitely_unused[i:i+10] for i in range(0, len(self.definitely_unused), 10)]
for i, chunk in enumerate(chunks, 1):
print(f"\n# 1단계-{i}: Equipment/UI 관련 파일들 ({len(chunk)}개)")
files_str = ' \\\n '.join(f'"{f}"' for f in chunk)
print(f"rm {files_str}")
print(f"\n# 2단계: 생성 파일들 정리 (자동 재생성됨)")
print(f"flutter packages pub run build_runner clean")
print(f"flutter packages pub run build_runner build --delete-conflicting-outputs")
print(f"\n# 3단계: 분석 재실행으로 효과 확인")
print(f"flutter analyze")
print(f"\n💡 삭제 후 예상 효과:")
print(f" 📊 파일 수: 290개 → {290 - len(self.definitely_unused)}개 (약 {len(self.definitely_unused)}개 감소)")
print(f" 🧹 코드 정리: 사용되지 않는 Equipment 모델, UI 컴포넌트, UseCase 파일 제거")
print(f" 🚀 빌드 성능: 불필요한 파일 컴파일 시간 단축")
print(f" 📦 앱 크기: 미사용 코드 제거로 번들 크기 최적화")
print(f"\n⚠️ 중요 주의사항:")
print(f" 1. 삭제 전 git commit으로 백업 생성 필수")
print(f" 2. 삭제 후 flutter analyze와 flutter test 실행")
print(f" 3. 문제 발생 시 git reset --hard HEAD~1로 복원")
print(f" 4. Phase 10 완료 상태에서 안전한 파일들만 선별됨")
print(f"\n🎯 권장 삭제 순서:")
print(f" 1⃣ Equipment 관련 모델 파일 (8개) - 백엔드 스키마 변경으로 확실히 미사용")
print(f" 2⃣ UI 위젯 컴포넌트 (20+ 개) - Phase 4-7에서 단순화로 미사용 확인")
print(f" 3⃣ UseCase 통합 파일 (10개) - 개별 파일로 분리되어 미사용")
print(f" 4⃣ 기타 Utils 및 Services (나머지) - import 없음 확인됨")
print("\n" + "="*80)
def main():
project_root = "/Users/maximilian.j.sul/Documents/flutter/superport"
analyzer = FinalDartFileAnalyzer(project_root)
analyzer.generate_final_report()
if __name__ == "__main__":
main()