File indexing completed on 2024-04-21 05:38:46
0001 /* 0002 SPDX-FileCopyrightText: 2017 Sergio Martins <smartins@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ClazyContext.h" 0008 #include "AccessSpecifierManager.h" 0009 #include "FixItExporter.h" 0010 #include "PreProcessorVisitor.h" 0011 #include "checkmanager.h" 0012 0013 #include <clang/AST/ParentMap.h> 0014 #include <clang/Frontend/CompilerInstance.h> 0015 #include <clang/Lex/PreprocessorOptions.h> 0016 #include <clang/Rewrite/Frontend/FixItRewriter.h> 0017 #include <llvm/Support/Regex.h> 0018 0019 #include <stdlib.h> 0020 0021 using namespace clang; 0022 0023 ClazyContext::ClazyContext(const clang::CompilerInstance &compiler, 0024 const std::string &headerFilter, 0025 const std::string &ignoreDirs, 0026 std::string exportFixesFilename, 0027 const std::vector<std::string> &translationUnitPaths, 0028 ClazyOptions opts) 0029 : ci(compiler) 0030 , astContext(ci.getASTContext()) 0031 , sm(ci.getSourceManager()) 0032 , m_noWerror(getenv("CLAZY_NO_WERROR") != nullptr) // Allows user to make clazy ignore -Werror 0033 , m_checksPromotedToErrors(CheckManager::instance()->checksAsErrors()) 0034 , options(opts) 0035 , extraOptions(clazy::splitString(getenv("CLAZY_EXTRA_OPTIONS"), ',')) 0036 , m_translationUnitPaths(translationUnitPaths) 0037 { 0038 if (!headerFilter.empty()) { 0039 headerFilterRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(headerFilter)); 0040 } 0041 0042 if (!ignoreDirs.empty()) { 0043 ignoreDirsRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(ignoreDirs)); 0044 } 0045 0046 if (exportFixesEnabled()) { 0047 if (exportFixesFilename.empty()) { 0048 // Only clazy-standalone sets the filename by argument. 0049 // clazy plugin sets it automatically here: 0050 const FileEntry *fileEntry = sm.getFileEntryForID(sm.getMainFileID()); 0051 exportFixesFilename = fileEntry->getName().str() + ".clazy.yaml"; 0052 } 0053 0054 const bool isClazyStandalone = !translationUnitPaths.empty(); 0055 exporter = new FixItExporter(ci.getDiagnostics(), sm, ci.getLangOpts(), exportFixesFilename, isClazyStandalone); 0056 } 0057 } 0058 0059 ClazyContext::~ClazyContext() 0060 { 0061 // delete preprocessorVisitor; // we don't own it 0062 delete accessSpecifierManager; 0063 delete parentMap; 0064 0065 static unsigned long count = 0; 0066 count++; 0067 0068 if (exporter) { 0069 // With clazy-standalone we use the same YAML file for all translation-units, so only 0070 // write out the last one. With clazy-plugin there's a YAML file per translation unit. 0071 const bool isClazyPlugin = m_translationUnitPaths.empty(); 0072 const bool isLast = count == m_translationUnitPaths.size(); 0073 if (isLast || isClazyPlugin) { 0074 exporter->Export(); 0075 } 0076 delete exporter; 0077 } 0078 0079 preprocessorVisitor = nullptr; 0080 accessSpecifierManager = nullptr; 0081 parentMap = nullptr; 0082 } 0083 0084 void ClazyContext::enableAccessSpecifierManager() 0085 { 0086 if (!accessSpecifierManager && !usingPreCompiledHeaders()) { 0087 accessSpecifierManager = new AccessSpecifierManager(this); 0088 } 0089 } 0090 0091 void ClazyContext::enablePreprocessorVisitor() 0092 { 0093 if (!preprocessorVisitor && !usingPreCompiledHeaders()) { 0094 preprocessorVisitor = new PreProcessorVisitor(ci); 0095 } 0096 } 0097 0098 void ClazyContext::enableVisitallTypeDefs() 0099 { 0100 // By default we only process decls from the .cpp file we're processing, not stuff included (for performance) 0101 /// But we might need to process all typedefs, not only the ones in our current .cpp files 0102 m_visitsAllTypeDefs = true; 0103 } 0104 0105 bool ClazyContext::visitsAllTypedefs() const 0106 { 0107 return m_visitsAllTypeDefs; 0108 } 0109 0110 bool ClazyContext::isQt() const 0111 { 0112 static const bool s_isQt = [this] { 0113 for (const auto &s : ci.getPreprocessorOpts().Macros) { 0114 if (s.first == "QT_CORE_LIB") { 0115 return true; 0116 } 0117 } 0118 return false; 0119 }(); 0120 0121 return s_isQt; 0122 }