File indexing completed on 2024-04-14 05:32:05

0001 /*
0002     SPDX-FileCopyrightText: 2016 Sergio Martins <smartins@kde.org>
0003     SPDX-FileCopyrightText: 2016 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef CLAZY_ACCESS_SPECIFIER_MANAGER_H
0009 #define CLAZY_ACCESS_SPECIFIER_MANAGER_H
0010 
0011 #include "checkbase.h"
0012 
0013 #include <clang/Basic/SourceLocation.h>
0014 #include <clang/Basic/Specifiers.h>
0015 #include <clang/Frontend/CompilerInstance.h>
0016 #include <llvm/ADT/StringRef.h>
0017 
0018 #include <unordered_map>
0019 #include <vector>
0020 
0021 /*
0022    clang supports "public", "private" and "protected"
0023    This is a small wrapper to have support for "public slots", "signals", etc. so you can easily
0024    query if a method is a signal or slot
0025 
0026    This works in two steps, first the pre-processor kicks in and we use a PPCallbacks class to catch
0027    Q_SLOTS and Q_SIGNALS, then the normal access specifiers come in from the AST, inside VisitDeclaration().
0028 
0029    After that we just need to merge the two lists, and sort by source location. All the info is kept
0030    inside m_specifiersMap, which is indexed by the class definition.
0031 */
0032 
0033 namespace clang
0034 {
0035 class SourceManager;
0036 class LangOptions;
0037 class Decl;
0038 class CXXRecordDecl;
0039 class SourceLocation;
0040 class CXXMethodDecl;
0041 class CompilerInstance;
0042 }
0043 
0044 class AccessSpecifierPreprocessorCallbacks;
0045 class ClazyContext;
0046 
0047 enum QtAccessSpecifierType { QtAccessSpecifier_None, QtAccessSpecifier_Unknown, QtAccessSpecifier_Slot, QtAccessSpecifier_Signal, QtAccessSpecifier_Invokable };
0048 
0049 struct ClazyAccessSpecifier {
0050     clang::SourceLocation loc;
0051     clang::AccessSpecifier accessSpecifier;
0052     QtAccessSpecifierType qtAccessSpecifier;
0053 };
0054 
0055 using ClazySpecifierList = std::vector<ClazyAccessSpecifier>;
0056 
0057 class AccessSpecifierManager
0058 {
0059 public:
0060     explicit AccessSpecifierManager(ClazyContext *);
0061     void VisitDeclaration(clang::Decl *decl);
0062 
0063     /**
0064      * Returns if a method is a signal, a slot, or neither.
0065      */
0066     QtAccessSpecifierType qtAccessSpecifierType(const clang::CXXMethodDecl *) const;
0067 
0068     /**
0069      * Returns if a method is scriptable (Q_SCRIPTABLE)
0070      */
0071     bool isScriptable(const clang::CXXMethodDecl *) const;
0072 
0073     /**
0074      * Returns a string representations of a Qt Access Specifier Type
0075      */
0076     llvm::StringRef qtAccessSpecifierTypeStr(QtAccessSpecifierType) const;
0077 
0078     clang::SourceLocation firstLocationOfSection(clang::AccessSpecifier specifier, clang::CXXRecordDecl *decl) const;
0079 
0080 private:
0081     ClazySpecifierList &entryForClassDefinition(clang::CXXRecordDecl *);
0082     const clang::CompilerInstance &m_ci;
0083     const clang::CXXRecordDecl *classDefinitionForLoc(clang::SourceLocation loc) const;
0084     std::unordered_map<const clang::CXXRecordDecl *, ClazySpecifierList> m_specifiersMap;
0085     AccessSpecifierPreprocessorCallbacks *const m_preprocessorCallbacks;
0086     const bool m_fixitsEnabled;
0087     bool m_visitsNonQObjects = false;
0088 };
0089 
0090 #endif