diff options
author | Noel Grandin <noel@peralex.com> | 2016-05-25 11:28:58 +0200 |
---|---|---|
committer | Noel Grandin <noelgrandin@gmail.com> | 2016-05-26 07:26:47 +0000 |
commit | 509f0c6a8aa36b7fa532f784e10bbe9ec4e57c4b (patch) | |
tree | a05e37827bdee103d11362388acbf6d0d57dca48 /compilerplugins/clang/unusedmethods.py | |
parent | 92d3025521ec8939b66500347f8d38ed5b24e3c8 (diff) |
loplugin:unusedreturntypes
and clean up the python script
Change-Id: I0a7068153290fbbb60bfeb4c8bda1c24d514500f
Reviewed-on: https://gerrit.libreoffice.org/25439
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Diffstat (limited to 'compilerplugins/clang/unusedmethods.py')
-rwxr-xr-x | compilerplugins/clang/unusedmethods.py | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py index a81bd6b5fd9f..a15107994374 100755 --- a/compilerplugins/clang/unusedmethods.py +++ b/compilerplugins/clang/unusedmethods.py @@ -4,17 +4,27 @@ import sys import re import io -definitionSet = set() -publicDefinitionSet = set() +# -------------------------------------------------------------------------------------------- +# globals +# -------------------------------------------------------------------------------------------- + +definitionSet = set() # set of tuple(return_type, name_and_params) definitionToSourceLocationMap = dict() -callSet = set() -usedReturnSet = set() -sourceLocationSet = set() -calledFromOutsideSet = set() + +# for the "unused methods" analysis +callSet = set() # set of tuple(return_type, name_and_params) + +# for the "unnecessary public" analysis +publicDefinitionSet = set() # set of tuple(return_type, name_and_params) +calledFromOutsideSet = set() # set of tuple(return_type, name_and_params) + +# for the "unused return types" analysis +usedReturnSet = set() # set of tuple(return_type, name_and_params) + # things we need to exclude for reasons like : # - it's a weird template thingy that confuses the plugin -exclusionSet = set([ +unusedMethodsExclusionSet = set([ "double basegfx::DoubleTraits::maxVal()", "double basegfx::DoubleTraits::minVal()", "double basegfx::DoubleTraits::neutral()", @@ -116,6 +126,10 @@ normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") def normalizeTypeParams( line ): return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) +# -------------------------------------------------------------------------------------------- +# primary input loop +# -------------------------------------------------------------------------------------------- + # The parsing here is designed to avoid grabbing stuff which is mixed in from gbuild. # I have not yet found a way of suppressing the gbuild output. with io.open(sys.argv[1], "rb", buffering=1024*1024) as txt: @@ -162,38 +176,46 @@ for k, definitions in sourceLocationToDefinitionMap.iteritems(): definitionSet.remove(d) def isOtherConstness( d, callSet ): - clazz = d[0] + " " + d[1] + method = d[0] + " " + d[1] # if this method is const, and there is a non-const variant of it, and the non-const variant is in use, then leave it alone if d[0].startswith("const ") and d[1].endswith(" const"): if ((d[0][6:],d[1][:-6]) in callSet): return True - elif clazz.endswith(" const"): - clazz2 = clazz[:len(clazz)-6] # strip off " const" - if ((d[0],clazz2) in callSet): + elif method.endswith(" const"): + method2 = method[:len(method)-6] # strip off " const" + if ((d[0],method2) in callSet): return True - if clazz.endswith(" const") and ("::iterator" in clazz): - clazz2 = clazz[:len(clazz)-6] # strip off " const" - clazz2 = clazz2.replace("::const_iterator", "::iterator") - if ((d[0],clazz2) in callSet): + if method.endswith(" const") and ("::iterator" in method): + method2 = method[:len(method)-6] # strip off " const" + method2 = method2.replace("::const_iterator", "::iterator") + if ((d[0],method2) in callSet): return True # if this method is non-const, and there is a const variant of it, and the const variant is in use, then leave it alone - if (not clazz.endswith(" const")) and ((d[0],"const " + clazz + " const") in callSet): + if (not method.endswith(" const")) and ((d[0],"const " + method + " const") in callSet): return True - if (not clazz.endswith(" const")) and ("::iterator" in clazz): - clazz2 = clazz.replace("::iterator", "::const_iterator") + " const" - if ((d[0],clazz2) in callSet): + if (not method.endswith(" const")) and ("::iterator" in method): + method2 = method.replace("::iterator", "::const_iterator") + " const" + if ((d[0],method2) in callSet): return True return False +# 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)] +def sort_set_by_natural_key(s): + return sorted(s, key=lambda v: natural_sort_key(v[1])) + -# ------------------------------------------- -# Do the "unused methods" part -# ------------------------------------------- +# -------------------------------------------------------------------------------------------- +# "unused methods" analysis +# -------------------------------------------------------------------------------------------- -tmp1set = set() +tmp1set = set() # set of tuple(method, source_location) +unusedSet = set() # set of tuple(return_type, name_and_params) for d in definitionSet: - clazz = d[0] + " " + d[1] - if clazz in exclusionSet: + method = d[0] + " " + d[1] + if method in unusedMethodsExclusionSet: continue if d in callSet: continue @@ -249,34 +271,30 @@ for d in definitionSet: if d[1].endswith("::CreateDefault()"): continue - tmp1set.add((clazz, definitionToSourceLocationMap[d])) + unusedSet.add(d) # used by the "unused return types" analysis + tmp1set.add((method, definitionToSourceLocationMap[d])) -# 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 results by name and line number -tmp1list = sorted(tmp1set, key=lambda v: natural_sort_key(v[1])) - -# print out the results +# print out the results, sorted by name and line number with open("unused.methods", "wt") as f: - for t in tmp1list: + for t in sort_set_by_natural_key(tmp1set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") -# ------------------------------------------- -# Do the "unused return types" part -# ------------------------------------------- +# -------------------------------------------------------------------------------------------- +# "unused return types" analysis +# -------------------------------------------------------------------------------------------- tmp2set = set() for d in definitionSet: - clazz = d[0] + " " + d[1] + method = d[0] + " " + d[1] if d in usedReturnSet: continue + if d in unusedSet: + continue if isOtherConstness(d, usedReturnSet): continue - if d[0] == "void": + # ignore methods with no return type, and constructors + if d[0] == "void" or d[0] == "": continue # ignore bool returns, provides important documentation in the code if d[0] == "_Bool": @@ -299,24 +317,22 @@ for d in definitionSet: # ignore the SfxPoolItem CreateDefault methods for now if d[1].endswith("::CreateDefault()"): continue - tmp2set.add((clazz, definitionToSourceLocationMap[d])) + tmp2set.add((method, definitionToSourceLocationMap[d])) -# sort results by name and line number -tmp2list = sorted(tmp2set, key=lambda v: natural_sort_key(v[1])) - +# print output, sorted by name and line number with open("unused.returns", "wt") as f: - for t in tmp2list: - f.write(t[1]) + for t in sort_set_by_natural_key(tmp2set): + f.write(t[1] + "\n") f.write(" " + t[0] + "\n") -# ------------------------------------------- -# Do the "unnecessary public" part -# ------------------------------------------- +# -------------------------------------------------------------------------------------------- +# "unnecessary public" analysis +# -------------------------------------------------------------------------------------------- tmp3set = set() for d in publicDefinitionSet: - clazz = d[0] + " " + d[1] + method = d[0] + " " + d[1] if d in calledFromOutsideSet: continue if isOtherConstness(d, calledFromOutsideSet): @@ -324,13 +340,11 @@ for d in publicDefinitionSet: # ignore external code if definitionToSourceLocationMap[d].startswith("external/"): continue - tmp3set.add((clazz, definitionToSourceLocationMap[d])) + tmp3set.add((method, definitionToSourceLocationMap[d])) -# sort results by name and line number -tmp3list = sorted(tmp3set, key=lambda v: natural_sort_key(v[1])) - +# print output, sorted by name and line number with open("unused.public", "wt") as f: - for t in tmp3list: + for t in sort_set_by_natural_key(tmp3set): f.write(t[1] + "\n") f.write(" " + t[0] + "\n") |