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/.
16 // Check for some basic naming mismatches which make the code harder to read
18 // This plugin is deliberately fairly lax, and only targets the most egregeriously faulty code,
19 // since we have a broad range of styles in our code and we don't want to generate unnecessary
25 public RecursiveASTVisitor
<StylePolice
>, public loplugin::Plugin
28 explicit StylePolice(InstantiationData
const & data
): Plugin(data
) {}
30 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
32 bool VisitVarDecl(const VarDecl
*);
34 StringRef
getFilename(SourceLocation loc
);
37 StringRef
StylePolice::getFilename(SourceLocation loc
)
39 SourceLocation spellingLocation
= compiler
.getSourceManager().getSpellingLoc(loc
);
40 StringRef name
{ compiler
.getSourceManager().getFilename(spellingLocation
) };
44 bool startswith(const std::string
& rStr
, const char* pSubStr
) {
45 return rStr
.compare(0, strlen(pSubStr
), pSubStr
) == 0;
47 bool isUpperLetter(char c
) {
48 return c
>= 'A' && c
<= 'Z';
50 bool isLowerLetter(char c
) {
51 return c
>= 'a' && c
<= 'z';
53 bool isIdentifierLetter(char c
) {
54 return isUpperLetter(c
) || isLowerLetter(c
);
56 bool matchPointerVar(const std::string
& s
) {
57 return s
.size() > 2 && s
[0] == 'p' && isUpperLetter(s
[1]);
59 bool matchRefCountedPointerVar(const std::string
& s
) {
60 return s
.size() > 2 && s
[0] == 'x' && isUpperLetter(s
[1]);
62 bool matchMember(const std::string
& s
) {
63 return s
.size() > 3 && s
[0] == 'm'
64 && ( ( strchr("abnprsx", s
[1]) && isUpperLetter(s
[2]) )
65 || ( s
[1] == '_' && isIdentifierLetter(s
[2]) ) );
68 bool StylePolice::VisitVarDecl(const VarDecl
* varDecl
)
70 if (ignoreLocation(varDecl
)) {
73 StringRef aFileName
= getFilename(varDecl
->getLocStart());
74 std::string name
= varDecl
->getName();
76 if (!varDecl
->isLocalVarDecl()) {
80 if (matchMember(name
))
82 // these names appear to be taken from some scientific paper
83 if (aFileName
== SRCDIR
"/scaddins/source/analysis/bessel.cxx" ) {
85 // lots of places where we are storing a "method id" here
86 else if (aFileName
.startswith(SRCDIR
"/connectivity/source/drivers/jdbc") && name
.compare(0,3,"mID") == 0) {
90 DiagnosticsEngine::Warning
,
91 "this local variable follows our member field naming convention, which is confusing",
92 varDecl
->getLocation())
93 << varDecl
->getType() << varDecl
->getSourceRange();
97 QualType qt
= varDecl
->getType().getDesugaredType(compiler
.getASTContext()).getCanonicalType();
98 qt
= qt
.getNonReferenceType();
99 std::string typeName
= qt
.getAsString();
100 if (startswith(typeName
, "const "))
101 typeName
= typeName
.substr(6);
102 if (startswith(typeName
, "class "))
103 typeName
= typeName
.substr(6);
104 if (startswith(typeName
, "struct "))
105 typeName
= typeName
.substr(7);
106 std::string aOriginalTypeName
= varDecl
->getType().getAsString();
107 if (startswith(aOriginalTypeName
, "const "))
108 aOriginalTypeName
= aOriginalTypeName
.substr(6);
110 if (!qt
->isPointerType() && !qt
->isArrayType() && !qt
->isFunctionPointerType() && !qt
->isMemberPointerType()
111 && matchPointerVar(name
)
112 && !startswith(typeName
, "boost::intrusive_ptr")
113 && !startswith(typeName
, "boost::optional")
114 && !startswith(typeName
, "boost::shared_ptr")
115 && !startswith(typeName
, "com::sun::star::uno::Reference")
116 && !startswith(typeName
, "cppu::OInterfaceIteratorHelper")
117 && !startswith(typeName
, "formula::FormulaCompiler::CurrentFactor")
118 && aOriginalTypeName
!= "GLXPixmap"
119 && !startswith(typeName
, "rtl::Reference")
120 && !startswith(typeName
, "ScopedVclPtr")
121 && typeName
.find("::mem_fun") == std::string::npos
122 && typeName
.find("shared_ptr") == std::string::npos
123 && typeName
.find("unique_ptr") == std::string::npos
124 && typeName
.find("::weak_ptr") == std::string::npos
125 && !startswith(typeName
, "_LOKDocViewPrivate")
126 && !startswith(typeName
, "sw::UnoCursorPointer")
127 && !startswith(typeName
, "tools::SvRef")
128 && !startswith(typeName
, "VclPtr")
129 && !startswith(typeName
, "vcl::ScopedBitmapAccess")
130 // lots of the code seems to regard iterator objects as being "pointer-like"
131 && typeName
.find("iterator<") == std::string::npos
132 && typeName
.find("iter<") == std::string::npos
133 // libc++ std::__1::__wrap_iter<...>
134 && aOriginalTypeName
!= "sal_IntPtr" )
136 if (aFileName
.startswith(SRCDIR
"/bridges/") ) {
137 } else if (aFileName
.startswith(SRCDIR
"/vcl/source/fontsubset/sft.cxx") ) {
140 DiagnosticsEngine::Warning
,
141 "this local variable of type '%0' follows our pointer naming convention, but it is not a pointer, %1",
142 varDecl
->getLocation())
143 << typeName
<< aOriginalTypeName
<< varDecl
->getSourceRange();
148 if (matchRefCountedPointerVar(name
)
149 && !startswith(typeName
, "boost::intrusive_ptr")
150 && !startswith(typeName
, "com::sun::star::uno::Reference")
151 && !startswith(typeName
, "com::sun::star::uno::Sequence")
152 && !startswith(typeName
, "com::sun::star::uno::WeakReference")
153 && !startswith(typeName
, "drawinglayer::primitive2d::Primitive2DContainer")
154 && !startswith(typeName
, "drawinglayer::primitive3d::Primitive3DContainer")
155 && !startswith(typeName
, "jfw::CXPathObjectPtr")
156 && !startswith(typeName
, "_LOKDocViewPrivate")
157 && !startswith(typeName
, "oox::dump::BinaryInputStreamRef")
158 && !startswith(typeName
, "oox::drawingml::chart::ModelRef")
159 && !startswith(typeName
, "rtl::Reference")
160 && !startswith(typeName
, "Reference")
161 && !startswith(typeName
, "SfxObjectShellLock")
162 && !startswith(typeName
, "store::PageHolderObject")
163 && !startswith(typeName
, "store::ResourceHolder")
164 && !startswith(typeName
, "store::OStoreHandle")
165 && typeName
.find("unique_ptr") == std::string::npos
166 && typeName
.find("shared_ptr") == std::string::npos
167 && !startswith(typeName
, "ScopedVclPtr")
168 && !startswith(typeName
, "svt::EmbeddedObjectRef")
169 && !startswith(typeName
, "tools::SvRef")
170 && !startswith(typeName
, "tools::WeakReference")
171 && !startswith(typeName
, "utl::SharedUNOComponent")
172 && !startswith(typeName
, "VclPtr")
173 && !startswith(typeName
, "vcl::DeleteOnDeinit")
174 && !startswith(typeName
, "vcl::DeleteUnoReferenceOnDeinit")
175 // there are lots of coordinate/position vars that start with "x"
176 && !qt
->isArithmeticType()
177 && !startswith(typeName
, "float [")
181 DiagnosticsEngine::Warning
,
182 "this local variable of type '%0' follows our ref-counted-pointer naming convention, but it is not a ref-counted-pointer, %1",
183 varDecl
->getLocation())
184 << typeName
<< aOriginalTypeName
<< varDecl
->getSourceRange();
191 loplugin::Plugin::Registration
< StylePolice
> X("stylepolice");
195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */