Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clangd/GlobalCompilationDatabase.h @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
line wrap: on
line source
//===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H #include "support/Function.h" #include "support/Path.h" #include "support/Threading.h" #include "support/ThreadsafeFS.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include <memory> #include <mutex> #include <vector> namespace clang { namespace clangd { struct ProjectInfo { // The directory in which the compilation database was discovered. // Empty if directory-based compilation database discovery was not used. std::string SourceRoot; }; /// Provides compilation arguments used for parsing C and C++ files. class GlobalCompilationDatabase { public: virtual ~GlobalCompilationDatabase() = default; /// If there are any known-good commands for building this file, returns one. virtual llvm::Optional<tooling::CompileCommand> getCompileCommand(PathRef File) const = 0; /// Finds the closest project to \p File. virtual llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const { return llvm::None; } /// Makes a guess at how to build a file. /// The default implementation just runs clang on the file. /// Clangd should treat the results as unreliable. virtual tooling::CompileCommand getFallbackCommand(PathRef File) const; /// If the CDB does any asynchronous work, wait for it to complete. /// For use in tests. virtual bool blockUntilIdle(Deadline D) const { return true; } using CommandChanged = Event<std::vector<std::string>>; /// The callback is notified when files may have new compile commands. /// The argument is a list of full file paths. CommandChanged::Subscription watch(CommandChanged::Listener L) const { return OnCommandChanged.observe(std::move(L)); } protected: mutable CommandChanged OnCommandChanged; }; // Helper class for implementing GlobalCompilationDatabases that wrap others. class DelegatingCDB : public GlobalCompilationDatabase { public: DelegatingCDB(const GlobalCompilationDatabase *Base); DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base); llvm::Optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override; tooling::CompileCommand getFallbackCommand(PathRef File) const override; bool blockUntilIdle(Deadline D) const override; private: const GlobalCompilationDatabase *Base; std::unique_ptr<GlobalCompilationDatabase> BaseOwner; CommandChanged::Subscription BaseChanged; }; /// Gets compile args from tooling::CompilationDatabases built for parent /// directories. class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: struct Options { Options(const ThreadsafeFS &TFS) : TFS(TFS) {} const ThreadsafeFS &TFS; // Frequency to check whether e.g. compile_commands.json has changed. std::chrono::steady_clock::duration RevalidateAfter = std::chrono::seconds(5); // Frequency to check whether e.g. compile_commands.json has been created. // (This is more expensive to check frequently, as we check many locations). std::chrono::steady_clock::duration RevalidateMissingAfter = std::chrono::seconds(30); // Used to provide per-file configuration. std::function<Context(llvm::StringRef)> ContextProvider; // Only look for a compilation database in this one fixed directory. // FIXME: fold this into config/context mechanism. llvm::Optional<Path> CompileCommandsDir; }; DirectoryBasedGlobalCompilationDatabase(const Options &Opts); ~DirectoryBasedGlobalCompilationDatabase() override; /// Scans File's parents looking for compilation databases. /// Any extra flags will be added. /// Might trigger OnCommandChanged, if CDB wasn't broadcasted yet. llvm::Optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; /// Returns the path to first directory containing a compilation database in /// \p File's parents. llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override; bool blockUntilIdle(Deadline Timeout) const override; private: Options Opts; class DirectoryCache; // Keyed by possibly-case-folded directory path. // We can hand out pointers as they're stable and entries are never removed. mutable llvm::StringMap<DirectoryCache> DirCaches; mutable std::mutex DirCachesMutex; std::vector<DirectoryCache *> getDirectoryCaches(llvm::ArrayRef<llvm::StringRef> Dirs) const; struct CDBLookupRequest { PathRef FileName; // Whether this lookup should trigger discovery of the CDB found. bool ShouldBroadcast = false; // Cached results newer than this are considered fresh and not checked // against disk. std::chrono::steady_clock::time_point FreshTime; std::chrono::steady_clock::time_point FreshTimeMissing; }; struct CDBLookupResult { std::shared_ptr<const tooling::CompilationDatabase> CDB; ProjectInfo PI; }; llvm::Optional<CDBLookupResult> lookupCDB(CDBLookupRequest Request) const; class BroadcastThread; std::unique_ptr<BroadcastThread> Broadcaster; // Performs broadcast on governed files. void broadcastCDB(CDBLookupResult Res) const; // cache test calls lookupCDB directly to ensure valid/invalid times. friend class DirectoryBasedGlobalCompilationDatabaseCacheTest; }; /// Extracts system include search path from drivers matching QueryDriverGlobs /// and adds them to the compile flags. Base may not be nullptr. /// Returns Base when \p QueryDriverGlobs is empty. std::unique_ptr<GlobalCompilationDatabase> getQueryDriverDatabase(llvm::ArrayRef<std::string> QueryDriverGlobs, std::unique_ptr<GlobalCompilationDatabase> Base); /// Wraps another compilation database, and supports overriding the commands /// using an in-memory mapping. class OverlayCDB : public DelegatingCDB { public: // Base may be null, in which case no entries are inherited. // FallbackFlags are added to the fallback compile command. // Adjuster is applied to all commands, fallback or not. OverlayCDB(const GlobalCompilationDatabase *Base, std::vector<std::string> FallbackFlags = {}, tooling::ArgumentsAdjuster Adjuster = nullptr); llvm::Optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; tooling::CompileCommand getFallbackCommand(PathRef File) const override; /// Sets or clears the compilation command for a particular file. void setCompileCommand(PathRef File, llvm::Optional<tooling::CompileCommand> CompilationCommand); private: mutable std::mutex Mutex; llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */ tooling::ArgumentsAdjuster ArgsAdjuster; std::vector<std::string> FallbackFlags; }; } // namespace clangd } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H