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:
38 virtual ~GlobalCompilationDatabase() = default;
39
40 /// If there are any known-good commands for building this file, returns one.
41 virtual std::optional<tooling::CompileCommand>
43
44 /// Finds the closest project to \p File.
45 virtual std::optional<ProjectInfo> getProjectInfo(PathRef File) const {
46 return std::nullopt;
47 }
48
49 /// Get the modules in the closest project to \p File
50 virtual std::unique_ptr<ProjectModules>
52 return nullptr;
53 }
54
55 /// Makes a guess at how to build a file.
56 /// The default implementation just runs clang on the file.
57 /// Clangd should treat the results as unreliable.
58 virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
59
60 /// If the CDB does any asynchronous work, wait for it to complete.
61 /// For use in tests.
62 virtual bool blockUntilIdle(Deadline D) const { return true; }
63
65 /// The callback is notified when files may have new compile commands.
66 /// The argument is a list of full file paths.
67 CommandChanged::Subscription watch(CommandChanged::Listener L) const {
68 return OnCommandChanged.observe(std::move(L));
69 }
70
71protected:
73};
74
75// Helper class for implementing GlobalCompilationDatabases that wrap others.
77public:
79 DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base);
80
81 std::optional<tooling::CompileCommand>
82 getCompileCommand(PathRef File) const override;
83
84 std::optional<ProjectInfo> getProjectInfo(PathRef File) const override;
85
86 std::unique_ptr<ProjectModules>
87 getProjectModules(PathRef File) const override;
88
89 tooling::CompileCommand getFallbackCommand(PathRef File) const override;
90
91 bool blockUntilIdle(Deadline D) const override;
92
93private:
94 const GlobalCompilationDatabase *Base;
95 std::unique_ptr<GlobalCompilationDatabase> BaseOwner;
96 CommandChanged::Subscription BaseChanged;
97};
98
99/// Gets compile args from tooling::CompilationDatabases built for parent
100/// directories.
103public:
104 struct Options {
106
108 // Frequency to check whether e.g. compile_commands.json has changed.
109 std::chrono::steady_clock::duration RevalidateAfter =
110 std::chrono::seconds(5);
111 // Frequency to check whether e.g. compile_commands.json has been created.
112 // (This is more expensive to check frequently, as we check many locations).
113 std::chrono::steady_clock::duration RevalidateMissingAfter =
114 std::chrono::seconds(30);
115 // Used to provide per-file configuration.
116 std::function<Context(llvm::StringRef)> ContextProvider;
117 // Only look for a compilation database in this one fixed directory.
118 // FIXME: fold this into config/context mechanism.
119 std::optional<Path> CompileCommandsDir;
120 };
121
124
125 /// Scans File's parents looking for compilation databases.
126 /// Any extra flags will be added.
127 /// Might trigger OnCommandChanged, if CDB wasn't broadcasted yet.
128 std::optional<tooling::CompileCommand>
129 getCompileCommand(PathRef File) const override;
130
131 /// Returns the path to first directory containing a compilation database in
132 /// \p File's parents.
133 std::optional<ProjectInfo> getProjectInfo(PathRef File) const override;
134
135 std::unique_ptr<ProjectModules>
136 getProjectModules(PathRef File) const override;
137
138 bool blockUntilIdle(Deadline Timeout) const override;
139
140private:
141 Options Opts;
142
143 class DirectoryCache;
144 // Keyed by possibly-case-folded directory path.
145 // We can hand out pointers as they're stable and entries are never removed.
146 mutable llvm::StringMap<DirectoryCache> DirCaches;
147 mutable std::mutex DirCachesMutex;
148
149 std::vector<DirectoryCache *>
150 getDirectoryCaches(llvm::ArrayRef<llvm::StringRef> Dirs) const;
151
152 struct CDBLookupRequest {
153 PathRef FileName;
154 // Whether this lookup should trigger discovery of the CDB found.
155 bool ShouldBroadcast = false;
156 // Cached results newer than this are considered fresh and not checked
157 // against disk.
158 std::chrono::steady_clock::time_point FreshTime;
159 std::chrono::steady_clock::time_point FreshTimeMissing;
160 };
161 struct CDBLookupResult {
162 std::shared_ptr<const tooling::CompilationDatabase> CDB;
163 ProjectInfo PI;
164 };
165 std::optional<CDBLookupResult> lookupCDB(CDBLookupRequest Request) const;
166
167 class BroadcastThread;
168 std::unique_ptr<BroadcastThread> Broadcaster;
169
170 // Performs broadcast on governed files.
171 void broadcastCDB(CDBLookupResult Res) const;
172
173 // cache test calls lookupCDB directly to ensure valid/invalid times.
175};
176
177/// Extracts system include search path from drivers matching QueryDriverGlobs
178/// and adds them to the compile flags.
179/// Returns null when \p QueryDriverGlobs is empty.
180using SystemIncludeExtractorFn = llvm::unique_function<void(
181 tooling::CompileCommand &, llvm::StringRef) const>;
183getSystemIncludeExtractor(llvm::ArrayRef<std::string> QueryDriverGlobs);
184
185/// Wraps another compilation database, and supports overriding the commands
186/// using an in-memory mapping.
187class OverlayCDB : public DelegatingCDB {
188public:
189 // Makes adjustments to a tooling::CompileCommand which will be used to
190 // process a file (possibly different from the one in the command).
191 using CommandMangler = llvm::unique_function<void(tooling::CompileCommand &,
192 StringRef File) const>;
193
194 // Base may be null, in which case no entries are inherited.
195 // FallbackFlags are added to the fallback compile command.
196 // Adjuster is applied to all commands, fallback or not.
198 std::vector<std::string> FallbackFlags = {},
199 CommandMangler Mangler = nullptr);
200
201 std::optional<tooling::CompileCommand>
202 getCompileCommand(PathRef File) const override;
203 tooling::CompileCommand getFallbackCommand(PathRef File) const override;
204
205 /// Sets or clears the compilation command for a particular file.
206 /// Returns true if the command was changed (including insertion and removal),
207 /// false if it was unchanged.
208 bool
210 std::optional<tooling::CompileCommand> CompilationCommand);
211
212 std::unique_ptr<ProjectModules>
213 getProjectModules(PathRef File) const override;
214
215private:
216 mutable std::mutex Mutex;
217 llvm::StringMap<tooling::CompileCommand> Commands; /* GUARDED_BY(Mut) */
218 CommandMangler Mangler;
219 std::vector<std::string> FallbackFlags;
220};
221
222} // namespace clangd
223} // namespace clang
224
225#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< 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.
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.
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)
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++ -*-===//