cURL: follow redirects
[LibreOffice.git] / compilerplugins / clang / store / stylepolice.cxx
bloba0f5373a16a6698b2bf0cf3737f2d5f2a2af4127
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <regex>
11 #include <string>
12 #include <set>
14 #include "plugin.hxx"
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
20 // churn.
22 namespace {
24 class StylePolice :
25 public RecursiveASTVisitor<StylePolice>, public loplugin::Plugin
27 public:
28 explicit StylePolice(InstantiationData const & data): Plugin(data) {}
30 virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
32 bool VisitVarDecl(const VarDecl *);
33 private:
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) };
41 return name;
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)) {
71 return true;
73 StringRef aFileName = getFilename(varDecl->getLocStart());
74 std::string name = varDecl->getName();
76 if (!varDecl->isLocalVarDecl()) {
77 return true;
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) {
88 else {
89 report(
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") ) {
138 } else {
139 report(
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 [")
180 report(
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();
188 return true;
191 loplugin::Plugin::Registration< StylePolice > X("stylepolice");
195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */