Coverage for models.py: 100%

1"""Shared data models for Vibelexity complexity analysis."""

2

3 from __future__ import annotations

4

5 from dataclasses import dataclass, field

6

7

8@dataclass

9 class PatternViolation:

10 type: str

11 line: int

12 description: str

13 severity: str = "warning"

14

15

16@dataclass

17 class HalsteadMetrics:

18 n1: int = 0 # distinct operators

19 n2: int = 0 # distinct operands

20 N1: int = 0 # total operators

21 N2: int = 0 # total operands

22 vocabulary: int = 0 # n = n1 + n2

23 length: int = 0 # N = N1 + N2

24 volume: float = 0.0 # V = N * log2(n)

25 difficulty: float = 0.0 # D = (n1/2) * (N2/n2)

26 effort: float = 0.0 # E = D * V

27 time: float = 0.0 # T = E / 18 (seconds)

28 bugs: float = 0.0 # B = E^(2/3) / 3000

29

30

31@dataclass

32 class FunctionComplexity:

33 name: str

34 line: int

35 complexity: int

36 halstead: HalsteadMetrics | None = None

37 npath: int | None = None

38 dtd: int | None = None

39 mi: float | None = None

40 ldi: float | None = None

41 cyclomatic: int | None = None

42 type1_hash: str | None = None

43 type2_hash: str | None = None

44 func_loc: int = 0

45 stmt_count: int = 0

46

47

48@dataclass

49 class DuplicateCluster:

50 dup_type: int # 1 or 2

51 hash_value: str

52 members: list[tuple[str, FunctionComplexity]]

53

54

55@dataclass

56 class FileComplexity:

57 path: str

58 functions: list[FunctionComplexity] = field(default_factory=list)

59 loc: int = 0

60 lloc: int = 0

61 sloc: int = 0

62 pattern_violations: list[PatternViolation] = field(default_factory=list)

63

64 @property

65 def total(self) -> int:

66 return sum(f.complexity for f in self.functions)

67

68

69@dataclass

70 class DeadCodeViolation:

71 type: str

72 symbol: str | None

73 location: str

74 line: int

75 confidence: str

76

77

78@dataclass

79 class FunctionDefinition:

80 name: str

81 filepath: str

82 line: int

83 def_type: str

84 class_name: str | None = None

85 params: list[str] = field(default_factory=list)

86

87

88@dataclass

89 class CallEdge:

90 caller_file: str

91 caller_function: str

92 caller_line: int

93 callee_file: str | None

94 callee_function: str

95 callee_line: int | None

96 call_site_line: int

97 call_type: str = "local"

98 receiver_object: str | None = None

99

100

101@dataclass

102 class CallGraph:

103 functions: dict[tuple[str, str], FunctionDefinition] = field(default_factory=dict)

104 calls: list[CallEdge] = field(default_factory=list)

105 reverse_calls: dict[str, list[CallEdge]] = field(default_factory=dict)