Move setting of LD_LIBRARY_PATH closer to invocation of cppunittester
[LibreOffice.git] / compilerplugins / clang / store / stylepolice.cxx
blobd3b2e8a4400e900c6b44cec61b47abfaf0dc6c3d
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 <memory>
11 #include <regex>
12 #include <string>
13 #include <set>
15 #include "plugin.hxx"
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
21 // churn.
23 namespace {
25 class StylePolice :
26 public loplugin::FilteringPlugin<StylePolice>
28 public:
29 explicit StylePolice(InstantiationData const & data): FilteringPlugin(data) {}
31 virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
33 bool VisitVarDecl(const VarDecl *);
34 private:
35 StringRef getFilename(SourceLocation loc);
38 StringRef StylePolice::getFilename(SourceLocation loc)
40 SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(loc);
41 StringRef name { getFilenameOfLocation(spellingLocation) };
42 return name;
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)) {
72 return true;
74 StringRef aFileName = getFilename(varDecl->getLocStart());
75 std::string name = varDecl->getName();
77 if (!varDecl->isLocalVarDecl()) {
78 return true;
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) {
89 else {
90 report(
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") ) {
139 } else {
140 report(
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 [")
181 report(
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();
189 return true;
192 loplugin::Plugin::Registration< StylePolice > X("stylepolice");
196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */