44from hashlib import sha256
55from pathlib import Path
66
7- from rich import print
8-
97from codesectools .sasts .all .sast import AllSAST
10- from codesectools .utils import group_successive , shorten_path
8+ from codesectools .utils import group_successive
119
1210
1311class ReportEngine :
@@ -82,38 +80,17 @@ def __init__(self, project: str, all_sast: AllSAST) -> None:
8280 self .result = all_sast .parser .load_from_output_dir (project_name = project )
8381 self .report_data = self .result .prepare_report_data ()
8482
85- def generate_single_defect (self , file_data : dict ) -> tuple :
83+ def generate_single_defect (self , defect_file : dict ) -> str :
8684 """Generate the HTML report for a single file with defects."""
8785 from rich .console import Console
8886 from rich .style import Style
8987 from rich .syntax import Syntax
9088 from rich .table import Table
9189 from rich .text import Text
9290
93- file_report_name = (
94- f"{ sha256 (file_data ['source_path' ].encode ()).hexdigest ()} .html"
95- )
9691 file_page = Console (record = True , file = io .StringIO ())
9792
98- # Defect stat table
99- file_stats_table = Table (title = "" )
100- for key in list (self .report_data ["files" ].values ())[0 ]["count" ].keys ():
101- file_stats_table .add_column (key .replace ("_" , " " ).title (), justify = "center" )
102-
103- rendered_scores = []
104- for v in file_data ["count" ].values ():
105- if isinstance (v , float ):
106- rendered_scores .append (f"~{ v } " )
107- else :
108- rendered_scores .append (str (v ))
109-
110- file_stats_table .add_row (* rendered_scores )
111- file_page .print (file_stats_table )
112-
113- file_report_redirect = Text (
114- shorten_path (file_data ["source_path" ], 60 ),
115- style = Style (link = file_report_name ),
116- )
93+ file_page .print (f"Score: { defect_file ['score' ]:.2f} " )
11794
11895 # Defect table
11996 defect_table = Table (title = "" , show_lines = True )
@@ -122,7 +99,7 @@ def generate_single_defect(self, file_data: dict) -> tuple:
12299 defect_table .add_column ("CWE" , justify = "center" )
123100 defect_table .add_column ("Message" )
124101 rows = []
125- for defect in file_data ["defects" ]:
102+ for defect in defect_file ["defects" ]:
126103 groups = group_successive (defect .lines )
127104 if groups :
128105 for group in groups :
@@ -161,14 +138,14 @@ def generate_single_defect(self, file_data: dict) -> tuple:
161138 file_page .print (defect_table )
162139
163140 # Syntax
164- if not Path (file_data ["source_path" ]).is_file ():
141+ if not Path (defect_file ["source_path" ]).is_file ():
165142 tippy_calls = ""
166- print (f"Source file { file_data ['source_path' ]} not found, skipping it..." )
143+ print (f"Source file { defect_file ['source_path' ]} not found, skipping it..." )
167144 else :
168- syntax = Syntax .from_path (file_data ["source_path" ], line_numbers = True )
145+ syntax = Syntax .from_path (defect_file ["source_path" ], line_numbers = True )
169146 tooltips = {}
170147 highlights = {}
171- for location in file_data ["locations" ]:
148+ for location in defect_file ["locations" ]:
172149 sast , cwe , message , (start , end ) = location
173150 for i in range (start , end + 1 ):
174151 text = (
@@ -199,13 +176,10 @@ def generate_single_defect(self, file_data: dict) -> tuple:
199176
200177 html_content = file_page .export_html (code_format = self .TEMPLATE )
201178 html_content = html_content .replace ('href="HACK' , 'id="' )
202- html_content = html_content .replace ("[name]" , file_data ["source_path" ])
179+ html_content = html_content .replace ("[name]" , defect_file ["source_path" ])
203180 html_content = html_content .replace ("[tippy_calls]" , tippy_calls )
204181
205- report_file = self .report_dir / file_report_name
206- report_file .write_text (html_content )
207-
208- return file_report_redirect , rendered_scores
182+ return html_content
209183
210184 def generate (self ) -> None :
211185 """Generate the HTML report.
@@ -215,7 +189,9 @@ def generate(self) -> None:
215189 """
216190 from rich .console import Console
217191 from rich .progress import track
192+ from rich .style import Style
218193 from rich .table import Table
194+ from rich .text import Text
219195
220196 self .TEMPLATE = self .TEMPLATE .replace (
221197 "[sasts]" , ", " .join (sast_name for sast_name in self .result .sast_names )
@@ -224,24 +200,38 @@ def generate(self) -> None:
224200 home_page = Console (record = True , file = io .StringIO ())
225201
226202 main_table = Table (title = "" )
203+ main_table .add_column ("Score" , justify = "center" )
227204 main_table .add_column ("Files" )
228- for key in list (self .report_data ["files" ].values ())[0 ]["score" ].keys ():
229- main_table .add_column (
230- key .replace ("_" , " " ).title (), justify = "center" , no_wrap = True
231- )
232205
233- for file_data in track (
234- self .report_data [ "files" ] .values (),
206+ for defect_file in track (
207+ self .report_data .values (),
235208 description = "Generating report for source file with defects..." ,
236209 ):
237- file_report_redirect , rendered_scores = self .generate_single_defect (
238- file_data
210+ html_content = self .generate_single_defect (defect_file )
211+ file_report_name = (
212+ f"{ sha256 (defect_file ['source_path' ].encode ()).hexdigest ()} .html"
213+ )
214+ file_report_redirect = Text (
215+ str (
216+ Path (defect_file ["source_path" ]).relative_to (
217+ self .result .source_path
218+ ) # ty:ignore[no-matching-overload]
219+ ),
220+ style = Style (link = file_report_name ),
221+ )
222+
223+ report_file = self .report_dir / file_report_name
224+ report_file .write_text (html_content )
225+
226+ main_table .add_row (
227+ Text (f"{ defect_file ['score' ]:.2f} " ), file_report_redirect
239228 )
240- main_table .add_row (file_report_redirect , * rendered_scores )
241229
242230 home_page .print (main_table )
243231 html_content = home_page .export_html (code_format = self .TEMPLATE )
244- html_content = html_content .replace ("[name]" , f"Project: { self .project } " )
232+ html_content = html_content .replace (
233+ "[name]" , f"Project: { self .result .source_path } "
234+ )
245235
246236 report_home_file = self .report_dir / "home.html"
247237 report_home_file .write_text (html_content )
0 commit comments