Skip to content

Commit 7b278dd

Browse files
committed
update to fix the PC Lint Plus html report
1 parent e941665 commit 7b278dd

File tree

2 files changed

+61
-74
lines changed

2 files changed

+61
-74
lines changed

generate_pclp_reports.py

Lines changed: 47 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
from safe_open import open
2626
except:
2727
pass
28-
29-
g_msgs = []
30-
g_fullMpName = ""
3128

29+
from global_state import globalState
30+
3231
# PC-lint Plus message representation and parsing
3332

3433
class Message:
@@ -95,7 +94,6 @@ def parse_msgs(filename):
9594
return msgs
9695

9796
# HTML summary output
98-
9997
class FileSummary:
10098
def __init__(self, filename):
10199
self.msg_count = 0
@@ -110,8 +108,11 @@ def __init__(self, filename):
110108
def summarize_files(msgs):
111109
file_summaries = dict()
112110
for msg in msgs:
111+
msg.file = msg.file.replace("\\","/")
112+
113113
if msg.file not in file_summaries:
114114
file_summaries[msg.file] = FileSummary(msg.file)
115+
115116
file_summary = file_summaries[msg.file]
116117

117118
if msg.category == 'error':
@@ -130,6 +131,7 @@ def summarize_files(msgs):
130131

131132
if 'MISRA' in msg.text:
132133
file_summary.misra_count += 1
134+
133135
return file_summaries
134136

135137
def build_html_table(column_headers, data_source, row_generator):
@@ -162,8 +164,7 @@ def format_benign_zero(x):
162164
return str(x) if x != 0 else "<span class=\"zero\">" + str(x) + "</span>"
163165

164166
def generate_details():
165-
global g_msgs
166-
msgs = g_msgs
167+
msgs = globalState.msgs
167168

