fix: Framework detection now works by including import-only files (fixes #239)

## Problem
Framework detection was broken because files with only imports (no
classes/functions) were excluded from analysis. The architectural pattern
detector received empty file lists, resulting in 0 frameworks detected.

## Root Cause
In codebase_scraper.py:873-881, the has_content check filtered out files
that didn't have classes, functions, or other structural elements. This
excluded simple __init__.py files that only contained import statements,
which are critical for framework detection.

## Solution (3 parts)

1. **Extract imports from Python files** (code_analyzer.py:140-178)
   - Added import extraction using AST (ast.Import, ast.ImportFrom)
   - Returns imports list in analysis results
   - Now captures: "from flask import Flask" → ["flask"]

2. **Include import-only files** (codebase_scraper.py:873-881)
   - Updated has_content check to include files with imports
   - Files with imports are now included in analysis results
   - Comment added: "IMPORTANT: Include files with imports for framework
     detection (fixes #239)"

3. **Enhance framework detection** (architectural_pattern_detector.py:195-240)
   - Extract imports from all Python files in analysis
   - Check imports in addition to file paths and directory structure
   - Prioritize import-based detection (high confidence)
   - Require 2+ matches for path-based detection (avoid false positives)
   - Added debug logging: "Collected N imports for framework detection"

## Results

**Before fix:**
- Test Flask project: 0 files analyzed, 0 frameworks detected
- Files with imports: excluded from analysis
- Framework detection: completely broken

**After fix:**
- Test Flask project: 3 files analyzed, Flask detected 
- Files with imports: included in analysis
- Framework detection: working correctly
- No false positives (ASP.NET, Rails, etc.)

## Testing

Added comprehensive test suite (tests/test_framework_detection.py):
-  test_flask_framework_detection_from_imports
-  test_files_with_imports_are_included
-  test_no_false_positive_frameworks

All existing tests pass:
-  38 tests in test_codebase_scraper.py
-  54 tests in test_code_analyzer.py
-  3 new tests in test_framework_detection.py

## Impact

- Fixes issue #239 completely
- Framework detection now works for Python projects
- Import-only files (common in Python packages) are properly analyzed
- No performance impact (import extraction is fast)
- No breaking changes to existing functionality

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
yusyus
2026-02-05 22:02:06 +03:00
parent 5492fe3dc0
commit a565b87a90
4 changed files with 249 additions and 11 deletions

View File

@@ -869,10 +869,12 @@ def analyze_codebase(
analysis = analyzer.analyze_file(str(file_path), content, language)
# Only include files with actual analysis results
# Check for any meaningful content (classes, functions, nodes, properties, etc.)
# Check for any meaningful content (classes, functions, imports, nodes, properties, etc.)
# IMPORTANT: Include files with imports for framework detection (fixes #239)
has_content = (
analysis.get("classes")
or analysis.get("functions")
or analysis.get("imports") # Include import-only files (fixes #239)
or analysis.get("nodes") # Godot scenes
or analysis.get("properties") # Godot resources
or analysis.get("uniforms") # Godot shaders
@@ -1176,7 +1178,8 @@ def analyze_codebase(
arch_detector = ArchitecturalPatternDetector(enhance_with_ai=enhance_architecture)
arch_report = arch_detector.analyze(directory, results["files"])
if arch_report.patterns:
# Save architecture analysis if we have patterns OR frameworks (fixes #239)
if arch_report.patterns or arch_report.frameworks_detected:
arch_output = output_dir / "architecture"
arch_output.mkdir(parents=True, exist_ok=True)
@@ -1185,12 +1188,19 @@ def analyze_codebase(
with open(arch_json, "w", encoding="utf-8") as f:
json.dump(arch_report.to_dict(), f, indent=2)
logger.info(f"🏗️ Detected {len(arch_report.patterns)} architectural patterns")
for pattern in arch_report.patterns:
logger.info(f" - {pattern.pattern_name} (confidence: {pattern.confidence:.2f})")
if arch_report.patterns:
logger.info(f"🏗️ Detected {len(arch_report.patterns)} architectural patterns")
for pattern in arch_report.patterns:
logger.info(f" - {pattern.pattern_name} (confidence: {pattern.confidence:.2f})")
else:
logger.info("No clear architectural patterns detected")
if arch_report.frameworks_detected:
logger.info(f"📦 Detected {len(arch_report.frameworks_detected)} frameworks")
logger.info(f"📁 Saved to: {arch_json}")
else:
logger.info("No clear architectural patterns detected")
logger.info("No architectural patterns or frameworks detected")
# Analyze signal flow patterns (C3.10) - Godot projects only
signal_analysis = None