File indexing completed on 2024-05-19 05:41:59
0001 // ct_lvtclp_clputil.h -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #ifndef INCLUDED_CT_LVTCLP_CLPUTIL 0021 #define INCLUDED_CT_LVTCLP_CLPUTIL 0022 0023 //@PURPOSE: Provide somewhere to contain things common to lvtclp 0024 // 0025 //@CLASSES: 0026 // lvtclp::ClpUtil: common definitions for lvtclp 0027 0028 #include <filesystem> 0029 #include <lvtclp_export.h> 0030 #include <memory> 0031 #include <optional> 0032 #include <string> 0033 #include <vector> 0034 0035 #include <result/result.hpp> 0036 0037 #include <clang/Basic/SourceManager.h> 0038 #include <clang/Tooling/CompilationDatabase.h> 0039 #include <llvm/Support/GlobPattern.h> 0040 0041 namespace Codethink { 0042 0043 // FORWARD DECLARATIONS 0044 0045 namespace lvtmdb { 0046 class FileObject; 0047 } 0048 namespace lvtmdb { 0049 class ObjectStore; 0050 } 0051 namespace lvtmdb { 0052 class PackageObject; 0053 } 0054 namespace lvtmdb { 0055 class TypeObject; 0056 } 0057 namespace lvtmdb { 0058 class FunctionObject; 0059 } 0060 0061 namespace lvtclp { 0062 0063 enum class FileType : short { 0064 e_Header, 0065 e_Source, 0066 e_KnownUnknown, 0067 // A file type we expect to see amongst source files but 0068 // which isn't a header or a source. 0069 e_UnknownUnknown, 0070 // A file type we don't recognise. 0071 }; 0072 0073 struct CompilationDatabaseError { 0074 enum class Kind { ErrorLoadingFromFile, CompileCommandsContainsNoCommands, CompileCommandsContainsNoFiles }; 0075 0076 Kind kind; 0077 std::string message = ""; 0078 }; 0079 0080 // ============== 0081 // struct ClpUtil 0082 // ============== 0083 0084 struct LVTCLP_EXPORT ClpUtil { 0085 // This struct groups things common to lvtclp 0086 0087 public: 0088 // CLASS METHODS 0089 static std::filesystem::path normalisePath(std::filesystem::path path, const std::filesystem::path& prefix); 0090 // Normalise a path for inclusion in the database 0091 0092 static lvtmdb::FileObject *writeSourceFile(const std::string& filename, 0093 bool isHeader, 0094 lvtmdb::ObjectStore& memDb, 0095 const std::filesystem::path& prefix, 0096 const std::vector<std::filesystem::path>& nonLakosianDirs, 0097 const std::vector<std::pair<std::string, std::string>>& thirdPartyDirs); 0098 0099 static std::string getRealPath(const clang::SourceLocation& loc, const clang::SourceManager& mgr); 0100 // Fetch ann absolute path to loc (or "") 0101 0102 static void writeDependencyRelations(lvtmdb::PackageObject *source, lvtmdb::PackageObject *target); 0103 // Add a package dependency from source to target 0104 0105 static void addUsesInInter(lvtmdb::TypeObject *source, lvtmdb::TypeObject *target); 0106 // Add a uses in the interface relationship between source and target 0107 0108 static void addUsesInImpl(lvtmdb::TypeObject *source, lvtmdb::TypeObject *target); 0109 // Add a uses in the impl relationship between source and target 0110 0111 static void addFnDependency(lvtmdb::FunctionObject *source, lvtmdb::FunctionObject *target); 0112 // Add a function-to-function dependency 0113 0114 static FileType categorisePath(const std::string& file); 0115 // return the FileType for the path 0116 0117 static const char *const NON_LAKOSIAN_GROUP_NAME; 0118 0119 static long getThreadId(); 0120 // returns the id of this thread as a long. 0121 0122 static bool isComponentOnPackageGroup(const std::filesystem::path& componentPath); 0123 static bool isComponentOnStandalonePackage(const std::filesystem::path& componentPath); 0124 0125 static bool isFileIgnored(const std::string& file, std::vector<llvm::GlobPattern> const& ignoreGlobs); 0126 0127 using PkgMatcherAddPkgFunction = std::function<void(std::string const& qualifiedName, 0128 std::optional<std::string> parentQualifiedName, 0129 std::optional<std::string> repositoryName, 0130 std::optional<std::string> path)>; 0131 class SemanticPackingRule { 0132 public: 0133 virtual ~SemanticPackingRule() = default; 0134 virtual bool accept(std::string const& filepath) const = 0; 0135 virtual std::string process(std::string const& filepath, PkgMatcherAddPkgFunction const& addPkg) const = 0; 0136 }; 0137 0138 class PySemanticPackingRule : public SemanticPackingRule { 0139 public: 0140 explicit PySemanticPackingRule(std::filesystem::path pythonFile); 0141 ~PySemanticPackingRule() = default; 0142 bool accept(std::string const& filepath) const override; 0143 std::string process(std::string const& filepath, PkgMatcherAddPkgFunction const& addPkg) const override; 0144 0145 private: 0146 std::filesystem::path d_pythonFile; 0147 }; 0148 static std::vector<std::unique_ptr<SemanticPackingRule>> getAllSemanticPackingRules(); 0149 }; 0150 0151 enum class CheckingMode : char { 0152 // Controls how clp behaves when it encounters something non-lakosian 0153 0154 e_error, // Non-lakosian is an error 0155 e_warn, // Non-lakosian is a warning 0156 e_permissive, // Non-lakosian is ignored silently 0157 }; 0158 0159 class LVTCLP_EXPORT CombinedCompilationDatabase : public clang::tooling::CompilationDatabase { 0160 // clang::ToolingCompilationDatabase formed from a combination of existing 0161 // compilation databases 0162 private: 0163 // TYPES 0164 struct Private; 0165 0166 // DATA 0167 std::unique_ptr<Private> d; 0168 0169 public: 0170 // CREATORS 0171 CombinedCompilationDatabase(); 0172 ~CombinedCompilationDatabase() noexcept override; 0173 0174 // MODIFIERS 0175 cpp::result<bool, CompilationDatabaseError> addCompilationDatabase(const std::filesystem::path& path); 0176 // Read in a compile_commands.json file from path 0177 0178 void addCompilationDatabase(const clang::tooling::CompilationDatabase& db, const std::filesystem::path& buildDir); 0179 // Add the contents of the compilation database given in as an argument 0180 // to this one, using the given build directory (the directory from which 0181 // relative paths in the database should be considered resolved) 0182 0183 // ACCESSORS 0184 [[nodiscard]] std::vector<clang::tooling::CompileCommand> 0185 getCompileCommands(llvm::StringRef FilePath) const override; 0186 0187 [[nodiscard]] std::vector<std::string> getAllFiles() const override; 0188 0189 [[nodiscard]] std::vector<clang::tooling::CompileCommand> getAllCompileCommands() const override; 0190 }; 0191 0192 class LvtCompilationDatabase : public clang::tooling::CompilationDatabase { 0193 // clang::Tooling::CompilationDatabase with some extra accessors to 0194 // efficiently figure out if files, packages or package groups are present 0195 // in the database 0196 0197 public: 0198 // CREATORS 0199 ~LvtCompilationDatabase() override = default; 0200 0201 // ACCESSORS 0202 [[nodiscard]] virtual bool containsFile(const std::string& path) const = 0; 0203 // Returns true if the file at path is in the compilation database 0204 0205 [[nodiscard]] virtual bool containsPackage(const std::string& pkg) const = 0; 0206 // Returns true if there is a package or package group with this 0207 // qualified name in the compilation database 0208 }; 0209 0210 } // end namespace lvtclp 0211 0212 } // end namespace Codethink 0213 0214 #endif