File indexing completed on 2024-04-21 05:38:45

0001 /*
0002     SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com
0003     SPDX-FileContributor: SĂ©rgio Martins <sergio.martins@kdab.com>
0004 
0005     SPDX-FileCopyrightText: 2015-2016 Sergio Martins <smartins@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef CLANG_LAZY_CHECK_MANAGER_H
0011 #define CLANG_LAZY_CHECK_MANAGER_H
0012 
0013 #include "checkbase.h"
0014 
0015 #include <clang/Lex/PreprocessorOptions.h>
0016 
0017 #include <functional>
0018 #include <mutex>
0019 #include <string>
0020 #include <unordered_map>
0021 #include <utility>
0022 #include <vector>
0023 
0024 class ClazyContext;
0025 
0026 struct RegisteredFixIt {
0027     using List = std::vector<RegisteredFixIt>;
0028     RegisteredFixIt()
0029         : id(-1)
0030     {
0031     }
0032     RegisteredFixIt(int id, const std::string &name)
0033         : id(id)
0034         , name(name)
0035     {
0036     }
0037     int id = -1;
0038     std::string name;
0039     bool operator==(const RegisteredFixIt &other) const
0040     {
0041         return id == other.id;
0042     }
0043 };
0044 
0045 using FactoryFunction = std::function<CheckBase *(ClazyContext *context)>;
0046 
0047 struct RegisteredCheck {
0048     enum Option { Option_None = 0, Option_Qt4Incompatible = 1, Option_VisitsStmts = 2, Option_VisitsDecls = 4 };
0049 
0050     using List = std::vector<RegisteredCheck>;
0051     using Options = int;
0052 
0053     std::string name;
0054     CheckLevel level;
0055     FactoryFunction factory;
0056     Options options;
0057     bool operator==(const RegisteredCheck &other) const
0058     {
0059         return name == other.name;
0060     }
0061 };
0062 
0063 inline bool checkLessThan(const RegisteredCheck &c1, const RegisteredCheck &c2)
0064 {
0065     return c1.name < c2.name;
0066 }
0067 
0068 inline bool checkLessThanByLevel(const RegisteredCheck &c1, const RegisteredCheck &c2)
0069 {
0070     if (c1.level == c2.level) {
0071         return checkLessThan(c1, c2);
0072     }
0073 
0074     return c1.level < c2.level;
0075 }
0076 
0077 class CheckManager
0078 {
0079 public:
0080     /**
0081      * @note You must hold the CheckManager lock when operating on the instance
0082      *
0083      * @sa lock()
0084      */
0085     static CheckManager *instance();
0086 
0087     static std::mutex &lock()
0088     {
0089         return m_lock;
0090     }
0091     RegisteredCheck::List availableChecks(CheckLevel maxLevel) const;
0092     RegisteredCheck::List requestedChecksThroughEnv(std::vector<std::string> &userDisabledChecks) const;
0093     std::vector<std::string> checksAsErrors() const;
0094 
0095     RegisteredCheck::List::const_iterator checkForName(const RegisteredCheck::List &checks, const std::string &name) const;
0096     RegisteredCheck::List checksForCommaSeparatedString(const std::string &str) const;
0097     RegisteredCheck::List checksForCommaSeparatedString(const std::string &str, std::vector<std::string> &userDisabledChecks) const;
0098     RegisteredFixIt::List availableFixIts(const std::string &checkName) const;
0099 
0100     /**
0101      * Returns all the requested checks.
0102      * This is a union of the requested checks via env variable and via arguments passed to compiler
0103      */
0104     RegisteredCheck::List requestedChecks(std::vector<std::string> &args, bool qt4Compat);
0105     std::vector<std::pair<CheckBase *, RegisteredCheck>> createChecks(const RegisteredCheck::List &requestedChecks, ClazyContext *context);
0106 
0107     static void removeChecksFromList(RegisteredCheck::List &list, std::vector<std::string> &checkNames);
0108 
0109 private:
0110     CheckManager();
0111     static std::mutex m_lock;
0112 
0113     void registerChecks();
0114     void registerFixIt(int id, const std::string &fititName, const std::string &checkName);
0115     void registerCheck(const RegisteredCheck &check);
0116     bool checkExists(const std::string &name) const;
0117     RegisteredCheck::List checksForLevel(int level) const;
0118     CheckBase *createCheck(const std::string &name, ClazyContext *context);
0119     std::string checkNameForFixIt(const std::string &) const;
0120     RegisteredCheck::List m_registeredChecks;
0121     std::unordered_map<std::string, std::vector<RegisteredFixIt>> m_fixitsByCheckName;
0122     std::unordered_map<std::string, RegisteredFixIt> m_fixitByName;
0123 };
0124 
0125 #endif