xref: /llvm-project/llvm/utils/clang-parse-diagnostics-file (revision 0c85c488e2b5be54ce26c9f772e66d48a9290c51)
1800f223bSChad Rosier#!/usr/bin/env python
2800f223bSChad Rosier
3fa40268fSDaniel Dunbarimport os
4800f223bSChad Rosierimport plistlib
5800f223bSChad Rosier
6800f223bSChad Rosierdef main():
7800f223bSChad Rosier    from optparse import OptionParser, OptionGroup
8800f223bSChad Rosier    parser = OptionParser("""\
9800f223bSChad RosierUsage: %prog [options] <path>
10800f223bSChad Rosier
11800f223bSChad RosierUtility for dumping Clang-style logged diagnostics.\
12800f223bSChad Rosier""")
13800f223bSChad Rosier    parser.add_option("-a", "--all", action="store_true", dest="all",
14800f223bSChad Rosier                      default=False, help="dump all messages.")
15800f223bSChad Rosier    parser.add_option("-e", "--error", action="store_true", dest="error",
16800f223bSChad Rosier                      default=False, help="dump 'error' messages.")
17800f223bSChad Rosier    parser.add_option("-f", "--fatal", action="store_true", dest="fatal",
18800f223bSChad Rosier                      default=False, help="dump 'fatal error' messages.")
19800f223bSChad Rosier    parser.add_option("-i", "--ignored", action="store_true", dest="ignored",
20800f223bSChad Rosier                      default=False, help="dump 'ignored' messages.")
21800f223bSChad Rosier    parser.add_option("-n", "--note", action="store_true", dest="note",
22800f223bSChad Rosier                      default=False, help="dump 'note' messages.")
23800f223bSChad Rosier    parser.add_option("-w", "--warning", action="store_true", dest="warning",
24800f223bSChad Rosier                      default=False, help="dump 'warning' messages.")
25800f223bSChad Rosier    (opts, args) = parser.parse_args()
26800f223bSChad Rosier
27800f223bSChad Rosier    if len(args) != 1:
28800f223bSChad Rosier        parser.error("invalid number of arguments")
29800f223bSChad Rosier
30800f223bSChad Rosier    levels = {'error': False, 'fatal error': False, 'ignored': False,
31800f223bSChad Rosier              'note': False, 'warning': False}
32800f223bSChad Rosier    if opts.error:
33800f223bSChad Rosier        levels['error'] = True
34800f223bSChad Rosier    if opts.fatal:
35800f223bSChad Rosier        levels['fatal error'] = True
36800f223bSChad Rosier    if opts.ignored:
37800f223bSChad Rosier        levels['ignored'] = True
38800f223bSChad Rosier    if opts.note:
39800f223bSChad Rosier        levels['note'] = True
40800f223bSChad Rosier    if opts.warning:
41800f223bSChad Rosier        levels['warning'] = True
42800f223bSChad Rosier
43800f223bSChad Rosier    path, = args
44800f223bSChad Rosier
45800f223bSChad Rosier    # Read the diagnostics log.
46800f223bSChad Rosier    f = open(path)
47800f223bSChad Rosier    try:
48800f223bSChad Rosier        data = f.read()
49800f223bSChad Rosier    finally:
50800f223bSChad Rosier        f.close()
51800f223bSChad Rosier
52800f223bSChad Rosier    # Complete the plist (the log itself is just the chunks).
53800f223bSChad Rosier    data = """\
54800f223bSChad Rosier<?xml version="1.0" encoding="UTF-8"?>
55800f223bSChad Rosier<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
56800f223bSChad Rosier                       "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
57800f223bSChad Rosier<plist version="1.0">
58800f223bSChad Rosier<array>
59800f223bSChad Rosier%s
60800f223bSChad Rosier</array>
61800f223bSChad Rosier</plist>""" % data
62800f223bSChad Rosier
63fa40268fSDaniel Dunbar    # Get the list of files and diagnostics to report.
64fa40268fSDaniel Dunbar    to_report = []
65800f223bSChad Rosier    diags = plistlib.readPlistFromString(data)
66fa40268fSDaniel Dunbar    for file_diags in diags:
67fa40268fSDaniel Dunbar        file = file_diags.get('main-file')
68800f223bSChad Rosier
69*0c85c488SDuncan P. N. Exon Smith        # Diagnostics from modules don't have a main-file listed.
70*0c85c488SDuncan P. N. Exon Smith        if not file:
71*0c85c488SDuncan P. N. Exon Smith            file = '<module-includes>'
72*0c85c488SDuncan P. N. Exon Smith
73fa40268fSDaniel Dunbar        # Ignore diagnostics for 'conftest.c', which is the file autoconf uses
74fa40268fSDaniel Dunbar        # for its tests (which frequently will have warnings).
75fa40268fSDaniel Dunbar        if os.path.basename(file) == 'conftest.c':
76fa40268fSDaniel Dunbar            continue
77fa40268fSDaniel Dunbar
78fa40268fSDaniel Dunbar        # Get the diagnostics for the selected levels.
79fa40268fSDaniel Dunbar        selected_diags = [d
80fa40268fSDaniel Dunbar                          for d in file_diags.get('diagnostics', ())
81fa40268fSDaniel Dunbar                          if levels[d.get('level')] or opts.all]
82fa40268fSDaniel Dunbar        if selected_diags:
83fa40268fSDaniel Dunbar            to_report.append((file, selected_diags))
84fa40268fSDaniel Dunbar
85fa40268fSDaniel Dunbar    # If there are no diagnostics to report, show nothing.
86fa40268fSDaniel Dunbar    if not to_report:
87fa40268fSDaniel Dunbar        return
88fa40268fSDaniel Dunbar
89fa40268fSDaniel Dunbar    # Otherwise, print out the diagnostics.
90800f223bSChad Rosier    print
91800f223bSChad Rosier    print "**** BUILD DIAGNOSTICS ****"
92fa40268fSDaniel Dunbar    for file,selected_diags in to_report:
93800f223bSChad Rosier        print "*** %s ***" % file
94fa40268fSDaniel Dunbar        for d in selected_diags:
95800f223bSChad Rosier            print " %s:%s:%s: %s: %s" % (
96800f223bSChad Rosier                d.get('filename'), d.get('line'), d.get('column'),
97800f223bSChad Rosier                d.get('level'), d.get('message'))
98800f223bSChad Rosier
99800f223bSChad Rosierif __name__ == "__main__":
100800f223bSChad Rosier    main()
101