improve unusedfields loplugin to find constructor-only fields
ie. fields that are only touched in the constructor Change-Id: Ia714cbfed9710e47e69ca9f0eb0eac4f7e8b8a86 Reviewed-on: https://gerrit.libreoffice.org/54412 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -67,6 +67,7 @@ bool operator < (const MyFieldInfo &lhs, const MyFieldInfo &rhs)
|
|||||||
// try to limit the voluminous output a little
|
// try to limit the voluminous output a little
|
||||||
static std::set<MyFieldInfo> touchedFromInsideSet;
|
static std::set<MyFieldInfo> touchedFromInsideSet;
|
||||||
static std::set<MyFieldInfo> touchedFromOutsideSet;
|
static std::set<MyFieldInfo> touchedFromOutsideSet;
|
||||||
|
static std::set<MyFieldInfo> touchedFromOutsideConstructorSet;
|
||||||
static std::set<MyFieldInfo> readFromSet;
|
static std::set<MyFieldInfo> readFromSet;
|
||||||
static std::set<MyFieldInfo> writeToSet;
|
static std::set<MyFieldInfo> writeToSet;
|
||||||
static std::set<MyFieldInfo> definitionSet;
|
static std::set<MyFieldInfo> definitionSet;
|
||||||
@@ -186,6 +187,8 @@ void UnusedFields::run()
|
|||||||
output += "inside:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
output += "inside:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
||||||
for (const MyFieldInfo & s : touchedFromOutsideSet)
|
for (const MyFieldInfo & s : touchedFromOutsideSet)
|
||||||
output += "outside:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
output += "outside:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
||||||
|
for (const MyFieldInfo & s : touchedFromOutsideConstructorSet)
|
||||||
|
output += "outside-constructor:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
||||||
for (const MyFieldInfo & s : readFromSet)
|
for (const MyFieldInfo & s : readFromSet)
|
||||||
output += "read:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
output += "read:\t" + s.parentClass + "\t" + s.fieldName + "\n";
|
||||||
for (const MyFieldInfo & s : writeToSet)
|
for (const MyFieldInfo & s : writeToSet)
|
||||||
@@ -989,6 +992,8 @@ void UnusedFields::checkTouchedFromOutside(const FieldDecl* fieldDecl, const Exp
|
|||||||
} else {
|
} else {
|
||||||
if (memberExprParentFunction->getParent() == fieldDecl->getParent()) {
|
if (memberExprParentFunction->getParent() == fieldDecl->getParent()) {
|
||||||
touchedFromInsideSet.insert(fieldInfo);
|
touchedFromInsideSet.insert(fieldInfo);
|
||||||
|
if (!constructorDecl)
|
||||||
|
touchedFromOutsideConstructorSet.insert(fieldInfo);
|
||||||
} else {
|
} else {
|
||||||
touchedFromOutsideSet.insert(fieldInfo);
|
touchedFromOutsideSet.insert(fieldInfo);
|
||||||
}
|
}
|
||||||
|
@@ -9,10 +9,11 @@ protectedAndPublicDefinitionSet = set() # set of tuple(type, name)
|
|||||||
definitionToSourceLocationMap = dict()
|
definitionToSourceLocationMap = dict()
|
||||||
definitionToTypeMap = dict()
|
definitionToTypeMap = dict()
|
||||||
touchedFromInsideSet = set()
|
touchedFromInsideSet = set()
|
||||||
|
touchedFromOutsideSet = set()
|
||||||
|
touchedFromOutsideConstructorSet = set()
|
||||||
readFromSet = set()
|
readFromSet = set()
|
||||||
writeToSet = set()
|
writeToSet = set()
|
||||||
sourceLocationSet = set()
|
sourceLocationSet = set()
|
||||||
touchedFromOutsideSet = set()
|
|
||||||
|
|
||||||
# clang does not always use exactly the same numbers in the type-parameter vars it generates
|
# 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.
|
# so I need to substitute them to ensure we can match correctly.
|
||||||
@@ -48,6 +49,8 @@ with io.open("workdir/loplugin.unusedfields.log", "rb", buffering=1024*1024) as
|
|||||||
touchedFromInsideSet.add(parseFieldInfo(tokens))
|
touchedFromInsideSet.add(parseFieldInfo(tokens))
|
||||||
elif tokens[0] == "outside:":
|
elif tokens[0] == "outside:":
|
||||||
touchedFromOutsideSet.add(parseFieldInfo(tokens))
|
touchedFromOutsideSet.add(parseFieldInfo(tokens))
|
||||||
|
elif tokens[0] == "outside-constructor:":
|
||||||
|
touchedFromOutsideConstructorSet.add(parseFieldInfo(tokens))
|
||||||
elif tokens[0] == "read:":
|
elif tokens[0] == "read:":
|
||||||
readFromSet.add(parseFieldInfo(tokens))
|
readFromSet.add(parseFieldInfo(tokens))
|
||||||
elif tokens[0] == "write:":
|
elif tokens[0] == "write:":
|
||||||
@@ -67,7 +70,7 @@ for k, definitions in sourceLocationToDefinitionMap.iteritems():
|
|||||||
for d in definitions:
|
for d in definitions:
|
||||||
definitionSet.remove(d)
|
definitionSet.remove(d)
|
||||||
|
|
||||||
# Calculate untouched or untouched-except-for-in-constructor
|
# Calculate untouched
|
||||||
untouchedSet = set()
|
untouchedSet = set()
|
||||||
untouchedSetD = set()
|
untouchedSetD = set()
|
||||||
for d in definitionSet:
|
for d in definitionSet:
|
||||||
@@ -103,6 +106,41 @@ for d in definitionSet:
|
|||||||
untouchedSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc))
|
untouchedSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc))
|
||||||
untouchedSetD.add(d)
|
untouchedSetD.add(d)
|
||||||
|
|
||||||
|
# Calculate only-touched-in-constructor set
|
||||||
|
onlyUsedInConstructorSet = set()
|
||||||
|
for d in definitionSet:
|
||||||
|
if d in touchedFromOutsideSet or d in touchedFromOutsideConstructorSet:
|
||||||
|
continue
|
||||||
|
srcLoc = definitionToSourceLocationMap[d];
|
||||||
|
# this is all representations of on-disk data structures
|
||||||
|
if (srcLoc.startswith("sc/source/filter/inc/scflt.hxx")
|
||||||
|
or srcLoc.startswith("sw/source/filter/ww8/")
|
||||||
|
or srcLoc.startswith("vcl/source/filter/sgvmain.hxx")
|
||||||
|
or srcLoc.startswith("vcl/source/filter/sgfbram.hxx")
|
||||||
|
or srcLoc.startswith("vcl/inc/unx/XIM.h")
|
||||||
|
or srcLoc.startswith("vcl/inc/unx/gtk/gloactiongroup.h")
|
||||||
|
or srcLoc.startswith("include/svl/svdde.hxx")
|
||||||
|
or srcLoc.startswith("lotuswordpro/source/filter/lwpsdwdrawheader.hxx")
|
||||||
|
or srcLoc.startswith("hwpfilter/")
|
||||||
|
or srcLoc.startswith("embeddedobj/source/inc/")
|
||||||
|
or srcLoc.startswith("svtools/source/dialogs/insdlg.cxx")
|
||||||
|
or srcLoc.startswith("bridges/")):
|
||||||
|
continue
|
||||||
|
fieldType = definitionToTypeMap[d]
|
||||||
|
if "std::unique_ptr" in fieldType:
|
||||||
|
continue
|
||||||
|
if "std::shared_ptr" in fieldType:
|
||||||
|
continue
|
||||||
|
if "Reference<" in fieldType:
|
||||||
|
continue
|
||||||
|
if "VclPtr<" in fieldType:
|
||||||
|
continue
|
||||||
|
if "osl::Mutex" in fieldType:
|
||||||
|
continue
|
||||||
|
if "::sfx2::sidebar::ControllerItem" in fieldType:
|
||||||
|
continue
|
||||||
|
onlyUsedInConstructorSet.add((d[0] + " " + d[1] + " " + fieldType, srcLoc))
|
||||||
|
|
||||||
writeonlySet = set()
|
writeonlySet = set()
|
||||||
for d in definitionSet:
|
for d in definitionSet:
|
||||||
parentClazz = d[0];
|
parentClazz = d[0];
|
||||||
@@ -196,6 +234,7 @@ tmp1list = sorted(untouchedSet, key=lambda v: natural_sort_key(v[1]))
|
|||||||
tmp2list = sorted(writeonlySet, key=lambda v: natural_sort_key(v[1]))
|
tmp2list = sorted(writeonlySet, key=lambda v: natural_sort_key(v[1]))
|
||||||
tmp3list = sorted(canBePrivateSet, key=lambda v: natural_sort_key(v[1]))
|
tmp3list = sorted(canBePrivateSet, key=lambda v: natural_sort_key(v[1]))
|
||||||
tmp4list = sorted(readonlySet, key=lambda v: natural_sort_key(v[1]))
|
tmp4list = sorted(readonlySet, key=lambda v: natural_sort_key(v[1]))
|
||||||
|
tmp5list = sorted(onlyUsedInConstructorSet, key=lambda v: natural_sort_key(v[1]))
|
||||||
|
|
||||||
# print out the results
|
# print out the results
|
||||||
with open("compilerplugins/clang/unusedfields.untouched.results", "wt") as f:
|
with open("compilerplugins/clang/unusedfields.untouched.results", "wt") as f:
|
||||||
@@ -215,5 +254,9 @@ with open("compilerplugins/clang/unusedfields.readonly.results", "wt") as f:
|
|||||||
for t in tmp4list:
|
for t in tmp4list:
|
||||||
f.write( t[1] + "\n" )
|
f.write( t[1] + "\n" )
|
||||||
f.write( " " + t[0] + "\n" )
|
f.write( " " + t[0] + "\n" )
|
||||||
|
with open("compilerplugins/clang/unusedfields.only-used-in-constructor.results", "wt") as f:
|
||||||
|
for t in tmp5list:
|
||||||
|
f.write( t[1] + "\n" )
|
||||||
|
f.write( " " + t[0] + "\n" )
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user