-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathParseAndSerializeSpotbugs.py
More file actions
101 lines (77 loc) · 3.16 KB
/
ParseAndSerializeSpotbugs.py
File metadata and controls
101 lines (77 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'''
Created on Nov. 23, 2017
@author Andrew Habib
'''
'''
Currently, the spotbugs output files may contain
analysis results of more than one .java file.
This happens in cases where analyzed bug involves
more than one .java file.
'''
import json
import os
import sys
from xml.etree import cElementTree as ET
from Util import XmlReader, SpotbugsMsg, CustomEncoder, NO_WARNING
def parse_spotbugs_xml_output(proj, tree):
reports = []
has_bugs = False
# Case where report file is NOT empty
try:
for _, elem in tree:
if elem.tag == "BugInstance":
'''
Tags gauaranteed to exist
'''
has_bugs = True
cls = elem.find('Class').get("classname", "")
cat = elem.attrib['category']
abbrev = elem.attrib['abbrev']
typ = elem.attrib['type']
prio = elem.attrib['priority']
rank = elem.attrib['rank']
msg = elem.find('LongMessage').text
'''
Optional Tags (may not always exist)
'''
elem_mth = elem.find('Method')
if elem_mth:
mth = elem_mth.get('name', '')
else: mth = ''
elem_field = elem.find('Field')
if elem_field:
field = elem_field.get('name', '')
else: field = ''
lines = []
elem_src_lines = elem.findall('SourceLine')
if elem_src_lines:
for src_line in elem_src_lines:
if (src_line.tag == 'SourceLine' and
all (attr in src_line.attrib for attr in ['start', 'end']) and
src_line.get('classname') == cls):
lines.append((src_line.get('start'), src_line.get('end'), src_line.get('role')))
parsed_msg = SpotbugsMsg(proj, cls, cat, abbrev, typ, prio, rank, msg, mth, field, lines)
reports.append(parsed_msg)
except ET.ParseError as err:
# print(proj + " failed to parse.")
# print(err)
pass
# Case where report file is empty
if not has_bugs:
reports.append(SpotbugsMsg(proj, "", "", "", NO_WARNING, "", "", "", "", "", ""))
return reports
'''
Takes only one argument: path to spotbugs raw data
'''
if __name__ == '__main__':
location_to_data = os.path.join(os.getcwd(), sys.argv[1])
list_of_data = sorted(os.listdir(location_to_data))
data_paths = list(map(lambda f: os.path.join(location_to_data, f), list_of_data))
parsed_reports_per_project = []
for proj, tree in XmlReader(data_paths):
parsed_reports_per_project.extend(parse_spotbugs_xml_output(proj, tree))
# time_stamp = time.strftime("%Y%m%d-%H%M%S")
time_stamp = ''
parsed_output_file_name = "sb_parsed" + time_stamp + ".json"
with open(parsed_output_file_name, "w") as file:
json.dump(parsed_reports_per_project, file, cls=CustomEncoder, indent=4)