File indexing completed on 2024-05-12 05:40:56

0001 /*
0002     SPDX-FileCopyrightText: 2023 Johnny Jazeix <jazeix@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "no-module-include.h"
0008 #include "ClazyContext.h"
0009 #include "PreProcessorVisitor.h"
0010 
0011 #include <clang/Basic/LLVM.h>
0012 
0013 #include <vector>
0014 
0015 namespace clang
0016 {
0017 class Decl;
0018 } // namespace clang
0019 
0020 using namespace clang;
0021 
0022 NoModuleInclude::NoModuleInclude(const std::string &name, ClazyContext *context)
0023     : CheckBase(name, context)
0024     , m_modulesList{
0025           "Core",
0026           "Gui",
0027           "Qml",
0028           "QmlModels",
0029           "Test",
0030           "Network",
0031           "DBus",
0032           "Quick",
0033           "Svg",
0034           "Widgets",
0035           "Xml",
0036           "Concurrent",
0037           "Multimedia",
0038           "Sql",
0039           "PrintSupport",
0040           "NetworkAuth",
0041           "QmlIntegration",
0042       }
0043 {
0044     for (const std::string &module : m_modulesList) {
0045         m_filesToIgnore.emplace_back("Qt" + module + "Depends");
0046     }
0047     enablePreProcessorCallbacks();
0048 }
0049 
0050 void NoModuleInclude::VisitInclusionDirective(clang::SourceLocation HashLoc,
0051                                               const clang::Token & /*IncludeTok*/,
0052                                               clang::StringRef FileName,
0053                                               bool /*IsAngled*/,
0054                                               clang::CharSourceRange FilenameRange,
0055                                               clazy::OptionalFileEntryRef /*File*/,
0056                                               clang::StringRef /*SearchPath*/,
0057                                               clang::StringRef /*RelativePath*/,
0058                                               const clang::Module * /*Imported*/,
0059                                               clang::SrcMgr::CharacteristicKind /*FileType*/)
0060 {
0061     if (shouldIgnoreFile(HashLoc)) {
0062         return;
0063     }
0064 
0065     for (const std::string &module : m_modulesList) {
0066         if (module == "DBus") { // Avoid false positive for generated files
0067             if (const clang::FileEntry *fileEntry = sm().getFileEntryForID(sm().getFileID(HashLoc))) {
0068                 llvm::StringRef fileName = fileEntry->getName();
0069                 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuffer = llvm::MemoryBuffer::getFile(fileName);
0070                 if (fileBuffer) {
0071                     llvm::StringRef fileContent = fileBuffer.get()->getBuffer();
0072                     if (fileContent.startswith("/*\n * This file was generated by qdbusxml2cpp")) {
0073                         continue;
0074                     }
0075                 }
0076             }
0077         }
0078 
0079         const std::string qtModule = "Qt" + module;
0080         if (FileName.str() == qtModule + "/" + qtModule || FileName.str() == qtModule) {
0081             emitWarning(FilenameRange.getAsRange().getBegin(), "Module " + qtModule + " should not be included directly");
0082         }
0083     }
0084 }