clang-tools 22.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 "ProjectModules.h"
13#include "support/Function.h"
14#include "support/Path.h"
15#include "support/Threading.h"
17#include "clang/Tooling/ArgumentsAdjusters.h"
18#include "clang/Tooling/CompilationDatabase.h"
19#include "llvm/ADT/FunctionExtras.h"
20#include "llvm/ADT/StringMap.h"
21#include <memory>
22#include <mutex>
23#include <optional>
24#include <vector>
25
26namespace clang {
27namespace clangd {
28
30 // The directory in which the compilation database was discovered.
31 // Empty if directory-based compilation database discovery was not used.
32 std::string SourceRoot;
33};
34
35/// Provides compilation arguments used for parsing C and C++ files.
37public:
41 virtual ~GlobalCompilationDatabase() = default;
42
43 /// If there are any known-good commands for building this file, returns one.
44 virtual std::optional<tooling::CompileCommand>
46
47 /// Finds the closest project to \p File.
48 virtual std::optional<ProjectInfo> getProjectInfo(PathRef File) const {
49 return std::nullopt;
50 }
51
52 /// Get the modules in the closest project to \p File
53 virtual std::unique_ptr<ProjectModules>
55 return nullptr;
56 }
57
58 /// Makes a guess at how to build a file.
59 /// The default implementation just runs clang on the file.
60 /// Clangd should treat the results as unreliable.
61 virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
62
63 /// If the CDB does any asynchronous work, wait for it to complete.
64 /// For use in tests.
65 virtual bool blockUntilIdle(Deadline D) const { return true; }
66
68 /// The callback is notified when files may have new compile commands.
69 /// The argument is a list of full file paths.
70 CommandChanged::Subscription watch(CommandChanged::Listener L) const {
71 return OnCommandChanged.observe(std::move(L));
72 }
73
74protected:
75 std::optional<std::string> FallbackWorkingDirectory;
77};
78
79// Helper class for implementing GlobalCompilationDatabases that wrap others.
81public:
83 const GlobalCompilationDatabase *Base,
84 std::optional<std::string> FallbackWorkingDirectory = std::nullopt);
86 std::unique_ptr<GlobalCompilationDatabase> Base,
87 std::optional<std::string> FallbackWorkingDirectory = std::nullopt);
88
89 std::optional<tooling::CompileCommand>
90 getCompileCommand(PathRef File) const override;
91
92 std::optional<ProjectInfo> getProjectInfo(PathRef File) const override;
93
94 std::unique_ptr<ProjectModules>
95 getProjectModules(PathRef File) const override;
96
97 tooling::CompileCommand getFallbackCommand(PathRef File) const override;
98
99 bool blockUntilIdle(Deadline D) const override;
100
101private:
102 const GlobalCompilationDatabase *Base;
103 std::unique_ptr<GlobalCompilationDatabase> BaseOwner;
104 CommandChanged::Subscription BaseChanged;
105};
106
107/// Gets compile args from tooling::CompilationDatabases built for parent
108/// directories.
111public:
112 struct Options {
114
116 // Frequency to check whether e.g. compile_commands.json has changed.
117 std::chrono::steady_clock::duration RevalidateAfter =
118 std::chrono::seconds(5);
119 // Frequency to check whether e.g. compile_commands.json has been created.
120 // (This is more expensive to check frequently, as we check many locations).
121 std::chrono::steady_clock::duration RevalidateMissingAfter =
122 std::chrono::seconds(30);
123 // Used to provide per-file configuration.
124 std::function<Context(llvm::StringRef)> ContextProvider;
125 // Only look for a compilation database in this one fixed directory.
126 // FIXME: fold this into config/context mechanism.
127 std::optional<Path> CompileCommandsDir;
128 // Working directory for fallback commands
129 // If unset, parent directory of file should be used
130 std::optional<std::string> FallbackWorkingDirectory;
131
133 std::optional<std::string> FallbackWorkingDirectory);
134 };
135
138
139 /// Scans File's parents looking for compilation databases.
140 /// Any extra flags will be added.
141 /// Might trigger OnCommandChanged, if CDB wasn't broadcasted yet.
142 std::optional<tooling::CompileCommand>
143 getCompileCommand(PathRef File) const override;
144
145 /// Returns the path to first directory containing a compilation database in
146 /// \p File's parents.
147 std::optional<ProjectInfo> getProjectInfo(PathRef File) const override;
148
149 std::unique_ptr<ProjectModules>
150 getProjectModules(PathRef File) const override;
151
152 bool blockUntilIdle(Deadline Timeout) const override;
153
154private:
155 Options Opts;
156
157 class DirectoryCache;
158 // Keyed by possibly-case-folded directory path.
159 // We can hand out pointers as they're stable and entries are never removed.
160 mutable llvm::StringMap<DirectoryCache> DirCaches;
161 mutable std::mutex DirCachesMutex;
162
163 std::vector<DirectoryCache *>
164 getDirectoryCaches(llvm::ArrayRef<llvm::StringRef> Dirs) const;
165
166 struct CDBLookupRequest {
167 PathRef FileName;
168 // Whether this lookup should trigger discovery of the CDB found.
169 bool ShouldBroadcast = false;
170 // Cached results newer than this are considered fresh and not checked
171 // against disk.
172 std::chrono::steady_clock::time_point FreshTime;
173 std::chrono::steady_clock::time_point FreshTimeMissing;
174 };
175 struct CDBLookupResult {
176 std::shared_ptr<const tooling::CompilationDatabase> CDB;
177 ProjectInfo PI;
178 };
179 std::optional<CDBLookupResult> lookupCDB(CDBLookupRequest Request) const;
180
181 class BroadcastThread;
182 std::unique_ptr<BroadcastThread> Broadcaster;
183
184 // Performs broadcast on governed files.
185 void broadcastCDB(CDBLookupResult Res) const;
186
187 // cache test calls lookupCDB directly to ensure valid/invalid times.
189};
190
191/// Extracts system include search path from drivers matching QueryDriverGlobs
192/// and adds them to the compile flags.
193/// Returns null when \p QueryDriverGlobs is empty.
194using SystemIncludeExtractorFn = llvm::unique_function<void(
195 tooling::CompileCommand &, llvm::StringRef) const>;
197getSystemIncludeExtractor(llvm::ArrayRef<std::string> QueryDriverGlobs);
198
199/// Wraps another compilation database, and supports overriding the commands
200/// using an in-memory mapping.
201class OverlayCDB : public DelegatingCDB {
202public:
203 // Makes adjustments to a tooling::CompileCommand which will be used to
204 // process a file (possibly different from the one in the command).
205 using CommandMangler = llvm::unique_function<void(tooling::CompileCommand &,
206 StringRef File) const>;
207
208 // Base may be null, in which case no entries are inherited.
209 // FallbackFlags are added to the fallback compile command.
210 // Adjuster is applied to all commands, fallback or not.
212 const GlobalCompilationDatabase *Base,
213 std::vector<std::string> FallbackFlags = {},
214 CommandMangler Mangler = nullptr,
215 std::optional<std::string> FallbackWorkingDirectory = std::nullopt);
216
217 std::optional<tooling::CompileCommand>
218 getCompileCommand(PathRef File) const override;
219 tooling::CompileCommand getFallbackCommand(PathRef File) const override;
220
221 /// Sets or clears the compilation command for a particular file.
222 /// Returns true if the command was changed (including insertion and removal),
223 /// false if it was unchanged.
224 bool
226 std::optional<tooling::CompileCommand> CompilationCommand);
227
228 std::unique_ptr<ProjectModules>
229 getProjectModules(PathRef File) const override;
230
231private:
232 mutable std::mutex Mutex;
233 llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */
234 CommandMangler Mangler;
235 std::vector<std::string> FallbackFlags;
236};
237
238} // namespace clangd
239} // namespace clang
240
241#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_GLOBALCOMPILATIONDATABASE_H
static cl::list< std::string > Commands("c", cl::desc("Specify command to run"), cl::value_desc("command"), cl::cat(ClangQueryCategory))
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition Context.h:69
A point in time we can wait for.
Definition Threading.h:46
tooling::CompileCommand getFallbackCommand(PathRef File) const override
Makes a guess at how to build a file.
DelegatingCDB(const GlobalCompilationDatabase *Base, std::optional< std::string > FallbackWorkingDirectory=std::nullopt)
std::optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
If there are any known-good commands for building this file, returns one.
bool blockUntilIdle(Deadline D) const override
If the CDB does any asynchronous work, wait for it to complete.
std::optional< ProjectInfo > getProjectInfo(PathRef File) const override
Finds the closest project to File.
std::unique_ptr< ProjectModules > getProjectModules(PathRef File) const override
Get the modules in the closest project to File.
bool blockUntilIdle(Deadline Timeout) const override
If the CDB does any asynchronous work, wait for it to complete.
std::unique_ptr< ProjectModules > getProjectModules(PathRef File) const override
Get the modules in the closest project to File.
std::optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
Scans File's parents looking for compilation databases.
std::optional< ProjectInfo > getProjectInfo(PathRef File) const override
Returns the path to first directory containing a compilation database in File's parents.
An Event<T> allows events of type T to be broadcast to listeners.
Definition Function.h:31
std::function< void(const std::vector< std::string > &)> Listener
Definition Function.h:34
Provides compilation arguments used for parsing C and C++ files.
std::optional< std::string > FallbackWorkingDirectory
CommandChanged::Subscription watch(CommandChanged::Listener L) const
The callback is notified when files may have new compile commands.
virtual tooling::CompileCommand getFallbackCommand(PathRef File) const
Makes a guess at how to build a file.
GlobalCompilationDatabase(std::optional< std::string > FallbackWorkingDirectory=std::nullopt)
virtual std::optional< ProjectInfo > getProjectInfo(PathRef File) const
Finds the closest project to File.
virtual std::unique_ptr< ProjectModules > getProjectModules(PathRef File) const
Get the modules in the closest project to File.
virtual bool blockUntilIdle(Deadline D) const
If the CDB does any asynchronous work, wait for it to complete.
virtual std::optional< tooling::CompileCommand > getCompileCommand(PathRef File) const =0
If there are any known-good commands for building this file, returns one.
Event< std::vector< std::string > > CommandChanged
llvm::unique_function< void(tooling::CompileCommand &, StringRef File) const > CommandMangler
bool setCompileCommand(PathRef File, std::optional< tooling::CompileCommand > CompilationCommand)
Sets or clears the compilation command for a particular file.
tooling::CompileCommand getFallbackCommand(PathRef File) const override
Makes a guess at how to build a file.
std::optional< tooling::CompileCommand > getCompileCommand(PathRef File) const override
If there are any known-good commands for building this file, returns one.
std::unique_ptr< ProjectModules > getProjectModules(PathRef File) const override
Get the modules in the closest project to File.
OverlayCDB(const GlobalCompilationDatabase *Base, std::vector< std::string > FallbackFlags={}, CommandMangler Mangler=nullptr, std::optional< std::string > FallbackWorkingDirectory=std::nullopt)
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
Definition AST.cpp:45
SystemIncludeExtractorFn getSystemIncludeExtractor(llvm::ArrayRef< std::string > QueryDriverGlobs)
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...
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition Path.h:29
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void applyFallbackWorkingDirectory(std::optional< std::string > FallbackWorkingDirectory)