bd3d2daa20
(*) remove some debugging code (*) loosen constraints a little so I can see if there are more interesting opportunities (*) rename some local vars to make it read better (*) strip const/& modifiers from types before comparing (*) ignore vars/fields that are references, they do indicate that a class was instantiated Change-Id: I66014b8f0aa24c2e3ca34af75b75e6cd6c939ea6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167383 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Tested-by: Jenkins
80 lines
3.1 KiB
Python
Executable file
80 lines
3.1 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
instantiatedSet = set()
|
|
definitionSet = set()
|
|
parentChildDict = {}
|
|
definitionToFileDict = {}
|
|
|
|
with open("workdir/loplugin.mergeclasses.log") as txt:
|
|
for line in txt:
|
|
tokens = line.strip().split("\t")
|
|
|
|
if len(tokens) == 1:
|
|
pass
|
|
|
|
elif tokens[0] == "instantiated:":
|
|
clazzName = tokens[1]
|
|
if (clazzName.startswith("const ")):
|
|
clazzName = clazzName[6:]
|
|
if (clazzName.startswith("class ")):
|
|
clazzName = clazzName[6:]
|
|
if (clazzName.startswith("::")):
|
|
clazzName = clazzName[2:]
|
|
instantiatedSet.add(clazzName)
|
|
|
|
elif tokens[0] == "definition:":
|
|
clazzName = tokens[1]
|
|
# the 1.. is so we skip the leading /
|
|
fileName = tokens[2][1:]
|
|
definitionSet.add(clazzName)
|
|
definitionToFileDict[clazzName] = fileName
|
|
|
|
elif tokens[0] == "has-subclass:":
|
|
child = tokens[1]
|
|
parent = tokens[2]
|
|
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]
|
|
|
|
with open("compilerplugins/clang/mergeclasses.results", "wt") as f:
|
|
# loop over defined, but not instantiated classes
|
|
for clazz in sorted(definitionSet - instantiatedSet):
|
|
# ignore classes without any children, and classes with more than one child
|
|
if (clazz not in parentChildDict) or (len(parentChildDict[clazz]) != 1):
|
|
continue
|
|
# exclude some common false positives
|
|
a = ['Dialog', 'Dlg', 'com::sun']
|
|
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
|
|
subclazz = next(iter(parentChildDict[clazz]))
|
|
# if the other class has more than child, it is not a candidate for merging
|
|
#if (otherclazz in parentChildDict) and (len(parentChildDict[otherclazz]) != 1):
|
|
# continue
|
|
# Combinations that span modules we often use those to make cross-module dependencies more manageable,
|
|
# so mark them with maybe.
|
|
module1 = extractModuleName(clazz)
|
|
module2 = extractModuleName(subclazz)
|
|
if module1 != module2:
|
|
f.write( "maybe merge " + clazz + " with " + subclazz + ", in modules " + module1 + " and " + module2 + "\n" )
|
|
else:
|
|
f.write( "merge " + clazz + " with " + subclazz + "\n" )
|
|
|