diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-11-10 11:33:41 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2017-11-10 15:19:04 +0100 |
commit | 4cc7ebcca3d5fa33556fbc2666d8c63ae30a3424 (patch) | |
tree | d6a300ee99de1c01b3f4cf809de228ad1f0a73b2 /compilerplugins | |
parent | 42344398a839eddf1b498c266d8fe8ac0b3bb6b6 (diff) |
loplugin:unusedmethods new analysis
look for classes containing protected methods where we can convert them
all to private
Change-Id: I4a448341943e0a613cde30501c4012da61dba713
Reviewed-on: https://gerrit.libreoffice.org/44588
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/unusedmethods.cxx | 15 | ||||
-rwxr-xr-x | compilerplugins/clang/unusedmethods.py | 33 |
2 files changed, 48 insertions, 0 deletions
diff --git a/compilerplugins/clang/unusedmethods.cxx b/compilerplugins/clang/unusedmethods.cxx index 3b7b4cb2a5fb..ef681f12c561 100644 --- a/compilerplugins/clang/unusedmethods.cxx +++ b/compilerplugins/clang/unusedmethods.cxx @@ -114,11 +114,13 @@ public: bool VisitFunctionDecl( const FunctionDecl* decl ); bool VisitDeclRefExpr( const DeclRefExpr* ); bool VisitCXXConstructExpr( const CXXConstructExpr* ); + bool TraverseCXXRecordDecl( CXXRecordDecl* ); private: void logCallToRootMethods(const FunctionDecl* functionDecl, std::set<MyFuncInfo>& funcSet); MyFuncInfo niceName(const FunctionDecl* functionDecl); std::string toString(SourceLocation loc); void functionTouchedFromExpr( const FunctionDecl* calleeFunctionDecl, const Expr* expr ); + CXXRecordDecl const * currentCxxRecordDecl = nullptr; }; MyFuncInfo UnusedMethods::niceName(const FunctionDecl* functionDecl) @@ -281,6 +283,10 @@ bool UnusedMethods::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr logCallToRootMethods(constructorDecl, callSet); + // Now do the checks necessary for the "can be private" analysis + if (constructorDecl->getParent() != currentCxxRecordDecl) + calledFromOutsideSet.insert(niceName(constructorDecl)); + return true; } @@ -341,6 +347,15 @@ bool UnusedMethods::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) return true; } +bool UnusedMethods::TraverseCXXRecordDecl(CXXRecordDecl* cxxRecordDecl) +{ + auto copy = currentCxxRecordDecl; + currentCxxRecordDecl = cxxRecordDecl; + bool ret = RecursiveASTVisitor::TraverseCXXRecordDecl(cxxRecordDecl); + currentCxxRecordDecl = copy; + return ret; +} + loplugin::Plugin::Registration< UnusedMethods > X("unusedmethods", false); } diff --git a/compilerplugins/clang/unusedmethods.py b/compilerplugins/clang/unusedmethods.py index aaa19abfc8e2..811eca65cae4 100755 --- a/compilerplugins/clang/unusedmethods.py +++ b/compilerplugins/clang/unusedmethods.py @@ -16,6 +16,7 @@ callSet = set() # set of tuple(return_type, name_and_params) # for the "method can be private" analysis publicDefinitionSet = set() # set of tuple(return_type, name_and_params) +protectedDefinitionSet = set() # set of tuple(return_type, name_and_params) calledFromOutsideSet = set() # set of tuple(return_type, name_and_params) virtualSet = set() # set of tuple(return_type, name_and_params) @@ -46,6 +47,8 @@ with io.open("loplugin.unusedmethods.log", "rb", buffering=1024*1024) as txt: definitionSet.add(funcInfo) if access == "public": publicDefinitionSet.add(funcInfo) + elif access == "protected": + protectedDefinitionSet.add(funcInfo) definitionToSourceLocationMap[funcInfo] = sourceLocation if virtual == "virtual": virtualSet.add(funcInfo) @@ -275,3 +278,33 @@ with open("loplugin.unusedmethods.report-can-be-private", "wt") as f: f.write(t[1] + "\n") f.write(" " + t[0] + "\n") + + +# -------------------------------------------------------------------------------------------- +# "all protected methods in class can be made private" analysis +# -------------------------------------------------------------------------------------------- + +potentialClasses = set() +excludedClasses = set() +potentialClassesSourceLocationMap = dict() +matchClassName = re.compile(r"(\w+)::") +for d in protectedDefinitionSet: + m = matchClassName.match(d[1]) + if not m: continue + clazz = m.group(1) + if d in calledFromOutsideSet: + excludedClasses.add(clazz) + else: + potentialClasses.add(clazz) + potentialClassesSourceLocationMap[clazz] = definitionToSourceLocationMap[d] + +tmp4set = set() +for d in (potentialClasses - excludedClasses): + tmp4set.add((d, potentialClassesSourceLocationMap[d])) + +# print output, sorted by name and line number +with open("loplugin.unusedmethods.report-all-protected-can-be-private", "wt") as f: + for t in sort_set_by_natural_key(tmp4set): + f.write(t[1] + "\n") + f.write(" " + t[0] + "\n") + |