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
« 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."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from typing import ClassVar
8from lintro.parsers.base_issue import BaseIssue
11@dataclass
12class SemgrepIssue(BaseIssue):
13 """Represents an issue found by Semgrep.
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 """
26 DISPLAY_FIELD_MAP: ClassVar[dict[str, str]] = {
27 **BaseIssue.DISPLAY_FIELD_MAP,
28 "code": "check_id",
29 "severity": "severity",
30 }
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)
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)
45 def _get_message(self, base_message: str = "") -> str:
46 """Get the formatted issue message with check_id and severity prefix.
48 Args:
49 base_message: The original message to include after the prefix.
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 ""