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 ¯oNameTok, 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 }