17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/StringMap.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Path.h"
33 mutable llvm::SmallVector<CompiledFragment, 1> CachedValue;
34 std::string Directory;
38 :
FileCache(Path), Directory(Directory) {}
41 std::chrono::steady_clock::time_point FreshTime,
bool Trusted,
42 std::vector<CompiledFragment> &Out)
const {
45 [&](std::optional<llvm::StringRef> Data) {
51 CachedValue.push_back(std::move(
Fragment).compile(DC));
54 [&]() { llvm::copy(CachedValue, std::back_inserter(Out)); });
62 class AbsFileProvider :
public Provider {
67 std::vector<CompiledFragment>
69 std::vector<CompiledFragment> Result;
70 Cache.
get(FS, DC, P.FreshTime, Trusted, Result);
75 AbsFileProvider(llvm::StringRef
Path, llvm::StringRef
Directory,
78 assert(llvm::sys::path::is_absolute(
Path));
82 return std::make_unique<AbsFileProvider>(AbsPath,
Directory, FS, Trusted);
85std::unique_ptr<Provider>
88 class RelFileProvider :
public Provider {
93 mutable std::mutex Mu;
97 mutable llvm::StringMap<FileConfigCache> Cache;
99 std::vector<CompiledFragment>
101 namespace path = llvm::sys::path;
107 llvm::SmallVector<llvm::StringRef, 8> Ancestors;
110 Ancestors.emplace_back(Ancestor);
113 llvm::SmallVector<FileConfigCache *, 8> Caches;
115 std::lock_guard<std::mutex> Lock(Mu);
116 for (llvm::StringRef Ancestor : Ancestors) {
117 auto It = Cache.find(Ancestor);
119 if (It == Cache.end()) {
120 llvm::SmallString<256> ConfigPath = Ancestor;
121 path::append(ConfigPath, RelPath);
123 llvm::sys::path::native(ConfigPath);
124 It = Cache.try_emplace(Ancestor, ConfigPath.str(), Ancestor).first;
126 Caches.push_back(&It->second);
131 std::vector<CompiledFragment> Result;
133 Cache->get(FS, DC, P.FreshTime, Trusted, Result);
138 RelFileProvider(llvm::StringRef RelPath,
const ThreadsafeFS &FS,
140 : RelPath(RelPath), FS(FS), Trusted(Trusted) {
141 assert(llvm::sys::path::is_relative(RelPath));
145 return std::make_unique<RelFileProvider>(RelPath, FS, Trusted);
148std::unique_ptr<Provider>
150 class CombinedProvider :
public Provider {
151 std::vector<std::unique_ptr<Provider>> Providers;
153 std::vector<CompiledFragment>
155 std::vector<CompiledFragment> Result;
156 for (
const auto &
Provider : Providers) {
158 Result.push_back(std::move(
Fragment));
164 CombinedProvider(std::vector<std::unique_ptr<Provider>> Providers)
165 : Providers(std::move(Providers)) {}
168 return std::make_unique<CombinedProvider>(std::move(Providers));
171std::vector<std::unique_ptr<Provider>>
173 std::vector<std::unique_ptr<Provider>> Providers;
175 llvm::SmallString<256> UserConfig;
176 if (llvm::sys::path::user_config_directory(UserConfig)) {
177 llvm::sys::path::append(UserConfig,
"clangd",
"config.yaml");
178 vlog(
"User config file is {0}", UserConfig);
182 elog(
"Couldn't determine user config file, not loading");
188 "Read user and project configuration from YAML files.\n"
189 "Project config is from a .clangd file in the project directory.\n"
190 "User config is from clangd/config.yaml in the following directories:\n"
191 "\tWindows: %USERPROFILE%\\AppData\\Local\n"
192 "\tMac OS: ~/Library/Preferences/\n"
193 "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n"
194 "Configuration is documented at https://clangd.llvm.org/config.html";
201 for (
const auto &
Fragment : getFragments(P, DC))
static cl::opt< std::string > Directory(cl::Positional, cl::Required, cl::desc("<Search Root Directory>"))
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
void read(const ThreadsafeFS &TFS, std::chrono::steady_clock::time_point FreshTime, llvm::function_ref< void(std::optional< llvm::StringRef >)> Parse, llvm::function_ref< void()> Read) const
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
void get(const ThreadsafeFS &TFS, DiagnosticCallback DC, std::chrono::steady_clock::time_point FreshTime, bool Trusted, std::vector< CompiledFragment > &Out) const
FileConfigCache(llvm::StringRef Path, llvm::StringRef Directory)
A source of configuration fragments.
static const char *const EnableConfigFlagDesc
Help text for the –enable-config flag, shared by clangd tools that expose createDefaultProviders() on...
static std::vector< std::unique_ptr< Provider > > createDefaultProviders(const ThreadsafeFS &)
Returns providers for the configuration files that clangd tools read by default: project config (ance...
static std::unique_ptr< Provider > fromYAMLFile(llvm::StringRef AbsPath, llvm::StringRef Directory, const ThreadsafeFS &, bool Trusted=false)
Reads fragments from a single YAML file with a fixed path.
Config getConfig(const Params &, DiagnosticCallback) const
Build a config based on this provider.
static std::unique_ptr< Provider > fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &, bool Trusted=false)
static std::unique_ptr< Provider > combine(std::vector< std::unique_ptr< Provider > >)
A provider that includes fragments from all the supplied providers.
Records an event whose duration is the lifetime of the Span object.
llvm::function_ref< void(const llvm::SMDiagnostic &)> DiagnosticCallback
Used to report problems in parsing or interpreting a config.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
void vlog(const char *Fmt, Ts &&... Vals)
PathRef absoluteParent(PathRef Path)
Variant of parent_path that operates only on absolute paths.
std::string Path
A typedef to represent a file path.
void elog(const char *Fmt, Ts &&... Vals)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Settings that express user/project preferences and control clangd behavior.
bool Trusted
Whether this fragment is allowed to make critical security/privacy decisions.
std::string Directory
Absolute path to directory the fragment is associated with.
A chunk of configuration obtained from a config file, LSP, or elsewhere.
static std::vector< Fragment > parseYAML(llvm::StringRef YAML, llvm::StringRef BufferName, DiagnosticCallback)
Parses fragments from a YAML file (one from each — delimited document).
Describes the context used to evaluate configuration fragments.