168169
out = ""
169170
out += build_html_table(
@@ -181,13 +182,13 @@ def generate_details():
181182
return out
182183

183184
def generate_summaries():
184-
185-
global g_msgs
186-
msgs = g_msgs
185+
msgs = globalState.msgs
186+
187187
out = ""
188188

189189
file_summaries = summarize_files(msgs)
190190
summary_total = FileSummary('Total')
191+
191192
for file in file_summaries.values():
192193
summary_total.msg_count += file.msg_count
193194
summary_total.error_count += file.error_count
@@ -213,24 +214,25 @@ def generate_summaries():
213214
return out
214215

215216
def generate_source():
216-
217-
global g_msgs
218-
msgs = g_msgs
219-
220-
global g_fullMpName
221-
fullMpName = g_fullMpName
222-
223-
output = "<h4>No Source Infomation avialable</h4>"
224-
225-
file_summaries = summarize_files(msgs)
217+
226218
if not checkVectorCASTVersion(21, True):
227219
print("XXX Cannot generate Source Code section of the PC-Line Report report")
228220
print("XXX The Summary and File Detail sections are present")
229221
print("XXX If you'd like to see the Source Code section of the PC-Line Report, please upgrade VectorCAST")
230-
231-
filenames = []
232-
filenames = list(map(lambda file: file.filename, file_summaries.values()))
233222

223+
fullMpName = globalState.fullMpName
224+
msgs = globalState.msgs
225+
226+
output = "<h4>No Source Infomation avialable</h4>"
227+
228+
file_summaries = summarize_files(msgs)
229+
230+
filenames = []
231+
filenames = sorted(
232+
(file.filename for file in file_summaries.values()),
233+
key=lambda f: os.path.basename(f).lower()
234+
)
235+
234236
filename_dict = {file.filename.replace("\\","/").lower(): file.filename for file in file_summaries.values()}
235237

236238
# Use a lambda inside map to create a dictionary keyed by file and then by line
@@ -239,42 +241,17 @@ def generate_source():
239241
# Group by file
240242
list(map(lambda msg: messages_by_file_and_line.setdefault(msg.file, {})
241243
.setdefault(msg.line, msg), msgs))
242-
243-
if fullMpName is None:
244-
return output
245-
246-
from vector.apps.DataAPI.vcproject_api import VCProjectApi
247-
248-
api = VCProjectApi(fullMpName)
249-
250-
localUnits = api.project.cover_api.SourceFile.all()
251-
localUnits.sort(key=lambda x: (x.name))
252-
253-
try:
254-
basepath = os.environ['WORKSPACE'].replace("\\","/") + "/"
255-
except:
256-
basepath = os.getcwd().replace("\\","/") + "/"
257244

258-
output = ""
259-
260245
listOfContent = []
261-
for f in localUnits:
262-
try:
263-
adjustedFname = os.path.relpath(f.display_path,basepath).replace("\\","/").lower()
264-
except:
265-
adjustedFname = f.display_path.lower()
266-
267-
if adjustedFname not in filename_dict.keys():
268-
continue
246+
for filename in filenames: #localUnits:
247+
248+
filename = filename.replace("\\","/")
249+
base_fname = os.path.basename(filename)
250+
adjustedFname = filename.lower()
269251

270252
fname = filename_dict[adjustedFname]
271253
orig_fname = fname;
272-
273-
smap = dict()
274-
275-
for line in f.iterate_coverage():
276-
smap[line.line_number] = line
277-
254+
278255
basename = os.path.basename(fname)
279256

280257
filename_anchor = orig_fname.replace("\\","_").replace("/","_").replace(".","_")
@@ -301,10 +278,6 @@ def generate_source():
301278
contents = fh.read()
302279
contents = contents.replace("\r\n", "\n").replace("\r","\n")
303280
for lineno, line in enumerate(contents.splitlines(), start=1):
304-
305-
# get all the statements
306-
srcLine = smap[lineno]
307-
308281
lineno_str = str(lineno)
309282
lineno_str_justified = str(lineno).ljust(6)
310283
esc_line = escape(line)
@@ -333,14 +306,12 @@ def generate_html_report(mpName, input_xml, output_html):
333306
from vector.apps.DataAPI.vcproject_api import VCProjectApi
334307
from vector.apps.ReportBuilder.custom_report import CustomReport
335308

336-
global g_fullMpName
337-
global g_msgs
338-
g_fullMpName = mpName
339-
g_msgs = parse_msgs(input_xml)
340-
309+
globalState.fullMpName = mpName
310+
globalState.msgs = parse_msgs(input_xml)
311+
341312
if output_html is None:
342313
output_html = "pclp_findings.html"
343-
314+
344315
api = VCProjectApi(mpName)
345316

346317
# Set custom report directory to the where this script was
@@ -518,31 +489,33 @@ def generate_reports(input_xml, output_text = None, output_html = None, output_j
518489
if output_text:
519490
write_output(emit_text(msgs), output_text)
520491
if output_html:
521-
generate_html_report(msgs, output_html)
522-
#write_output(emit_html(msgs), output_html)
492+
generate_html_report(full_mp_name, input_xml, output_html)
523493
if output_json:
524494
write_output(emit_json(msgs), output_json)
525495
if output_gitlab:
526496
write_output(emit_gitlab(msgs), output_gitlab)
527497

528498
def main():
529499
parser = argparse.ArgumentParser(description='Generate HTML, JSON, or text output from PC-lint Plus XML reports (XML reports are produced by running PC-lint Plus with env-xml.lnt)')
530-
parser.add_argument('--input-xml', action='store', help='XML input filename', required=True)
531-
parser.add_argument('--output-text', action='store', help='Text output filename', default = None, required=False)
532-
parser.add_argument('--output-html', action='store', help='HTML output filename', default = None, required=False)
533-
parser.add_argument('--output-json', action='store', help='JSON output filename', default = None, required=False)
534-
parser.add_argument('--output-gitlab', action='store', help='GitLab output filename', default = None, required=False)
535-
parser.add_argument('--vc-project', action='store', help='VectorCAST Project Name. Used for source view', dest="full_mp_name", default = None, required=False)
536-
parser.add_argument('-g', '--gen-lint-xml-cmd', action='store', help='Command to genreate lint XML files', dest="gen_lint_xml_cmd", default = None, required=False)
537500

501+
parser.add_argument('--input-xml', action='store', help='XML input filename', required=True)
502+
parser.add_argument('--output-html', action='store', help='HTML output filename', default = None, required=False)
503+
parser.add_argument('--vc-project', action='store', help='VectorCAST Project Name. Used for source view', dest="full_mp_name", required=True)
504+
505+
parser.add_argument('--output-text', action='store', help=argparse.SUPPRESS, default = None, required=False)
506+
parser.add_argument('--output-json', action='store', help=argparse.SUPPRESS, default = None, required=False)
507+
parser.add_argument('--output-gitlab', action='store', help=argparse.SUPPRESS, default = None, required=False)
508+
parser.add_argument('-g', '--gen-lint-xml-cmd', action='store', help=argparse.SUPPRESS, dest="gen_lint_xml_cmd", default = None, required=False)
538509
args = parser.parse_args()
539510
if args.gen_lint_xml_cmd is not None:
540511
subprocess.run(args.gen_lint_xml_cmd)
541512

542513
if not (args.output_text or args.output_html or args.output_json or args.output_gitlab):
543514
parser.error("please specify one or more outputs using the '--output-<FORMAT>=<FILENAME>' options")
544-
545-
generate_reports(args.input_xml, args.output_text, args.output_html, args.output_json, args.output_gitlab)
515+
516+
args.full_mp_name = os.path.abspath(args.full_mp_name)
517+
518+
generate_reports(input_xml = args.input_xml, output_text = args.output_text, output_html=args.output_html, output_json=args.output_json, output_gitlab=args.output_gitlab, full_mp_name = args.full_mp_name)
546519

547520
## if opened from VectorCAST GUI...
548521
if (args.full_mp_name is not None) and (args.output_html is not None) and (os.getenv('VCAST_PROG_STARTED_FROM_GUI') == "true"):

global_state.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#global_state.py
2+
3+
# global_state.py
4+
class GlobalState:
5+
_instance = None
6+
7+
def __new__(cls):
8+
if cls._instance is None:
9+
cls._instance = super().__new__(cls)
10+
cls._instance.fullMpName = ""
11+
cls._instance.msgs = []
12+
return cls._instance
13+
14+
globalState = GlobalState()

0 commit comments

Comments
 (0)