diff options
author | Noel Grandin <noel@peralex.com> | 2016-06-23 13:12:53 +0200 |
---|---|---|
committer | Noel Grandin <noel@peralex.com> | 2016-06-23 13:13:57 +0200 |
commit | 8d861bd7028a6ac3cf21ca9758d1f72eef2ac05c (patch) | |
tree | fb75db9a183c287f476251fce40e4c3932465c51 /compilerplugins/clang/singlevalfields.py | |
parent | 1f1f26bf0fcd695fcfb4b034bca001631646674e (diff) |
new loplugin: singlevalfields
look for fields that only have a single constant value assigned to them
Change-Id: Iafcd37fdb8a8119bbc00f92981a1a01badf9c5a2
Diffstat (limited to 'compilerplugins/clang/singlevalfields.py')
-rwxr-xr-x | compilerplugins/clang/singlevalfields.py | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/compilerplugins/clang/singlevalfields.py b/compilerplugins/clang/singlevalfields.py new file mode 100755 index 000000000000..523ffa5520f2 --- /dev/null +++ b/compilerplugins/clang/singlevalfields.py @@ -0,0 +1,69 @@ +#!/usr/bin/python + +import sys +import re +import io + +definitionToSourceLocationMap = dict() # dict of tuple(parentClass, fieldName) to sourceLocation +fieldAssignDict = dict() # dict of tuple(parentClass, fieldName) to (set of values) + +# clang does not always use exactly the same numbers in the type-parameter vars it generates +# so I need to substitute them to ensure we can match correctly. +normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") +def normalizeTypeParams( line ): + return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) + +# reading as binary (since we known it is pure ascii) is much faster than reading as unicode +with io.open("singlevalfields.log", "rb", buffering=1024*1024) as txt: + for line in txt: + if line.startswith("defn:\t"): + idx1 = line.find("\t") + idx2 = line.find("\t",idx1+1) + idx3 = line.find("\t",idx2+1) + parentClass = normalizeTypeParams(line[idx1+1:idx2]) + fieldName = normalizeTypeParams(line[idx2+1:idx3]) + sourceLocation = line[idx3+1:].strip() + fieldInfo = (parentClass, fieldName) + definitionToSourceLocationMap[fieldInfo] = sourceLocation + elif line.startswith("asgn:\t"): + idx1 = line.find("\t") + idx2 = line.find("\t",idx1+1) + idx3 = line.find("\t",idx2+1) + parentClass = normalizeTypeParams(line[idx1+1:idx2]) + fieldName = normalizeTypeParams(line[idx2+1:idx3]) + assignValue = line[idx3+1:].strip() + fieldInfo = (parentClass, fieldName) + if not fieldInfo in fieldAssignDict: + fieldAssignDict[fieldInfo] = set() + fieldAssignDict[fieldInfo].add(assignValue) + +tmp1list = list() +for fieldInfo, assignValues in fieldAssignDict.iteritems(): + if len(assignValues) != 1: + continue + if "?" in assignValues: + continue + # if it contains anything other than this set, ignore it + if len(assignValues - set(["0", "1", "-1", "nullptr"])) > 0: + continue + v0 = fieldInfo[0] + " " + fieldInfo[1] + v1 = (",".join(assignValues)) + v2 = "" + if fieldInfo in definitionToSourceLocationMap: + v2 = definitionToSourceLocationMap[fieldInfo] + tmp1list.append((v0,v1,v2)) + +# sort results by filename:lineno +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)] +tmp1list.sort(key=lambda v: natural_sort_key(v[2])) + +# print out the results +with open("loplugin.singlevalfields", "wt") as f: + for v in tmp1list: + f.write(v[2] + "\n") + f.write(" " + v[0] + "\n") + f.write(" " + v[1] + "\n") + + |