summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/unnecessaryvirtual.py
blob: 063fcba3c06838bb35cd5c62036d49eb7813a702 (plain)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/python3

import io
import re

definitionSet = set()
definitionToSourceLocationMap = dict()
overridingSet = set()
nonEmptySet = set()


with io.open("workdir/loplugin.unnecessaryvirtual.log", "r", buffering=1024*1024) as txt:
    for line in txt:
        tokens = line.strip().split("\t")
        if tokens[0] == "definition:":
            fullMethodName = tokens[1]
            sourceLocation = tokens[2]
            definitionSet.add(fullMethodName)
            definitionToSourceLocationMap[fullMethodName] = sourceLocation
        elif tokens[0] == "overriding:":
            fullMethodName = tokens[1]
            overridingSet.add(fullMethodName)
        elif tokens[0] == "nonempty:":
            fullMethodName = tokens[1]
            nonEmptySet.add(fullMethodName)
        else:
            print( "unknown line: " + line)

unnecessaryVirtualSet = set()

for clazz in (definitionSet - overridingSet):
    # windows-specific stuff
    if clazz.startswith("canvas::"):
        continue
    if clazz.startswith("psp::PrinterInfoManager"):
        continue
    if clazz.startswith("DdeTopic::"):
        continue
    if clazz == "basegfx::unotools::UnoPolyPolygon::void-modifying()const":
        continue
    if clazz == "SalLayout::_Bool-IsKashidaPosValid(int,)const":
        continue
    if clazz == "SalLayout::void-DisableGlyphInjection(_Bool,)":
        continue
    # Linux-TDF specific
    if clazz == "X11SalFrame::void-updateGraphics(_Bool,)":
        continue
    # OSX specific
    if clazz == "SalFrame::void-SetRepresentedURL(const class rtl::OUString &,)":
        continue
    if clazz == "SalMenu::_Bool-AddMenuBarButton(const struct SalMenuButtonItem &,)":
        continue
    if clazz == "SalMenu::class Rectangle-GetMenuBarButtonRectPixel(sal_uInt16,class SalFrame *,)":
        continue
    if clazz == "SalMenu::void-RemoveMenuBarButton(sal_uInt16,)":
        continue
    if clazz == "SalLayout::_Bool-DrawTextSpecial(class SalGraphics &,sal_uInt32,)const":
        continue
    # GTK < 3
    if clazz == "GtkSalDisplay::int-CaptureMouse(class SalFrame *,)":
        continue
    # some test magic
    if clazz.startswith("apitest::"):
        continue

    loc = definitionToSourceLocationMap[clazz]

    # ignore external code
    if loc.startswith("external/"):
        continue
    if loc.startswith("workdir/"):
        continue
    if loc.startswith("64-linux-gnu/"):
        continue
    # there is a bunch of Windows specific code that we don't see
    if loc.startswith("include/canvas/"):
        continue
    # not sure what the problem is here
    if loc.startswith("include/test/"):
        continue

    unnecessaryVirtualSet.add( (clazz,loc) )


deadSet = set()

for clazz in (definitionSet - nonEmptySet):

    # ignore destructors
    if "::~" in clazz:
        continue

    loc = definitionToSourceLocationMap[clazz]

    # ignore external code
    if loc.startswith("external/"):
        continue
    if loc.startswith("workdir/"):
        continue
    if loc.startswith("64-linux-gnu/"):
        continue

    deadSet.add( (clazz,loc) )


# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely
def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
    return [int(text) if text.isdigit() else text.lower()
            for text in re.split(_nsre, s)]
# sort by both the source-line and the datatype, so the output file ordering is stable
# when we have multiple items on the same source line
def v_sort_key(v):
    return natural_sort_key(v[1]) + [v[0]]

# sort results by name and line number
tmp1list = sorted(unnecessaryVirtualSet, key=lambda v: v_sort_key(v))
tmp2list = sorted(deadSet, key=lambda v: v_sort_key(v))

with open("compilerplugins/clang/unnecessaryvirtual.results", "wt") as f:
    for t in tmp1list:
        f.write( t[1] + "\n" )
        f.write( "    " + t[0] + "\n" )
    # add an empty line at the end to make it easier for the removevirtuals plugin to mmap() the output file
    f.write("\n")

with open("compilerplugins/clang/unnecessaryvirtual-dead.results", "wt") as f:
    for t in tmp2list:
        f.write( t[1] + "\n" )
        f.write( "    " + t[0] + "\n" )