clang-tools  16.0.0git
GlobalCompilationDatabase.h
Go to the documentation of this file.
1 //===--- GlobalCompilationDatabase.h -----------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
11 
12 #include "support/Function.h"
13 #include "support/Path.h"
14 #include "support/Threading.h"
15 #include "support/ThreadsafeFS.h"
16 #include "clang/Tooling/ArgumentsAdjusters.h"
17 #include "clang/Tooling/CompilationDatabase.h"
18 #include "llvm/ADT/FunctionExtras.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/StringMap.h"
21 #include <memory>
22 #include <mutex>
23 #include <vector>
24 
25 namespace clang {
26 namespace clangd {
27 
28 struct ProjectInfo {
29  // The directory in which the compilation database was discovered.
30  // Empty if directory-based compilation database discovery was not used.
31  std::string SourceRoot;
32 };
33 
34 /// Provides compilation arguments used for parsing C and C++ files.
36 public:
37  virtual ~GlobalCompilationDatabase() = default;
38 
39  /// If there are any known-good commands for building this file, returns one.
40  virtual llvm::Optional<tooling::CompileCommand>
41  getCompileCommand(PathRef File) const = 0;
42 
43  /// Finds the closest project to \p File.
44  virtual llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const {
45  return std::nullopt;
46  }
47 
48  /// Makes a guess at how to build a file.
49  /// The default implementation just runs clang on the file.
50  /// Clangd should treat the results as unreliable.
51  virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
52 
53  /// If the CDB does any asynchronous work, wait for it to complete.
54  /// For use in tests.
55  virtual bool blockUntilIdle(Deadline D) const { return true; }
56 
58  /// The callback is notified when files may have new compile commands.
59  /// The argument is a list of full file paths.
60  CommandChanged::Subscription watch(CommandChanged::Listener L) const {
61  return OnCommandChanged.observe(std::move(L));
62  }
63 
64 protected:
66 };
67 
68 // Helper class for implementing GlobalCompilationDatabases that wrap others.
70 public:
72  DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base);
73 
74  llvm::Optional<tooling::CompileCommand>
75  getCompileCommand(PathRef File) const override;
76 
77  llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override;
78 
79  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
80 
81  bool blockUntilIdle(Deadline D) const override;
82 
83 private:
84  const GlobalCompilationDatabase *Base;
85  std::unique_ptr<GlobalCompilationDatabase> BaseOwner;
86  CommandChanged::Subscription BaseChanged;
87 };
88 
89 /// Gets compile args from tooling::CompilationDatabases built for parent
90 /// directories.
92  : public GlobalCompilationDatabase {
93 public:
94  struct Options {
95  Options(const ThreadsafeFS &TFS) : TFS(TFS) {}
96 
97  const ThreadsafeFS &TFS;
98  // Frequency to check whether e.g. compile_commands.json has changed.
99  std::chrono::steady_clock::duration RevalidateAfter =
100  std::chrono::seconds(5);
101  // Frequency to check whether e.g. compile_commands.json has been created.
102  // (This is more expensive to check frequently, as we check many locations).
103  std::chrono::steady_clock::duration RevalidateMissingAfter =
104  std::chrono::seconds(30);
105  // Used to provide per-file configuration.
106  std::function<Context(llvm::StringRef)> ContextProvider;
107  // Only look for a compilation database in this one fixed directory.
108  // FIXME: fold this into config/context mechanism.
109  llvm::Optional<Path> CompileCommandsDir;
110  };
111 
114 
115  /// Scans File's parents looking for compilation databases.
116  /// Any extra flags will be added.
117  /// Might trigger OnCommandChanged, if CDB wasn't broadcasted yet.
118  llvm::Optional<tooling::CompileCommand>
119  getCompileCommand(PathRef File) const override;
120 
121  /// Returns the path to first directory containing a compilation database in
122  /// \p File's parents.
123  llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override;
124 
125  bool blockUntilIdle(Deadline Timeout) const override;
126 
127 private:
128  Options Opts;
129 
130  class DirectoryCache;
131  // Keyed by possibly-case-folded directory path.
132  // We can hand out pointers as they're stable and entries are never removed.
133  mutable llvm::StringMap<DirectoryCache> DirCaches;
134  mutable std::mutex DirCachesMutex;
135 
136  std::vector<DirectoryCache *>
137  getDirectoryCaches(llvm::ArrayRef<llvm::StringRef> Dirs) const;
138 
139  struct CDBLookupRequest {
141  // Whether this lookup should trigger discovery of the CDB found.
142  bool ShouldBroadcast = false;
143  // Cached results newer than this are considered fresh and not checked
144  // against disk.
145  std::chrono::steady_clock::time_point FreshTime;
146  std::chrono::steady_clock::time_point FreshTimeMissing;
147  };
148  struct CDBLookupResult {
149  std::shared_ptr<const tooling::CompilationDatabase> CDB;
150  ProjectInfo PI;
151  };
152  llvm::Optional<CDBLookupResult> lookupCDB(CDBLookupRequest Request) const;
153 
154  class BroadcastThread;
155  std::unique_ptr<BroadcastThread> Broadcaster;
156 
157  // Performs broadcast on governed files.
158  void broadcastCDB(CDBLookupResult Res) const;
159 
160  // cache test calls lookupCDB directly to ensure valid/invalid times.
162 };
163 
164 /// Extracts system include search path from drivers matching QueryDriverGlobs
165 /// and adds them to the compile flags.
166 /// Returns null when \p QueryDriverGlobs is empty.
167 using SystemIncludeExtractorFn = llvm::unique_function<void(
168  tooling::CompileCommand &, llvm::StringRef) const>;
170 getSystemIncludeExtractor(llvm::ArrayRef<std::string> QueryDriverGlobs);
171 
172 /// Wraps another compilation database, and supports overriding the commands
173 /// using an in-memory mapping.
174 class OverlayCDB : public DelegatingCDB {
175 public:
176  // Makes adjustments to a tooling::CompileCommand which will be used to
177  // process a file (possibly different from the one in the command).
178  using CommandMangler = llvm::unique_function<void(tooling::CompileCommand &,
179  StringRef File) const>;
180 
181  // Base may be null, in which case no entries are inherited.
182  // FallbackFlags are added to the fallback compile command.
183  // Adjuster is applied to all commands, fallback or not.
185  std::vector<std::string> FallbackFlags = {},
186  CommandMangler Mangler = nullptr);
187 
188  llvm::Optional<tooling::CompileCommand>
189  getCompileCommand(PathRef File) const override;
190  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
191 
192  /// Sets or clears the compilation command for a particular file.
193  void
195  llvm::Optional<tooling::CompileCommand> CompilationCommand);
196 
197 private:
198  mutable std::mutex Mutex;
199  llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */
200  CommandMangler Mangler;
201  std::vector<std::string> FallbackFlags;
202 };
203 
204 } // namespace clangd
205 } // namespace clang
206 
207 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
clang::clangd::ProjectInfo::SourceRoot
std::string SourceRoot
Definition: GlobalCompilationDatabase.h:31
clang::clangd::DirectoryBasedGlobalCompilationDatabase::~DirectoryBasedGlobalCompilationDatabase
~DirectoryBasedGlobalCompilationDatabase() override
Path.h
clang::clangd::DirectoryBasedGlobalCompilationDatabase::getCompileCommand
llvm::Optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
Scans File's parents looking for compilation databases.
Definition: GlobalCompilationDatabase.cpp:358
clang::clangd::DirectoryBasedGlobalCompilationDatabaseCacheTest
Definition: GlobalCompilationDatabaseTests.cpp:427
clang::clangd::OverlayCDB::getCompileCommand
llvm::Optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
If there are any known-good commands for building this file, returns one.
Definition: GlobalCompilationDatabase.cpp:748
clang::clangd::DirectoryBasedGlobalCompilationDatabase::getProjectInfo
llvm::Optional< ProjectInfo > getProjectInfo(PathRef File) const override
Returns the path to first directory containing a compilation database in File's parents.
Definition: GlobalCompilationDatabase.cpp:729
clang::clangd::SystemIncludeExtractorFn
llvm::unique_function< void(tooling::CompileCommand &, llvm::StringRef) const > SystemIncludeExtractorFn
Extracts system include search path from drivers matching QueryDriverGlobs and adds them to the compi...
Definition: GlobalCompilationDatabase.h:168
clang::clangd::GlobalCompilationDatabase::getCompileCommand
virtual llvm::Optional< tooling::CompileCommand > getCompileCommand(PathRef File) const =0
If there are any known-good commands for building this file, returns one.
clang::clangd::CommandMangler
Definition: CompileCommands.h:28
clang::clangd::GlobalCompilationDatabase
Provides compilation arguments used for parsing C and C++ files.
Definition: GlobalCompilationDatabase.h:35
clang::clangd::ProjectInfo
Definition: GlobalCompilationDatabase.h:28
clang::clangd::Event::observe
Subscription observe(Listener L)
Definition: Function.h:75
clang::clangd::DelegatingCDB::blockUntilIdle
bool blockUntilIdle(Deadline D) const override
If the CDB does any asynchronous work, wait for it to complete.
Definition: GlobalCompilationDatabase.cpp:823
clang::clangd::DelegatingCDB::getFallbackCommand
tooling::CompileCommand getFallbackCommand(PathRef File) const override
Makes a guess at how to build a file.
Definition: GlobalCompilationDatabase.cpp:817
clang::clangd::Deadline
A point in time we can wait for.
Definition: Threading.h:45
ThreadsafeFS.h
clang::clangd::getSystemIncludeExtractor
SystemIncludeExtractorFn getSystemIncludeExtractor(llvm::ArrayRef< std::string > QueryDriverGlobs)
Definition: SystemIncludeExtractor.cpp:369
clang::clangd::DelegatingCDB::getCompileCommand
llvm::Optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
If there are any known-good commands for building this file, returns one.
Definition: GlobalCompilationDatabase.cpp:805
clang::clangd::DirectoryBasedGlobalCompilationDatabase::blockUntilIdle
bool blockUntilIdle(Deadline Timeout) const override
If the CDB does any asynchronous work, wait for it to complete.
Definition: GlobalCompilationDatabase.cpp:723
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
Threading.h
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:46
clang::clangd::GlobalCompilationDatabase::blockUntilIdle
virtual bool blockUntilIdle(Deadline D) const
If the CDB does any asynchronous work, wait for it to complete.
Definition: GlobalCompilationDatabase.h:55
clang::clangd::OverlayCDB::getFallbackCommand
tooling::CompileCommand getFallbackCommand(PathRef File) const override
Makes a guess at how to build a file.
Definition: GlobalCompilationDatabase.cpp:765
clang::clangd::GlobalCompilationDatabase::getFallbackCommand
virtual tooling::CompileCommand getFallbackCommand(PathRef File) const
Makes a guess at how to build a file.
Definition: GlobalCompilationDatabase.cpp:54
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::Options
Options(const ThreadsafeFS &TFS)
Definition: GlobalCompilationDatabase.h:95
clang::clangd::GlobalCompilationDatabase::~GlobalCompilationDatabase
virtual ~GlobalCompilationDatabase()=default
clang::clangd::Event< std::vector< std::string > >::Listener
std::function< void(const std::vector< std::string > &)> Listener
Definition: Function.h:34
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::RevalidateAfter
std::chrono::steady_clock::duration RevalidateAfter
Definition: GlobalCompilationDatabase.h:99
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options
Definition: GlobalCompilationDatabase.h:94
clang::clangd::OverlayCDB::OverlayCDB
OverlayCDB(const GlobalCompilationDatabase *Base, std::vector< std::string > FallbackFlags={}, CommandMangler Mangler=nullptr)
Definition: GlobalCompilationDatabase.cpp:741
clang::clangd::OverlayCDB::setCompileCommand
void setCompileCommand(PathRef File, llvm::Optional< tooling::CompileCommand > CompilationCommand)
Sets or clears the compilation command for a particular file.
Definition: GlobalCompilationDatabase.cpp:775
clang::clangd::DelegatingCDB::getProjectInfo
llvm::Optional< ProjectInfo > getProjectInfo(PathRef File) const override
Finds the closest project to File.
Definition: GlobalCompilationDatabase.cpp:811
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
clang::clangd::ThreadsafeFS
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
Definition: ThreadsafeFS.h:27
clang::clangd::DirectoryBasedGlobalCompilationDatabase::DirectoryCache
Definition: GlobalCompilationDatabase.cpp:81
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::RevalidateMissingAfter
std::chrono::steady_clock::duration RevalidateMissingAfter
Definition: GlobalCompilationDatabase.h:103
clang::clangd::DelegatingCDB::DelegatingCDB
DelegatingCDB(const GlobalCompilationDatabase *Base)
Definition: GlobalCompilationDatabase.cpp:791
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
Function.h
clang::clangd::GlobalCompilationDatabase::getProjectInfo
virtual llvm::Optional< ProjectInfo > getProjectInfo(PathRef File) const
Finds the closest project to File.
Definition: GlobalCompilationDatabase.h:44
clang::clangd::OverlayCDB::CommandMangler
llvm::unique_function< void(tooling::CompileCommand &, StringRef File) const > CommandMangler
Definition: GlobalCompilationDatabase.h:179
clang::clangd::DirectoryBasedGlobalCompilationDatabase
Gets compile args from tooling::CompilationDatabases built for parent directories.
Definition: GlobalCompilationDatabase.h:91
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::CompileCommandsDir
llvm::Optional< Path > CompileCommandsDir
Definition: GlobalCompilationDatabase.h:109
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::TFS
const ThreadsafeFS & TFS
Definition: GlobalCompilationDatabase.h:97
clang::clangd::DirectoryBasedGlobalCompilationDatabase::Options::ContextProvider
std::function< Context(llvm::StringRef)> ContextProvider
Definition: GlobalCompilationDatabase.h:106
clang::clangd::DirectoryBasedGlobalCompilationDatabase::DirectoryBasedGlobalCompilationDatabase
DirectoryBasedGlobalCompilationDatabase(const Options &Opts)
Definition: GlobalCompilationDatabase.cpp:346
clang::clangd::GlobalCompilationDatabase::watch
CommandChanged::Subscription watch(CommandChanged::Listener L) const
The callback is notified when files may have new compile commands.
Definition: GlobalCompilationDatabase.h:60
clang::clangd::DelegatingCDB
Definition: GlobalCompilationDatabase.h:69
clang::clangd::Context
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
clang::clangd::GlobalCompilationDatabase::OnCommandChanged
CommandChanged OnCommandChanged
Definition: GlobalCompilationDatabase.h:65
clang::clangd::Event< std::vector< std::string > >
clang::clangd::OverlayCDB
Wraps another compilation database, and supports overriding the commands using an in-memory mapping.
Definition: GlobalCompilationDatabase.h:174