1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
17 // Check for some basic naming mismatches which make the code harder to read
19 // This plugin is deliberately fairly lax, and only targets the most egregeriously faulty code,
20 // since we have a broad range of styles in our code and we don't want to generate unnecessary
26 public loplugin::FilteringPlugin
<StylePolice
>
29 explicit StylePolice(InstantiationData
const & data
): FilteringPlugin(data
) {}
31 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
33 bool VisitVarDecl(const VarDecl
*);
35 StringRef
getFilename(SourceLocation loc
);
38 StringRef
StylePolice::getFilename(SourceLocation loc
)
40 SourceLocation spellingLocation
= compiler
.getSourceManager().getSpellingLoc(loc
);
41 StringRef name
{ getFilenameOfLocation(spellingLocation
) };
45 bool startswith(const std::string
& rStr
, const char* pSubStr
) {
46 return rStr
.compare(0, strlen(pSubStr
), pSubStr
) == 0;
48 bool isUpperLetter(char c
) {
49 return c
>= 'A' && c
<= 'Z';
51 bool isLowerLetter(char c
) {
52 return c
>= 'a' && c
<= 'z';
54 bool isIdentifierLetter(char c
) {
55 return isUpperLetter(c
) || isLowerLetter(c
);
57 bool matchPointerVar(const std::string
& s
) {
58 return s
.size() > 2 && s
[0] == 'p' && isUpperLetter(s
[1]);
60 bool matchRefCountedPointerVar(const std::string
& s
) {
61 return s
.size() > 2 && s
[0] == 'x' && isUpperLetter(s
[1]);
63 bool matchMember(const std::string
& s
) {
64 return s
.size() > 3 && s
[0] == 'm'
65 && ( ( strchr("abnprsx", s
[1]) && isUpperLetter(s
[2]) )
66 || ( s
[1] == '_' && isIdentifierLetter(s
[2]) ) );
69 bool StylePolice::VisitVarDecl(const VarDecl
* varDecl
)
71 if (ignoreLocation(varDecl
)) {
74 StringRef aFileName
= getFilename(varDecl
->getLocStart());
75 std::string name
= varDecl
->getName();
77 if (!varDecl
->isLocalVarDecl()) {
81 if (matchMember(name
))
83 // these names appear to be taken from some scientific paper
84 if (aFileName
== SRCDIR
"/scaddins/source/analysis/bessel.cxx" ) {
86 // lots of places where we are storing a "method id" here
87 else if (aFileName
.startswith(SRCDIR
"/connectivity/source/drivers/jdbc") && name
.compare(0,3,"mID") == 0) {
91 DiagnosticsEngine::Warning
,
92 "this local variable follows our member field naming convention, which is confusing",
93 varDecl
->getLocation())
94 << varDecl
->getType() << varDecl
->getSourceRange();
98 QualType qt
= varDecl
->getType().getDesugaredType(compiler
.getASTContext()).getCanonicalType();
99 qt
= qt
.getNonReferenceType();
100 std::string typeName
= qt
.getAsString();
101 if (startswith(typeName
, "const "))
102 typeName
= typeName
.substr(6);
103 if (startswith(typeName
, "class "))
104 typeName
= typeName
.substr(6);
105 if (startswith(typeName
, "struct "))
106 typeName
= typeName
.substr(7);
107 std::string aOriginalTypeName
= varDecl
->getType().getAsString();
108 if (startswith(aOriginalTypeName
, "const "))
109 aOriginalTypeName
= aOriginalTypeName
.substr(6);
111 if (!qt
->isPointerType() && !qt
->isArrayType() && !qt
->isFunctionPointerType() && !qt
->isMemberPointerType()
112 && matchPointerVar(name
)
113 && !startswith(typeName
, "boost::intrusive_ptr")
114 && !startswith(typeName
, "std::optional")
115 && !startswith(typeName
, "boost::shared_ptr")
116 && !startswith(typeName
, "com::sun::star::uno::Reference")
117 && !startswith(typeName
, "cppu::OInterfaceIteratorHelper")
118 && !startswith(typeName
, "formula::FormulaCompiler::CurrentFactor")
119 && aOriginalTypeName
!= "GLXPixmap"
120 && !startswith(typeName
, "rtl::Reference")
121 && !startswith(typeName
, "ScopedVclPtr")
122 && typeName
.find("::mem_fun") == std::string::npos
123 && typeName
.find("shared_ptr") == std::string::npos
124 && typeName
.find("unique_ptr") == std::string::npos
125 && typeName
.find("::weak_ptr") == std::string::npos
126 && !startswith(typeName
, "_LOKDocViewPrivate")
127 && !startswith(typeName
, "sw::UnoCursorPointer")
128 && !startswith(typeName
, "tools::SvRef")
129 && !startswith(typeName
, "VclPtr")
130 && !startswith(typeName
, "vcl::ScopedBitmapAccess")
131 // lots of the code seems to regard iterator objects as being "pointer-like"
132 && typeName
.find("iterator<") == std::string::npos
133 && typeName
.find("iter<") == std::string::npos
134 // libc++ std::__1::__wrap_iter<...>
135 && aOriginalTypeName
!= "sal_IntPtr" )
137 if (aFileName
.startswith(SRCDIR
"/bridges/") ) {
138 } else if (aFileName
.startswith(SRCDIR
"/vcl/source/fontsubset/sft.cxx") ) {
141 DiagnosticsEngine::Warning
,
142 "this local variable of type '%0' follows our pointer naming convention, but it is not a pointer, %1",
143 varDecl
->getLocation())
144 << typeName
<< aOriginalTypeName
<< varDecl
->getSourceRange();
149 if (matchRefCountedPointerVar(name
)
150 && !startswith(typeName
, "boost::intrusive_ptr")
151 && !startswith(typeName
, "com::sun::star::uno::Reference")
152 && !startswith(typeName
, "com::sun::star::uno::Sequence")
153 && !startswith(typeName
, "com::sun::star::uno::WeakReference")
154 && !startswith(typeName
, "drawinglayer::primitive2d::Primitive2DContainer")
155 && !startswith(typeName
, "drawinglayer::primitive3d::Primitive3DContainer")
156 && !startswith(typeName
, "jfw::CXPathObjectPtr")
157 && !startswith(typeName
, "_LOKDocViewPrivate")
158 && !startswith(typeName
, "oox::dump::BinaryInputStreamRef")
159 && !startswith(typeName
, "oox::drawingml::chart::ModelRef")
160 && !startswith(typeName
, "rtl::Reference")
161 && !startswith(typeName
, "Reference")
162 && !startswith(typeName
, "SfxObjectShellLock")
163 && !startswith(typeName
, "store::PageHolderObject")
164 && !startswith(typeName
, "store::ResourceHolder")
165 && !startswith(typeName
, "store::OStoreHandle")
166 && typeName
.find("unique_ptr") == std::string::npos
167 && typeName
.find("shared_ptr") == std::string::npos
168 && !startswith(typeName
, "ScopedVclPtr")
169 && !startswith(typeName
, "svt::EmbeddedObjectRef")
170 && !startswith(typeName
, "tools::SvRef")
171 && !startswith(typeName
, "tools::WeakReference")
172 && !startswith(typeName
, "utl::SharedUNOComponent")
173 && !startswith(typeName
, "VclPtr")
174 && !startswith(typeName
, "vcl::DeleteOnDeinit")
175 && !startswith(typeName
, "vcl::DeleteUnoReferenceOnDeinit")
176 // there are lots of coordinate/position vars that start with "x"
177 && !qt
->isArithmeticType()
178 && !startswith(typeName
, "float [")
182 DiagnosticsEngine::Warning
,
183 "this local variable of type '%0' follows our ref-counted-pointer naming convention, but it is not a ref-counted-pointer, %1",
184 varDecl
->getLocation())
185 << typeName
<< aOriginalTypeName
<< varDecl
->getSourceRange();
192 loplugin::Plugin::Registration
< StylePolice
> X("stylepolice");
196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */