Coverage for lintro / parsers / semgrep / semgrep_issue.py: 100%

25 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Semgrep issue model for security and code quality findings.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass, field 

6from typing import ClassVar 

7 

8from lintro.parsers.base_issue import BaseIssue 

9 

10 

11@dataclass 

12class SemgrepIssue(BaseIssue): 

13 """Represents an issue found by Semgrep. 

14 

15 Attributes: 

16 DISPLAY_FIELD_MAP: Mapping of display field names to attribute names. 

17 check_id: Rule ID that triggered this issue. 

18 end_line: Ending line number of the issue. 

19 end_column: Ending column number of the issue. 

20 severity: Severity level (ERROR, WARNING, INFO). 

21 category: Category of the issue (security, correctness, performance, etc.). 

22 cwe: List of CWE IDs associated with this issue. 

23 metadata: Additional metadata from the rule. 

24 """ 

25 

26 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = { 

27 **BaseIssue.DISPLAY_FIELD_MAP, 

28 "code": "check_id", 

29 "severity": "severity", 

30 } 

31 

32 check_id: str = field(default="") 

33 end_line: int = field(default=0) 

34 end_column: int = field(default=0) 

35 severity: str = field(default="WARNING") 

36 category: str = field(default="") 

37 cwe: list[str] | None = field(default=None) 

38 metadata: dict[str, object] | None = field(default=None) 

39 

40 def __post_init__(self) -> None: 

41 """Initialize the inherited fields with formatted message.""" 

42 # Always format the message to include check_id and severity prefix 

43 self.message = self._get_message(self.message) 

44 

45 def _get_message(self, base_message: str = "") -> str: 

46 """Get the formatted issue message with check_id and severity prefix. 

47 

48 Args: 

49 base_message: The original message to include after the prefix. 

50 

51 Returns: 

52 Formatted issue message including check_id and severity. 

53 """ 

54 parts: list[str] = [] 

55 if self.check_id: 

56 parts.append(f"[{self.check_id}]") 

57 if self.severity: 

58 parts.append(f"{self.severity}:") 

59 if base_message: 

60 parts.append(base_message) 

61 return " ".join(parts) if parts else ""