run ruff
This commit is contained in:
@@ -21,11 +21,9 @@ Credits:
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Optional, Set
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,41 +31,43 @@ logger = logging.getLogger(__name__)
|
||||
@dataclass
|
||||
class ArchitecturalPattern:
|
||||
"""Detected architectural pattern"""
|
||||
|
||||
pattern_name: str # e.g., "MVC", "MVVM", "Repository"
|
||||
confidence: float # 0.0-1.0
|
||||
evidence: List[str] # List of evidence supporting detection
|
||||
components: Dict[str, List[str]] # Component type -> file paths
|
||||
framework: Optional[str] = None # Detected framework (Django, Spring, etc.)
|
||||
evidence: list[str] # List of evidence supporting detection
|
||||
components: dict[str, list[str]] # Component type -> file paths
|
||||
framework: str | None = None # Detected framework (Django, Spring, etc.)
|
||||
description: str = "" # Human-readable description
|
||||
|
||||
|
||||
@dataclass
|
||||
class ArchitecturalReport:
|
||||
"""Complete architectural analysis report"""
|
||||
patterns: List[ArchitecturalPattern]
|
||||
directory_structure: Dict[str, int] # Directory name -> file count
|
||||
total_files_analyzed: int
|
||||
frameworks_detected: List[str]
|
||||
ai_analysis: Optional[Dict] = None # AI enhancement (C3.6 integration)
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
patterns: list[ArchitecturalPattern]
|
||||
directory_structure: dict[str, int] # Directory name -> file count
|
||||
total_files_analyzed: int
|
||||
frameworks_detected: list[str]
|
||||
ai_analysis: dict | None = None # AI enhancement (C3.6 integration)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Export to dictionary"""
|
||||
return {
|
||||
'patterns': [
|
||||
"patterns": [
|
||||
{
|
||||
'pattern_name': p.pattern_name,
|
||||
'confidence': p.confidence,
|
||||
'evidence': p.evidence,
|
||||
'components': p.components,
|
||||
'framework': p.framework,
|
||||
'description': p.description
|
||||
"pattern_name": p.pattern_name,
|
||||
"confidence": p.confidence,
|
||||
"evidence": p.evidence,
|
||||
"components": p.components,
|
||||
"framework": p.framework,
|
||||
"description": p.description,
|
||||
}
|
||||
for p in self.patterns
|
||||
],
|
||||
'directory_structure': self.directory_structure,
|
||||
'total_files_analyzed': self.total_files_analyzed,
|
||||
'frameworks_detected': self.frameworks_detected,
|
||||
'ai_analysis': self.ai_analysis
|
||||
"directory_structure": self.directory_structure,
|
||||
"total_files_analyzed": self.total_files_analyzed,
|
||||
"frameworks_detected": self.frameworks_detected,
|
||||
"ai_analysis": self.ai_analysis,
|
||||
}
|
||||
|
||||
|
||||
@@ -79,25 +79,25 @@ class ArchitecturalPatternDetector:
|
||||
"""
|
||||
|
||||
# Common directory patterns for architectures
|
||||
MVC_DIRS = {'models', 'views', 'controllers', 'model', 'view', 'controller'}
|
||||
MVVM_DIRS = {'models', 'views', 'viewmodels', 'viewmodel'}
|
||||
LAYERED_DIRS = {'presentation', 'business', 'data', 'dal', 'bll', 'ui'}
|
||||
CLEAN_ARCH_DIRS = {'domain', 'application', 'infrastructure', 'presentation'}
|
||||
REPO_DIRS = {'repositories', 'repository'}
|
||||
SERVICE_DIRS = {'services', 'service'}
|
||||
MVC_DIRS = {"models", "views", "controllers", "model", "view", "controller"}
|
||||
MVVM_DIRS = {"models", "views", "viewmodels", "viewmodel"}
|
||||
LAYERED_DIRS = {"presentation", "business", "data", "dal", "bll", "ui"}
|
||||
CLEAN_ARCH_DIRS = {"domain", "application", "infrastructure", "presentation"}
|
||||
REPO_DIRS = {"repositories", "repository"}
|
||||
SERVICE_DIRS = {"services", "service"}
|
||||
|
||||
# Framework detection patterns
|
||||
FRAMEWORK_MARKERS = {
|
||||
'Django': ['django', 'manage.py', 'settings.py', 'urls.py'],
|
||||
'Flask': ['flask', 'app.py', 'wsgi.py'],
|
||||
'Spring': ['springframework', '@Controller', '@Service', '@Repository'],
|
||||
'ASP.NET': ['Controllers', 'Models', 'Views', '.cshtml', 'Startup.cs'],
|
||||
'Rails': ['app/models', 'app/views', 'app/controllers', 'config/routes.rb'],
|
||||
'Angular': ['app.module.ts', '@Component', '@Injectable', 'angular.json'],
|
||||
'React': ['package.json', 'react', 'components'],
|
||||
'Vue.js': ['vue', '.vue', 'components'],
|
||||
'Express': ['express', 'app.js', 'routes'],
|
||||
'Laravel': ['artisan', 'app/Http/Controllers', 'app/Models']
|
||||
"Django": ["django", "manage.py", "settings.py", "urls.py"],
|
||||
"Flask": ["flask", "app.py", "wsgi.py"],
|
||||
"Spring": ["springframework", "@Controller", "@Service", "@Repository"],
|
||||
"ASP.NET": ["Controllers", "Models", "Views", ".cshtml", "Startup.cs"],
|
||||
"Rails": ["app/models", "app/views", "app/controllers", "config/routes.rb"],
|
||||
"Angular": ["app.module.ts", "@Component", "@Injectable", "angular.json"],
|
||||
"React": ["package.json", "react", "components"],
|
||||
"Vue.js": ["vue", ".vue", "components"],
|
||||
"Express": ["express", "app.js", "routes"],
|
||||
"Laravel": ["artisan", "app/Http/Controllers", "app/Models"],
|
||||
}
|
||||
|
||||
def __init__(self, enhance_with_ai: bool = True):
|
||||
@@ -113,12 +113,13 @@ class ArchitecturalPatternDetector:
|
||||
if self.enhance_with_ai:
|
||||
try:
|
||||
from skill_seekers.cli.ai_enhancer import AIEnhancer
|
||||
|
||||
self.ai_enhancer = AIEnhancer()
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Failed to initialize AI enhancer: {e}")
|
||||
self.enhance_with_ai = False
|
||||
|
||||
def analyze(self, directory: Path, files_analysis: List[Dict]) -> ArchitecturalReport:
|
||||
def analyze(self, directory: Path, files_analysis: list[dict]) -> ArchitecturalReport:
|
||||
"""
|
||||
Analyze codebase for architectural patterns.
|
||||
|
||||
@@ -151,7 +152,7 @@ class ArchitecturalPatternDetector:
|
||||
patterns=patterns,
|
||||
directory_structure=dir_structure,
|
||||
total_files_analyzed=len(files_analysis),
|
||||
frameworks_detected=frameworks
|
||||
frameworks_detected=frameworks,
|
||||
)
|
||||
|
||||
# Enhance with AI if enabled (C3.6)
|
||||
@@ -161,11 +162,11 @@ class ArchitecturalPatternDetector:
|
||||
logger.info(f"✅ Detected {len(patterns)} architectural patterns")
|
||||
return report
|
||||
|
||||
def _analyze_directory_structure(self, directory: Path) -> Dict[str, int]:
|
||||
def _analyze_directory_structure(self, directory: Path) -> dict[str, int]:
|
||||
"""Analyze directory structure and count files"""
|
||||
structure = defaultdict(int)
|
||||
|
||||
for path in directory.rglob('*'):
|
||||
for path in directory.rglob("*"):
|
||||
if path.is_file():
|
||||
# Get relative directory path
|
||||
rel_dir = path.parent.relative_to(directory)
|
||||
@@ -180,13 +181,13 @@ class ArchitecturalPatternDetector:
|
||||
|
||||
return dict(structure)
|
||||
|
||||
def _detect_frameworks(self, directory: Path, files: List[Dict]) -> List[str]:
|
||||
def _detect_frameworks(self, directory: Path, files: list[dict]) -> list[str]:
|
||||
"""Detect frameworks being used"""
|
||||
detected = []
|
||||
|
||||
# Check file paths and content
|
||||
all_paths = [str(f.get('file', '')) for f in files]
|
||||
all_content = ' '.join(all_paths)
|
||||
all_paths = [str(f.get("file", "")) for f in files]
|
||||
all_content = " ".join(all_paths)
|
||||
|
||||
for framework, markers in self.FRAMEWORK_MARKERS.items():
|
||||
matches = sum(1 for marker in markers if marker.lower() in all_content.lower())
|
||||
@@ -196,7 +197,7 @@ class ArchitecturalPatternDetector:
|
||||
|
||||
return detected
|
||||
|
||||
def _detect_mvc(self, dirs: Dict[str, int], files: List[Dict], frameworks: List[str]) -> List[ArchitecturalPattern]:
|
||||
def _detect_mvc(self, dirs: dict[str, int], files: list[dict], frameworks: list[str]) -> list[ArchitecturalPattern]:
|
||||
"""Detect MVC pattern"""
|
||||
patterns = []
|
||||
|
||||
@@ -213,58 +214,62 @@ class ArchitecturalPatternDetector:
|
||||
|
||||
# Find MVC files
|
||||
for file in files:
|
||||
file_path = str(file.get('file', '')).lower()
|
||||
file_path = str(file.get("file", "")).lower()
|
||||
|
||||
if 'model' in file_path and ('models/' in file_path or '/model/' in file_path):
|
||||
components['Models'].append(file.get('file', ''))
|
||||
if len(components['Models']) == 1:
|
||||
if "model" in file_path and ("models/" in file_path or "/model/" in file_path):
|
||||
components["Models"].append(file.get("file", ""))
|
||||
if len(components["Models"]) == 1:
|
||||
evidence.append("Models directory with model classes")
|
||||
|
||||
if 'view' in file_path and ('views/' in file_path or '/view/' in file_path):
|
||||
components['Views'].append(file.get('file', ''))
|
||||
if len(components['Views']) == 1:
|
||||
if "view" in file_path and ("views/" in file_path or "/view/" in file_path):
|
||||
components["Views"].append(file.get("file", ""))
|
||||
if len(components["Views"]) == 1:
|
||||
evidence.append("Views directory with view files")
|
||||
|
||||
if 'controller' in file_path and ('controllers/' in file_path or '/controller/' in file_path):
|
||||
components['Controllers'].append(file.get('file', ''))
|
||||
if len(components['Controllers']) == 1:
|
||||
if "controller" in file_path and ("controllers/" in file_path or "/controller/" in file_path):
|
||||
components["Controllers"].append(file.get("file", ""))
|
||||
if len(components["Controllers"]) == 1:
|
||||
evidence.append("Controllers directory with controller classes")
|
||||
|
||||
# Calculate confidence
|
||||
has_models = len(components['Models']) > 0
|
||||
has_views = len(components['Views']) > 0
|
||||
has_controllers = len(components['Controllers']) > 0
|
||||
has_models = len(components["Models"]) > 0
|
||||
has_views = len(components["Views"]) > 0
|
||||
has_controllers = len(components["Controllers"]) > 0
|
||||
|
||||
if sum([has_models, has_views, has_controllers]) >= 2:
|
||||
confidence = 0.6 + (sum([has_models, has_views, has_controllers]) * 0.15)
|
||||
|
||||
# Boost confidence if framework detected
|
||||
framework = None
|
||||
for fw in ['Django', 'Flask', 'Spring', 'ASP.NET', 'Rails', 'Laravel']:
|
||||
for fw in ["Django", "Flask", "Spring", "ASP.NET", "Rails", "Laravel"]:
|
||||
if fw in frameworks:
|
||||
confidence = min(0.95, confidence + 0.1)
|
||||
framework = fw
|
||||
evidence.append(f"{fw} framework detected (uses MVC)")
|
||||
break
|
||||
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name="MVC (Model-View-Controller)",
|
||||
confidence=confidence,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
framework=framework,
|
||||
description="Separates application into Models (data), Views (UI), and Controllers (logic)"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name="MVC (Model-View-Controller)",
|
||||
confidence=confidence,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
framework=framework,
|
||||
description="Separates application into Models (data), Views (UI), and Controllers (logic)",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _detect_mvvm(self, dirs: Dict[str, int], files: List[Dict], frameworks: List[str]) -> List[ArchitecturalPattern]:
|
||||
def _detect_mvvm(
|
||||
self, dirs: dict[str, int], files: list[dict], frameworks: list[str]
|
||||
) -> list[ArchitecturalPattern]:
|
||||
"""Detect MVVM pattern"""
|
||||
patterns = []
|
||||
|
||||
# Look for ViewModels directory or classes ending with ViewModel
|
||||
has_viewmodel_dir = 'viewmodels' in dirs or 'viewmodel' in dirs
|
||||
viewmodel_files = [f for f in files if 'viewmodel' in str(f.get('file', '')).lower()]
|
||||
has_viewmodel_dir = "viewmodels" in dirs or "viewmodel" in dirs
|
||||
viewmodel_files = [f for f in files if "viewmodel" in str(f.get("file", "")).lower()]
|
||||
|
||||
if not (has_viewmodel_dir or len(viewmodel_files) >= 2):
|
||||
return patterns
|
||||
@@ -274,63 +279,68 @@ class ArchitecturalPatternDetector:
|
||||
|
||||
# Find MVVM files
|
||||
for file in files:
|
||||
file_path = str(file.get('file', '')).lower()
|
||||
classes = file.get('classes', [])
|
||||
file_path = str(file.get("file", "")).lower()
|
||||
classes = file.get("classes", [])
|
||||
|
||||
if 'model' in file_path and 'viewmodel' not in file_path:
|
||||
components['Models'].append(file.get('file', ''))
|
||||
if "model" in file_path and "viewmodel" not in file_path:
|
||||
components["Models"].append(file.get("file", ""))
|
||||
|
||||
if 'view' in file_path:
|
||||
components['Views'].append(file.get('file', ''))
|
||||
if "view" in file_path:
|
||||
components["Views"].append(file.get("file", ""))
|
||||
|
||||
if 'viewmodel' in file_path or any('viewmodel' in c.get('name', '').lower() for c in classes):
|
||||
components['ViewModels'].append(file.get('file', ''))
|
||||
if "viewmodel" in file_path or any("viewmodel" in c.get("name", "").lower() for c in classes):
|
||||
components["ViewModels"].append(file.get("file", ""))
|
||||
|
||||
if len(components['ViewModels']) >= 2:
|
||||
if len(components["ViewModels"]) >= 2:
|
||||
evidence.append(f"ViewModels directory with {len(components['ViewModels'])} ViewModel classes")
|
||||
|
||||
if len(components['Views']) >= 2:
|
||||
if len(components["Views"]) >= 2:
|
||||
evidence.append(f"Views directory with {len(components['Views'])} view files")
|
||||
|
||||
if len(components['Models']) >= 1:
|
||||
if len(components["Models"]) >= 1:
|
||||
evidence.append(f"Models directory with {len(components['Models'])} model files")
|
||||
|
||||
# Calculate confidence
|
||||
has_models = len(components['Models']) > 0
|
||||
has_views = len(components['Views']) > 0
|
||||
has_viewmodels = len(components['ViewModels']) >= 2
|
||||
has_models = len(components["Models"]) > 0
|
||||
has_views = len(components["Views"]) > 0
|
||||
has_viewmodels = len(components["ViewModels"]) >= 2
|
||||
|
||||
if has_viewmodels and (has_models or has_views):
|
||||
confidence = 0.7 if (has_models and has_views and has_viewmodels) else 0.6
|
||||
|
||||
framework = None
|
||||
for fw in ['ASP.NET', 'Angular', 'Vue.js']:
|
||||
for fw in ["ASP.NET", "Angular", "Vue.js"]:
|
||||
if fw in frameworks:
|
||||
confidence = min(0.95, confidence + 0.1)
|
||||
framework = fw
|
||||
evidence.append(f"{fw} framework detected (supports MVVM)")
|
||||
break
|
||||
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name="MVVM (Model-View-ViewModel)",
|
||||
confidence=confidence,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
framework=framework,
|
||||
description="ViewModels provide data-binding between Views and Models"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name="MVVM (Model-View-ViewModel)",
|
||||
confidence=confidence,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
framework=framework,
|
||||
description="ViewModels provide data-binding between Views and Models",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _detect_repository(self, dirs: Dict[str, int], files: List[Dict]) -> List[ArchitecturalPattern]:
|
||||
def _detect_repository(self, dirs: dict[str, int], files: list[dict]) -> list[ArchitecturalPattern]:
|
||||
"""Detect Repository pattern"""
|
||||
patterns = []
|
||||
|
||||
# Look for repositories directory or classes ending with Repository
|
||||
has_repo_dir = any(d in dirs for d in self.REPO_DIRS)
|
||||
repo_files = [f for f in files
|
||||
if 'repository' in str(f.get('file', '')).lower() or
|
||||
any('repository' in c.get('name', '').lower() for c in f.get('classes', []))]
|
||||
repo_files = [
|
||||
f
|
||||
for f in files
|
||||
if "repository" in str(f.get("file", "")).lower()
|
||||
or any("repository" in c.get("name", "").lower() for c in f.get("classes", []))
|
||||
]
|
||||
|
||||
if not (has_repo_dir or len(repo_files) >= 2):
|
||||
return patterns
|
||||
@@ -339,30 +349,35 @@ class ArchitecturalPatternDetector:
|
||||
components = defaultdict(list)
|
||||
|
||||
for file in repo_files:
|
||||
components['Repositories'].append(file.get('file', ''))
|
||||
components["Repositories"].append(file.get("file", ""))
|
||||
|
||||
if len(components['Repositories']) >= 2:
|
||||
if len(components["Repositories"]) >= 2:
|
||||
evidence.append(f"Repository pattern: {len(components['Repositories'])} repository classes")
|
||||
evidence.append("Repositories abstract data access logic")
|
||||
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name="Repository Pattern",
|
||||
confidence=0.75,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Encapsulates data access logic in repository classes"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name="Repository Pattern",
|
||||
confidence=0.75,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Encapsulates data access logic in repository classes",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _detect_service_layer(self, dirs: Dict[str, int], files: List[Dict]) -> List[ArchitecturalPattern]:
|
||||
def _detect_service_layer(self, dirs: dict[str, int], files: list[dict]) -> list[ArchitecturalPattern]:
|
||||
"""Detect Service Layer pattern"""
|
||||
patterns = []
|
||||
|
||||
has_service_dir = any(d in dirs for d in self.SERVICE_DIRS)
|
||||
service_files = [f for f in files
|
||||
if 'service' in str(f.get('file', '')).lower() or
|
||||
any('service' in c.get('name', '').lower() for c in f.get('classes', []))]
|
||||
service_files = [
|
||||
f
|
||||
for f in files
|
||||
if "service" in str(f.get("file", "")).lower()
|
||||
or any("service" in c.get("name", "").lower() for c in f.get("classes", []))
|
||||
]
|
||||
|
||||
if not (has_service_dir or len(service_files) >= 3):
|
||||
return patterns
|
||||
@@ -371,23 +386,25 @@ class ArchitecturalPatternDetector:
|
||||
components = defaultdict(list)
|
||||
|
||||
for file in service_files:
|
||||
components['Services'].append(file.get('file', ''))
|
||||
components["Services"].append(file.get("file", ""))
|
||||
|
||||
if len(components['Services']) >= 3:
|
||||
if len(components["Services"]) >= 3:
|
||||
evidence.append(f"Service layer: {len(components['Services'])} service classes")
|
||||
evidence.append("Services encapsulate business logic")
|
||||
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name="Service Layer Pattern",
|
||||
confidence=0.75,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Encapsulates business logic in service classes"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name="Service Layer Pattern",
|
||||
confidence=0.75,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Encapsulates business logic in service classes",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _detect_layered_architecture(self, dirs: Dict[str, int], files: List[Dict]) -> List[ArchitecturalPattern]:
|
||||
def _detect_layered_architecture(self, dirs: dict[str, int], files: list[dict]) -> list[ArchitecturalPattern]:
|
||||
"""Detect Layered Architecture (3-tier, N-tier)"""
|
||||
patterns = []
|
||||
|
||||
@@ -400,32 +417,34 @@ class ArchitecturalPatternDetector:
|
||||
components = defaultdict(list)
|
||||
layers_found = []
|
||||
|
||||
if 'presentation' in dirs or 'ui' in dirs:
|
||||
if "presentation" in dirs or "ui" in dirs:
|
||||
layers_found.append("Presentation Layer")
|
||||
evidence.append("Presentation/UI layer detected")
|
||||
|
||||
if 'business' in dirs or 'bll' in dirs:
|
||||
if "business" in dirs or "bll" in dirs:
|
||||
layers_found.append("Business Logic Layer")
|
||||
evidence.append("Business logic layer detected")
|
||||
|
||||
if 'data' in dirs or 'dal' in dirs:
|
||||
if "data" in dirs or "dal" in dirs:
|
||||
layers_found.append("Data Access Layer")
|
||||
evidence.append("Data access layer detected")
|
||||
|
||||
if len(layers_found) >= 2:
|
||||
confidence = 0.65 + (len(layers_found) * 0.1)
|
||||
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name=f"Layered Architecture ({len(layers_found)}-tier)",
|
||||
confidence=min(confidence, 0.9),
|
||||
evidence=evidence,
|
||||
components={'Layers': layers_found},
|
||||
description=f"Separates concerns into {len(layers_found)} distinct layers"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name=f"Layered Architecture ({len(layers_found)}-tier)",
|
||||
confidence=min(confidence, 0.9),
|
||||
evidence=evidence,
|
||||
components={"Layers": layers_found},
|
||||
description=f"Separates concerns into {len(layers_found)} distinct layers",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _detect_clean_architecture(self, dirs: Dict[str, int], files: List[Dict]) -> List[ArchitecturalPattern]:
|
||||
def _detect_clean_architecture(self, dirs: dict[str, int], files: list[dict]) -> list[ArchitecturalPattern]:
|
||||
"""Detect Clean Architecture"""
|
||||
patterns = []
|
||||
|
||||
@@ -437,50 +456,52 @@ class ArchitecturalPatternDetector:
|
||||
evidence = []
|
||||
components = defaultdict(list)
|
||||
|
||||
if 'domain' in dirs:
|
||||
if "domain" in dirs:
|
||||
evidence.append("Domain layer (core business logic)")
|
||||
components['Domain'].append('domain/')
|
||||
components["Domain"].append("domain/")
|
||||
|
||||
if 'application' in dirs:
|
||||
if "application" in dirs:
|
||||
evidence.append("Application layer (use cases)")
|
||||
components['Application'].append('application/')
|
||||
components["Application"].append("application/")
|
||||
|
||||
if 'infrastructure' in dirs:
|
||||
if "infrastructure" in dirs:
|
||||
evidence.append("Infrastructure layer (external dependencies)")
|
||||
components['Infrastructure'].append('infrastructure/')
|
||||
components["Infrastructure"].append("infrastructure/")
|
||||
|
||||
if 'presentation' in dirs:
|
||||
if "presentation" in dirs:
|
||||
evidence.append("Presentation layer (UI/API)")
|
||||
components['Presentation'].append('presentation/')
|
||||
components["Presentation"].append("presentation/")
|
||||
|
||||
if len(components) >= 3:
|
||||
patterns.append(ArchitecturalPattern(
|
||||
pattern_name="Clean Architecture",
|
||||
confidence=0.85,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Dependency inversion with domain at center, infrastructure at edges"
|
||||
))
|
||||
patterns.append(
|
||||
ArchitecturalPattern(
|
||||
pattern_name="Clean Architecture",
|
||||
confidence=0.85,
|
||||
evidence=evidence,
|
||||
components=dict(components),
|
||||
description="Dependency inversion with domain at center, infrastructure at edges",
|
||||
)
|
||||
)
|
||||
|
||||
return patterns
|
||||
|
||||
def _enhance_with_ai(self, report: ArchitecturalReport) -> Dict:
|
||||
def _enhance_with_ai(self, report: ArchitecturalReport) -> dict:
|
||||
"""Enhance architectural analysis with AI insights"""
|
||||
if not self.ai_enhancer:
|
||||
return {}
|
||||
|
||||
# Prepare summary for AI
|
||||
summary = f"""Detected {len(report.patterns)} architectural patterns:
|
||||
{chr(10).join(f'- {p.pattern_name} (confidence: {p.confidence:.2f})' for p in report.patterns)}
|
||||
{chr(10).join(f"- {p.pattern_name} (confidence: {p.confidence:.2f})" for p in report.patterns)}
|
||||
|
||||
Frameworks: {', '.join(report.frameworks_detected) if report.frameworks_detected else 'None'}
|
||||
Frameworks: {", ".join(report.frameworks_detected) if report.frameworks_detected else "None"}
|
||||
Total files: {report.total_files_analyzed}
|
||||
|
||||
Provide brief architectural insights and recommendations."""
|
||||
|
||||
try:
|
||||
response = self.ai_enhancer._call_claude(summary, max_tokens=500)
|
||||
return {'insights': response} if response else {}
|
||||
return {"insights": response} if response else {}
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ AI enhancement failed: {e}")
|
||||
return {}
|
||||
|
||||
Reference in New Issue
Block a user