// try to limit the voluminous output a little static std::set<std::string> inheritedFromSet; static std::map<std::string,std::string> definitionMap; // className -> filename
class FinalClasses: public RecursiveASTVisitor<FinalClasses>, public loplugin::Plugin
{ public: explicit FinalClasses(loplugin::InstantiationData const & data):
Plugin(data) {}
// dump all our output in one write call - this is to try and limit IO "crosstalk" between multiple processes // writing to the same logfile
std::string output; for (const std::string & s : inheritedFromSet)
output += "inherited-from:\t" + s + "\n"; for (constauto & s : definitionMap)
output += "definition:\t" + s.first + "\t" + s.second + "\n";
std::ofstream myfile;
myfile.open( WORKDIR "/loplugin.finalclasses.log", std::ios::app | std::ios::out);
myfile << output;
myfile.close();
}
bool ignoreClass(StringRef s)
{ // ignore stuff in the standard library, and UNO stuff we can't touch. if (compat::starts_with(s, "rtl::") || compat::starts_with(s, "sal::")
|| compat::starts_with(s, "com::sun::") || compat::starts_with(s, "std::")
|| compat::starts_with(s, "boost::")
|| s == "OString" || s == "OUString" || s == "bad_alloc")
{ returntrue;
} returnfalse;
}
bool FinalClasses::VisitCXXRecordDecl(const CXXRecordDecl* decl)
{ if (ignoreLocation(decl)) returntrue; if (!decl->hasDefinition()) returntrue;
for (auto it = decl->bases_begin(); it != decl->bases_end(); ++it)
{ const CXXBaseSpecifier spec = *it;
checkBase(spec.getType());
} for (auto it = decl->vbases_begin(); it != decl->vbases_end(); ++it)
{ const CXXBaseSpecifier spec = *it;
checkBase(spec.getType());
}
if (decl->hasAttr<FinalAttr>()) returntrue; bool bFoundVirtual = false; bool bFoundProtected = false; for (auto it = decl->method_begin(); it != decl->method_end(); ++it) { auto i = *it; // ignore methods that are overriding base-class methods, making them private // isn't useful if ( !i->hasAttr<OverrideAttr>() && i->getAccess() == AS_protected )
bFoundProtected = true; if ( i->isVirtual() )
bFoundVirtual = true;
}
if (!bFoundProtected)
{ for (auto it = decl->field_begin(); it != decl->field_end(); ++it) { auto i = *it; if ( i->getAccess() == AS_protected ) {
bFoundProtected = true; break;
}
}
} if (!bFoundProtected && !bFoundVirtual) returntrue;
std::string s = decl->getQualifiedNameAsString(); if (ignoreClass(s)) returntrue;
void FinalClasses::checkBase(QualType baseType)
{ // need to look through typedefs, hence the getUnqualifiedDesugaredType
baseType = baseType.getDesugaredType(compiler.getASTContext());
std::string x; // so that we get just the template name, excluding the template parameters if (baseType->isRecordType())
x = baseType->getAsCXXRecordDecl()->getQualifiedNameAsString(); elseif (auto templateType = baseType->getAs<TemplateSpecializationType>())
x = templateType->getTemplateName().getAsTemplateDecl()->getQualifiedNameAsString(); else
x = baseType.getAsString();
inheritedFromSet.insert( x );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.