summaryrefslogtreecommitdiffstats
path: root/compilerplugins/clang/finalclasses.py
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/finalclasses.py')
-rwxr-xr-xcompilerplugins/clang/finalclasses.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/compilerplugins/clang/finalclasses.py b/compilerplugins/clang/finalclasses.py
new file mode 100755
index 0000000000..5e9f25a24a
--- /dev/null
+++ b/compilerplugins/clang/finalclasses.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python3
+
+import re
+
+definitionSet = set()
+inheritFromSet = set()
+definitionToFileDict = {}
+
+with open("workdir/loplugin.finalclasses.log") as txt:
+ for line in txt:
+ tokens = line.strip().split("\t")
+
+ if len(tokens) == 1:
+ pass
+
+ 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] == "inherited-from:":
+ parent = tokens[1]
+ if (parent.startswith("class ")):
+ parent = parent[6:]
+ elif (parent.startswith("struct ")):
+ parent = parent[7:]
+ inheritFromSet.add(parent);
+
+ else:
+ print( "unknown line: " + line)
+
+match_module_inc1 = re.compile(r'^\w+/inc/')
+match_module_inc2 = re.compile(r'^\w+/.*/inc/')
+tmpset = set()
+for clazz in sorted(definitionSet - inheritFromSet):
+ file = definitionToFileDict[clazz]
+ # ignore classes defined inside compilation units, the compiler knows they are final already
+ if (".cxx" in file): continue
+ # ignore test and external code
+ if ("/qa/" in file): continue
+ if (file.startswith("workdir/")): continue
+ # We are only really interested in classes that are shared between linkage units, where the compiler
+ # is not able to figure out for itself that classes are final.
+ if not(file.startswith("include/") or match_module_inc1.match(file) or match_module_inc2.match(file)): continue
+ #if not(file.endswith(".hxx")): continue
+ # Exclude URE
+ if file.startswith("include/com/"): continue
+ if file.startswith("include/cppu/"): continue
+ if file.startswith("include/cppuhelper/"): continue
+ if file.startswith("include/osl/"): continue
+ if file.startswith("include/rtl/"): continue
+ if file.startswith("include/sal/"): continue
+ if file.startswith("include/salhelper/"): continue
+ if file.startswith("include/typelib/"): continue
+ if file.startswith("include/uno/"): continue
+ # some kind of template noise
+ if file.startswith("include/unotest/"): continue
+ # no point optimising test code
+ if file.startswith("include/test/"): continue
+ tmpset.add((clazz, file))
+
+# 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]]
+def sort_set_by_natural_key(s):
+ return sorted(s, key=lambda v: v_sort_key(v))
+
+# print output, sorted by name and line number
+with open("compilerplugins/clang/finalclasses.results", "wt") as f:
+ for t in sort_set_by_natural_key(tmpset):
+ f.write(t[1] + "\n")
+ f.write(" " + t[0] + "\n")
+