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