summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/mergeclasses.py
blob: 58a65c58c8376c29d3101de2115f24040792c6eb (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
#!/usr/bin/python

import sys

instantiatedSet = set()
definitionSet = set()
parentChildDict = {}
definitionToFileDict = {}

with open("mergeclasses.log") as txt:
    for line in txt:
    
        if line.startswith("instantiated:\t"):
            idx1 = line.find("\t")
            clazzName = line[idx1+1 : len(line)-1]
            if (clazzName.startswith("const ")):
                clazzName = clazzName[6:]
            if (clazzName.startswith("class ")):
                clazzName = clazzName[6:]
            if (clazzName.endswith(" &")):
                clazzName = clazzName[:len(clazzName)-3]
            instantiatedSet.add(clazzName)
            
        elif line.startswith("definition:\t"):
            idx1 = line.find("\t")
            idx2 = line.find("\t", idx1+1)
            clazzName = line[idx1+1 : idx2]
            # the +2 is so we skip the leading /
            fileName  = line[idx2+2 : len(line)-1]
            definitionSet.add(clazzName)
            definitionToFileDict[clazzName] = fileName
            
        elif line.startswith("has-subclass:\t"):
            idx1 = line.find("\t")
            idx2 = line.find("\t", idx1+1)
            child  = line[idx1+1 : idx2]
            parent = line[idx2+1 : len(line)-1]
            if (parent.startswith("class ")):
                parent = parent[6:]
            elif (parent.startswith("struct ")):
                parent = parent[7:]
            if (child.startswith("class ")):
                child = child[6:]
            elif (child.startswith("struct ")):
                child = child[7:]
            if (parent not in parentChildDict):
                parentChildDict[parent] = set()
            parentChildDict[parent].add(child)
            
def extractModuleName(clazz):
    filename = definitionToFileDict[clazz]
    if filename.startswith("include/"):
        filename = filename[8:]
    idx = filename.find("/")
    return filename[:idx]

for clazz in sorted(definitionSet - instantiatedSet):
    # find uninstantiated classes without any subclasses
    if (not(clazz in parentChildDict)) or (len(parentChildDict[clazz]) != 1):
        continue
    # exclude some common false positives
    a = ['Dialog', 'Dlg', 'com::sun', 'Base']
    if any(x in clazz for x in a):
        continue
    # ignore base class that contain the word "mutex", they are normally there to
    # help with the WeakComponentImpl template magic
    if ("mutex" in clazz) or ("Mutex" in clazz):
        continue
    otherclazz = next(iter(parentChildDict[clazz]))
    # exclude combinations that span modules because we often use those to make cross-module dependencies more manageable.
    if extractModuleName(clazz) != extractModuleName(otherclazz):
        continue
    print "merge", clazz, "with", otherclazz