@@ -98,19 +98,250 @@ create or replace package body ut_coverage_report_html_helper is
9898 return '<a href="#' || object_id(a_object_full_name) || '" class="src_link" title="' || a_object_full_name || '">' || a_object_full_name || '</a>';
9999 end;
100100
101+
102+
103+
104+ function get_details_file_content(a_object_id varchar2, a_unit ut_object_name, a_unit_coverage ut_coverage.t_unit_coverage)
105+ return clob is
106+ l_source_code ut_varchar2_list;
107+ l_result clob;
108+
109+ function get_block_file_attributes(a_coverage_unit ut_coverage.t_unit_coverage) return varchar2 is
110+ l_result varchar2(32767);
111+ begin
112+ if (a_coverage_unit.partcovered_lines is not null) OR (a_coverage_unit.partcovered_lines > 0) then
113+ l_result := ' (including <span class="yellow"><b>'|| a_coverage_unit.partcovered_lines ||'</b> lines partially covered</span> )';
114+ else
115+ l_result := null;
116+ end if;
117+ return l_result;
118+ end;
119+
120+ function get_common_file_attributes(a_coverage_unit ut_coverage.t_unit_coverage) return varchar2 is
121+ l_attributes varchar2(32767);
122+ begin
123+ l_attributes := '<div> <b>' ||(a_coverage_unit.covered_lines + a_coverage_unit.uncovered_lines)
124+ ||'</b> relevant lines. ' || '<span class="green"><b>' || a_coverage_unit.covered_lines
125+ ||'</b> lines covered</span>'
126+ || get_block_file_attributes(a_coverage_unit)
127+ || ' and <span class="red"><b>' || a_coverage_unit.uncovered_lines ||'</b> lines missed</span>';
128+ return l_attributes;
129+ end;
130+
131+ function build_details_file_content(a_object_id varchar2, a_object_full_name varchar2, a_source_code ut_varchar2_list, a_coverage_unit ut_coverage.t_unit_coverage)
132+ return clob is
133+ l_file_part varchar2(32767);
134+ l_result clob;
135+ l_coverage_pct number(5, 2);
136+ l_coverage_block_pct number(5, 2);
137+ l_hits varchar2(30);
138+ l_blocks varchar2(30);
139+ begin
140+ dbms_lob.createtemporary(l_result, true);
141+
142+ l_coverage_pct := coverage_pct(a_coverage_unit.covered_lines, a_coverage_unit.uncovered_lines);
143+
144+ l_file_part := '<div class="source_table" id="' || a_object_id || '"><div class="header"> <h3>' ||
145+ dbms_xmlgen.convert(a_object_full_name) || '</h3><h4><span class="' || coverage_css_class(l_coverage_pct) || '">'
146+ || l_coverage_pct || ' %</span> lines covered</h4>'
147+ ||get_common_file_attributes(a_coverage_unit) ||'</div></div><pre><ol>';
148+ ut_utils.append_to_clob(l_result, l_file_part);
149+
150+ for line_no in 1 .. a_source_code.count loop
151+ if not a_coverage_unit.lines.exists(line_no) then
152+ l_file_part := '
153+ <li class="' || line_status(null) || '" data-hits="" data-linenumber="' || line_no || '">
154+ <code class="sql">' || (dbms_xmlgen.convert(a_source_code(line_no))) ||
155+ '</code></li>';
156+ else
157+ l_hits := to_char(a_coverage_unit.lines(line_no).executions);
158+ if nvl(a_coverage_unit.lines(line_no).covered_blocks,0) < nvl(a_coverage_unit.lines(line_no).no_blocks,0)
159+ and nvl(a_coverage_unit.lines(line_no).partcove,0) = 1 then
160+ l_blocks := to_char(a_coverage_unit.lines(line_no).covered_blocks) || chr(47)||
161+ to_char(a_coverage_unit.lines(line_no).no_blocks);
162+ else
163+ l_blocks := null;
164+ end if;
165+
166+ l_file_part := '
167+ <li class="' || line_status(a_coverage_unit.lines(line_no)) || '" data-hits="' ||
168+ dbms_xmlgen.convert(l_hits)|| '"'||
169+ case
170+ when l_blocks is not null
171+ then ' data-blocks="'||dbms_xmlgen.convert(l_blocks)||'"'
172+ else
173+ null
174+ end
175+ ||' data-linenumber="' || (line_no) || '">';
176+ if a_coverage_unit.lines(line_no).executions > 0 then
177+
178+ l_file_part := l_file_part ||
179+ case when l_blocks is not null
180+ then '
181+ <span class="blocks">' ||dbms_xmlgen.convert(l_blocks) ||
182+ '</span>'
183+ else
184+ null
185+ end
186+ || '
187+ <span class="hits">' || dbms_xmlgen.convert(l_hits) ||
188+ '</span>';
189+ end if;
190+ l_file_part := l_file_part || '
191+ <code class="sql">' || (dbms_xmlgen.convert(a_source_code(line_no))) ||
192+ '</code></li>';
193+ end if;
194+ ut_utils.append_to_clob(l_result, l_file_part);
195+ end loop;
196+
197+ l_file_part := '</ol></pre></div>';
198+ ut_utils.append_to_clob(l_result, l_file_part);
199+ return l_result;
200+ end;
201+ begin
202+ l_source_code := ut_coverage_helper.get_tmp_table_object_lines(a_unit.owner, a_unit.name);
203+ dbms_lob.createtemporary(l_result, true);
204+ l_result := build_details_file_content(a_object_id
205+ ,a_unit.identity
206+ ,l_source_code
207+ ,a_unit_coverage
208+ );
209+ return l_result;
210+ end;
211+
212+ function get_block_list_attributes(a_coverage_unit ut_coverage.t_coverage) return varchar2 is
213+ l_result varchar2(32767);
214+ begin
215+ if (a_coverage_unit.partcovered_lines is not null) OR (a_coverage_unit.partcovered_lines > 0) then
216+ l_result := ' (including <span class="yellow"><b>'|| a_coverage_unit.partcovered_lines ||'</b> lines partially covered</span> )';
217+ else
218+ l_result := null;
219+ end if;
220+ return l_result;
221+ end;
222+
223+ function file_list(a_title varchar2, a_coverage ut_coverage.t_coverage) return clob is
224+ l_file_part varchar2(32767);
225+ l_title varchar2(100) := 'All files';
226+ l_coverage_pct number(5, 2);
227+ l_coverage_block_pct number(5, 2);
228+ l_result clob;
229+ l_id varchar2(50) := object_id(a_title);
230+ l_unit_coverage ut_coverage.t_unit_coverage;
231+ l_unit ut_coverage.t_object_name;
232+ begin
233+ l_coverage_pct := coverage_pct(a_coverage.covered_lines, a_coverage.uncovered_lines);
234+
235+ dbms_lob.createtemporary(l_result, true);
236+
237+ l_file_part := '<div class="file_list_container" id="' || l_id || '">' || '<h2><span class="group_name">' || l_title ||
238+ '</span>' || ' (<span class="covered_percent"><span class="' || coverage_css_class(l_coverage_pct) || '">' ||
239+ l_coverage_pct || '%</span></span>' || ' lines covered'||
240+ ' at <span class="covered_strength">' ||
241+ '<span class="' ||line_hits_css_class(executions_per_line(a_coverage.executions
242+ ,a_coverage.uncovered_lines + a_coverage.covered_lines)) || '">' ||
243+ executions_per_line(a_coverage.executions, a_coverage.uncovered_lines + a_coverage.covered_lines)
244+ || '</span></span> hits/line)</h2>' || '<a name="' || l_id || '"></a>' || '<div><b>' ||
245+ a_coverage.objects.count || '</b> files in total. </div><div>' || '<b>' ||
246+ (a_coverage.uncovered_lines + a_coverage.covered_lines)
247+ || '</b> relevant lines. ' || '<span class="green"><b>' || a_coverage.covered_lines ||
248+ '</b> lines covered</span>'|| get_block_list_attributes(a_coverage)
249+ ||' and <span class="red"><b>' || a_coverage.uncovered_lines || '</b> lines missed.</span>'||
250+ '<table class="file_list"><thead>' || '<tr>' ||
251+ '<th>File</th><th>% covered</th><th>Lines</th><th>Relevant Lines</th><th>Lines covered</th><th>Lines missed</th><th>'
252+ ||'Avg. Hits / Line </th>' ||
253+ '</tr></thead><tbody>';
254+ ut_utils.append_to_clob(l_result, l_file_part);
255+ l_unit := a_coverage.objects.first;
256+ loop
257+ exit when l_unit is null;
258+ l_unit_coverage := a_coverage.objects(l_unit);
259+ l_coverage_pct := coverage_pct(l_unit_coverage.covered_lines, l_unit_coverage.uncovered_lines);
260+
261+ l_file_part := chr(10) || '<tr>' || '<td class="strong">' || link_to_source_file(dbms_xmlgen.convert(l_unit)) ||
262+ '</td>' || '<td class="' || coverage_css_class(l_coverage_pct) || ' strong">' || l_coverage_pct ||
263+ ' %</td>' || '<td>' || l_unit_coverage.total_lines || '</td>' || '<td>' ||
264+ (l_unit_coverage.covered_lines + l_unit_coverage.uncovered_lines) || '</td>' || '<td>' ||
265+ l_unit_coverage.covered_lines || '</td><td>' || l_unit_coverage.uncovered_lines || '</td>' ||
266+ '<td>' || to_char(executions_per_line(l_unit_coverage.executions
267+ ,l_unit_coverage.uncovered_lines + l_unit_coverage.covered_lines))
268+ || '</td></tr>';
269+ ut_utils.append_to_clob(l_result, l_file_part);
270+ l_unit := a_coverage.objects.next(l_unit);
271+ end loop;
272+ l_file_part := '</tbody></table></div>';
273+ ut_utils.append_to_clob(l_result, l_file_part);
274+ return l_result;
275+ end;
276+
101277 /*
102278 * public definitions
103279 */
104280 function get_index(a_coverage_data ut_coverage.t_coverage, a_assets_path varchar2, a_project_name varchar2 := null, a_command_line varchar2 := null)
105281 return clob is
282+
283+ l_file_part varchar2(32767);
106284 l_result clob;
107- begin
108- $if dbms_db_version.version = 12 and dbms_db_version.release >= 2 or dbms_db_version.version > 12 $then
109- l_result := ut_extended_report_html_helper.get_index(a_coverage_data => a_coverage_data, a_assets_path => a_assets_path,a_project_name=>a_project_name,a_command_line=> a_command_line);
110- $else
111- l_result := ut_proftab_report_html_helper.get_index(a_coverage_data => a_coverage_data, a_assets_path => a_assets_path,a_project_name=>a_project_name,a_command_line=> a_command_line);
112- $end
285+ l_title varchar2(250);
286+ l_coverage_pct number(5, 2);
287+ l_time_str varchar2(50);
288+ l_using varchar2(1000);
289+ l_unit ut_coverage.t_full_name;
290+ begin
291+ l_coverage_pct := coverage_pct(a_coverage_data.covered_lines, a_coverage_data.uncovered_lines);
113292
293+ l_time_str := ut_utils.to_string(sysdate);
294+ l_using := case
295+ when a_command_line is not null then
296+ '<br/>using ' || dbms_xmlgen.convert(a_command_line)
297+ end;
298+ dbms_lob.createtemporary(l_result, true);
299+
300+ l_title := case
301+ when a_project_name is null then
302+ 'Code coverage'
303+ else
304+ dbms_xmlgen.convert(a_project_name) || ' code coverage'
305+ end;
306+ --TODO - build main file containing total run data and per schema data
307+ l_file_part := '<!DOCTYPE html><html xmlns=''http://www.w3.org/1999/xhtml''><head>' || '<title>' || l_title ||
308+ '</title>' || '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' ||
309+ '<script src=''' || a_assets_path || 'application.js'' type=''text/javascript''></script>' ||
310+ '<link href=''' || a_assets_path ||
311+ 'application.css'' media=''screen, projection, print'' rel=''stylesheet'' type=''text/css''>' ||
312+ '<link rel="shortcut icon" type="image/png" href="' || a_assets_path || 'favicon_' ||
313+ coverage_css_class(l_coverage_pct) || '.png" />' || '<link rel="icon" type="image/png" href="' ||
314+ a_assets_path || 'favicon_' || coverage_css_class(l_coverage_pct) || '.png" />' || '</head>' ||
315+ '<body><div id="loading"><img src="' || a_assets_path || 'loading.gif" alt="loading"/></div>' ||
316+ '<div id="wrapper" style="display:none;">' ||
317+ '<div class="timestamp">Generated <abbr class="timeago" title="' || l_time_str || '">' || l_time_str ||
318+ '</abbr></div>' || '<ul class="group_tabs"></ul>' || '<div id="content">';
319+ ut_utils.append_to_clob(l_result, l_file_part);
320+
321+ dbms_lob.append(l_result, file_list('All files', a_coverage_data));
322+
323+ l_file_part := chr(10) || '</div><div id="footer">' ||
324+ 'Generated by <a href="http://github.com/utPLSQL/utPLSQL">utPLSQL ' || ut_utils.gc_version ||
325+ '</a><br/>' ||
326+ 'Based on <a href="http://github.com/colszowka/simplecov-html">simplecov-html</a> v0.10.0 ' ||
327+ l_using || '' || '</div><div class="source_files">';
328+ ut_utils.append_to_clob(l_result, l_file_part);
329+
330+ l_unit := a_coverage_data.objects.first;
331+ loop
332+ exit when l_unit is null;
333+ dbms_lob.append(l_result
334+ ,get_details_file_content(object_id(l_unit)
335+ ,ut_object_name(a_coverage_data.objects(l_unit).owner
336+ ,a_coverage_data.objects(l_unit).name)
337+ ,a_coverage_data.objects(l_unit)
338+ ));
339+ l_unit := a_coverage_data.objects.next(l_unit);
340+ end loop;
341+
342+ l_file_part := '</div></div></body></html>';
343+
344+ ut_utils.append_to_clob(l_result, l_file_part);
114345 return l_result;
115346 end;
116347
0 commit comments