File indexing completed on 2024-05-19 05:41:43

0001 /*
0002     SPDX-FileCopyrightText: 2018 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "qt-keywords.h"
0008 #include "ClazyContext.h"
0009 #include "FixItUtils.h"
0010 #include "PreProcessorVisitor.h"
0011 #include "clazy_stl.h"
0012 
0013 #include <clang/Basic/Diagnostic.h>
0014 #include <clang/Basic/IdentifierTable.h>
0015 #include <clang/Basic/SourceManager.h>
0016 #include <clang/Lex/MacroInfo.h>
0017 #include <clang/Lex/Token.h>
0018 #include <llvm/ADT/StringRef.h>
0019 
0020 #include <algorithm>
0021 #include <ctype.h>
0022 #include <vector>
0023 
0024 using namespace clang;
0025 
0026 QtKeywords::QtKeywords(const std::string &name, ClazyContext *context)
0027     : CheckBase(name, context)
0028 {
0029     enablePreProcessorCallbacks();
0030     context->enablePreprocessorVisitor();
0031 }
0032 
0033 void QtKeywords::VisitMacroExpands(const Token &macroNameTok, const SourceRange &range, const clang::MacroInfo *minfo)
0034 {
0035     IdentifierInfo *ii = macroNameTok.getIdentifierInfo();
0036     if (!ii || !minfo) {
0037         return;
0038     }
0039 
0040     if (auto *ppvisitor = m_context->preprocessorVisitor) {
0041         // Save some CPU cycles. No point in running if QT_NO_KEYWORDS
0042         if (ppvisitor->isQT_NO_KEYWORDS()) {
0043             return;
0044         }
0045     }
0046 
0047     static const std::vector<StringRef> keywords = {"foreach", "signals", "slots", "emit"};
0048     std::string name = static_cast<std::string>(ii->getName());
0049     if (!clazy::contains(keywords, name)) {
0050         return;
0051     }
0052 
0053     // Make sure the macro is Qt's. It must be defined in Qt's headers, not 3rdparty
0054     std::string qtheader = static_cast<std::string>(sm().getFilename(sm().getSpellingLoc(minfo->getDefinitionLoc())));
0055     if (!clazy::endsWithAny(qtheader, {"qglobal.h", "qobjectdefs.h", "qtmetamacros.h", "qforeach.h"})) {
0056         return;
0057     }
0058 
0059     std::vector<FixItHint> fixits;
0060     std::string replacement = "Q_" + name;
0061     std::transform(replacement.begin(), replacement.end(), replacement.begin(), ::toupper);
0062     fixits.push_back(clazy::createReplacement(range, replacement));
0063 
0064     emitWarning(range.getBegin(), "Using a Qt keyword (" + std::string(ii->getName()) + ")", fixits);
0065 }