update emoji autocorrect entries from po-files
[LibreOffice.git] / compilerplugins / clang / rendercontext.cxx
blobcc2a945769c337d55dc792015c99e7167071488b
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 <string>
11 #include <iostream>
13 #include "plugin.hxx"
14 #include "compat.hxx"
15 #include "clang/AST/CXXInheritance.h"
17 // Check for calls to OutputDevice methods that are not passing through RenderContext
19 namespace
22 class RenderContext:
23 public RecursiveASTVisitor<RenderContext>, public loplugin::Plugin
25 public:
26 explicit RenderContext(InstantiationData const & data): Plugin(data) {}
28 virtual void run() override {
29 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
32 bool TraverseFunctionDecl(const FunctionDecl * decl);
34 bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *);
36 private:
37 bool mbChecking = false;
40 // We use Traverse to set a flag so we can easily ignore certain method calls
41 bool RenderContext::TraverseFunctionDecl(const FunctionDecl * pFunctionDecl)
43 if (ignoreLocation(pFunctionDecl)) {
44 return true;
46 if (!pFunctionDecl->hasBody()) {
47 return true;
49 if ( pFunctionDecl != pFunctionDecl->getCanonicalDecl() ) {
50 return true;
52 // Ignore methods inside the OutputDevice class
53 const CXXMethodDecl *pCXXMethodDecl = dyn_cast<CXXMethodDecl>(pFunctionDecl);
54 if (pCXXMethodDecl) {
55 std::string aParentName = pCXXMethodDecl->getParent()->getQualifiedNameAsString();
56 if (aParentName == "OutputDevice")
57 return true;
59 // we are only currently interested in methods where the first parameter is RenderContext
60 if (pFunctionDecl->getNumParams() == 0)
61 return true;
62 string arg0 = pFunctionDecl->getParamDecl( 0 )->getType().getAsString();
63 if ( arg0.find("RenderContext") != std::string::npos ) {
64 return true;
66 mbChecking = true;
67 TraverseStmt(pFunctionDecl->getBody());
68 mbChecking = false;
69 return true;
72 bool RenderContext::VisitCXXMemberCallExpr(const CXXMemberCallExpr* pCXXMemberCallExpr)
74 if (!mbChecking)
75 return true;
76 if (ignoreLocation(pCXXMemberCallExpr)) {
77 return true;
79 const CXXRecordDecl *pCXXRecordDecl = pCXXMemberCallExpr->getRecordDecl();
80 if (pCXXRecordDecl->getQualifiedNameAsString() != "OutputDevice") {
81 return true;
83 // ignore a handful of methods. They will most probably still be present in Window for use during processing outside of the Paint()
84 // method lifecycle
85 const CXXMethodDecl *pCXXMethodDecl = pCXXMemberCallExpr->getMethodDecl();
86 if (pCXXMethodDecl->isInstance()) {
87 StringRef name = pCXXMethodDecl->getName();
88 if (name == "LogicToPixel" || name == "GetMapMode" || name == "GetFontMetric" || name == "LogicToLogic"
89 || name == "PixelToLogic" || name == "SetDigitLanguage")
91 return true;
94 // for calling through a pointer
95 const ImplicitCastExpr *pImplicitCastExpr = dyn_cast<ImplicitCastExpr>(pCXXMemberCallExpr->getImplicitObjectArgument());
96 std::string x = "0"; // for debugging
97 if (pImplicitCastExpr) {
98 x += "1";
99 QualType aType = pImplicitCastExpr->getSubExpr()->getType();
100 if (aType->isPointerType())
101 aType = aType->getPointeeType();
102 std::string t2 = aType.getAsString();
103 if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext")
104 return true;
106 // for calling through a reference
107 const DeclRefExpr *pDeclRefExpr = dyn_cast<DeclRefExpr>(pCXXMemberCallExpr->getImplicitObjectArgument());
108 if (pDeclRefExpr) {
109 x += "2";
110 QualType aType = pDeclRefExpr->getType();
111 std::string t2 = aType.getAsString();
112 if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext")
113 return true;
115 // for calling through a chain of methods
116 const CXXMemberCallExpr *pMemberExpr = dyn_cast<CXXMemberCallExpr>(pCXXMemberCallExpr->getImplicitObjectArgument());
117 if (pMemberExpr) {
118 x += "3";
119 QualType aType = pMemberExpr->getType();
120 if (aType->isPointerType())
121 aType = aType->getPointeeType();
122 std::string t2 = aType.getAsString();
123 x += t2;
124 if (t2 == "vcl::RenderContext" || t2 == "const vcl::RenderContext")
125 return true;
127 report(
128 DiagnosticsEngine::Warning,
129 // + x + pCXXMemberCallExpr->getImplicitObjectArgument()->getStmtClassName()
130 "Should be calling OutputDevice method through RenderContext.",
131 pCXXMemberCallExpr->getLocStart())
132 << pCXXMemberCallExpr->getSourceRange();
133 return true;
136 loplugin::Plugin::Registration< RenderContext > X("rendercontext", false);
140 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */