9ad252b2e7
...now that macOS builds are guaranteed to have std::optional since
358146bbbd
"Bump macOS build baseline to
Xcode 11.3 and macOS 10.14.4".
The change is done mostly mechanically with
> for i in $(git grep -Fl optional); do
> sed -i -e 's:<o3tl/optional\.hxx>\|\"o3tl/optional\.hxx\":<optional>:' \
> -e 's/\<o3tl::optional\>/std::optional/g' \
> -e 's/\<o3tl::make_optional\>/std::make_optional/g' "$i"
> done
> for i in $(git grep -Flw o3tl::nullopt); do
> sed -i -e 's/\<o3tl::nullopt\>/std::nullopt/g' "$i"
> done
(though that causes some of the resulting
#include <optional>
to appear at different places relative to other includes than if they had been
added manually), plus a few manual modifications:
* adapt bin/find-unneeded-includes
* adapt desktop/IwyuFilter_desktop.yaml
* remove include/o3tl/optional.hxx
* quote resulting "<"/">" as "<"/">" in officecfg/registry/cppheader.xsl
* and then solenv/clang-format/reformat-formatted-files
Change-Id: I68833d9f7945e57aa2bc703349cbc5a56b342273
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89165
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
196 lines
7.7 KiB
C++
196 lines
7.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <regex>
|
|
#include <string>
|
|
#include <set>
|
|
|
|
#include "plugin.hxx"
|
|
|
|
// Check for some basic naming mismatches which make the code harder to read
|
|
//
|
|
// This plugin is deliberately fairly lax, and only targets the most egregeriously faulty code,
|
|
// since we have a broad range of styles in our code and we don't want to generate unnecessary
|
|
// churn.
|
|
|
|
namespace {
|
|
|
|
class StylePolice :
|
|
public loplugin::FilteringPlugin<StylePolice>
|
|
{
|
|
public:
|
|
explicit StylePolice(InstantiationData const & data): FilteringPlugin(data) {}
|
|
|
|
virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
|
|
|
|
bool VisitVarDecl(const VarDecl *);
|
|
private:
|
|
StringRef getFilename(SourceLocation loc);
|
|
};
|
|
|
|
StringRef StylePolice::getFilename(SourceLocation loc)
|
|
{
|
|
SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
|
|
StringRef name { getFilenameOfLocation(spellingLocation) };
|
|
return name;
|
|
}
|
|
|
|
bool startswith(const std::string& rStr, const char* pSubStr) {
|
|
return rStr.compare(0, strlen(pSubStr), pSubStr) == 0;
|
|
}
|
|
bool isUpperLetter(char c) {
|
|
return c >= 'A' && c <= 'Z';
|
|
}
|
|
bool isLowerLetter(char c) {
|
|
return c >= 'a' && c <= 'z';
|
|
}
|
|
bool isIdentifierLetter(char c) {
|
|
return isUpperLetter(c) || isLowerLetter(c);
|
|
}
|
|
bool matchPointerVar(const std::string& s) {
|
|
return s.size() > 2 && s[0] == 'p' && isUpperLetter(s[1]);
|
|
}
|
|
bool matchRefCountedPointerVar(const std::string& s) {
|
|
return s.size() > 2 && s[0] == 'x' && isUpperLetter(s[1]);
|
|
}
|
|
bool matchMember(const std::string& s) {
|
|
return s.size() > 3 && s[0] == 'm'
|
|
&& ( ( strchr("abnprsx", s[1]) && isUpperLetter(s[2]) )
|
|
|| ( s[1] == '_' && isIdentifierLetter(s[2]) ) );
|
|
}
|
|
|
|
bool StylePolice::VisitVarDecl(const VarDecl * varDecl)
|
|
{
|
|
if (ignoreLocation(varDecl)) {
|
|
return true;
|
|
}
|
|
StringRef aFileName = getFilename(varDecl->getLocStart());
|
|
std::string name = varDecl->getName();
|
|
|
|
if (!varDecl->isLocalVarDecl()) {
|
|
return true;
|
|
}
|
|
|
|
if (matchMember(name))
|
|
{
|
|
// these names appear to be taken from some scientific paper
|
|
if (aFileName == SRCDIR "/scaddins/source/analysis/bessel.cxx" ) {
|
|
}
|
|
// lots of places where we are storing a "method id" here
|
|
else if (aFileName.startswith(SRCDIR "/connectivity/source/drivers/jdbc") && name.compare(0,3,"mID") == 0) {
|
|
}
|
|
else {
|
|
report(
|
|
DiagnosticsEngine::Warning,
|
|
"this local variable follows our member field naming convention, which is confusing",
|
|
varDecl->getLocation())
|
|
<< varDecl->getType() << varDecl->getSourceRange();
|
|
}
|
|
}
|
|
|
|
QualType qt = varDecl->getType().getDesugaredType(compiler.getASTContext()).getCanonicalType();
|
|
qt = qt.getNonReferenceType();
|
|
std::string typeName = qt.getAsString();
|
|
if (startswith(typeName, "const "))
|
|
typeName = typeName.substr(6);
|
|
if (startswith(typeName, "class "))
|
|
typeName = typeName.substr(6);
|
|
if (startswith(typeName, "struct "))
|
|
typeName = typeName.substr(7);
|
|
std::string aOriginalTypeName = varDecl->getType().getAsString();
|
|
if (startswith(aOriginalTypeName, "const "))
|
|
aOriginalTypeName = aOriginalTypeName.substr(6);
|
|
|
|
if (!qt->isPointerType() && !qt->isArrayType() && !qt->isFunctionPointerType() && !qt->isMemberPointerType()
|
|
&& matchPointerVar(name)
|
|
&& !startswith(typeName, "boost::intrusive_ptr")
|
|
&& !startswith(typeName, "std::optional")
|
|
&& !startswith(typeName, "boost::shared_ptr")
|
|
&& !startswith(typeName, "com::sun::star::uno::Reference")
|
|
&& !startswith(typeName, "cppu::OInterfaceIteratorHelper")
|
|
&& !startswith(typeName, "formula::FormulaCompiler::CurrentFactor")
|
|
&& aOriginalTypeName != "GLXPixmap"
|
|
&& !startswith(typeName, "rtl::Reference")
|
|
&& !startswith(typeName, "ScopedVclPtr")
|
|
&& typeName.find("::mem_fun") == std::string::npos
|
|
&& typeName.find("shared_ptr") == std::string::npos
|
|
&& typeName.find("unique_ptr") == std::string::npos
|
|
&& typeName.find("::weak_ptr") == std::string::npos
|
|
&& !startswith(typeName, "_LOKDocViewPrivate")
|
|
&& !startswith(typeName, "sw::UnoCursorPointer")
|
|
&& !startswith(typeName, "tools::SvRef")
|
|
&& !startswith(typeName, "VclPtr")
|
|
&& !startswith(typeName, "vcl::ScopedBitmapAccess")
|
|
// lots of the code seems to regard iterator objects as being "pointer-like"
|
|
&& typeName.find("iterator<") == std::string::npos
|
|
&& typeName.find("iter<") == std::string::npos
|
|
// libc++ std::__1::__wrap_iter<...>
|
|
&& aOriginalTypeName != "sal_IntPtr" )
|
|
{
|
|
if (aFileName.startswith(SRCDIR "/bridges/") ) {
|
|
} else if (aFileName.startswith(SRCDIR "/vcl/source/fontsubset/sft.cxx") ) {
|
|
} else {
|
|
report(
|
|
DiagnosticsEngine::Warning,
|
|
"this local variable of type '%0' follows our pointer naming convention, but it is not a pointer, %1",
|
|
varDecl->getLocation())
|
|
<< typeName << aOriginalTypeName << varDecl->getSourceRange();
|
|
}
|
|
}
|
|
|
|
|
|
if (matchRefCountedPointerVar(name)
|
|
&& !startswith(typeName, "boost::intrusive_ptr")
|
|
&& !startswith(typeName, "com::sun::star::uno::Reference")
|
|
&& !startswith(typeName, "com::sun::star::uno::Sequence")
|
|
&& !startswith(typeName, "com::sun::star::uno::WeakReference")
|
|
&& !startswith(typeName, "drawinglayer::primitive2d::Primitive2DContainer")
|
|
&& !startswith(typeName, "drawinglayer::primitive3d::Primitive3DContainer")
|
|
&& !startswith(typeName, "jfw::CXPathObjectPtr")
|
|
&& !startswith(typeName, "_LOKDocViewPrivate")
|
|
&& !startswith(typeName, "oox::dump::BinaryInputStreamRef")
|
|
&& !startswith(typeName, "oox::drawingml::chart::ModelRef")
|
|
&& !startswith(typeName, "rtl::Reference")
|
|
&& !startswith(typeName, "Reference")
|
|
&& !startswith(typeName, "SfxObjectShellLock")
|
|
&& !startswith(typeName, "store::PageHolderObject")
|
|
&& !startswith(typeName, "store::ResourceHolder")
|
|
&& !startswith(typeName, "store::OStoreHandle")
|
|
&& typeName.find("unique_ptr") == std::string::npos
|
|
&& typeName.find("shared_ptr") == std::string::npos
|
|
&& !startswith(typeName, "ScopedVclPtr")
|
|
&& !startswith(typeName, "svt::EmbeddedObjectRef")
|
|
&& !startswith(typeName, "tools::SvRef")
|
|
&& !startswith(typeName, "tools::WeakReference")
|
|
&& !startswith(typeName, "utl::SharedUNOComponent")
|
|
&& !startswith(typeName, "VclPtr")
|
|
&& !startswith(typeName, "vcl::DeleteOnDeinit")
|
|
&& !startswith(typeName, "vcl::DeleteUnoReferenceOnDeinit")
|
|
// there are lots of coordinate/position vars that start with "x"
|
|
&& !qt->isArithmeticType()
|
|
&& !startswith(typeName, "float [")
|
|
)
|
|
{
|
|
report(
|
|
DiagnosticsEngine::Warning,
|
|
"this local variable of type '%0' follows our ref-counted-pointer naming convention, but it is not a ref-counted-pointer, %1",
|
|
varDecl->getLocation())
|
|
<< typeName << aOriginalTypeName << varDecl->getSourceRange();
|
|
}
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
loplugin::Plugin::Registration< StylePolice > X("stylepolice");
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|