Coverage for src\llm_code_lens\analyzer\config.py: 17%
52 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-05-25 12:07 +0300
« prev ^ index » next coverage.py v7.7.0, created at 2025-05-25 12:07 +0300
1"""
2Configuration file analyzers for project context.
3"""
5import json
6from pathlib import Path
7from typing import Dict, Optional, List
9try:
10 import tomli
11except ImportError:
12 tomli = None
14def analyze_package_json(file_path: Path) -> Optional[Dict]:
15 """Extract key information from package.json."""
16 if not file_path.exists():
17 return None
19 try:
20 with open(file_path, 'r') as f:
21 data = json.load(f)
23 return {
24 'name': data.get('name'),
25 'version': data.get('version'),
26 'description': data.get('description'),
27 'main': data.get('main'),
28 'scripts': list(data.get('scripts', {}).keys()),
29 'dependencies': list(data.get('dependencies', {}).keys()),
30 'devDependencies': list(data.get('devDependencies', {}).keys()),
31 'framework_indicators': _detect_frameworks(data)
32 }
33 except (json.JSONDecodeError, Exception):
34 return {'error': 'Failed to parse package.json'}
36def _detect_frameworks(package_data: dict) -> List[str]:
37 """Detect frameworks based on dependencies."""
38 frameworks = []
39 all_deps = {**package_data.get('dependencies', {}), **package_data.get('devDependencies', {})}
41 if 'react' in all_deps: frameworks.append('React')
42 if 'next' in all_deps: frameworks.append('Next.js')
43 if 'vue' in all_deps: frameworks.append('Vue.js')
44 if 'angular' in all_deps: frameworks.append('Angular')
45 if 'typescript' in all_deps: frameworks.append('TypeScript')
46 if 'tailwindcss' in all_deps: frameworks.append('Tailwind CSS')
48 return frameworks
50def analyze_tsconfig(file_path: Path) -> Optional[Dict]:
51 """Extract TypeScript configuration."""
52 if not file_path.exists():
53 return None
55 try:
56 with open(file_path, 'r') as f:
57 # Simple JSON parsing (ignoring comments for now)
58 content = f.read()
59 # Remove comments (basic approach)
60 lines = [line.split('//')[0].strip() for line in content.split('\n')]
61 clean_content = '\n'.join(lines)
62 data = json.loads(clean_content)
64 compiler_options = data.get('compilerOptions', {})
65 return {
66 'target': compiler_options.get('target'),
67 'module': compiler_options.get('module'),
68 'jsx': compiler_options.get('jsx'),
69 'strict': compiler_options.get('strict'),
70 'baseUrl': compiler_options.get('baseUrl'),
71 'paths': bool(compiler_options.get('paths')),
72 'include': data.get('include', []),
73 'exclude': data.get('exclude', [])
74 }
75 except (json.JSONDecodeError, Exception):
76 return {'error': 'Failed to parse tsconfig.json'}
78def extract_readme_summary(file_path: Path) -> Optional[Dict]:
79 """Extract first few lines of README for project description."""
80 readme_files = ['README.md', 'README.txt', 'README.rst', 'README']
82 for readme_name in readme_files:
83 readme_path = file_path / readme_name
84 if readme_path.exists():
85 try:
86 with open(readme_path, 'r', encoding='utf-8') as f:
87 lines = f.readlines()[:10] # First 10 lines
88 content = ''.join(lines).strip()
90 return {
91 'filename': readme_name,
92 'summary': content[:500] + '...' if len(content) > 500 else content,
93 'has_badges': '[![' in content,
94 'has_installation': any(word in content.lower() for word in ['install', 'setup', 'getting started'])
95 }
96 except Exception:
97 continue
99 return None