Coverage for src\llm_code_lens\analyzer\javascript.py: 100%

35 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-01-12 10:23 +0200

1# src/codelens/analyzer/javascript.py 

2import re 

3from pathlib import Path 

4from typing import Dict, List 

5 

6class JavaScriptAnalyzer: 

7 """JavaScript/TypeScript code analyzer using regex patterns.""" 

8 

9 def analyze_file(self, file_path: Path) -> dict: 

10 """Analyze a JavaScript/TypeScript file.""" 

11 with open(file_path, 'r', encoding='utf-8') as f: 

12 content = f.read() 

13 

14 analysis = { 

15 'imports': [], 

16 'exports': [], 

17 'functions': [], 

18 'classes': [], 

19 'comments': [], 

20 'todos': [], 

21 'metrics': { 

22 'loc': len(content.splitlines()), 

23 'classes': 0, 

24 'functions': 0, 

25 'imports': 0, 

26 } 

27 } 

28 

29 # Extract imports and exports 

30 import_pattern = r'^(?:import|export)\s+.*?[\n;]' 

31 for match in re.finditer(import_pattern, content, re.MULTILINE): 

32 stmt = match.group().strip() 

33 analysis['metrics']['imports'] += 1 

34 if stmt.startswith('import'): 

35 analysis['imports'].append(stmt) 

36 else: 

37 analysis['exports'].append(stmt) 

38 

39 # Extract functions 

40 function_pattern = r'(?:async\s+)?(?:function\s+(\w+)|const\s+(\w+)\s*=\s*(?:async\s+)?(?:\([^)]*\)\s*=>|\function\s*\([^)]*\)))' 

41 for match in re.finditer(function_pattern, content): 

42 analysis['metrics']['functions'] += 1 

43 name = match.group(1) or match.group(2) 

44 if name: 

45 analysis['functions'].append({ 

46 'name': name, 

47 'line_number': content[:match.start()].count('\n') + 1 

48 }) 

49 

50 # Extract classes 

51 class_pattern = r'class\s+(\w+)(?:\s+extends\s+(\w+))?\s*\{' 

52 for match in re.finditer(class_pattern, content): 

53 analysis['metrics']['classes'] += 1 

54 analysis['classes'].append({ 

55 'name': match.group(1), 

56 'extends': match.group(2), 

57 'line_number': content[:match.start()].count('\n') + 1 

58 }) 

59 

60 # Extract comments and TODOs 

61 comment_patterns = [ 

62 r'//.*$', # Single-line comments 

63 r'/\*[^*]*\*+(?:[^/*][^*]*\*+)*/' # Multi-line comments 

64 ] 

65 

66 for pattern in comment_patterns: 

67 for match in re.finditer(pattern, content, re.MULTILINE): 

68 comment = match.group() 

69 # Clean up comment markers 

70 comment = (comment.strip('/') # For single-line 

71 .strip('*') # For multi-line 

72 .strip()) 

73 

74 line_number = content[:match.start()].count('\n') + 1 

75 

76 if any(marker in comment.upper() 

77 for marker in ['TODO', 'FIXME', 'XXX']): 

78 analysis['todos'].append({ 

79 'line': line_number, 

80 'text': comment 

81 }) 

82 else: 

83 analysis['comments'].append({ 

84 'line': line_number, 

85 'text': comment 

86 }) 

87 

88 return analysis